[GIS] Putting piechart in of Geoserver style

geoserversldstyle

I reckon that GeoServer layer label style has excellent feature of TextSymbolizer where text label can be positioned relatively on centroid of VISIBLE PART of polygon, as oppose to a geographically fixed position. The GeoServer website states that <sld:Graphic> can be specified in a <sld:TextSymbolizer>.

With this kind of placement i also need to visualise piechart. This is where i found difficulties.

Here is my SLD, within the <sld:TextSymbolizer> there's a piechart <sld:ExternalGraphic> and a <sld:Label>.

<?xml version="1.0" encoding="UTF-8"?>
<sld:StyledLayerDescriptor xmlns="http://www.opengis.net/sld"
 xmlns:sld="http://www.opengis.net/sld"
 xmlns:ogc="http://www.opengis.net/ogc"
 xmlns:gml="http://www.opengis.net/gml"
 xmlns:xlink="http://www.w3.org/1999/xlink"
 version="1.0.0">
  <sld:NamedLayer>
    <sld:Name>test</sld:Name>
    <sld:UserStyle>
      <sld:Name>test</sld:Name>
      <sld:Title/>
      <sld:FeatureTypeStyle>
        <sld:Rule>
          <sld:TextSymbolizer>
            <sld:Graphic>
              <sld:ExternalGraphic>
                <sld:OnlineResource
                  xlink:href="http://chart?cht=p&amp;chd=t:${100 * revenue_percentage},${100 * (1 - revenue_percentage)}&amp;chf=bg,s,FFFFFF00" />
                <sld:Format>application/chart</sld:Format>
              </sld:ExternalGraphic>
              <sld:Size>
                <ogc:Add>
                  <ogc:Literal>20</ogc:Literal>
                  <ogc:Mul>
                    <ogc:Div>
                      <ogc:PropertyName>revenue_target</ogc:PropertyName>
                      <ogc:Literal>2e13</ogc:Literal>
                    </ogc:Div>
                    <ogc:Literal>60</ogc:Literal>
                  </ogc:Mul>
                </ogc:Add>
              </sld:Size>
            </sld:Graphic>
            <sld:Label>
              <ogc:Literal>PIECHART GRAPHIC</ogc:Literal>
            </sld:Label>
            <sld:Font>
              <sld:CssParameter name="font-family">SansSerif</sld:CssParameter>
              <sld:CssParameter name="font-size">14</sld:CssParameter>
              <sld:CssParameter name="font-style">normal</sld:CssParameter>
              <sld:CssParameter name="font-weight">bold</sld:CssParameter>
            </sld:Font>      
            <sld:LabelPlacement>
            <sld:Fill>
              <CssParameter name="fill-opacity">1</CssParameter>
            </sld:Fill>            
              <sld:PointPlacement>
                <sld:AnchorPoint>
                  <sld:AnchorPointX>0.5</sld:AnchorPointX>
                  <sld:AnchorPointY>0.5</sld:AnchorPointY>
                </sld:AnchorPoint>
              </sld:PointPlacement>
            </sld:LabelPlacement>
          </sld:TextSymbolizer>
        </sld:Rule>
      </sld:FeatureTypeStyle>
    </sld:UserStyle>
  </sld:NamedLayer>
</sld:StyledLayerDescriptor>

I found that:

  1. In order a graphic to show, <sld:Label> text must be present in a <sld:TextSymbolizer>. And the <sld:Label> must not be empty. If <sld:Label> is not wanted then the only getaway is to hide it with <CssParameter name="fill-opacity">0</CssParameter>
  2. If <sld:Label> is not wanted it is good to put a shortest possible string in the <sld:Label><ogc:Literal> (for example a point ".") to make sure that <sld:Graphic> element of the same <sld:Rule> are drawn.
  3. With <sld:Label> in <sld:TextSymbolizer>, GeoServer GUI
    complaints when i click the "Validate" button in Style Editor. The
    Style Editor says enter image description here while i
    believe <Priority> and <VendorOption> are optional. However, the
    style can be submitted and can be use with a WMS Layer without
    error.
  4. The piechart <sld:ExternalGraphic> never showed up in WMS, and not even an error message from GeoServer (this is observed using FireBug, the request is fine and nothing is wrong).enter image description hereBy the way the expected piechart is below

enter image description here

  1. If I replace the piechart in <sld:ExternalGraphic> with a PNG image then the PNG Images are drawn nicely in WMS response, off course with <sld:Label> in the <sld:TextSymbolizer>. The expected placement works. The <sld:Size> also works, depending on value of a field. enter image description here Screenshot below is when i panned slightly to the west.enter image description here
  2. If I replace the <sld:TextSymbolizer> with <sld:PointSymbolizer>, the piechart shows. Surely if i panned the map, the piechart stay at the same geographic location. Unfortunately the extent in the above images do not cover centroid of polygon, hence the below screenshot uses different extent. Here's the screenshot:enter image description here

My questions:

  1. How to make the piechart <sld:ExternalGraphic> in <sld:TextSymbolizer> drawn in WMS response?
  2. Is this because <sld:TextSymbolizer> doesn't like piechart <sld:ExternalGraphic> ?

My environment:

  • GeoServer 2.5 (+Chart Extension) on Apache Tomcat 6.0.35
  • OpenLayers 2.12
  • PostgreSQL 9.2.4-1 + PostGIS 2.0.3-2
  • Windows Server 2003 32-bit

Best Answer

So you raise a number of issues:

  1. If there is no label to draw then the renderer will skip the entire rule as a speed up. Since the external graphic is designed to back the label it also gets skipped.

  2. The validation fails because <Label> should be the first element of the <TextSymbolizer>.

  3. It is entirely possible that you can not use a TextSymbolizer's graphic element to display a pie chart (it is not what it is designed for).

So this seems to come down to where the <PointSymbolizer> will place the pie chart. In normal use it will place it on the centroid of the polygon which seems like a good plan. However you can control that using the <Geometry> element.

To acheive the effect you want you will need something like the following to intersect your geometry and the current bounding box:

<Geometry>
  <ogc:Function name="intersection">
    <ogc:PropertyName>the_geom</ogc:PropertyName>
    <ogc:Function name="env">
      <ogc:Literal>wms_bbox</ogc:Literal>
    </ogc:Function>
   </ogc:Function>
</Geometry>

Please note that there is no guarantee that the above will work with really old versions of geoserver like 2.5, please upgrade to at least 2.11.x.

Related Question