1

The standard behaviour when rendering WMS layers is to keep the text size across all scales and then filter out colliding labels so that the text remains readable, although delivering incomplete information.

Now, I'd like to invite the user to zoom in when he wants to actually read the labels while keeping the overall view on all data (i.e. very small, unreadable text labels) when zooming out.

I know that the simplest way to render scale-based elements is to use the and elements on rules, but that will end up in tens of rules, which I'd like to avoid.

The idea is then to use a function to define the text size, something like:

<TextSymbolizer>
     <Label>
       <ogc:PropertyName>name</ogc:PropertyName>
     </Label>
     <Font>
       <CssParameter name="font-family">Arial</CssParameter>
       <CssParameter name="font-size">
           <function name="get_number_between_1_and_14_depending_on_scale" />
       </CssParameter>
       <CssParameter name="font-style">normal</CssParameter>
       <CssParameter name="font-weight">bold</CssParameter>
     </Font>
</TextSymbolizer>

2 Answers 2

2

From the answer at https://gis.stackexchange.com/a/72016/7515 I found out that a wms environment parameter can be used to get the actual scale denominator:

  <ogc:Function name="env">
    <ogc:Literal>wms_scale_denominator</ogc:Literal>
  </ogc:Function>

Now, the matter is to define a function that maps it to the desired range:

map : ]0,1[ * (max_size + 1)

A mapping of the scale in the interval 0,1 is given by the scale itself, so:

m(s) = 1/scale_denominator

Taking also from the answer at https://gis.stackexchange.com/a/131111/7515 , we have the following (geoserver specific) naive SLD function:

<ogc:Mul>
    <ogc:Div>
        <ogc:Literal>1</ogc:Literal>
        <ogc:Function name="env">
            <ogc:Literal>wms_scale_denominator</ogc:Literal>
        </ogc:Function>
    </ogc:Div>
    <ogc:Literal>15</ogc:Literal>
</ogc:Mul>

EDIT: It turns out the approach above is quite naive for actual data. The scale denominator is exponential of map level and actual ranges are very close to 0 instead of equally distributed. Adding a logarithm and a second mapping on actual values (I got ]0.1,0.4[ for levels 1 to 18 ) give a smoother formula.

EDIT2: Since the SLD filter support only the natural logarithm ln, the correct values become ]0.05,0.13[ up to max level 18, hence the correct formula is:

<ogc:Add>
    <ogc:Mul>
        <ogc:Div>
            <ogc:Sub>
                <ogc:Div>
                    <ogc:Literal>1</ogc:Literal>
                    <ogc:Function name="log">
                        <ogc:Function name="env">
                            <ogc:Literal>wms_scale_denominator</ogc:Literal>
                        </ogc:Function>
                    </ogc:Function>
                </ogc:Div>
                <ogc:Literal>0.0513</ogc:Literal>
            </ogc:Sub>
            <ogc:Literal>0.08</ogc:Literal>
        </ogc:Div>
        <ogc:Literal>13</ogc:Literal>
    </ogc:Mul>
    <ogc:Literal>1</ogc:Literal>
</ogc:Add>

Which works fine on Geoserver 2.7.1

1

A simpler approach that might not be giving you exact control is to use the "unit of measure" support.

While I haven't tried, give this one a kick (GeoServer specific, OGC way would be quite a bit more verbose):

<CssParameter name="font-size">100m</CssParameter>

See also the docs for the OGC way: http://docs.geoserver.org/stable/en/user/styling/sld-extensions/uom.html

1
  • This would be feasible if the uom can also be "degrees" since I do not want a different size to be computed towards poles (i.e. following EPSG:3226 distortion).
    – a1an
    Commented Aug 26, 2015 at 12:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.