pygeoapi icon indicating copy to clipboard operation
pygeoapi copied to clipboard

Add Support for OGC API - Styles

Open doublebyte1 opened this issue 1 year ago • 9 comments

The OGC API - Styles Draft Standard enables map servers, clients as well as visual style editors, to manage and fetch styles. The styles consist of symbolizing instructions that can be applied by a rendering engine on features and/or coverages. The API implements the conceptual model for style encodings and style metadata.

doublebyte1 avatar Sep 12 '24 15:09 doublebyte1

As discussed, an initial iteration could be listing/access of styles via /styles. Future iterations would include association of a style to a resource and transaction interfaces.

tomkralidis avatar Sep 12 '24 16:09 tomkralidis

I have a question regarding how styles should be configured in the pygeoapi configuration YAML file. Specifically, how should styles be associated with a collection?

For example, should the style be configured under the providers section of a collection, and how would this work for both Mapbox and SLD 1.1 styles? Could you provide a sample configuration for both vector tiles (Mapbox style) and GeoJSON (SLD 1.1)?

Here are two example configurations I'm trying to achieve:

resources:
    bathingwater-estonia:
        type: collection
        title: Bathing water sources
        description: Data of bathing water sources used by water supply systems under the supervision of the Health Board from the Water Health Information System.
        keywords:
            - Water
            - Water bodies
            - Drilled wells
            - Surface water
            - Groundwater
            - Environmental health
            - Health
            - Bathing water
        links:
            - type: text/html
              rel: canonical
              title: information
              href: https://avaandmed.eesti.ee/api/datasets/slug/supluskohad
              hreflang: en-US
        extents:
            spatial:
                bbox:
                    [
                        22.2290936066586440,
                        57.6912449743385451,
                        28.2024877654160555,
                        59.6097269178904412,
                    ]
                crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
            temporal:
                begin: null
                end: null # or empty
        providers:
            - type: feature
              name: GeoJSON
              data: tests/data/tartu/bathingwater-estonia.geojson
              id_field: id
              styles:
                  - name: water-bodies
                    title: Water Bodies SLD Style
                    style:
                        type: sld
                        version: 1.1
                        data: tests/styles/bathing_water_sources.sld
            - type: tile
              name: MVT-tippecanoe
              data: tests/data/tiles_es/ # local directory tree
              options:
                  zoom:
                      min: 0
                      max: 16
              format:
                  name: pbf
                  mimetype: application/vnd.mapbox-vector-tile
              styles:
                  - name: mapbox style test
                    title: style title
                    style:
                        type: mapbox
                        data: tests/styles/bathing_water_sources.json

Could you confirm if this is the right way to configure the styles, and if there's anything else that should be included for proper style support?

Additionally, I'm curious about the compatibility of certain style types with specific providers (assuming that it will be under providers). From what I understand, it's possible to define a GeoJSON source (either inline or as a remote URL) within a Mapbox style JSON, but it's not possible to define an SLD style for a vector tiles (PBF) provider. Could you clarify if this assumption is correct?

If there are limitations on which style types (e.g., Mapbox vs. SLD) can be applied to specific providers (e.g., GeoJSON vs. PBF), it would be helpful to understand how pygeoapi handles this, and whether these limitations are enforced in the configuration.

yharby avatar Sep 17 '24 23:09 yharby

Should we add XML support in https://github.com/geopython/pygeoapi/blob/master/pygeoapi/api/init.py#L81-L101 for SLD ? Or it will be a different query parameter like ?f=mbsor ?f=sld for example ?

yharby avatar Sep 18 '24 18:09 yharby

I have a question regarding how styles should be configured in the pygeoapi configuration YAML file. Specifically, how should styles be associated with a collection?

For example, should the style be configured under the providers section of a collection, and how would this work for both Mapbox and SLD 1.1 styles? Could you provide a sample configuration for both vector tiles (Mapbox style) and GeoJSON (SLD 1.1)?

Here are two example configurations I'm trying to achieve:

resources:
    bathingwater-estonia:
        type: collection
        title: Bathing water sources
        description: Data of bathing water sources used by water supply systems under the supervision of the Health Board from the Water Health Information System.
        keywords:
            - Water
            - Water bodies
            - Drilled wells
            - Surface water
            - Groundwater
            - Environmental health
            - Health
            - Bathing water
        links:
            - type: text/html
              rel: canonical
              title: information
              href: https://avaandmed.eesti.ee/api/datasets/slug/supluskohad
              hreflang: en-US
        extents:
            spatial:
                bbox:
                    [
                        22.2290936066586440,
                        57.6912449743385451,
                        28.2024877654160555,
                        59.6097269178904412,
                    ]
                crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
            temporal:
                begin: null
                end: null # or empty
        providers:
            - type: feature
              name: GeoJSON
              data: tests/data/tartu/bathingwater-estonia.geojson
              id_field: id
              styles:
                  - name: water-bodies
                    title: Water Bodies SLD Style
                    style:
                        type: sld
                        version: 1.1
                        data: tests/styles/bathing_water_sources.sld
            - type: tile
              name: MVT-tippecanoe
              data: tests/data/tiles_es/ # local directory tree
              options:
                  zoom:
                      min: 0
                      max: 16
              format:
                  name: pbf
                  mimetype: application/vnd.mapbox-vector-tile
              styles:
                  - name: mapbox style test
                    title: style title
                    style:
                        type: mapbox
                        data: tests/styles/bathing_water_sources.json

Could you confirm if this is the right way to configure the styles, and if there's anything else that should be included for proper style support?

Additionally, I'm curious about the compatibility of certain style types with specific providers (assuming that it will be under providers). From what I understand, it's possible to define a GeoJSON source (either inline or as a remote URL) within a Mapbox style JSON, but it's not possible to define an SLD style for a vector tiles (PBF) provider. Could you clarify if this assumption is correct?

If there are limitations on which style types (e.g., Mapbox vs. SLD) can be applied to specific providers (e.g., GeoJSON vs. PBF), it would be helpful to understand how pygeoapi handles this, and whether these limitations are enforced in the configuration.

Hi @Youssef-Harby these are all valid questions, but they regard the application of styles in other Standards (e.g: tiles) and we may be stepping ourselves ahead a bit, as we do not have any support for serving the actual style, yet (:

The PR I am working on aims for support for publishing styles, starting from a very simple case (e.g.: SLDs on a folder). Once we are able to provide a list of styles and styles metadata, we can start thinking about calling these styles from other APIs (:

If you have some sample style files that you can provide, as examples, I would be very grateful! ☺️

doublebyte1 avatar Oct 15 '24 14:10 doublebyte1

Thanks, @doublebyte1 . I am using the exercise data from https://dive.pygeoapi.io/setup/ (bathingwater-estonia) to generate a very simple style using QGIS for SLD 1.1 and Maputnik for Mapbox GL style.

tests/styles/bathing_water_sources.json:

{
  "version": 8,
  "name": "Empty Style",
  "metadata": {"maputnik:renderer": "mlgljs"},
  "sources": {
    "earth": {
      "type": "raster",
      "tiles": ["https://tile.openstreetmap.org/{z}/{x}/{y}.png"],
      "minzoom": 0,
      "maxzoom": 16
    },
    "pygeoapi": {
      "type": "vector",
      "tiles": [
        "https://localhost/collections/bathingwater-estonia/tiles/WebMercatorQuad/{z}/{x}/{y}?f=pbf"
      ],
      "minzoom": 0,
      "maxzoom": 16
    }
  },
  "sprite": "",
  "glyphs": "https://orangemug.github.io/font-glyphs/glyphs/{fontstack}/{range}.pbf",
  "layers": [
    {"id": "earth", "type": "raster", "source": "earth"},
    {
      "id": "bathingwaterestonia",
      "type": "circle",
      "source": "pygeoapi",
      "source-layer": "bathingwaterestonia",
      "paint": {"circle-color": "rgba(255, 0, 0, 1)", "circle-radius": 10}
    }
  ],
  "id": "oi0gcaa"
}

tests/styles/bathing_water_sources.sld:

<?xml version="1.0" encoding="UTF-8"?>
<StyledLayerDescriptor xmlns="http://www.opengis.net/sld" version="1.1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:se="http://www.opengis.net/se" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd">
  <NamedLayer>
    <se:Name>bathingwater-estonia</se:Name>
    <UserStyle>
      <se:Name>bathingwater-estonia</se:Name>
      <se:FeatureTypeStyle>
        <se:Rule>
          <se:Name>Single symbol</se:Name>
          <se:PointSymbolizer>
            <se:Graphic>
              <se:Mark>
                <se:WellKnownName>star</se:WellKnownName>
                <se:Fill>
                  <se:SvgParameter name="fill">#b80808</se:SvgParameter>
                </se:Fill>
                <se:Stroke>
                  <se:SvgParameter name="stroke">#b80808</se:SvgParameter>
                  <se:SvgParameter name="stroke-width">1</se:SvgParameter>
                </se:Stroke>
              </se:Mark>
              <se:Size>24</se:Size>
            </se:Graphic>
          </se:PointSymbolizer>
          <se:PointSymbolizer>
            <se:Graphic>
              <se:Mark>
                <se:WellKnownName>star</se:WellKnownName>
                <se:Fill>
                  <se:SvgParameter name="fill">#ff0000</se:SvgParameter>
                </se:Fill>
                <se:Stroke>
                  <se:SvgParameter name="stroke">#ff0000</se:SvgParameter>
                  <se:SvgParameter name="stroke-width">1</se:SvgParameter>
                </se:Stroke>
              </se:Mark>
              <se:Size>26</se:Size>
              <se:Rotation>
                <ogc:Literal>34</ogc:Literal>
              </se:Rotation>
            </se:Graphic>
          </se:PointSymbolizer>
        </se:Rule>
      </se:FeatureTypeStyle>
    </UserStyle>
  </NamedLayer>
</StyledLayerDescriptor>

Also, I have started working on https://github.com/Youssef-Harby/pygeoapi/tree/styles , incorporating your changes/boilerplate, and began drafting from that point. However, since your plan involves serving only simple SLDs from a directory, I would like to ask if you could provide an example configuration YAML showing how you would prefer the SLD to be defined, so we're aligned on the same page.

yharby avatar Oct 15 '24 15:10 yharby

@Youssef-Harby: sure, based on your example, I was thinking of something like this (but open to feedback!): 😁

          bathingwater-estonia:
              type: collection
              title: Bathing water sources
              description: Data of bathing water sources used by water supply systems under the supervision of the Health Board from the Water Health Information System.
              keywords:
                  - Water
                  - Water bodies
                  - Drilled wells
                  - Surface water
                  - Groundwater
                  - Environmental health
                  - Health
                  - Bathing water
              links:
                  - type: text/html
                    rel: canonical
                    title: information
                    href: https://avaandmed.eesti.ee/api/datasets/slug/supluskohad
                    hreflang: en-US
              extents:
                  spatial:
                      bbox:
                          [
                              22.2290936066586440,
                              57.6912449743385451,
                              28.2024877654160555,
                              59.6097269178904412,
                          ]
                      crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
                  temporal:
                      begin: null
                      end: null # or empty
              providers:
                  - type: feature
                    name: GeoJSON
                    data: tests/data/tartu/bathingwater-estonia.geojson
                    id_field: id
                  - type: tile
                    name: MVT-tippecanoe
                    data: tests/data/tiles_es/ # local directory tree
                    options:
                        zoom:
                            min: 0
                            max: 16
                    format:
                        name: pbf
                        mimetype: application/vnd.mapbox-vector-tile
                  - type: style
                    name: style-file
                    options:
                        format: mbs
                    data: tests/styles/bathing_water_sources.json # local directory tree

In summary, the type would be the new type, style and we would have to implement one provider to load the style from a file on disk. Ultimately, this plugin should have as option the style format, but for now, we could even remove the options and just assume a default format (e.g.: mapbox or sld).

doublebyte1 avatar Oct 15 '24 15:10 doublebyte1

@tomkralidis what do you think? :-)

doublebyte1 avatar Oct 15 '24 15:10 doublebyte1

Catching up here, as @doublebyte1 mentions, we have styles in a couple of contexts. Below are thoughts on workflows:

  1. OGC API - Styles support: this means listing/fetching styles from a repository (default would be filesystem). We implement this workflow in a similar manner as processes, i.e.:
resources:
    my-styles:
        type: style
        provider: pygeoapi.style.filesystem.MyStyleFileSystemProvider
  1. Any OGC API that can use a style: this means applying a style definition to generation of a map, tile, etc. In this case, pointing to a style file is fine/safe. A styles array can be used (we can update/normalize in future work w/ maps) to idenitfy 1..n styles in scope. For large workflows/configurations, YAML anchoring/referencing can be leveraged for reuse.

tomkralidis avatar Dec 08 '24 04:12 tomkralidis

This Issue has been inactive for 90 days. As per RFC4, in order to manage maintenance burden, it will be automatically closed in 7 days.

github-actions[bot] avatar Jun 29 '25 03:06 github-actions[bot]

As per RFC4, this Issue has been closed due to there being no activity for more than 90 days.

github-actions[bot] avatar Jul 13 '25 04:07 github-actions[bot]