Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Creating stunning maps with GeoServer With SLD, CSS, YSLD and MBStyles

Creating stunning maps with GeoServer With SLD, CSS, YSLD and MBStyles

Simone Giannecchini

August 29, 2019
Tweet

More Decks by Simone Giannecchini

Other Decks in Technology

Transcript

  1. Creating stunning maps
    with GeoServer
    With SLD, CSS, YSLD and MBStyles
    Ing. Andrea Aime
    GeoSolutions
    1

    View full-size slide

  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
    2
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  3. Quick tour of styling languages
    3

    View full-size slide

  4. Languages
    SLD 1.0
    core
    SLD 1.1
    core
    YSLD
    extension
    MBStyles
    community
    GeoCSS
    extension
    SLD 1.0
    inspired
    object
    model, with
    extensions
    parse
    parse
    parse
    parse
    and translate
    parse
    and translate
    4
    Map
    rendering
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  5. Shared concepts

    Layer (the styles applies to)

    Rules

    Filters/selectors (what should be painted)

    Scale dependencies (zoomed in, zoomed out?)

    Symbolizers (how should it be painted)

    Point

    Line

    Polygon

    Text
    5
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  6. Styled Layer Descriptor 1.0 and 11

    The only OGC styling standard

    XML based, verbose, hard to hand edit

    Was meant for machine export but ended
    up being edited a lot by hand

    Autocomplete in the style editor

    Can be generated by external tools and
    imported

    However interoperability is limited

    Often needs to be hand tweaked
    6
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  7. SLD 1.0 example





    type
    alpine_hut


    100000.0



    xlink:type="simple"
    xlink:href="symbols/alpinehut.p.16.png"/>
    image/png





    Filter
    Scale dep.
    Symbolizer
    7
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  8. YSLD

    SLD in YAML syntax

    Filtering by CQL

    Can define reusable variables and blocks

    Verbosity it’s between SLD and CSS

    Has a notion of zoom levels, if needed
    feature-styles:
    - rules:
    - filter: type = 'alpine_hut'
    scale: (,100000.0)
    symbolizers:
    - point:
    symbols:
    - external:
    url: symbols/alpinehut.p.16.png
    format: image/png
    8
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  9. GeoCSS

    Compact syntax, familiar for web developers

    CQL based filtering, rule nesting and cascading
    keeps complex styling compact (you just
    express the overrides to the base)

    Autocomplete in the style editor

    Does not get any more compact than this:

    Cons: some are confused by “rule cascading”
    → can now be turned off
    [type = 'alpine_hut'][@sd < 100k] {
    mark: url('symbols/alpinehut.p.16.png');
    }
    9
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  10. MBStyles (aka MapBox GL)

    JSON based, designed for GUI editing (like
    SLD) instead of hand editing

    Only Web Mercator zoom level based scale
    control

    Symbols coming from “sprites” (symbol
    collections)

    Unlike others, no styling extensions

    No rendering transformations

    Limited expressions usage

    Pro: can be applied both on the client side and
    the server side
    10
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  11. MBStyles (aka MapBox GL)
    {
    "version": 8,
    … boilerplate omitted here
    "name": "mountain huts",
    "sprite": "https://my.sever/sprite",
    "layers": [
    {
    "id": "huts",
    "type": "symbol",
    "minzoom": 9,
    "filter": [
    "==",
    "type",
    "alpine_hut"
    ],
    "layout": {
    "icon-image": "alpinehut",
    "icon-size": 1,
    "icon-allow-overlap": true
    }
    }
    ]
    }
    Filter (in postfix notation!)
    Scale dep.
    Symbolizer
    The sprint contains various images,
    like in videogames
    11
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  12. What’s next

    Going to explore styling concepts

    Languages used in examples

    SLD 1.0 + GS extensions

    YSLD

    GeoCSS
    YSLD
    SLD
    CSS
    12
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  13. Scale dependencies
    13

    View full-size slide

  14. 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
    14
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  15. Expressing scale dependency filters

    SLD:


    1000



    1000000


    CSS

    [@sd > 1k][@sd < 1M]

    Compact expression of large numbers makes them
    readable at a glance, e.g., 100k, 1M

    YSLD:

    scale: (1000, 1000000)

    scale: (1e3, 1e6)

    zoom: (8, 16)
    grid:
    name: WGS84
    15
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  16. Unit of Measure

    Useful if you have real world measures of line
    thicknesses and the like



    #0000FF
    5


    ...

    stroke: blue;
    stroke-width: 5m;

    line:
    stroke-color: '#0000FF'
    uom: metre;
    stroke-width: '5';
    SLD
    YSLD
    CSS
    16
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  17. Transformation functions

    Another way of setting a different value
    depending on the current scale/zoom level

    Useful if the scaling is not linear
    [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
    CSS
    17
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  18. Transformation functions in SLD


    #e66e89



    wms_scale_denominator

    2
    400000
    1.9
    800000
    1.4
    1500000
    1
    3000000
    0.8
    6000000
    0.5




    SLD
    18
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  19. Point styling
    19

    View full-size slide

  20. Simple image
    [type = 'alpine_hut'][@sd < 100k] {
    mark: url('symbols/alpinehut.p.16.png');
    }



    type
    alpine_hut


    100000.0



    xlink:type="simple"
    xlink:href="symbols/alpinehut.p.16.png"/>
    image/png




    SLD
    CSS
    20
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  21. Marks (SVG in this case)
    [type = 'bank'][@sd < 6k] {
    mark: symbol('file://symbols/bank.svg');
    :mark { fill: #734a08 };
    mark-size: 14;
    }
    feature-styles:
    - rules:
    - filter: type = 'bank'
    scale: (,6000.0)
    symbolizers:
    - point:
    symbols:
    - mark:
    shape: file://symbols/bank.svg
    fill-color: ! '#734a08'
    size: 14 YSLD
    CSS
    21
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  22. Marks composition and override
    [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; };
    }
    }
    CSS
    22
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide


  23. Many other options!

    Built-in symbol names (well known marks): circle,
    square, triangle, …

    From TTF fonts using the name
    ttf://#charcode

    Windbarbs, e.g.:
    windbarbs://default(15)[kts]

    WKT specification, e.g.
    wkt://MULTIPOLYGON(((-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
    23
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  24. Filling polygons
    24

    View full-size slide

  25. Solid filling
    * {
    fill: lightgrey;
    stroke-width: 0.5;
    }


    #d3d3d3


    0.5

    SLD
    CSS
    25
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  26. Solid fills and repeating images
    fill
    [@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');
    };
    };
    } CSS
    26
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  27. Filling with repeating images (YSLD)
    feature-styles:
    - rules:
    - filter: type IN ('cemetery','grave_yard')
    scale: (,800000.0)
    symbolizers:
    - polygon:
    fill-color: ! '#aacbaf'
    - filter: (type IN ('cemetery','grave_yard')) AND religion =
    'jewish'
    scale: (,50000.0)
    symbolizers:
    - polygon:
    fill-graphic:
    symbols:
    - external:
    url: symbols/grave_yard_jewish.png
    format: image/png
    # continues in the next slide
    First uniform background fill
    Then foreground symbols for
    various religions
    YSLD
    27
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  28. Filling with repeating images (YSLD)
    - filter: (type IN ('cemetery','grave_yard')) AND religion =
    'christian'
    scale: (,50000.0)
    symbolizers:
    - polygon:
    fill-graphic:
    symbols:
    - external:
    url: symbols/grave_yard_christian.png
    format: image/png
    - filter: (type IN ('cemetery','grave_yard')) AND religion =
    'INT-generic'
    scale: (,50000.0)
    symbolizers:
    - polygon:
    fill-graphic:
    symbols:
    - external:
    url: symbols/grave_yard_generic.png
    format: image/png YSLD
    28
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  29. Hatching





    shape://times

    #ADD8E6


    8





    [@scale < 10000] {
    fill: symbol('shape://times');
    fill-size: 8;
    :fill {
    stroke: #ADD8E6;
    }
    }
    SLD
    CSS
    29
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  30. Painting lines
    30

    View full-size slide

  31. Solid lines (OSM admin borders)
    [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;
    }
    }
    CSS
    31
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  32. Dashes/Marks/images along a line
    * {
    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
    CSS
    32
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  33. Vendor options
    34
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  34. Point labels and obstacles
    [@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 URL
    Labels won’t overlap
    the symbol
    CSS
    35
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  35. Line labels
    [@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
    CSS
    36
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  36. Polygon labels


    FULLNAME


    Arial
    14.0
    bold




    0.5
    0.5




    #000000

    50000
    100
    200
    0.9

    37
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  37. Raster styling
    38

    View full-size slide

  38. A DEM and a color map

    SRTM from USGS

    Standard color map

    Also shaded relief (not
    shown in the css below)
    [@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);
    }
    CSS
    39
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  39. Contrast enhancement
    http://docs.geoserver.org/latest/en/user/styling/sld-
    reference/rastersymbolizer.html#contrastenhancement




    StretchToMinimumMaximum

    50
    800



    GeoServer
    vendor extension
    SLD
    40
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  40. Other assorted features
    41

    View full-size slide

  41. Color blending and alpha compositing
    http://docs.geoserver.org/stable/user/styling/sld-extensions/composite-blend/index.html
    More info
    at:
    42
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  42. Z ordering
    http://docs.geoserver.org/latest/en/user/styling/sld-
    extensions/z-order/example.html
    [class = 'motorways'] {
    stroke: #990000, #ff6666;
    stroke-width: 8, 6;
    stroke-linecap: round;
    z-index: 0, 3;
    }
    [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;
    }
    * {
    sort-by: "z_order";
    sort-by-group:
    "roadsGroup";
    } CSS
    43
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  43. Geometry transformations
    [@scale < 10000] {
    fill-geometry: [offset(the_geom, 6, -6)];
    fill: darkgray;
    z-index: 0;
    }
    [@scale < 10000] {
    fill: #b3b3b3;
    z-index: 1;
    } CSS
    44
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  44. Rendering transformations
    * {
    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
    } CSS
    45
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  45. New transform in 2.14: map algebra
    * {
    transform: ras:Jiffle(script:
    ‘ nir = src[7];
    vir = src[3];
    dest = (nir-vir)/(nir+vir);’);
    raster-channels: auto;
    raster-color-map:
    color-map-entry(#00BFBF, -100.0, 0)
    color-map-entry(#00FF00, 920.0, 0)

    } CSS
    46
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  46. Desktop tool export
    47

    View full-size slide

  47. QGIS SLD export work

    In QGIS 2.18, Bonn code sprint improvements

    In QGIS 3.0 support for label exports (thanks for
    OpenGeoGroep sponsoring)
    48
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  48. Raster symbolizer export

    Thanks to OSGeo UK
    sponsorship, GeoServer PSC
    donation, and GeoSolutions in-
    kind support

    Available since QGIS 3.4.5
    49
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  49. GeoStyler
    50
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  50. MapStore styler (in the making)
    51
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  51. MapStore styler
    52
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  52. SLDEditor
    53
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide

  53. That’s all folks!
    Questions?
    [email protected]
    54
    FOSS4G 2019, August 26th/30th, Bucharest

    View full-size slide