[Geoserver-users] Problems with TextSymbolizer label near tile edges

I am having a problem with the labels for some points not appearing at some zoom levels.

I am using GWC to serve 256x256 900913 tiles to a Bing map, using GeoServer 2.0.1 (I also tested 2.0.2 which showed the same issue).

Looking back through the archive I see that labels not being able to overlap tiles was an issue in the past. I assume that the issue was resolved at some point as I have plenty of layers that overlap tile edges without any difficulty.

This image illustrates my problem:

http://norman.cx/photos/links/closetotheedge.png

As you can see the label for Amsterdam crosses a tile boundary and is rendered correctly. The problem point in that image is London, you can see the black square where London is, but there is no label appearing.

The same SLD rule is being used for all the cities in that image. Many in my dataset cross a tile and the label is drawn, but for some reason London is not.

The same problem occurs with some other points as well, for example Accra also sits very close to the right hand side of a tile and also doesn’t get rendered at many zoom levels. Madrid is another problem case and that isn’t even particularly near the edge of the tile.

Is this a known issue ? Is there a way to fix or work around it ?

I am having a problem with the labels for some points not appearing at some zoom levels.

I am using GWC to serve 256x256 900913 tiles to a Bing map, using GeoServer 2.0.1 (I also tested 2.0.2 which showed the same issue).

Looking back through the archive I see that labels not being able to overlap tiles was an issue in the past. I assume that the issue was resolved at some point as I have plenty of layers that overlap tile edges without any difficulty.

There is no magic fix, it’s an artifact of WMS being stateless so every request is independent of every other. Metatiling[1] reduces the number of places where you see edge effects.

This image illustrates my problem:

http://norman.cx/photos/links/closetotheedge.png

As you can see the label for Amsterdam crosses a tile boundary and is rendered correctly. The problem point in that image is London, you can see the black square where London is, but there is no label appearing.

The same SLD rule is being used for all the cities in that image. Many in my dataset cross a tile and the label is drawn, but for some reason London is not.

The same problem occurs with some other points as well, for example Accra also sits very close to the right hand side of a tile and also doesn’t get rendered at many zoom levels. Madrid is another problem case and that isn’t even particularly near the edge of the tile.

Is this a known issue ? Is there a way to fix or work around it ?

AFAIK there is never a guarantee that a label will be drawn, there’s an algorithm that determines whether it fits or not relative to other labels or edges. ( I see there at least was an SLD extension to prioritize[1], I don’t know whether it still exists and I don’t think it makes a difference in your case. )

If you configure GWC manually (geowebcache.xml) you can specify a gutter the same size as the largest label (in pixels). This is a border around the metatiles that is sliced away when the tiles are saved, but by having it you eliminate the edge effects.

-Arne

1 http://geowebcache.org/docs/current/concepts/metatile.html
2: http://geoserver.org/display/GEOSDOC/LabelingOptions

This image illustrates my problem:

http://norman.cx/photos/links/closetotheedge.png

As you can see the label for Amsterdam crosses a tile boundary and is rendered correctly. The problem point in that image is London, you can see the black square where London is, but there is no label appearing.

The same SLD rule is being used for all the cities in that image. Many in my dataset cross a tile and the label is drawn, but for some reason London is not.

The same problem occurs with some other points as well, for example Accra also sits very close to the right hand side of a tile and also doesn’t get rendered at many zoom levels. Madrid is another problem case and that isn’t even particularly near the edge of the tile.

Is this a known issue ? Is there a way to fix or work around it ?

AFAIK there is never a guarantee that a label will be drawn, there’s an algorithm that determines whether it fits or not relative to other labels or edges. ( I see there at least was an SLD extension to prioritize[1], I don’t know whether it still exists and I don’t think it makes a difference in your case. )

So with the default install of GeoServer/GeoWebCache it is already doing meta tiling out of the box ?

I’m still not sure that I understand why Amsterdam (and many other examples at other zoom levels) gets treated successfully, yet London and some other examples don’t ?

Doing some zooming around it becomes clear that it will never draw the London label unless it fits completely in the current tile, yet other cities will get their label drawn even when over 50% of their label is in the adjacent tile. I can be at zoom levels where 90% of the London label would fit on the current tile and yet it still isn’t drawn.

Is this something to do with the 3x3 or 4x4 meta tile boxes that I’ve read about ? Is London maybe sitting on the right hand edge of one of these meta tiles ?

If you configure GWC manually (geowebcache.xml) you can specify a gutter the same size as the largest label (in pixels). This is a border around the metatiles that is sliced away when the tiles are saved, but by having it you eliminate the edge effects.

I will take a look.

On 7/12/10 6:06 PM, Andy Norman wrote:

I’m still not sure that I understand why Amsterdam (and many other examples at other zoom levels) gets treated successfully, yet London and some other examples don’t ?

Doing some zooming around it becomes clear that it will never draw the London label unless it fits completely in the current tile, yet other cities will get their label drawn even when over 50% of their label is in the adjacent tile. I can be at zoom levels where 90% of the London label would fit on the current tile and yet it still isn’t drawn.

3x3 metatiling is used by default. It doesn’t matter whether a label fits inside a tile, it needs to fit 110% (or so) inside the metatile.

With 3x3 metatiling the metatile boundaries should “move” in terms of the real world (the grid itself is a power of two). So if it really never shows up for London then something else is probably amiss. I assume you’ve checked the preview in GeoServer.

-Arne

London doesn’t never show up, it just doesn’t show up at some zoom levels.

So you are saying what when a tile is requested by a client that GWC/GS render that tile and the 8 tiles around it as the meta tile (rather than having a fixed grid of meta tiles that London could end up sitting on the right hand edge of) ? If that is the case then in my cases where London isn’t appearing it would definitely fit on the meta tile.

The problem with London doesn’t occur on the OpenLayers preview in GeoServer, I use the following URL so that I get the 900913 projection:

http://localhost:8080/geoserver/wms?service=WMS&version=1.1.0&request=GetMap&layers=tss&styles=&bbox=-20000000.0,-7000000.0,20000000.0,16000000.624&width=684&height=330&srs=EPSG:900913&format=application/openlayers

Using the preview (set to tiled) I get:

http://norman.cx/photos/links/europeol.png

The same data with the same SLD coming via GWC:

http://norman.cx/photos/links/europegwc.png

In the OpenLayers preview I see London, coming via GWC I don’t (but I also note that via OL Stockholm, Warsaw and probably others don’t get drawn).

Does this look like it is just down to the tile edge issue or have I got something else broken ?

Thanks for you help.

On 12/07/2010 15:56, Arne Kepp wrote:

If you configure GWC manually (geowebcache.xml) you can specify a gutter the same size as the largest label (in pixels). This is a border around the metatiles that is sliced away when the tiles are saved, but by having it you eliminate the edge effects.

Ok, I’ve set up my geowebcache.xml and it is serving my layer. I’ve set the gutter to 128 pixels, which is plenty wide enough for the label for London.

Doing that hasn’t changed the behaviour at all. The label for London is still not drawn.

Does this mean I have something else going wrong or I am just misunderstanding how this all works ?

  Ok, I am now trying to take a very methodical approach to this now. I've created a test dataset:

insert TwnTest (town, geom) values ('L0', geometry::STGeomFromText('POINT (0 0)', 4326))
insert TwnTest (town, geom) values ('LR', geometry::STGeomFromText('POINT (-0.12565612792968881 10)', 4326))
insert TwnTest (town, geom) values ('L1', geometry::STGeomFromText('POINT (-1 20)', 4326))
insert TwnTest (town, geom) values ('L2', geometry::STGeomFromText('POINT (-2 30)', 4326))
insert TwnTest (town, geom) values ('L3', geometry::STGeomFromText('POINT (-3 40)', 4326))
insert TwnTest (town, geom) values ('L4', geometry::STGeomFromText('POINT (-4 50)', 4326))
insert TwnTest (town, geom) values ('L5', geometry::STGeomFromText('POINT (-5 60)', 4326))
insert TwnTest (town, geom) values ('L6', geometry::STGeomFromText('POINT (-6 70)', 4326))
insert TwnTest (town, geom) values ('L7', geometry::STGeomFromText('POINT (-7 80)', 4326))

At zoom level 1 it looks like this, all the labels display:

   http://www.norman.cx/photos/links/zoom1.png

At zoom level 2 it looks like this, again all labels showing, several straddling the tile edge:

   http://www.norman.cx/photos/links/zoom1.png

At zoom level 3 it starts to go wrong, every label within 4 degrees of the tile edge is not drawn:

   http://www.norman.cx/photos/links/zoom1.png

Is what you can see here just normal tile edge issues or is something else going wrong ? From the descriptions of meta tiling I've seen here, I expect it to deal with and draw these labels correctly.

I also notice that the label at 0,0 is drawn up to level 3 and then never drawn in any zoom levels beyond that. I also note that 4x4 meta tiles appear to be the default and that there are 4x4 tiles at level 3.

I suspect therefore that meta tiles aren't sliding, but are in fact a fixed grid. That would mean that beyond level 3 a point at lat/long 0,0 will always be on the edge of a meta tile and the label will therefore never be drawn. Does that make sense ?

I guess I next have to work out why my metatiling and gutter settings for GWC aren't using used. I've set the meta tile to 5x5 and set the gutter to 128, but it doesn't appear to actually be being used (as 16 tiles get cached at a time, suggesting a 4x4 meta tile is being used).

I'm using the following SLD:

<?xml version="1.0" encoding="iso-8859-1"?>
<StyledLayerDescriptor version="1.0.0" xmlns="http://www.opengis.net/sld&quot; xmlns:ogc="http://www.opengis.net/ogc&quot;
   xmlns:xlink="http://www.w3.org/1999/xlink&quot; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&quot;
   xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd&quot;&gt;
<NamedLayer>
<Name>London test</Name>
<UserStyle>
<Title>London test</Title>
<Abstract>London test</Abstract>
<FeatureTypeStyle>
<Rule>
<Title>Red square</Title>
<PointSymbolizer>
<Graphic>
<Mark>
<WellKnownName>square</WellKnownName>
<Fill>
<CssParameter name="fill">#FF0000</CssParameter>
</Fill>
</Mark>
<Size>5</Size>
</Graphic>
</PointSymbolizer>
<TextSymbolizer>
<Label>
<ogc:PropertyName>town</ogc:PropertyName>
</Label>
<LabelPlacement>
<PointPlacement>
<AnchorPoint>
<AnchorPointX>0.0</AnchorPointX>
<AnchorPointY>0.5</AnchorPointY>
</AnchorPoint>
<Displacement>
<DisplacementX>5</DisplacementX>
<DisplacementY>-3</DisplacementY>
</Displacement>
</PointPlacement>
</LabelPlacement>
<Fill>
<CssParameter name="fill">#000000</CssParameter>
</Fill>
</TextSymbolizer>
</Rule>
</FeatureTypeStyle>
</UserStyle>
</NamedLayer>
</StyledLayerDescriptor>

Is it possible that London doesn't get labelled because Amsterdam is in the way?

Ian

  Very sorry, I remembered incorrectly about 3x3. You are right that 4x4 metatiling is used by default in the layers configured for GeoServer.

So
- the metatiling factors
- the fact that for every zoom level the tiles are doubled in size, and
- the fact that the Brits decided that the Prime Meridian runs straight through London
are all conspiring against you, London will always be at the edge of a metatile.

I'm still not sure why the gutter doesn't take. Did you define the layer with a new name in geowebcache.xml, to distinguish it from the old one?

-Arne

On 7/14/10 2:55 PM, Andy Norman wrote:

   Ok, I am now trying to take a very methodical approach to this now.
I've created a test dataset:

insert TwnTest (town, geom) values ('L0',
geometry::STGeomFromText('POINT (0 0)', 4326))
insert TwnTest (town, geom) values ('LR',
geometry::STGeomFromText('POINT (-0.12565612792968881 10)', 4326))
insert TwnTest (town, geom) values ('L1',
geometry::STGeomFromText('POINT (-1 20)', 4326))
insert TwnTest (town, geom) values ('L2',
geometry::STGeomFromText('POINT (-2 30)', 4326))
insert TwnTest (town, geom) values ('L3',
geometry::STGeomFromText('POINT (-3 40)', 4326))
insert TwnTest (town, geom) values ('L4',
geometry::STGeomFromText('POINT (-4 50)', 4326))
insert TwnTest (town, geom) values ('L5',
geometry::STGeomFromText('POINT (-5 60)', 4326))
insert TwnTest (town, geom) values ('L6',
geometry::STGeomFromText('POINT (-6 70)', 4326))
insert TwnTest (town, geom) values ('L7',
geometry::STGeomFromText('POINT (-7 80)', 4326))

At zoom level 1 it looks like this, all the labels display:

    http://www.norman.cx/photos/links/zoom1.png

At zoom level 2 it looks like this, again all labels showing, several
straddling the tile edge:

    http://www.norman.cx/photos/links/zoom1.png

At zoom level 3 it starts to go wrong, every label within 4 degrees of
the tile edge is not drawn:

    http://www.norman.cx/photos/links/zoom1.png

Is what you can see here just normal tile edge issues or is something
else going wrong ? From the descriptions of meta tiling I've seen here,
I expect it to deal with and draw these labels correctly.

I also notice that the label at 0,0 is drawn up to level 3 and then
never drawn in any zoom levels beyond that. I also note that 4x4 meta
tiles appear to be the default and that there are 4x4 tiles at level 3.

I suspect therefore that meta tiles aren't sliding, but are in fact a
fixed grid. That would mean that beyond level 3 a point at lat/long 0,0
will always be on the edge of a meta tile and the label will therefore
never be drawn. Does that make sense ?

I guess I next have to work out why my metatiling and gutter settings
for GWC aren't using used. I've set the meta tile to 5x5 and set the
gutter to 128, but it doesn't appear to actually be being used (as 16
tiles get cached at a time, suggesting a 4x4 meta tile is being used).

On 14 Jul 2010, at 19:20, Arne Kepp <arne@anonymised.com> wrote:

I'm still not sure why the gutter doesn't take. Did you define the layer with a new name in geowebcache.xml, to distinguish it from the old one?

I realised that I am still using an old layer not the one I setup in gwc. Can't get the gwc one to work yet, clearly haven't got the config quite right yet.

On 7/14/10 2:55 PM, Andy Norman wrote:

  Ok, I am now trying to take a very methodical approach to this now.
I've created a test dataset:

insert TwnTest (town, geom) values ('L0',
geometry::STGeomFromText('POINT (0 0)', 4326))
insert TwnTest (town, geom) values ('LR',
geometry::STGeomFromText('POINT (-0.12565612792968881 10)', 4326))
insert TwnTest (town, geom) values ('L1',
geometry::STGeomFromText('POINT (-1 20)', 4326))
insert TwnTest (town, geom) values ('L2',
geometry::STGeomFromText('POINT (-2 30)', 4326))
insert TwnTest (town, geom) values ('L3',
geometry::STGeomFromText('POINT (-3 40)', 4326))
insert TwnTest (town, geom) values ('L4',
geometry::STGeomFromText('POINT (-4 50)', 4326))
insert TwnTest (town, geom) values ('L5',
geometry::STGeomFromText('POINT (-5 60)', 4326))
insert TwnTest (town, geom) values ('L6',
geometry::STGeomFromText('POINT (-6 70)', 4326))
insert TwnTest (town, geom) values ('L7',
geometry::STGeomFromText('POINT (-7 80)', 4326))

At zoom level 1 it looks like this, all the labels display:

   http://www.norman.cx/photos/links/zoom1.png

At zoom level 2 it looks like this, again all labels showing, several
straddling the tile edge:

   http://www.norman.cx/photos/links/zoom1.png

At zoom level 3 it starts to go wrong, every label within 4 degrees of
the tile edge is not drawn:

   http://www.norman.cx/photos/links/zoom1.png

Is what you can see here just normal tile edge issues or is something
else going wrong ? From the descriptions of meta tiling I've seen here,
I expect it to deal with and draw these labels correctly.

I also notice that the label at 0,0 is drawn up to level 3 and then
never drawn in any zoom levels beyond that. I also note that 4x4 meta
tiles appear to be the default and that there are 4x4 tiles at level 3.

I suspect therefore that meta tiles aren't sliding, but are in fact a
fixed grid. That would mean that beyond level 3 a point at lat/long 0,0
will always be on the edge of a meta tile and the label will therefore
never be drawn. Does that make sense ?

I guess I next have to work out why my metatiling and gutter settings
for GWC aren't using used. I've set the meta tile to 5x5 and set the
gutter to 128, but it doesn't appear to actually be being used (as 16
tiles get cached at a time, suggesting a 4x4 meta tile is being used).

  On 14/07/2010 19:20, Arne Kepp wrote:

I'm still not sure why the gutter doesn't take. Did you define the layer with a new name in geowebcache.xml, to distinguish it from the old one?

I'm pleased to say I have resolved the issue. My newly added layer in GWC wasn't working because the example I had copied was using port 80 on localhost for the GeoServer instance and of course mine is on the default port 8080.

I experimented with the gutter size and found I needed to go to 192 pixels to stop getting truncated and repeated labels.

Thanks for helping me fix this.

For anyone who is interested, here is the GWC XML that I ended up with:

<?xml version="1.0" encoding="utf-8"?>
<gwcConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&quot;
   xsi:noNamespaceSchemaLocation="http://geowebcache.org/schema/1.2.1/geowebcache.xsd&quot;
   xmlns="http://geowebcache.org/schema/1.2.1&quot;&gt;
<version>1.2.1</version>
<backendTimeout>60</backendTimeout>
<layers>
<wmsLayer>
<name>gwctss</name>
<wmsUrl>
<string>http://localhost:8080/geoserver/wms&lt;/string&gt;
</wmsUrl>
<wmsLayers>tss</wmsLayers>
<metaWidthHeight>
<int>4</int>
</metaWidthHeight>
<gutter>192</gutter>
</wmsLayer>
</layers>
</gwcConfiguration>

Andy Norman ha scritto:

  On 14/07/2010 19:20, Arne Kepp wrote:

I'm still not sure why the gutter doesn't take. Did you define the layer with a new name in geowebcache.xml, to distinguish it from the old one?

I'm pleased to say I have resolved the issue. My newly added layer in GWC wasn't working because the example I had copied was using port 80 on localhost for the GeoServer instance and of course mine is on the default port 8080.

I experimented with the gutter size and found I needed to go to 192 pixels to stop getting truncated and repeated labels.

In my understanding by using the gutter you'll be getting truncated
labels somewhere. If you don't it's by pure chance afaik (it might
work in your specific case, with your specific data source and
specific data, but it's not a general solution)

Cheers
Andrea

--
Andrea Aime
OpenGeo - http://opengeo.org
Expert service straight from the developers.

On 07/15/2010 10:38 AM, Andrea Aime wrote:

Andy Norman ha scritto:
   

   On 14/07/2010 19:20, Arne Kepp wrote:
     

  I'm still not sure why the gutter doesn't take. Did you define the
layer with a new name in geowebcache.xml, to distinguish it from the
old one?
       

I'm pleased to say I have resolved the issue. My newly added layer in
GWC wasn't working because the example I had copied was using port 80 on
localhost for the GeoServer instance and of course mine is on the
default port 8080.

I experimented with the gutter size and found I needed to go to 192
pixels to stop getting truncated and repeated labels.
     

In my understanding by using the gutter you'll be getting truncated
labels somewhere. If you don't it's by pure chance afaik (it might
work in your specific case, with your specific data source and
specific data, but it's not a general solution)

Cheers
Andrea
   
You're right of course, I've seen it happen too. However, people don't like maps that are overloaded with labels (i.e. the collision algorithm isn't used all that much), so in practice this works quite well, at least for cities. Since things are sufficiently complicated already, I don't bring it up in these threads.

If it's just a few labels that cause problems in the end, you can just move them or omit them using the SLD.

-Arne

Arne Kepp ha scritto:
  >

You're right of course, I've seen it happen too. However, people don't like maps that are overloaded with labels (i.e. the collision algorithm isn't used all that much), so in practice this works quite well, at least for cities. Since things are sufficiently complicated already, I don't bring it up in these threads.

If it's just a few labels that cause problems in the end, you can just move them or omit them using the SLD.

I guess I should add a new vendor option to have labels drawn even
if they cross the tile borders then.
If people really want to shoot themselves in the foot at least they
get a more efficient and "easier" way to do so :wink:

Cheers
Andrea

--
Andrea Aime
OpenGeo - http://opengeo.org
Expert service straight from the developers.

On 15 Jul 2010, at 09:38, Andrea Aime <aaime@anonymised.com> wrote:

Andy Norman ha scritto:

On 14/07/2010 19:20, Arne Kepp wrote:

I'm still not sure why the gutter doesn't take. Did you define the layer with a new name in geowebcache.xml, to distinguish it from the old one?

I'm pleased to say I have resolved the issue. My newly added layer in GWC wasn't working because the example I had copied was using port 80 on localhost for the GeoServer instance and of course mine is on the default port 8080.
I experimented with the gutter size and found I needed to go to 192 pixels to stop getting truncated and repeated labels.

In my understanding by using the gutter you'll be getting truncated
labels somewhere. If you don't it's by pure chance afaik (it might
work in your specific case, with your specific data source and
specific data, but it's not a general solution)

Understood, I seem to have got lucky with my dataset with gutter set to 192, haven't spotted any issues.

Right, now I have that working it is time to go and work out where to submit my patch that speeds up SQL Server Spatial queries from GeoServer :wink:

Andy Norman ha scritto:

On 15 Jul 2010, at 09:38, Andrea Aime <aaime@anonymised.com> wrote:

Andy Norman ha scritto:

On 14/07/2010 19:20, Arne Kepp wrote:

I'm still not sure why the gutter doesn't take. Did you define
the layer with a new name in geowebcache.xml, to distinguish it
from the old one?

I'm pleased to say I have resolved the issue. My newly added
layer in GWC wasn't working because the example I had copied was
using port 80 on localhost for the GeoServer instance and of
course mine is on the default port 8080. I experimented with the
gutter size and found I needed to go to 192 pixels to stop
getting truncated and repeated labels.

In my understanding by using the gutter you'll be getting truncated
labels somewhere. If you don't it's by pure chance afaik (it might
work in your specific case, with your specific data source and specific data, but it's not a general solution)

Understood, I seem to have got lucky with my dataset with gutter set
to 192, haven't spotted any issues.

Right, now I have that working it is time to go and work out where to
submit my patch that speeds up SQL Server Spatial queries from
GeoServer :wink:

jira.codehaus.org, make it a GeoTools issue of type "improvements"

Cheers
Andrea

--
Andrea Aime
OpenGeo - http://opengeo.org
Expert service straight from the developers.