Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Creating Stunning Maps in GeoServer: mastering SLD and CSS styles

13,604 views

Published on

Various software can style maps and generate a proper SLD document for OGC compliant WMS like GeoServer to use. However, in most occasions, the styling allowed by the graphical tools is pretty limited and not good enough to achieve good looking, readable and efficient cartographic output. For those that like to write their own styles CSS also represents a nice alternatives thanks to its compactness and expressiveness.

Several topics will be covered, providing examples in both SLD and CSS for each, including: mastering multi-scale styling, using GeoServer extensions to build common hatch patterns, line styling beyond the basics, such as cased lines, controlling symbols along a line and the way they repeat, leveraging TTF symbol fonts and SVGs to generate good looking point thematic maps, using the full power of GeoServer label lay-outing tools to build pleasant, informative maps on both point, polygon and line layers, including adding road plates around labels, leverage the labeling subsystem conflict resolution engine to avoid overlaps in stand alone point symbology, blending charts into a map, dynamically transform data during rendering to get more explicative maps without the need to pre-process a large amount of views.

The presentation aims to provide the attendees with enough information to master SLD/CSS documents and most of GeoServer extensions to generate appealing, informative, readable maps that can be quickly rendered on screen.

Published in: Technology

Creating Stunning Maps in GeoServer: mastering SLD and CSS styles

  1. 1. Creating stunning maps with GeoServer Mastering SLD and CSS Ing. Andrea Aime GeoSolutions
  2. 2. GeoSolutions  Founded in Italy in late 2006  Expertise • Image Processing, GeoSpatial Data Fusion • Java, Java Enterprise, C++, Python • JPEG2000, JPIP, Advanced 2D visualization  Supporting/Developing FOSS4G projects  GeoServer, MapStore  GeoNetwork, GeoNode, Ckan  Clients  Public Agencies  Private Companies  http://www.geo-solutions.it FOSS4G 2017, Boston August 14th-19th 2017
  3. 3. SLD vs CSS  Styled Layer Descriptor  OGC standard  XML based, verbose, hard to hand edit  Only showing relevant bits of the SLD  GeoCSS  CSS with extensions for map rendering  Simple, Compact, designed for human beings  Not a standard (several incompatible variants for mapping, GeoServer one has nothing to do with CartoDB/MapBox one) FOSS4G 2017, Boston August 14th-19th 2017
  4. 4. CSS features  Familiar for web developers  Compact syntax  Symbolization triggered by “key” properties (stroke, fill, mark, label, channel-selection)  CQL based filtering  Cascading keeps complex styling compact (you just express the overrides to the base)  Interactive editor for productive style development FOSS4G 2017, Boston August 14th-19th 2017
  5. 5. GeoCSS in a nutshell • Filter by attribute/env variable in CQL • Filter by scale • Set properties to control symbolization • Key properties activate certain symbolization: – mark/fill/stroke/label/raster-channels FOSS4G 2017, Boston August 14th-19th 2017 [admin_level < 2][@sd < 1M][@sd > 100k] { label: name; font-family: ‘Noto Sans’; … /* this is nested rule */ [special = true][@sd < 500k] { font-weight: bold; … } }
  6. 6. SLD equivalents FOSS4G 2017, Boston August 14th-19th 2017 <sld:Rule> <ogc:Filter> <ogc:PropertyIsEqualTo> <ogc:PropertyName>admin_level</ogc:PropertyName> <ogc:Literal>2</ogc:Literal> </ogc:PropertyIsEqualTo> </ogc:Filter> <sld:MinScaleDenominator>100000</sld:MinScaleDenominator> <sld:MaxScaleDenominator>1000000</sld:MaxScaleDenominator> <sld:TextSymbolizer> <sld:Label> <ogc:PropertyName>name</ogc:PropertyName> </sld:Label> <sld:Font> <sld:CssParameter name="font-family"> Noto Sans </sld:CssParameter> <sld:CssParameter name="font-size">10 ... </sld:TextSymbolizer> <!–- Override would require a separate rule specifying everything again --> </sld:Rule> Filter Scale dependency Symbolizers and their properties
  7. 7. Scale dependencies FOSS4G 2017, Boston August 14th-19th 2017
  8. 8. Types of Scale dependency  Decide whether to symbolize based on the scale or not  E.g., at lower scales/lower zoom levels do not show buildings  Symbolize in a different way depending on the scale  E.g., different thickness based on the current zoom FOSS4G 2017, Boston August 14th-19th 2017
  9. 9. Expressing scale dependency filters  SLD:  <MinScaleDenominator>  <MaxScaleDenominator>  CSS  Legacy: [@scale > 10000000]  GeoServer 2.12+: [@sd > 1M]  More compact variable, more correct (it’s a scale denominator, not a scale!)  Compact expression of large numbers makes them readable at a glance, e.g., 100k, 1M FOSS4G 2017, Boston August 14th-19th 2017
  10. 10. Unit of Measure FOSS4G 2017, Boston August 14th-19th 2017  Useful if you have real world measures of line thicknesses and the like <LineSymbolizer uom="http://www.opengeospatial.org/se/units/metre"> <Stroke> <CssParameter name="stroke">#0000FF</CssParameter> <CssParameter name="stroke-width">5</CssParameter> </Stroke> </LineSymbolizer> * { stroke: blue; stroke-width: 5m; }
  11. 11. Transformation functions FOSS4G 2017, Boston August 14th-19th 2017  OSM like, setting a different value depending on the current scale/zoom level  Not a linear scale mind [class = 'highway’ and type in ('motorway’, 'motorway_link’)] [@sd < 25M] { stroke: #e66e89; stroke-width: categorize(@sd, 2, 400k, 1.9, 800k, 1.4, 1.5M, 1, 3M, 0.8, 6M, 0.5); …  Less than 400k  2px  [400k, 800k]  1.9px  [800k, 1.5M]  1.4px  [1.5M, 3M]  1  [3M, 6M]  0.8  Above 6M -> 0.5
  12. 12. Transformation functions in SLD FOSS4G 2017, Boston August 14th-19th 2017 <sld:LineSymbolizer> <sld:Stroke> <sld:CssParameter name="stroke">#e66e89</sld:CssParameter> <sld:CssParameter name="stroke-width"> <ogc:Function name="Categorize"> <ogc:Function name="env"> <ogc:Literal>wms_scale_denominator</ogc:Literal> </ogc:Function> <ogc:Literal>2</ogc:Literal> <ogc:Literal>400000</ogc:Literal> <ogc:Literal>1.9</ogc:Literal> <ogc:Literal>800000</ogc:Literal> <ogc:Literal>1.4</ogc:Literal> <ogc:Literal>1500000</ogc:Literal> <ogc:Literal>1</ogc:Literal> <ogc:Literal>3000000</ogc:Literal> <ogc:Literal>0.8</ogc:Literal> <ogc:Literal>6000000</ogc:Literal> <ogc:Literal>0.5</ogc:Literal> </ogc:Function> </sld:CssParameter> </sld:Stroke> </sld:LineSymbolizer>
  13. 13. Point styling FOSS4G 2017, Boston August 14th-19th 2017
  14. 14. Simple symbol FOSS4G 2017, Boston August 14th-19th 2017 [type = 'alpine_hut'][@sd < 100k] { mark: url('symbols/alpinehut.p.16.png'); } <sld:Rule> <ogc:Filter> <ogc:PropertyIsEqualTo> <ogc:PropertyName>type</ogc:PropertyName> <ogc:Literal>alpine_hut</ogc:Literal> </ogc:PropertyIsEqualTo> </ogc:Filter> <sld:MaxScaleDenominator>100000.0</sld:MaxScaleDenominator> <sld:PointSymbolizer> <sld:Graphic> <sld:ExternalGraphic> <sld:OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="symbols/alpinehut.p.16.png"/> <sld:Format>image/png</sld:Format> </sld:ExternalGraphic> </sld:Graphic> </sld:PointSymbolizer> </sld:Rule>
  15. 15. Marks (SVG in this case) FOSS4G 2017, Boston August 14th-19th 2017 [type = 'bank'][@sd < 6k] { mark: symbol('file://symbols/bank.svg'); :mark { fill: #734a08 }; mark-size: 14; } <sld:Rule> <ogc:Filter> <ogc:PropertyIsEqualTo> <ogc:PropertyName>type</ogc:PropertyName> <ogc:Literal>bank</ogc:Literal> </ogc:PropertyIsEqualTo> </ogc:Filter> <sld:MaxScaleDenominator>6000.0</sld:MaxScaleDenominator> <sld:PointSymbolizer> <sld:Graphic> <sld:Mark> <sld:WellKnownName>file://symbols/bank.svg</sld:WellKnownName> <sld:Fill> <sld:CssParameter name="fill">#734a08</sld:CssParameter> </sld:Fill> </sld:Mark> <sld:Size>14</sld:Size> </sld:Graphic> </sld:PointSymbolizer> </sld:Rule> New in GeoServer 2.12!
  16. 16. Marks composition and override FOSS4G 2017, Boston August 14th-19th 2017 [type = 'fountain'][@sd < 6k] { mark: symbol(circle), symbol(circle); :nth-mark(1) { fill: #b5d0d0 }; :nth-mark(2) { fill: #576ddf }; mark-size: 10, 3; [@sd < 3k] { mark: symbol('file://symbols/fountain.svg'); :mark { fill: #576ddf; }; } }
  17. 17.  Many other options!  Built-in symbol names (well known marks): circle, square, triangle, …  From TTF fonts using the name ttf://<fontname>#charcode  Windbarbs, e.g.: windbarbs://default(15)[kts]  WKT specification, e.g. wkt://MULTILINESTRING((-0.25 -0.25, -0.125 -0.25), (0.125 - 0.25, 0.25 -0.25), (-0.25 0.25, -0.125 0.25), (0.125 0.25, 0.25 0.25))  See more here: http://docs.geoserver.org/latest/en/user/styling/sld/exte nsions/pointsymbols.html Other mark options FOSS4G 2017, Boston August 14th-19th 2017
  18. 18. Filling polygons FOSS4G 2017, Boston August 14th-19th 2017
  19. 19. Solid filling FOSS4G 2017, Boston August 14th-19th 2017 * { fill: lightgrey; stroke: black; stroke-width: 0.5; } <sld:PolygonSymbolizer> <sld:Fill> <sld:CssParameter name="fill">#d3d3d3</sld:CssParameter> </sld:Fill> <sld:Stroke> <sld:CssParameter name="stroke-width">0.5</sld:CssParameter> </sld:Stroke> </sld:PolygonSymbolizer>
  20. 20. Filling with repeating images fill FOSS4G 2017, Boston August 14th-19th 2017 [@sd < 800k][type in ('cemetery', 'grave_yard')] { fill: #aacbaf; [@sd < 50k] { [religion = 'jewish'] { fill: #aacbaf, url('symbols/grave_yard_jewish.png'); }; [religion = 'christian'] { fill: #aacbaf, url('symbols/grave_yard_christian.png'); }; [religion = 'INT-generic'] { fill: #aacbaf, url('symbols/grave_yard_generic.png'); }; }; }
  21. 21. Filling with repeating images (SLD) FOSS4G 2017, Boston August 14th-19th 2017 <sld:Rule> <ogc:Filter> <ogc:And> <ogc:Or> <ogc:PropertyIsEqualTo> <ogc:PropertyName>type</ogc:PropertyName> <ogc:Literal>cemetery</ogc:Literal> </ogc:PropertyIsEqualTo> <ogc:PropertyIsEqualTo> <ogc:PropertyName>type</ogc:PropertyName> <ogc:Literal>grave_yard</ogc:Literal> </ogc:PropertyIsEqualTo> </ogc:Or> <ogc:PropertyIsEqualTo> <ogc:PropertyName>religion</ogc:PropertyName> <ogc:Literal>jewish</ogc:Literal> </ogc:PropertyIsEqualTo> </ogc:And> </ogc:Filter> <sld:MaxScaleDenominator>50000.0</sld:MaxScaleDenominator> One sample rule (the Jewish religion one). Three more needed to get the same display as with CSS
  22. 22. Filling with repeating images (SLD) FOSS4G 2017, Boston August 14th-19th 2017 <sld:PolygonSymbolizer> <sld:Fill> <sld:CssParameter name="fill">#aacbaf</sld:CssParameter> </sld:Fill> </sld:PolygonSymbolizer> <sld:PolygonSymbolizer> <sld:Fill> <sld:GraphicFill> <sld:Graphic> <sld:ExternalGraphic> <sld:OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="symbols/grave_yard_jewish.png" /> <sld:Format>image/png</sld:Format> </sld:ExternalGraphic> </sld:Graphic> </sld:GraphicFill> </sld:Fill> </sld:PolygonSymbolizer> </sld:Rule>
  23. 23. Filling with marks FOSS4G 2017, Boston August 14th-19th 2017 <sld:PolygonSymbolizer> <sld:Fill> <sld:GraphicFill> <sld:Graphic> <sld:Mark> <sld:WellKnownName>shape://times</sld:WellKnownName> <sld:Stroke> <sld:CssParameter name="stroke">#ADD8E6</sld:CssParameter> </sld:Stroke> </sld:Mark> <sld:Size>8</sld:Size> </sld:Graphic> </sld:GraphicFill> </sld:Fill> </sld:PolygonSymbolizer> </sld:Rule> [@scale < 10000] { fill: symbol('shape://times'); fill-size: 8; :fill { stroke: #ADD8E6; } }
  24. 24. Painting lines FOSS4G 2017, Boston August 14th-19th 2017
  25. 25. Solid lines (OSM admin borders) FOSS4G 2017, Boston August 14th-19th 2017 [type = 'administrative'] { [admin_level <= 4], [admin_level = 5 or admin_level = 6][@sd <= 400k], [admin_level = 7 or admin_level = 8][@sd <= 200k], [admin_level = 9 or admin_level = 10][@sd <= 100k] { stroke: #ac46ac; stroke-opacity: 0.4; } } <!-- 5 different rules with different filters followed by this --> <sld:LineSymbolizer> <sld:Stroke> <sld:CssParameter name="stroke">#ac46ac</sld:CssParameter> <sld:CssParameter name="stroke-opacity">0.4</sld:CssParameter> </sld:Stroke> </sld:LineSymbolizer>
  26. 26. Dashes FOSS4G 2017, Boston August 14th-19th 2017 … <sld:LineSymbolizer> <sld:Stroke> <sld:CssParameter name="stroke">#6B4900</sld:CssParameter> <sld:CssParameter name="stroke-width">0.1</sld:CssParameter> <sld:CssParameter name="stroke-dasharray">2 2</sld:CssParameter> </sld:Stroke> </sld:LineSymbolizer> [@sd < 75k] { stroke: #6B4900; stroke-width: 0.1; stroke-dasharray: 2; }
  27. 27. Alternating dashes with marks FOSS4G 2017, Boston August 14th-19th 2017 * { stroke: darkRed, symbol('circle'); stroke-dasharray: 10 14, 6 18; stroke-dashoffset: 14, 0; :stroke { fill: darkRed; size: 6; } }  Two coordinated dashed lines  One made with lines  One made with circles  The offset shifts them to have one appear in the empty spaces of the other
  28. 28. Labeling FOSS4G 2017, Boston August 14th-19th 2017
  29. 29. Vendor options FOSS4G 2017, Boston August 14th-19th 2017
  30. 30. Point labels and obstacles FOSS4G 2017, Boston August 14th-19th 2017 [@sd < 200k] { label: [FULLNAME]; label-anchor: 0.5 1.0; label-offset: 0.0 -14.0; font-fill: #000033; font-family: Arial; font-size: 12; halo-color: white; halo-radius: 1.5; label-priority: 200000; label-auto-wrap: 100; mark: url('./img/landmarks/${IMAGE}’); mark-label-obstacle: true; } «FULLNAME» attribute Auto wrapping label with halo. Data driven symbol URLLabels won’t overlap the symbol
  31. 31. Line labels FOSS4G 2017, Boston August 14th-19th 2017 [@sd < 200k] { label: [LABEL_NAME]; font-fill: #000000; font-family: Arial; font-size: 13; font-style: normal; font-weight: bold; halo-color: #FFFFFF; halo-radius: 1; label-follow-line: true; label-repeat: 400; label-group: true; label-max-displacement: 200; } Draw «LABEL_NAME», black, with white halo Draw them along lines, fuse segments with same label, repeat
  32. 32. Polygon labels FOSS4G 2017, Boston August 14th-19th 2017 <sld:TextSymbolizer> <sld:Label> <ogc:PropertyName>FULLNAME</ogc:PropertyName> </sld:Label> <sld:Font> <sld:CssParameter name="font-family">Arial</sld:CssParameter> <sld:CssParameter name="font-size">14.0</sld:CssParameter> <sld:CssParameter name="font-weight">bold</sld:CssParameter> </sld:Font> <sld:LabelPlacement> <sld:PointPlacement> <sld:AnchorPoint> <sld:AnchorPointX>0.5</sld:AnchorPointX> <sld:AnchorPointY>0.5</sld:AnchorPointY> </sld:AnchorPoint> </sld:PointPlacement> </sld:LabelPlacement> <sld:Fill> <sld:CssParameter name="fill">#000000</sld:CssParameter> </sld:Fill> <sld:Priority>50000</sld:Priority> <sld:VendorOption name="autoWrap">100</sld:VendorOption> <sld:VendorOption name="maxDisplacement">200</sld:VendorOption> <sld:VendorOption name="goodnessOfFit">0.9</sld:VendorOption> </sld:TextSymbolizer>
  33. 33. Support for pre-laid-out labels FOSS4G 2017, Boston August 14th-19th 2017
  34. 34. Raster styling FOSS4G 2017, Boston August 14th-19th 2017
  35. 35. A DEM and a color map FOSS4G 2016, Bonn 24nd – 24th August 2016  SRTM from USGS  Standard color map  No-data natively transparent in 2.8.x thanks to JAI-EXT [@sd > 75000] { raster-channels: auto; raster-color-map: color-map-entry(#00BFBF, -100.0, 0) color-map-entry(#00FF00, 920.0, 0) color-map-entry(#00FF00, 920.0, 1.0) color-map-entry(#FFFF00, 1940.0, 1.0) color-map-entry(#FFFF00, 1940.0, 1.0) color-map-entry(#FF7F00, 2960.0, 1.0) color-map-entry(#FF7F00, 2960.0, 1.0) color-map-entry(#BF7F3F, 3980.0, 1.0) color-map-entry(#BF7F3F, 3980.0, 1.0) color-map-entry(#141514, 5000.0, 1.0); }
  36. 36. Contrast enhancement http://docs.geoserver.org/latest/en/user/styling/sld- reference/rastersymbolizer.html#contrastenhancement FOSS4G 2017, Boston August 14th-19th 2017 <sld:RasterSymbolizer> <sld:ContrastEnhancement> <sld:Normalize> <sld:VendorOption name="algorithm"> StretchToMinimumMaximum </sld:VendorOption> <sld:VendorOption name="minValue">50</sld:VendorOption> <sld:VendorOption name="maxValue">800</sld:VendorOption> </sld:Normalize> </sld:ContrastEnhancement> </sld:RasterSymbolizer> GeoServer vendor extension
  37. 37. Other assorted features FOSS4G 2017, Boston August 14th-19th 2017
  38. 38. Geometry transformations FOSS4G 2017, Boston August 14th-19th 2017 [@scale < 10000] { fill-geometry: [offset(the_geom, 6, -6)]; fill: darkgray; z-index: 0; } [@scale < 10000] { fill: #b3b3b3; z-index: 1; }
  39. 39. Rendering transformations FOSS4G 2017, Boston August 14th-19th 2017 * { transform: ras:Contour(levels: 1100 1200 1300 1400 1500 1600 1700 1800); stroke: black; label: [GRAY-INDEX]; font-fill: black; font-family: Sans; font-size: 12; halo-radius: 2; halo-color: white; label-follow-line: true }
  40. 40. Masking via alpha compositing FOSS4G 2016, Bonn 24nd – 24th August 2016 destination-in
  41. 41. Color blendin FOSS4G 2017, Boston August 14th-19th 2017 http://docs.geoserver.org/stable/user/styling/sld-extensions/composite-blend/index.html More info at:
  42. 42. Z ordering http://docs.geoserver.org/latest/en/user/styling/sld- extensions/z-order/example.html FOSS4G 2017, Boston August 14th-19th 2017 [class = 'motorways'] { stroke: #990000; stroke-width: 8; z-index: 0; } [class = 'railways'] { stroke: #333333; stroke-width: 3; z-index: 2; } [class = 'railways'] { stroke: #ffffff; stroke-width: 1.5; stroke-dasharray: 5, 5; z-index: 3; } [class = 'motorways'] { stroke: #ff6666; stroke-width: 6; stroke-linecap: round; z-index: 3; } * { sort-by: "z_order"; sort-by-group: "roadsGroup"; }
  43. 43. New in 2.12 FOSS4G 2017, Boston August 14th-19th 2017
  44. 44. Autocomplete for CSS editor  Because there are too many properties to remember! FOSS4G 2017, Boston August 14th-19th 2017
  45. 45. No more -gt- prefix in CSS  Vendor options used to be prefixed with “-gt-”  But CSS is its own language, no need to mark something as “vendor” or refer to GeoTools  Don’t worry, old syntax still supported FOSS4G 2017, Boston August 14th-19th 2017 * { ... -gt-mark-label-obstacle: true; -gt-label-priority: 200000; -gt-label-auto-wrap: 100; } * { ... mark-label-obstacle: true; label-priority: 200000; label-auto-wrap: 100; }
  46. 46. GeoCSS env variable expansion  Use @var or @var(defaultValue) in place of calling the env function  @var -> env(‘var’)  @var(defaultValue)  env(‘var’, defaultValue)  Exception for @sd  @sd -> env(‘wms_scale_denominator’)  to get a more fluent syntax for scale dependencies  New in 2.12 FOSS4G 2017, Boston August 14th-19th 2017
  47. 47. Underline and strikethrough  New vendor options to control underline and strikethrough FOSS4G 2017, Boston August 14th-19th 2017 <VendorOption name="underlineText">true</VendorOption> <VendorOption name="strikethroughText">true</VendorOption>
  48. 48. Char and word spacing  Control how much space there is between each char  And between words FOSS4G 2017, Boston August 14th-19th 2017 <VendorOption name="charSpacing">3</VendorOption> <VendorOption name="wordSpacing">5</VendorOption> charSpacing = 3 wordSpacing = 5
  49. 49. SVG marks  Refer to a SVG file insinde mark/WellKnownMark  The outline of the SVG will be extracted  Then filled and stroked as requested  Suitable for simple shapes FOSS4G 2017, Boston August 14th-19th 2017 :mark { fill: red; stroke: yellow; stroke-width: 3; stroke-opacity: 50%; }
  50. 50. More QGIS SLD export work  In QGIS 3.0 support for label exports (thanks for OpenGeoGroep sponsoring)  Want to see more? Help us fund the effort  FOSS4G 2017, Boston August 14th-19th 2017
  51. 51. That’s all folks! Questions? info@geo-solutions.it FOSS4G 2017, Boston August 14th-19th 2017

×