Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Labelling Enhancement - Draw labels that start outside requested extents #4284

Closed
DonaldKerr opened this issue Apr 14, 2012 · 16 comments
Closed

Comments

@DonaldKerr
Copy link

The is a request to create an enhancement to the labelling process whereby labels that have their origin outside the requested extents draw that part of the label that should appear within the extents.

The problem is obvious when tiling map images using the likes of OpenLayers and a WMS request. Labels that cross tile boundaries are clipped. The following link shows an example of the problem (I have rendered some tiles in grey scale to make the boundaries more obvious):

Clipped Labels Example (png)

The following example shows how the labels should appear when a larger tile is requested:

Unclipped Labels Example (png)

I know there are various methods for alleviating the problem both in Mapserver and OpenLayers but none of the solutions sort the problem absolutely.

The solution, I think, would be to add an option in LAYER/CLASS/LABEL that can be set so that labels with an anchor position outside any requested extents, that would normally render part of the resultant label within those extents, can be drawn as part of the resultant image.

EDGEBUFFER [double] - default of 1.

So, for example, if the requested image has a width and height of 256 px, the following would be the case:

EDGEBUFFER 1 - 1 x image width/height (256) - Only labels with a starting position inside the 256 x 256 px image are drawn.

EDGEBUFFER 1.5 - 1.5 x image width/height (384) - The part of any label, with a starting position inside the 384 px square, that encroaches on the 256 px square is drawn.

EDGEBUFFER 2 - 2 x image width/height (512) - The part of any label, with a starting position inside the 512 px square, that encroaches on the 256 px square is drawn.

... and so on.

@tbonfort
Copy link
Member

This is the task of a tiling software, not mapserver. Implementing your solution means that mapserver will be requesting and rendering data outside of the rendered extent, which is not optimal. Furthermore, applying this will not correct the cut label problem, as you are never assured that the label priorities will let a given label be rendered on two adjacent tiles.

For tiling output:

  • always set partials false on all your labels
  • If you're using a tiling software, use metatiles, and set metabuffer = mapserver->labelcache_map_edge_buffer = size of your largest symbology (i.e. a road width or a point icon size)
  • If you are not using a tiling software, you will get very few rendered labels. You might also end up with some cut point symbols.

cheers,
thomas

@DonaldKerr
Copy link
Author

Thanks for your reply Thomas but I have to disagree with you in that I believe that this should be the job of Mapserver rather than any tiling software (should the map file owner desire it).

If we take the tiling software out of the equation, I still want to see the part of a label that extends into a map image where the origin is outside my requested extents. To me, a label, as in the examples in the images above, is similar to any other type e.g. a line or a polygon. Those are rendered even though part thereof may be outside the requested extents.

I agree that it's not optimal but the overhead would be minimal in my circumstances and it would be an option that I specify in my map file for this particular layer type. There would be no change to the default so the additional overhead would only be there if it's specified in the layer.

In my circumstances, I want all labels to be rendered in exactly the position specified. PARTIALS has to be true as does FORCE so label priorities do not come into it.

As for alternatives, I could request the labels via a WFS and render them on the client but that is so slow (and probably inaccurate) that it would not be worthwhile.

I think you were too quick to close this without allowing discussion of the merits.

@tbonfort tbonfort reopened this Apr 15, 2012
@tbonfort
Copy link
Member

Labels with FORCE are a bit different, you're right.

  • With a tile cache, you can obtain your desired result by setting a large metabuffer (set to the halft the size of your largest label)
  • Without a tile cache, you can get the same result using openlayer's gutter parameter (also set to half the max label size). This isn't optimal because you'll be transferring larger images to your client, but the rendered result should be ok.

I closed the ticket because there are workarounds to get what you are expecting, and in all honesty it is such a marginal use-case (force true label positions need to be precomputed, and will only be collision free at a single scale) that I don't believe it will get implemented anytime soon without funding (in other words, it does not scratch a developer's itch and has some non trivial repercussions throughout the codebase, so it'll need financial motivation to get implemented).

Reopening...

@DonaldKerr
Copy link
Author

I just don't think that doing this from the client end is desirable. OpenLayer's gutter just results in much larger files being transferred as you say. To be honest, I have not seen a workaround that actually works.

There's no issues with collisions using:

MINSCALEDENOM
MAXSCALEDENOM
SYMBOLSCALEDENOM

CLASS/LABEL/
MAXSIZE
MINSIZE

The labels I need to render are as accurate and as absolute as the lines and polygons.

It's a pity you don't have the same need as it would likely give you the required itch! Thanks anyway.

@tbonfort
Copy link
Member

Donald,
With force true labels, I do not see how you cannot have label collisions, unless you preprocess your data to determine which labels should be rendered at a given zoom level (i.e., the work that mapserver's labelcache code is doing when you don't use force true). Am I missing something ?

@DonaldKerr
Copy link
Author

There are no label collisions as the positioning and size are predetermined in a database. The labels all come from a database where the font, anchor position, font, fontsize and orientation are set absolutely.

DATA "geom FROM (SELECT toid, featurecode, textstring, height, orientation/10 AS orientation, ('x'||substring(col,1,2))::text::bit(8)::int || ' ' || ('x'||substring(col,3,2))::text::bit(8)::int || ' ' || ('x'||substring(col,1,2))::text::bit(8)::int AS oscolor, CASE WHEN fontnumber = 0 AND textstyle = 0 THEN 'BlackCastleMF' WHEN fontnumber = 0 AND textstyle = 1 THEN 'BlackCastleMF' WHEN fontnumber = 1 AND textstyle = 0 THEN 'arial' WHEN fontnumber = 1 AND textstyle = 1 THEN 'arialitalic' WHEN fontnumber = 2 AND textstyle = 0 THEN 'arial' WHEN fontnumber = 2 AND textstyle = 1 THEN 'arialitalic' ELSE 'arial' END AS font, CASE WHEN anchorposition=0 THEN 'ur' WHEN anchorposition=1 THEN 'cr' WHEN anchorposition=2 THEN 'lr' WHEN anchorposition=3 THEN 'uc' WHEN anchorposition=4 THEN 'cc' WHEN anchorposition=5 THEN 'lc' WHEN anchorposition=6 THEN 'ul' WHEN anchorposition=7 THEN 'cl' WHEN anchorposition=8 THEN 'll' ELSE 'auto' END AS anchorpositiontxt, geom FROM cartographictext) AS foo USING UNIQUE toid"

I forgot to say above that LABELCACHE is also off so that the labels are drawn when the layer is rendered.

@DonaldKerr
Copy link
Author

What kind of "financial motivation" would be required to implement this change?

@stodge
Copy link

stodge commented Apr 17, 2012

You'll have to forgive me as I'm not familiar with Mapserver's internals, but I hit this problem a while ago and failed to get labels that weren't clipped across tiles. We're about to try again with the current version so this discussion is of interest to me.

@tbonfort
Copy link
Member

@DonaldKerr I still don't understand how having fixed positions in your database will solve labelling issues at all scales, as:

  • when zooming out far enough, you'll end up with colliding labels
  • when zooming in close enough, additional labels could be added (this might not be an issue for your use case)

However, I see some use cases for this in the more general case if the label positions have been pre-computed for multiple predefined scales (e.g., your databse query returns a set of labels and positions, given the actual map scale. I haven't yet seen this in actual mapserver usages, but it would be nice to have).

Concerning the implementation:

  • I don't think the usage is widespread enough to warrant a dedicated mapfile keyword. A processing option would be more suited I believe.
  • I would think that specifying the edgebuffer as a factor as you proposed is not the correct solution, as in fine you want to expand the search extent by the number of pixels occupied by your largest label, which is unrelated to the extent of the map you are currently rendering.

@DonaldKerr
Copy link
Author

Thomas,

In the UK, Ordnance Survey have a massive and comprehensive database of all geographic features. In addition to points, lines and polygons, cartographic text is provided for labelling including road names, building name house numbers etc. each record has a very precise location, anchor point, text size, font, rotation etc. I currently have this set up in PostGIS/Mapserver and all works very well at all zoom levels where I would want to show this type of map. As I zoom out, scaled text becomes irrelevant when it's illegible. This type of may is designed to be show when zoomed in quite far so I have my maps showing three zoom levels. Using the following keywords, I can get the text to render at the correct size and position:

MINSCALEDENOM
MAXSCALEDENOM
SYMBOLSCALEDENOM

CLASS/LABEL/
MAXSIZE
MINSIZE

Therefore, there seems to be no need to pre-compute for various pre-defined scales.

Maybe my explanation is confusing but I certainly have the idea clear in my mind :) I will try to load some addition images into this thread later which should show the output from my setup in a clearer way.

tb> when zooming out far enough, you'll end up with colliding labels

When I zoom out, the labels are resized automatically using the keywords above. They are switched off automatically, also using the keywords above.

tb> when zooming in close enough, additional labels could be added

This may be true, but, as you say, not in my case.

tb> I don't think the usage is widespread enough

MasterMap is the UK defacto detailed mapping database. It's use within the UK is widespread and common. I do not think that any GIS provider has truly cracked the problem of partial labels when tiling. With OpenLayers, I can switch to singleTile for these layers but the enhanced user experience gained by tiling is lost.

My proposal would address this ad make Mapserver the only GIS, that I know of, that could circumvent the problem. It would certainly complete things for me in respect of rendering MasterMap with Mapserver in the tiled environment.

Using EDGEBUFFER, as I have described, is only an idea. There may be other, and better, ideas as to how this could be specified in order to achieve the desired outcome: "labels that have their origin outside the requested extents draw that part of the label that should appear within the extents".

Can you explain what you mean by a "processing option" please?

Thanks for your time.

Regards,

Donald

@tbonfort
Copy link
Member

by processing option, I mean using a simple syntax change that does not oblige us to define a new mapfile keyword

PROCESSING "EDGEBUFFER=2"

instead of

EDGEBUFFER 2

I still believe the edgebuffer should be give in pixels rather than as a factor, so the notation would more likely be

PROCESSING "EDGEBUFFER=256"

@DonaldKerr
Copy link
Author

I have no issue with a pixel value and a processing option at the layer level would be fine. In my case, the layer is TYPE ANNOTATION.

@havatv
Copy link

havatv commented Jul 4, 2012

This one labelled "Docs MapServer". What should be documented?

@tbonfort
Copy link
Member

tbonfort commented Jul 4, 2012

wrong label, removed ...

@mapserver-bot
Copy link

This is an automated comment

This issue has been closed due to lack of activity. This doesn't mean the issue is invalid, it simply got no attention within the last year. Please reopen with missing/relevant information if still valid.

Typically, issues fall in this state for one of the following reasons:

  • Hard, impossible or not enough information to reproduce
  • Missing test case
  • Lack of a champion with interest and/or funding to address the issue

@chbhhz
Copy link

chbhhz commented Jul 10, 2018

symbol was cutted on 7.0.7 version also.
If use "PARTIALS false",some symbol does not display on some level

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants