Dynamic layers in templates

From Maria GDK Wiki
Jump to navigation Jump to search

Available since Maria GDK 3.1.+.

It is possible to dynamically build up templates using overlay-templates and corresponding tags. This is done by creating a (basemap) template containing references to (overlay) templates. (Overlay-templates use the same syntax as regular templates, but are NOT regarded as "normal" templates by Maria GDK). The purpose is to ease the process of replacing and adding maps to a basemap without continously having to update the template.xml.

Basic example

First you need to add templatefilters (with tags for referencing) in overlay-templates.

<compositemaptemplate name="testOverlay" id="0CB9BB2B-3C4E-4922-889B-7442E683C2AB" type="overlay">
  <templatefilter tags="groundraster" pri="500"/> <!-- tag this overlay -->
  <layer type="OverlayLayer" name="OpenstreetMap">
    <opacity>1</opacity>
    <brightness>0</brightness>
    <gamma>1</gamma>
    <contrast>0</contrast>
    <grayscale>false</grayscale>
    <compression>Any</compression>
    <minscalevisible>100</minscalevisible>
    <maxscalevisible>128000000</maxscalevisible>
    <datasource>
      <mapsignature>wms</mapsignature>
      <maptype>WmsMap</maptype>
      <hostcategory>DontCare</hostcategory>
      <showlabels>false</showlabels>
      <usecache>false</usecache>
    </datasource>
    <visible>true</visible>
    <property key="serviceType" value="OpenstreetMap" />
    <property key="osMapStyle" value="Standard" />
  </layer>
  </compositemaptemplate>

Then add templatefilters in basemap-templates to reference maplayers or datasources in overlay-templates.

Either method 1:

<compositemaptemplate name="testTemplateRef" id="5497D2A9-25C6-429B-AA9A-0ADAB98721C0">
  <!-- reference all layers in overlays tagged with groundraster and seaoverlay-->
  <templatefilter refs="groundraster, seaoverlay"/> 
</compositemaptemplate>

or method 2 (only available since Maria GDK 3.1.1(?)):

<compositemaptemplate name="TestDatasourceRef" id="5497D2A9-25C6-429B-AA9A-0ADAB98721C0">
  <layer type="MapLayer" name="Groundrasters"> 
    <.../>
    <datasource>
      <!-- reference all overlays tagged with groundraster but include only datasource information -->
      <templatefilter refs="groundraster"/> 
    </datasource>
    <visible>true</visible> 
  </layer>
</compositemaptemplate>


When Maria GDK is loading the basemaptemplate - all available overlay-templates with a referenced tag will be included. Templatefilters located outside the layer-block(s) (method 1) will include all maplayers from the referenced overlays. Templatefilters located inside the datasource-block (method 2) will include only the datasouce-blocks (from the referenced overlays).

Overlay-templates will also provide a prioritynumber used for sorting the overlay-templates when including them in the basemap. Lower number equals higher priority. Default value is 100.

Map layers specified directly in the basemap-template will always be placed first in the completed maptemplate and thus drawn first (lowest priority layers). The ordering of map layers internally in an overlay-template will not be disturbed when included into a basemap via tag references.

Complex example

Say you have four overlays defined: OL:Plain, OL:Special, OL:AlsoSpecial and OL:Peaceful. Overlay-xml-syntax is the same as for a "normal" template, but these overlays include a <templatefilter> used for tagging. OL:Plain is tagged with "wms", OL:Special is tagged with "specialground", OL:AlsoSpecial is tagged with "specialground" and "beware" and OL:Peaceful is tagged with "nothingtoseehere".

OL:Plain

<compositemaptemplate id="x" name="OL:Plain" version="0.0.127">
<templatefilter tags="wms" pri="500"/> <!-- tagged -->
  <layer type="MapLayer" name="PlainOpenstreet">
    <opacity>1</opacity>
    <brightness>0</brightness>
    <gamma>1</gamma>
    <contrast>0</contrast>
    <grayscale>false</grayscale>
    <minscalevisible>244</minscalevisible>
    <maxscalevisible>128000000</maxscalevisible>
    <datasource>
      <mapsignature>openstreet</mapsignature>
      <maptype>WmsMap</maptype>
      <showlabels>false</showlabels>
      <usecache>true</usecache>
    </datasource>
    <visible>true</visible>
    <property key="serviceType" value="OpenstreetMap" />
    <property key="labels:fetchdata" value="false" />
  </layer>
</compositemaptemplate>

OL:Special

<compositemaptemplate id="y" name="OL:Special" version="0.0.127">
  <templatefilter tags="specialground" pri="250"/> <!-- tagged -->
  <layer type="MapLayer" name="SpecialInfo">
    <opacity>1</opacity>
    <brightness>0</brightness>
    <gamma>1</gamma>
    <contrast>0</contrast>
    <grayscale>false</grayscale>
    <minscalevisible>1000</minscalevisible>
    <maxscalevisible>100000</maxscalevisible>
    <datasource>
      <mapsignature>scary</mapsignature>
      <maptype>VectorMap</maptype>
      <showlabels>true</showlabels>
      <usecache>true</usecache>
    </datasource>
    <visible>true</visible>
    <property key="labels:fetchdata" value="true" />
  </layer>
</compositemaptemplate>

OL:AlsoSpecial

<compositemaptemplate id="z" name="OL:AlsoSpecial" version="0.0.127">
  <templatefilter tags="specialground, beware" pri="150"/> <!-- tagged -->
  <layer type="MapLayer" name="VerySpecialInfo">
    <opacity>1</opacity>
    <brightness>0</brightness>
    <gamma>1</gamma>
    <contrast>0</contrast>
    <grayscale>false</grayscale>
    <minscalevisible>200</minscalevisible>
    <maxscalevisible>2000000</maxscalevisible>
    <datasource>
      <mapsignature>danger</mapsignature>
      <maptype>VectorMap</maptype>
      <showlabels>true</showlabels>
      <usecache>true</usecache>
    </datasource>
    <visible>true</visible>
    <property key="labels:fetchdata" value="true" />
  </layer>
</compositemaptemplate>

OL:Peaceful

<compositemaptemplate id="xyz" name="OL:Peaceful" version="0.0.127">
  <templatefilter tags="nothingtoseehere" pri="10"/> <!-- tagged -->
  <layer type="MapLayer" name="Peaceful">
    <opacity>1</opacity>
    <brightness>0</brightness>
    <gamma>1</gamma>
    <contrast>0</contrast>
    <grayscale>false</grayscale>
    <minscalevisible>1</minscalevisible>
    <maxscalevisible>4M</maxscalevisible>
    <datasource>
      <mapsignature>bliss</mapsignature>
      <maptype>VectorMap</maptype>
      <showlabels>false</showlabels>
      <usecache>true</usecache>
    </datasource>
    <visible>true</visible>
  </layer>
</compositemaptemplate>

You should also have a basemaptemplate. This is the template that Maria GDK will relate to.

Basemap example 1 (referencing complete layers):

The following template contains only a templatefilter referencing tags "wms" and "specialground".

<compositemaptemplate id="xyz" name="BM:Complex" version="0.0.127">
  <templatefilter refs="wms, specialground"/>
</compositemaptemplate>

Maria GDK will analyze all available overlays and include only layers from those tagged with either "wms" or "specialground" - in this case OL:Plain, OL:Special and OL:AlsoSpecial. The result template will contain three separate layers: PlainOpenstreet, SpecialInfo and VerySpecialInfo. The templatefilter-priority argument will decide how the layers are ordered. (Overlays with multiple layers will keep its internal ordering.)

Basemap example 2 (referencing only datasources):

The following template contains filters inside the datasource-blocks. This makes it possible to include multiple datasources in one layer and control them as one. Only datasource-information will be extracted from the overlays. All other layer-parameters (as opacity, max/minscale etc) will be discarded and replaced by the parameters in the referencing basemaplayer.

<compositemaptemplate id="xyz" name="BM:Complex" version="0.0.127">
  <layer type="MapLayer" name="SingleTag">
    <opacity>1</opacity>
    <brightness>0</brightness>
    <gamma>1</gamma>
    <contrast>0</contrast>
    <grayscale>false</grayscale>
    <minscalevisible>5000</minscalevisible>
    <maxscalevisible>8000000</maxscalevisible>
    <datasource>
      <templatefilter refs="wms"/>
    </datasource>
    <visible>true</visible>
    <property key="serviceType" value="OpenstreetMap" />
    <property key="labels:fetchdata" value="false" />
  </layer>
  
  <layer type="MapLayer" name="MultiTag">
    <opacity>1</opacity>
    <brightness>0</brightness>
    <gamma>1</gamma>
    <contrast>0</contrast>
    <grayscale>false</grayscale>
    <minscalevisible>244</minscalevisible>
    <maxscalevisible>32000000</maxscalevisible>
    <datasource>
      <templatefilter refs="specialground"/>
    </datasource>
    <visible>true</visible>
    <property key="labels:fetchdata" value="true" />
  </layer>
   
</compositemaptemplate>

After analyzing the available overlays, only those tagged "wms" or "specialground" will be included (OL:Plain, OL:Special and OL:AlsoSpecial). Datasource-information from each overlay will be added to its referencing basemap-layer. This results in a template with two layers:
- SingleTag: one datasource ("openstreet") included from the OL:Plain-overlay.
- MultiTag: two datasources ("scary") and ("danger"), included from the OL:Special and OL:AlsoSpecial-overlays.

This enables the two datasources included in MultiTag to be handled as one (dynamic) layer. Hiding MultiTag-layer will hide data from both "scary"- and "danger"-mapsignatures.

Combining different template filters

It is also possible to combine the different template filters. Say you have a basemap-template like this:

<compositemaptemplate id="xyz" name="BM:Complex" version="0.0.127">
  <layer type="MapLayer" name="Peaceful">
    <opacity>1</opacity>
    <brightness>0</brightness>
    <gamma>1</gamma>
    <contrast>0</contrast>
    <grayscale>false</grayscale>
    <minscalevisible>1</minscalevisible>
    <maxscalevisible>4M</maxscalevisible>
    <datasource>
      <mapsignature>bliss</mapsignature>
      <maptype>VectorMap</maptype>
      <showlabels>false</showlabels>
      <usecache>true</usecache>
    </datasource>
    <visible>true</visible>
  </layer>

  <templatefilter refs="wms"/>
  
  <layer type="MapLayer" name="MultiTag">
    <opacity>1</opacity>
    <brightness>0</brightness>
    <gamma>1</gamma>
    <contrast>0</contrast>
    <grayscale>false</grayscale>
    <minscalevisible>244</minscalevisible>
    <maxscalevisible>32000000</maxscalevisible>
    <datasource>
      <templatefilter refs="specialground"/>
    </datasource>
    <visible>true</visible>
    <property key="labels:fetchdata" value="true" />
  </layer>
</compositemaptemplate>

When the template is resolved - this will appear as a template with 3 maplayers: PlainOpenstreet, MultiTag and Peaceful, but including 4 different datasources (plainopenstreet, scary, danger and bliss).

IMapLayerViewModel

        /// <summary>
        /// Get all layernames and corresponding layerids in active template.
        /// The layerid returned for dynamic layers is a group id.
        /// Use that id as input to GetReferencedMapLayers to fetch referenced overlays.
        /// </summary>
        /// <returns>Returns a dictionary with layernames and corresponding layerids (guid-string)</returns>
        Dictionary<string, string> GetMapLayers();
        /// <summary>
        /// Get all referenced overlays for a dynamic templatelayer.
        /// </summary>
        /// <param name="id">Layer id</param>
        /// <returns>Returns a list of all referenced overlays</returns>
        IEnumerable<IRasterLayerData> GetReferencedMapLayers(string id);