5

I would like to write an SLD that defines point size by zoom level using zoom denominators and color by a comparison operator. I am having trouble combining the two into rules because I cannot find evidence in the SLD cookbook that logical (And) operators are supported for anything other than combinations of spatial and comparison operators. Here is what I have for my first zoom level (denominator based off Bing maps scales, this part works fine), can anyone suggest a work-around or a missing step? [Note: the only thing that is changing in the rule filter is the color based off of whether the point belongs to Company A or Company B.] Thanks for any insight!

<NamedLayer>
<Name>default_point</Name>
<UserStyle>
  <Title>Default Point</Title>
  <Abstract>A sample style that draws a point</Abstract>
  <FeatureTypeStyle>
    <Rule>
      <Name>Local company A</Name>
      <Title>Local Company A</Title>
      <ogc:Filter>
        <ogc:And>
          <ogc:PropertyIsEqualTo>
            <ogc:PropertyName>company</ogc:PropertyName>
            <ogc:Literal>A</ogc:Literal>
          </ogc:PropertyIsEqualTo>
          <MaxScaleDenominator>144447.93</MaxScaleDenominator>
        </ogc:And>
      </ogc:Filter>
      <PointSymbolizer>
        <Graphic>
          <Mark>
            <WellKnownName>circle</WellKnownName>
            <Fill>
              <CssParameter name="fill">#000080</CssParameter>
            </Fill>
          </Mark>
          <Size>8</Size>
        </Graphic>
      </PointSymbolizer>  
    </Rule>
    <Rule>
      <Name>Local Company B</Name>
      <Title>Local Company B</Title>
      <ogc:Filter>
        <ogc:And>
          <MaxScaleDenominator>144447.93</MaxScaleDenominator>
          <ogc:PropertyIsEqualTo>
            <ogc:PropertyName>company</ogc:PropertyName>
            <ogc:Literal>B</ogc:Literal>
          </ogc:PropertyIsEqualTo>
        </ogc:And>
      </ogc:Filter>
      <PointSymbolizer>
        <Graphic>
          <Mark>
            <WellKnownName>circle</WellKnownName>
            <Fill>
              <CssParameter name="fill">#696969</CssParameter>
            </Fill>
          </Mark>
          <Size>8</Size>
        </Graphic>
      </PointSymbolizer>  
    </Rule>
  </FeatureTypeStyle>
</UserStyle>

1 Answer 1

6

The usual way to set a point size based on the scale denominator is to use the <MinScaleDenominator> and <MaxScaleDenominator> elements across multiple rules. So, to take your example you would need to do something like:

<Rule>
  <Name>Local Company A - Large</Name>
  <Title>Local Company A</Title>
  <MaxScaleDenominator>100000</MaxScaleDenominator>
  <ogc:Filter>
    <ogc:PropertyIsEqualTo>
      <ogc:PropertyName>company</ogc:PropertyName>
      <ogc:Literal>A</ogc:Literal>
    </ogc:PropertyIsEqualTo>
  </ogc:Filter>
  <PointSymbolizer>
    <Graphic>
      <Mark>
        <WellKnownName>circle</WellKnownName>
        <Fill>
          <CssParameter name="fill">#000080</CssParameter>
        </Fill>
      </Mark>
      <Size>12</Size>
    </Graphic>
  </PointSymbolizer>  
  </Rule>
  <Rule>
    <Name>Local Company A - Medium</Name>
    <Title>Local Company A</Title>
    <MinScaleDenominator>100000</MinScaleDenominator>
    <MaxScaleDenominator>500000</MaxScaleDenominator>
    <ogc:Filter>
      <ogc:PropertyIsEqualTo>
        <ogc:PropertyName>company</ogc:PropertyName>
        <ogc:Literal>A</ogc:Literal>
      </ogc:PropertyIsEqualTo>
    </ogc:Filter>
    <PointSymbolizer>
      <Graphic>
        <Mark>
          <WellKnownName>circle</WellKnownName>
          <Fill>
            <CssParameter name="fill">#000080</CssParameter>
          </Fill>
        </Mark>
        <Size>8</Size>
      </Graphic>
    </PointSymbolizer>  
    </Rule>
    <Rule>
      <Name>Local Company A - Small</Name>
      <Title>Local Company A</Title>
      <MinScaleDenominator>500000</MinScaleDenominator>
      <ogc:Filter>
        <ogc:PropertyIsEqualTo>
          <ogc:PropertyName>company</ogc:PropertyName>
          <ogc:Literal>A</ogc:Literal>
        </ogc:PropertyIsEqualTo>
      </ogc:Filter>
      <PointSymbolizer>
        <Graphic>
          <Mark>
            <WellKnownName>circle</WellKnownName>
            <Fill>
              <CssParameter name="fill">#000080</CssParameter>
            </Fill>
          </Mark>
          <Size>4</Size>
        </Graphic>
      </PointSymbolizer>  
    </Rule>

So the above three rules will set the size of the point for company A based on the current scale denominator in relation to ranges. The three rules in this case are:

Rule 1: <= 1:100000 point size = 12

Rule 2: 1:100000 to 1:500000 point size = 8

Rule 3: >= 1:500000 point size = 4

So the point size gets progressively smaller the more the user zooms out. These three rules would then need to be repeated for Company B to give you the different coloured points based on company name.

GeoServer does also contain the ability to get properties from the request and then use these within the SLD. There may be potential to use this, as an environment variable that GeoServer provides for all WMS requests is wms_scale_denominator. It might be possible to set the point size dynamically using this, for example by doing something with the number you get.

<PointSymbolizer>
  <Graphic>
    <Mark>
      <WellKnownName>circle</WellKnownName>
      <Fill>
        <CssParameter name="fill">#000080</CssParameter>
    </Mark>
    <Size>
      <ogc:Function name="env">
        <ogc:Literal>wms_scale_denominator</ogc:Literal>
      </ogc:Function>
    </Size>
  </Graphic>
</PointSymbolizer>

This is a poor example because the value returned will be huge and so the point would be huge, or it will kill GeoServer. Much more likely would be to do something with that number so as it changes the point size changes in a more appropriate way. You could use <ogc:Div> for example to divide the number by something (map resolution maybe) to get a sensible point size.

2
  • 1
    Thank you, this worked great. I may have actually been on the right track in previous attempts, but was thrown off by the errors that Geoserver returns upon validating the style (i.e. cvc-complex-type.2.4.a: Invalid content was found starting with element 'ogc:Filter'. One of '{"opengis.net/sld":Symbolizer}' is expected.) - but if I just ignore these the SLD works perfectly fine.
    – Nicole
    Sep 23, 2013 at 16:04
  • How to color by attribute? my colors are stored as attribute in column of data.
    – prem30488
    Sep 19, 2015 at 9:27

Your Answer

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

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