Geographical data are most often apprehended as thematic layers: you
may have a layer "Rivers", a layer "Aerial view", a layer "Average
income", just to cite a few examples. Now the basic purpose of any viewer
is to make these data available to users by allowing navigation within a
layer as well as comparison between layers. A way to organize the layers
is thus mandatory if an user-friendly application is to be developed. In
CartoWeb, the files that contain the configuration instructions for the
layers are on the server-side, in the directory
server_conf/<myMap>. Usually this directory is
part of a project.
CartoWeb is based on the geographical engine Mapserver. The
Mapserver documentation
http://mapserver.gis.umn.edu/doc.html is an integral part of the
CartoWeb doc. To be concise, you have to know how to write a mapfile if
you want to use CartoWeb. So it doesn't come as a surprise that a
mapfile, myMap.map, is included in the
<myMap> directory, together with its annexes
(typically a symbol file myMap.sym, a directory
etc for the required fonts, the graphic file used as
keymap background, maybe also data files).
We'll see that some functionalities of CartoWeb require small
changes of the mapfile content. But most of the configuration is done in
the file layers.ini.
The file myMap.ini sets the required plugins
and the initial state of the map. Its content is described in Chapter 4, Configuration Files
Contrary to Mapserver itself, CartoWeb supports an arbitrarily complex hierarchy of layers and different rendering options. The notion of LayerGroup makes it possible.
There are two types of "layers-like objects" in
layers.ini : Layers and LayerGroups. They play
fairly different roles and consequently have different possible
attributes. Layers have a 1-to-1 correspondance to Mapserver layers (as
defined in the layers.map), while LayerGroups
group together atomic Layers or other LayerGroups.
As seen before, the Layer object maps directly to a layer in the mapfile. By default, all layers in the mapfile are made available as a Layer in the layers.ini, with an identifier having the same name as the name of the mapserver layer. Thus, if you have the following option in your mapfile:
LAYER NAME "my_layer" TYPE line END
This is equivalent as writing the following configuration in the
layers.ini:
layers.my_layer.class = Layer layers.my_layer.label = my_layer layers.my_layer.msLayer = my_layer
Tip
If you don't need special parameters (see below) for your layer
then you can avoid adding it in the
layers.ini
However, if you want these layers to appear in the layer list, you
still have the responsibility to affect them a parent layer, using the
children property of the
LayerGroup layer declarations.
Here is the syntax for the various configuration parameters of a Layer.
- layers.layerId.className = Layer : defines the object as a Layer; layerId is a string that uniquely identifies the object. The general rules of syntax for a .ini file must be respected in the choice of the layerId (e.g. no '-' are allowed).
- layers.layerId.msLayer = string : name of the corresponding Mapserver layer in the mapfile
- layers.layerId.label = string : caption of the layer in the layer tree on the client; this is a 'raw' label, before any internationalization. The i18n scripts automatically include this label in the strings that can be translated.
- layers.layerId.icon = filename : filename of the static picto
that illustrates this Layer in the layer tree. The file is expected
to be in
server_conf/<mapId>/iconsand a setup script launch is in most cases required. See also Section 6.4, “Layers Legends” for a description of the automatic legending process. - layers.layerId.link = url : provides a link for the layer (e.g. to some metadata); makes the caption in the tree clickable.
Here is the syntax for the various configuration parameters of LayerGroups. Note that a special LayerGroup with layerId=root must be present. Unsurprisingly, it is the root (top level) of the hierarchy. It doesn't appear in the visible tree.
- layers.layerId.className = LayerGroup : defines the object as a LayerGroup; layerId is a string that uniquely identifies the object. The general rules of syntax for a .ini file must be respected in the choice of the layerId (e.g. no '-' are allowed).
- layers.layerId.children = list of layerIds : comma-separated list of layerIds; these children may be Layers or other LayerGroups.
- layers.layerId.children.switchId = list of layerIds : comma-separated list of layerIds, when using switching (see Section 6.2.4, “Children Switching”). This option cannot be used together with simple children option.
- layers.layerId.aggregate = true|false : if true, the children objects are not listed in the tree and not individually selectable. Default is false.
- layers.layerId.label = string : caption of the layer in the layer tree on the client; this is a 'raw' label, before any internationalization. The i18n scripts automatically include this label in the strings that can be translated.
- layers.layerId.icon = filename : filename of the static picto
that illustrates this Layer in the layer tree. The path is relative
to
myMap.ini. See also Section 6.4, “Layers Legends” for a description of the automatic legending process. - layers.layerId.link = url : provides a link for the layer (e.g. to some metadata); makes the caption in the tree clickable.
- layers.layerId.rendering = tree|block|radio|dropdown :
indicates how to display the LayerGroup children.
- tree (default value): children layers are rendered below the LayerGroup with an indentation. If children are not declared as "frozen" or "hidden" (see Section 4.3.3.3, “Initial Mapstates”) they will be preceded by a checkbox input. A node folding/unfolding link is displayed before the LayerGroup.
- radio: quite similar to the "tree" rendering with "radio" buttons replacing checkboxes. Only one child layer can be selected at a time.
- block: children layers are separated as blocks (separation medium depends on the template layout). Note that the rendering will be applied to the children, not to the LayerGroup itself, which is not displayed at all.
- dropdown: as for block rendering, the LayerGroup is not displayed. Its children are simply rendered as an HTML "simple select" options list. If the selected child layer cannot be determined using posted or session-saved data, first child (according to the layers.layerId.children list order) is selected. If any, only the selected child layer's own children are displayed under the dropdown list.
- layers.layerId.metadata.minScale (resp. maxScale): one may specify a numerical minimal (resp. maximal) scale for the given LayerGroup. This parameter has absolutely no effect on Mapserver behavior and is only used to display out-of-scale icons and links in the layers tree. For more info about
layers.inimetadata parameters, see Section 6.3.2, “Metadata inlayers.ini”.
Children switching is useful to define several lists of children for one layer group. The children that will be displayed is choosen by a special parameter : the switch ID.
Switch IDs and labels are listed in file
layers.ini(server side). In default test environment, a
dropdown is constructed using this list and displayed in the GUI.
switches.switch1.label = Switch 1 switches.switch2.label = Switch 2 switches.switch3.label = Switch 3
Then, each layer group that needs to change its children depending on the switch ID may add this ID as a suffix to the children option.
layers.layerId.className = LayerGroup layers.layerId.children.switch1 = layer1, layer3 layers.layerId.children.switch2 = layer2, layer3 layers.layerId.children.switch3 =
Special suffix default can be used to define
a default children list :
layers.layerId.className = LayerGroup layers.layerId.children.switch2 = layer2, layer3 layers.layerId.children.default =
The following layer group definitions are equivalent :
layers.layerId.className = LayerGroup layers.layerId.children.default = layer4
layers.layerId.className = LayerGroup layers.layerId.children = layer4
By default, the switch input is positionned above the layers tree. If you wish to change its position, simply place the {$switches} variable somewhere else in your template. If you are using AJAX, you also need to define the switchTargetId parameter in client_conf/layers.ini.
- switchTargetId = elementid : the id of the element in the template, containing the
{$switches}variable. For example :<div id="switchTarget"> {$switches} </div>
If you do not wish to duplicate the "default" switch and the switch you want to use as reference (default behaviour), you can use the relatedDefaultSwitchId parameter.
- relatedDefaultSwitchId = switchid : the id of the switch you want to use as default switch (you need to modify the
switches.tpltemplate!).
For example :
switches.switch1.label = human switches.switch2.label = categ ; layers layers.root.className = LayerGroup ;layers.root.children = background, human, categ, wmsLayers layers.root.children.default = background, human, wmsLayers layers.root.children.switch2 = background, categ, wmsLayers layers.root.rendering = block
We have 2 switchs defined: switch1 and switch2. By default, the switch select in the interface will contains 3 switchs: default, switch1, switch2. If we set relatedDefaultSwitchId = switch1 and modify the template accordingly (see the example in project demoCW3), the select will contains only switch1 and switch2.
In the layers definition, we only use default and switch2. If the user select switch1 in the interface, the default switch will be used as switch1 is not defined: no more duplicate definition of switch.
Metadata are (keyword, value) pairs which can be associated to a MapServer layer in the mapfile, or to a Layer or LayerGroup in the layers.ini configuration file. These metadata are used in several different contextes, such as layer specific configuration, security handling, ... The metadata related to the functionalities of CartoWeb are described in the documentation of the corresponding plugins.
Specifying metadata in mapfiles is based on the standard MapServer syntax. For instance:
LAYER
NAME "my_layer"
[...]
METADATA
"exported_values" "security_view,some_specific_parameter,data_encoding"
"security_view" "admin"
"some_specific_parameter" "value"
"data_encoding" "value_iso"
"id_attribute_string" "FID|string"
"mask_transparency" "50"
"mask_color" "255, 255, 0"
"area_fixed_value" "10"
END
[...]
END
The metadata key exported_values is a bit
special: It gives the list of metadata keys (coma separated), which
will be transmitted to the client. This is required for the metadata
keys describing layer security for instance, as they are used on the
CartoClient.
The configuration file layers.ini may also
contain metadata (key, value) pairs. This is needed for LayerGroup
objects, as these have no counterparts in the mapfile. For simple
layers, the metadata specified in the layers.ini
take precedence over the values from the mapfile.
For each layer object in the layers.ini file,
the following syntax is used to set metadata:
layers.layerId.metadata.METADATA = value
For instance:
layers.group_admin.className = LayerGroup layers.group_admin.children = grid_defaulthilight layers.group_admin.metadata.security_view = admin
layers.foo.className = Layer layers.foo.metadata.data_encoding = value_iso
Note
It is possible to specify minScale and
maxScale attributes as layers.ini
metadata for layerGroups items. The equivalent mapfile metadata
is not available for layers. In that case, simply use mapfile MINSCALE and MAXSCALE
attributes.
Metadata declared in mapfiles or layers.ini
can be used in the layers.tpl Smarty templates
using the following notation:
{capture name=caption}
{$element.layerLabel} <a
href="/?lang={$element.layerMeta.lang}&client_id={$element.layerMeta.client_id}">
{element.layerMeta.complex_label}</a>
{/capture}
As we can see in the previous example, metadata values can be used through the
layerMeta property of the $element Smarty
variable. Typical usage of this feature is to render for instance several
HTML links for each layers.
CartoWeb includes a mechanism for the automatic generation of legends. If desired, an icon is drawn for each class of the layers. There are two conditions that must be fulfilled to make it work :
1. The mechanism must be enabled by setting
autoClassLegend = true
2. Each class (or more precisely each class that should appear in the legend) must have a name. Here an example :
LAYER
NAME "spur_spurweite"
METADATA
...
END
TYPE line
...
CLASS
NAME "Normalspur (1435 mm)"
EXPRESSION ([MM] = 1435)
STYLE
COLOR 0 0 255 # blue
END
END
CLASS
# NAME "Meterspur (1000 mm)"
EXPRESSION ([MM] = 1000)
STYLE
COLOR 255 0 0 # red
END
END
CLASS
NAME "Schmalspur (< 900 mm)"
EXPRESSION ([MM] < 900)
STYLE
COLOR 128 0 128 # lila
END
END
END
In this case, the second class would not appear in the legend, because the NAME is commented out.
Provided that no static icon is defined for a layer in
layers.ini, the icon of the first visible class is
used for the layer.
Legend icons are also used when exporting maps in PDF (see
Chapter 12, PDF Export [plugin]). Standard legend icons are used by default,
which means that they may seem pixelized when printing a 300 dpi map.
To resolve this issue, the following parameter can be set in
layers.ini:
legendResolutions = 96, 150, 300
Each resolution must correspond to one of those set in PDF Export configuration file. This file is described in Section 12.2.1, “General Configuration”.
Mapserver could
act like a WMS client and retrieved layer from
distant WMS server. In this specific case, layers
legends could be retrieved directly from a distant server with
SLD support (getLegendGraphic
method).
You must
also add a metadata on each WMS layer to retrieve its legend icon:
wms_legend_graphic
Here is an example:
LAYER
NAME 'prov_boundary'
TYPE RASTER
CONNECTION 'http://www2.dmsolutions.ca/cgi-bin/mswms_gmap?'
CONNECTIONTYPE WMS
METADATA
'wms_srs' 'EPSG:4326'
'wms_name' 'prov_bound'
'wms_server_version' '1.1.1'
'wms_format' 'image/png'
'wms_legend_graphic' 'true'
END
END
In some cases, it may be useful to generate several layers out of a single "template" layer. An example would be floors : each floor must be displayed with the same color, etc. but the data source is different (different shapefile or different where clause for a database layer). In CartoWeb, it is possible to add PHP code into mapfiles. True mapfiles are then generated by a batch script. The generated layers are called "Auto Layers".
First, you have to declare the list of auto layers indexes. Indexes will be used as suffixes for generated layers :
autoLayersIndexes = index1, index2
Then you can use auto layers just as other layers. In this exemple,
an auto layer myAutoLayer_ was declared in the
mapfile template (see Section 6.6.2, “Mapfile Templates”).
layers.layer1.className = LayerGroup layers.layer1.children = layer2, myAutoLayer_index1 layers.layer2.className = LayerGroup layers.layer2.children = myAutoLayer_index2
Mapfile templates for auto layers are PHP files. The main template
must be called mapId.map.php. If this file exists,
then CartoWeb assumes that auto layers generation is used. If the
file does not exists, CartoWeb looks for a standard
mapId.map.
The following functions are predefined and can be used in mapfile templates :
-
printLayer($name, $contents): adds a new auto layer. The name is the final name of the layer without the index suffix. Contents include Mapserver layer definition with PHP code for parts that will be different for each instance of auto layer printIndex(): adds the current auto layer index. Must be used in auto layer contentsprintName(): adds the current auto layer full name. Must be used in auto layer contentsgetIndex(): returns the current auto layer index. It can be useful for instance in conditional statements. Must be used in auto layer contentsincludeFile($path): adds the content of another PHP mapfile template
Here is an example :
MAP
NAME "MyMapfile"
EXTENT -10 -10 10 10
# ...
<?php
printLayer('myAutoLayer_',
<<<AUTOLAYER
# This is my auto layer with index <?php printIndex(); ?>
LAYER
NAME <?php printName(); ?>
TYPE POLYGON
# ...
CLASS
NAME "MyClass"
STYLE
COLOR <?php if(getIndex() == 'index2') print "200 200 255";
else print "255 153 102"; ?>
END
END
END
AUTOLAYER
);
?>
END
Script makemaps.php located in directory
scripts generates mapfiles out of mapfile
templates for all projects. Mapfiles are generated in the same
directory. The script must be called once during installation and then
each time a change is made to the mapfile templates.
It uses filelayers.ini to find out which auto
layers are needed. For instance, with the following
layers.ini, myAutoLayer_index3 won't be
generated.
autoLayersIndexes = index1, index2, index3
layers.layer1.className = LayerGroup
layers.layer1.children = layer2, myAutoLayer_index1
layers.layer2.className = LayerGroup
layers.layer2.children = myAutoLayer_index2
At least one file is generated. Its name is
auto.mapId.all.map and it contains all auto layers
used in file layers.ini. When children switching
is used (see Section 6.2.4, “Children Switching”), one mapfile
is generated per switch. One more is generated for special switch
default. This way, only auto layers used with
the current switch are actually loaded at runtime. Mapfile
auto.mapId.all.map is still generated.
In the following example, 4 mapfiles are generated :
autoLayersIndexes = index1, index2, index3, index4
switches.switch1.label = Switch 1
switches.switch2.label = Switch 2
layers.layer1.className = LayerGroup
layers.layer1.children.switch1 = layer2, myAutoLayer_index1
layers.layer1.children.default = layer2, myAutoLayer_index2
layers.layer2.className = LayerGroup
layers.layer2.children = myAutoLayer_index4
-
auto.mapId.all.map: contains all layers used inlayers.ini, ie. layers myAutoLayer_index1, myAutoLayer_index2 and myAutoLayer_index4 -
auto.mapId.switch1.map: contains layers used when Switch 1 is selected, ie. layers myAutoLayer_index1 and myAutoLayer_index4 -
auto.mapId.switch2.map: contains layers used when Switch 2 is selected, ie. layers myAutoLayer_index2 and myAutoLayer_index4 -
auto.mapId.default.map: contains layers used when no switch is selected, ie. layers myAutoLayer_index2 and myAutoLayer_index4
Ability to reorder displayed layers could be appreciated by end user. And so, even if your map is well designed with largest features layers on bottom and smallest on top, and/or even with well used transparent properties. The plugin layerReorder , is designed to do so. Layers could be reorder on the displayed stack to improve visibility of one layer.
Each layer defined in the mapfile and currently selected in legend menu (and only them) will be displayed in the reorder menu list.
To activate the plugin, add it to
loadPlugins from Both CartoClient and
CartoServer configuration files:
client_conf/client.ini and
server_conf/<mapId>/<mapId>.ini.
For instance:
loadPlugins = layerReorder
If you want to exclude some layers and then not allow them to be
reordered, have a look on
client_conf/layerReorder.ini. You will be able to
exclude some layers and to choose to keep them on bottom (or on top).
To do so, use the following configuration parameters:
You could also add a transparency selector on each layer displayed with this plugin. End user will so be able to choose a different transparency level for each displayed layer.
To activate it, set enableTransparency to
true in client_conf/layerReorder.ini.
Default transparency selector values are : 10%, 20%, 50%, 75% and 100%.
You could also customize transparency values available in this
selector, with a comma separated value in
transparencyLevels. A transparency value is a
integer between 1 to 100 ; with 100 mean an opaque layer as 1 mean a
nearly invisible one.
This plugin is used to filter objects displayed on the map according to some criteria. Those criteria are set by users using a special form, automatically built according to the plugin configuration.
To activate the plugin, add it to
loadPlugins from Both CartoClient and
CartoServer configuration files:
client_conf/client.ini and
server_conf/<mapId>/<mapId>.ini.
For instance:
loadPlugins = layerFilter
Client configuration is mainly used to described what the filter form must look like. Aside from a i18n parameter - a boolean telling if form inputs titles and labels must be internationalized - the configuration uses an object-like notation to list filter form inputs and their properties. Three types of inputs are available: radio buttons, checkboxes and dropdowns. Each input config object has a "criterion name" and several properties:
title, title of the criteriontype, (checkbox|radio|dropdown), rendering of the criterion inputallOptionsListed, (boolean), only relevant whentype=checkbox. If this setting istrue, no filter is applied when all boxes are checked. Default setting isfalse.options, a list of object-like options with an "option name" alabeland aselectedboolean status (indicates the initial state of the filter form).
For instance:
i18n = true criteria.foo.title = foobar criteria.foo.type = checkbox criteria.foo.allOptionsListed = true criteria.foo.options.bou.label = some text criteria.foo.options.bou.selected = true criteria.foo.options.bla.label = blabla criteria.foo.options.bla.selected = true criteria.foo.options.chon.label = some other option not checked
If users check all the boxes of a criterion, no filter will be applied for this criterion. If no box is checked for a criterion, all its filters will be applied.
For radio and dropdown criterion, it is possible to specify a neutral option (if selected, no filter is applied for this criterion) using the null keyword. For instance:
criteria.foo.title = foobar criteria.foo.type = dropdown criteria.foo.options.bou.label = some text criteria.foo.options.chon.label = some other text criteria.foo.options.null.label = no filter criteria.foo.options.null.selected = true
The plugin server-side configuration described what layers criteria must apply to and what the conditions matching the criteria options (PostGIS or ShapeFile FILTER syntax) are. An object-like notation, symetrical to the client-side configuration, is used. Each criterion owns the following properties:
layers, a comma-separated list of one or more layers to whom the criterion appliesoptions, a collection of options "objects" with afilterproperty that indicates what PostGIS or ShapeFile filter to apply. If you need to use double-quotes (") within that property (for instance to enclose a table field name), rather user # characters instead to avoid conflicts. The plugin will then replace them by double-quotes characters.
For instance:
criteria.surf.layers = zone_a, zone_b criteria.surf.options.surf1.filter = "#SOME_FIELD# < 1" criteria.surf.options.surf2.filter = "MAX(some_other_field) BETWEEN 1 AND 2"
In order to make the filter form available in the general layout, a Smarty {$layerFilter} tag must be included in the templates/cartoclient.tpl template. If the AJAX mode is activated, make sure that it is encapsulated within a <div id="layerFilter"></div> element:
<div id="layerFilter">{$layerFilter}</div>