Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In response to GetMap, GetFeatureInfo with the format_options=mapmlfeatures:true parameter, add ability to recursively 'de-layer' a layergroup into a text/mapml document composed of its composite layers as features and tiles #74

Open
prushforth opened this issue May 2, 2024 · 3 comments
Labels
help wanted Extra attention is needed
Milestone

Comments

@prushforth
Copy link
Member

prushforth commented May 2, 2024

Background

A LayerGroup in GeoServer is composed of one or more Layer or LayerGroup objects, ordered from bottom to top of the rendering stack i.e. in painter's model order. Because a LayerGroup is a composition of layers, per the previous statement, it's possible that there are many levels of nesting within a LayerGroup's definition. Despite this nesting, at the end of processing a WMS GetMap or GetFeatureInfo for such a layer, it must be de-nested into a linear set of layers to be rendered, each one on top of all the previous layers, in the painter's model.

A MapML document that requests the above result as a bitmapped image doesn't have to concern itself with the recursive rendering of the component layers, it only has to render the bitmapped image. On the other hand, if the de-nested layers were rendered as ordered sets of <map-feature> vectors and <map-tile> elements, it would be possible to render that content on the <mapml-viewer> client or in the MapML preview.

Currently in GeoServer, a GetMap for format=text/mapml can indeed support a request for one or more layer groups among the layers that are requested via the layers=layer1,layer2,layer3 parameter i.e. any one or all of layer1 , layer2 or layer3 can be a LayerGroup. When this occurs (that is, any multi-layer request where the global "Use Tiles" setting is set to use a single map-extent), GeoServer MapML extension "falls back" to processing the request via a GetMap-style client for images (<map-link rel="image"...>). Processing a single-layer request in which the layer is a LayerGroup is a similar process to processing a multi-layer request in general. This issue, together with issues #73 and #72 will enable vector-based +/- tile MapML responses for a layer group or multi-layer GetMap / GetFeatureInfo requests, i.e. true "vector tiles" potentially containing data from more than a single layer. This issue focuses on LayerGroup processing.

Aside: The MapML language has a <map-tile> element that is like a "square feature", in which the network source of the tile image is pointed to by the src attribute, and the placement of the tile is specified by its row, col and zoom attributes. We need to use the <map-tile> element in this requirement to support the processing of non-vector-capable layers in GeoServer in the context of GetMap / GetFeature requests for layer groups that contain such layers.

The requirement outlined in this issue is to enable a request for a single LayerGroup to be serialized according to the passed mapmlusefeatures, mapmlusetiles, mapmlmultiextent token values for the format_options GeoServer WMS parameter, regardless of its inclusion of non-vector-capable layers.

The implementation of this requirement will make it possible to render the component layers of any LayerGroup as though it was a simple vector-capable GeoServer Layer, as MapML <map-feature> +/- <map-tile> elements for each of the nested layers, rendered as sets of adjacent elements, in painter's model order in the response document.

The first requirement would be to add a "Use Features" checkbox to the LayerGroup Publishing tab's MapML section, right below the currently implemented "Use Tiles" checkbox:

This interface:

image

should be updated to become this:

image

(just as that panel has for the Layer Publishing tab currently).

Building upon previous requirements

To summarize #73, the user interface checkbox settings are used to dictate the URLs used (with the associated mapmlusetiles,mapmlusefeatures,mapmlmultiextent format_options values) in the GeoServer preview, but they may be set (dynamically) at runtime by a client in the format_options value that is passed via the GetMap / GetFeatureInfo parameter. In other words, the user interface checkboxes affect the preview that is generated, but do not diminish or affect the client's ability to select a different option at runtime. Put another way, the geoserver user interface settings are ignored when processing requests dynamically, relying instead on the format_options vendor parameter.

In sum:

mapmlmultiextent tells GeoServer if individual layers referenced in the layers parameter list should be represented as individual elements, or if they may all be piled into a single (pair of) <map-link rel="tile">GetMap and GetFeatureInfo URL template(s) (depending on the queryable nature of the layers).

mapmlusetiles tells the extension what the configuration of the <map-input>s in the <map-extent>(s) should be: true means that the inputs should be created to support <map-link rel="tile"> GetMap and GetFeatureInfo URL templates.

mapmlusefeatures tells GeoServer to generate a <map-extent> for which the <map-link>(s) is/are configured to make GetMap / GetFeatureInfo requests for feature data. When mapmlusetiles:true is also set, the generated <map-link rel="tile"> will also contain the type="text/mapml" attribute, which tells the client to expect a "leaf-node" MapML document (i.e. a "leaf-node" document does not reference other text/mapml documents in a tree-like structure -- it is the deepest such node in the tree).

Statement of Requirement on LayerGroup processing

For this requirement on GeoServer LayerGroup processing, when a GetMap or GetFeatureInfo request is received that includes this layer group in which the format_options=mapmlfeatures:true (note it's mapmlfeatures:true here, not mapmlusefeatures:true) request parameter is found, GeoServer MapML extension should render the response "leaf-node" document as (painter's) ordered grouped-by-layer sets of <map-feature>s and/or <map-tile> elements.

Below is an example of a MapML document generated in response to a traditional whole-map WMS GetMap request(for a layer group) like GetMap&format=text/mapml&format_options=mapmlusefeatures:true - note that the GetMap template below contains the mapmlfeatures:true format option, because the received request contained the mapml**use**features:true parameter value:

<mapml- xmlns="http://www.w3.org/1999/xhtml">
    <map-head>
        <map-title>Layer Group ZZZ</map-title>
        <map-style>.bbox {display:none} .population-r1-s1{fill:#4DFF4D; fill-opacity:0.7}
            .population-r2-s1{fill:#FF4D4D; fill-opacity:0.7} .population-r3-s1{fill:#4D4DFF;
            fill-opacity:0.7} .population-r4-s1{stroke-opacity:1.0; stroke-dashoffset:0;
            stroke-width:0.2; stroke:#000000; stroke-linecap:butt}</map-style>
    </map-head>
        <map-extent units="CBMTILE" checked="checked" hidden="hidden">
            <map-input name="z" type="zoom" min="0" max="25" />
            <map-input name="xmin" type="location" rel="map" position="top-left" axis="easting" units="pcrs" min="-3385113" max="3204541" />
            <map-input name="ymin" type="location" rel="map" position="bottom-left" axis="northing" units="pcrs" min="-2857720" max="536137" />
            <map-input name="xmax" type="location" rel="map" position="top-right" axis="easting" units="pcrs" min="-3385114" max="3204541" />
            <map-input name="ymax" type="location" rel="map" position="top-left" axis="northing" units="pcrs" min="-2857720" max="536137" />
            <map-input name="w" type="width" min="1" max="4079" />
            <map-input name="h" type="height" min="1" max="4079" />
            <map-link
                tref="format_options=mapmlfeatures:true&request=GetMap&crs=MapML:CBMTILE&bbox={xmin},{ymin},{xmax},{ymax}&format=text/mapml&language=en&version=1.3.0&transparent=true&service=WMS&layers=layergroupZZZ&width={w}&styles=&height={h}"
                rel="features" />
        </map-extent>
    </map-body>
</mapml->

If a given layer encountered in the recursive expansion of the layergroup's set of layers can NOT be represented as <map-feature> data i.e. is backed by a raster data set, it should be represented as a set of one or more <map-tile> elements within the stack of serialized layer data, ordered by distance of the tile center point from the request envelope/bbox center point.

So long as the non-templated GetMap request used in the <map-tile src="GetMap or GetTile> returns transparent imagery, it may still be useful mixed into the feature information as such, TBD by experimentation with actual data, and it will be up to the GeoServer admin to validate that their layer groups are useful as configured.

e.g. the tref URL template above, when variable references were resolved to a WMS GetMap URL, the response might look like the following text/mapml document:

<mapml- xmlns="...">
  <map-head>
   <map-title>Layer Group ZZZ Example of interleaved features and tiles</map-title>
  </map-head>
  <map-body>
    <map-feature>
      <map-featurecaption>A feature from Layer A</map-featurecaption>
      <map-geometry><map-point><map-coordinates>-72 43.5</map-coordinates></map-point></map-geometry>
    </map-feature>
   <!-- Layer B is imagery must be represented by the tiles that cover the bbox of the GetMap -->
    <map-tile row="12" col="14" zoom="3" src="tile-shaped non-templated GetMap resource URL"></map-tile>
    <map-tile row="12" col="13" zoom="3" src="tile-shaped non-templated GetMap resource URL"></map-tile>
    <map-tile row="13" col="14" zoom="3" src="tile-shaped non-templated GetMap resource URL"></map-tile>
    <map-tile row="13" col="13" zoom="3" src="tile-shaped non-templated GetMap resource URL"></map-tile>
   <map-feature>
      <map-featurecaption>A feature from Layer C</map-featurecaption>
      <map-geometry><map-linestring><map-coordinates>...</map-coordinates></map-linestring></map-geometry>
   </map-feature
  </map-body>
</mapml->

Similarly, a layer group may be requested as tiled data, via the mapmlusetiles:true format option. In this case the <map-extent> elements generated to represent requests for tiled data for the layer group are configured to either make "tile-shaped" WMS GetMap requests, or if the layer group has previously defined a tile cache and associated gridset, the <map-extent> will be configured to generate WMTS GetTile requests via the embedded <map-link> element. This is possible today, although the configuration is not passed as a format_option until #73 is resolved.

Once #73 is working, it should now be possible, in response to a GetMap involving a layer group, to generate <map-extent>s and associated child <map-link rel="tile" type="text/mapml" tref="...GetMap / GetTile..."></map-link> which will generate requests for the layer group's content to be serialized as "tile shaped" text/mapml documents, with the appropriately clipped / spanned+styled and layer-ordered groups of <map-feature> elements to represent the layer group's constituent layers, with non-vector capable layers in the group represented by non-templated <map-tile> elements coded to the calculated zoom level (calculated based on the scale which is calculated from either the bbox of the GetMap, or the tile matrix level from the GetTile.

<mapml- xmlns="...">
  <map-head>
   <map-title>Layer Group ZZZ Example of interleaved features and tiles</map-title>
  </map-head>
  <map-body>
    <map-feature>
      <map-featurecaption>A feature from Layer A</map-featurecaption>
      <map-geometry><map-point><map-coordinates>-72 43.5</map-coordinates></map-point></map-geometry>
    </map-feature>
   <!-- Layer B is imagery must be represented by the tile that covers the bbox of the GetMap -->
    <map-tile row="13" col="13" zoom="3" src="tile-shaped non-templated GetMap resource URL"></map-tile>
   <map-feature>
      <map-featurecaption>A feature from Layer C</map-featurecaption>
      <map-geometry><map-linestring><map-coordinates>...</map-coordinates></map-linestring></map-geometry>
   </map-feature
  </map-body>
</mapml->
@prushforth prushforth added the help wanted Extra attention is needed label May 3, 2024
@prushforth prushforth changed the title Add ability to recursively 'delayer' a layergroup into a text/mapml document composed of its composite layers In response to GetMap, GetFeatureInfo add ability to recursively 'delayer' a layergroup into a text/mapml document composed of its composite layers May 3, 2024
@prushforth prushforth changed the title In response to GetMap, GetFeatureInfo add ability to recursively 'delayer' a layergroup into a text/mapml document composed of its composite layers In response to GetMap, GetFeatureInfo add ability to recursively 'de-layer' a layergroup into a text/mapml document composed of its composite layers Jun 3, 2024
@prushforth prushforth changed the title In response to GetMap, GetFeatureInfo add ability to recursively 'de-layer' a layergroup into a text/mapml document composed of its composite layers In response to GetMap, GetFeatureInfo with the format_options=mapmlfeatures parameter, add ability to recursively 'de-layer' a layergroup into a text/mapml document composed of its composite layers Jun 5, 2024
@prushforth prushforth changed the title In response to GetMap, GetFeatureInfo with the format_options=mapmlfeatures parameter, add ability to recursively 'de-layer' a layergroup into a text/mapml document composed of its composite layers In response to GetMap, GetFeatureInfo with the format_options=mapmlfeatures:true parameter, add ability to recursively 'de-layer' a layergroup into a text/mapml document composed of its composite layers Jun 5, 2024
@prushforth prushforth changed the title In response to GetMap, GetFeatureInfo with the format_options=mapmlfeatures:true parameter, add ability to recursively 'de-layer' a layergroup into a text/mapml document composed of its composite layers In response to GetMap, GetFeatureInfo with the format_options=mapmlfeatures:true parameter, add ability to recursively 'de-layer' a layergroup into a text/mapml document composed of its composite layers as features and tiles Jun 6, 2024
@prushforth prushforth added this to the Vector Tiles milestone Jun 7, 2024
@aaime
Copy link

aaime commented Jun 27, 2024

When mixing rasters and vectors in the same output, we need a TiledCRS to locate where the tiles are.
If we don't have a TiledCRS, then we need to skip the imagery layer. If we have a TiledCRS and the request is not tiled anyways, we'll have to generate enough map-tiles references to cover the entire area.

@aaime
Copy link

aaime commented Jul 9, 2024

It's going to be quite likely to have a mapmlfeatures and mapmlusefeatures be used by mistake in each other place.
How about a mapmlbody option with two possible values: layers and flat instead?

@prushforth
Copy link
Member Author

How about a mapmlbody option with two possible values: layers and flat instead?

mapmlfeatures already exists, so I was / am hesitant about changing anything in how it works. Are you suggesting that mapmlbody would have the same meaning as mapmlusefeatures, OR would it replace both mapmlusefeatures and mapmlfeatures , or something else? I'm unsure how that would work, need to think about it more. Currently, mapmlfeatures only appears in templated URLs generated in the tref attribute. mapmlusefeatures is a flag controlling the 'inner node' document. If mapmlbody does something related to mapmlusefeatures, I will have to re-write the table in the first details over here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants