Skip to content

A Point Map

Overview

In this exercise we'll create a map of POIs (Points of Interest) from OpenStreetMap.

The diagram below shows the Mapfile directives used for the point map:

Mapfile classes used in the Points map

Symbols

The Mapfile symbolises the points using different SYMBOLs. There are several different symbol TYPEs available in MapServer.

A simple circle symbol is defined in the Mapfile as follows:

SYMBOL
    NAME "circle"
    TYPE ELLIPSE
    FILLED TRUE
    POINTS
        1 1
    END
END

A symbol can also reference a character in a font file using TYPE TRUETYPE. References to different font files are added to a FONTSET.

Fonts

A FONTSET includes an alias for the name of the font, and the path to the font file itself. This workshop uses the following fontset.txt file (found in workshop/exercises/mapfiles/data/fonts/fontset.txt):

# Alias                # Font file
MaterialIcons          MaterialIcons-Regular.ttf
MaterialIconsRound     MaterialIconsRound-Regular.otf
LiberationMono         LiberationMono-Regular.ttf
LiberationSans         LiberationSans-Regular.ttf

In the Mapfile itself we then reference this file and use any of the font aliases for symbols and labels.

In the example below we're using a cinema character from Google's Material Symbols. We use HTML entity number of the symbol we want in the CHARACTER keyword. A list of these codes and their associated symbols can be seen at http://localhost:5001/fonts.html.

FONTSET "data/fonts/fontset.txt"
SYMBOL
    NAME "cinema"
    TYPE TRUETYPE
    FONT "MaterialIcons"
    CHARACTER ""
END

Code

Javascript
import '../css/style.css';
import ImageWMS from 'ol/source/ImageWMS.js';
import Map from 'ol/Map.js';
import OSM from 'ol/source/OSM.js';
import View from 'ol/View.js';
import { Image as ImageLayer, Tile as TileLayer } from 'ol/layer.js';

const mapserverUrl = import.meta.env.VITE_MAPSERVER_BASE_URL;
const mapfilesPath = import.meta.env.VITE_MAPFILES_PATH;

const layers = [
    new TileLayer({
        source: new OSM(),
        visible: true
    }),
    new ImageLayer({
            source: new ImageWMS({
            url: mapserverUrl + mapfilesPath + 'points.map&',
            params: { 'LAYERS': 'pois', 'STYLES': '' }
        }),
    }),
];
const map = new Map({
    layers: layers,
    target: 'map',
    view: new View({
        center: [2975862.75916499, 8046369.8646329],
        zoom: 14,
    }),
});
Mapfile
MAP
    NAME "Points"
    EXTENT 26.668678 58.339241 26.796582 58.40941
    SIZE 800 600
    PROJECTION
        "init=epsg:4326"
    END
    FONTSET "data/fonts/fontset.txt"
    WEB
        METADATA
            "wms_enable_request" "*"
            "wms_srs" "EPSG:4326 EPSG:3857"
            "wms_onlineresource" "http://localhost:5000/?map=/etc/mapserver/points.map&"
        END
    END
    SYMBOL
        NAME "circle"
        TYPE ELLIPSE
        FILLED TRUE
        POINTS
            1 1
        END
    END
    SYMBOL
        NAME "cinema"
        TYPE TRUETYPE
        FONT "MaterialIcons"
        CHARACTER ""
    END
    SYMBOL
        NAME "local_library"
        TYPE TRUETYPE
        FONT "MaterialIcons"
        CHARACTER ""
    END
    SYMBOL
        NAME "storefront"
        TYPE TRUETYPE
        FONT "MaterialIcons"
        CHARACTER ""
    END
    # A MAP can have one or more layers, configured
    # using LAYER blocks
    LAYER
        NAME "pois"
        STATUS ON
        TYPE POINT # each LAYER must have a TYPE such as POINT, LINE, or POLYGON
        CONNECTIONTYPE FLATGEOBUF
        DATA "data/osm/pois.fgb"
        CLASSITEM "fclass"
        # data within a LAYER is classified using one or more CLASSes
        # these use EXPRESSIONs to define which features are assigned to
        # which CLASS
        CLASS
            NAME "cinema"
            EXPRESSION "cinema"
            # we can now STYLE the data in the CLASS using
            # one or more STYLE blocks
            STYLE
                SYMBOL "cinema"
                SIZE 16
                COLOR 0 0 0
            END
        END
        CLASS
            NAME "library"
            EXPRESSION "library"
            STYLE
                SYMBOL "local_library"
                SIZE 16
                COLOR 0 0 0
            END
        END
        CLASS
            NAME "shop"
            EXPRESSION {computer_shop,shoe_shop,sports_shop}
            STYLE
                SYMBOL "storefront"
                SIZE 16
                COLOR 0 0 0
            END
        END
        CLASS
            NAME "poi"
            # when there is no expression any features
            # that don't match a previous class will be displayed
            # using this style
            STYLE
                SYMBOL "circle"
                SIZE 1
                COLOR 0 0 0
            END
        END # CLASS ends here
    END # LAYER ends here
END # MAP ends here

Exercises

  1. Edit the workshop/exercises/app/js/points.js to hide the OpenStreetMap base layer. You need to set the visible: true to visible: false.
  2. Change the default CLASS to use larger points in a more visible colour.
  3. Add another class to display another point type. Choose an appropriate symbol from the list at http://localhost:5001/fonts.html. Some example attribute types include fast_food, monument, and post_box. The source dataset is workshop/exercises/mapfiles/data/osm/pois.fgb - this can be opened in QGIS to view all available attributes and values.