Geometry Module

The Geometry Module in the TomTom Maps SDK enables displaying and visualizing geographic shapes and polygons on maps. This module provides comprehensive functionality for rendering complex geometries, administrative boundaries, and custom geographic data with customizable styling.

import type { BBox, Places } from '@tomtom-org/maps-sdk/core';
import { TomTomConfig } from '@tomtom-org/maps-sdk/core';
import {
    calculateFittingBBox,
    GeometriesModule,
    type GeometryBeforeLayerConfig,
    type StandardStyleID,
    standardStyleIDs,
    TomTomMap,
} from '@tomtom-org/maps-sdk/map';
import { geocode, geometryData } from '@tomtom-org/maps-sdk/services';
import type { LngLatBoundsLike } from 'maplibre-gl';
import type { Config } from './placeConfiguration';
import { namedConfigs } from './placeConfiguration';
import './style.css';
import { API_KEY } from './config';
import { initTogglePanel } from './togglePanel';

// (Set your own API key when working in your own environment)
TomTomConfig.instance.put({ apiKey: API_KEY, language: 'en-GB' });

(async () => {
    const map = new TomTomMap({
        mapLibre: {
            container: 'sdk-map',
        },
    });
    const geometryModule = await GeometriesModule.get(map);
    let placeSubdivisions: Places;

    const placeBBox = () =>
        calculateFittingBBox({
            map,
            toBeContainedBBox: placeSubdivisions.bbox as BBox,
            surroundingElements: ['#sdk-example-panel'],
        }) as LngLatBoundsLike;

    const updateMap = async (config: Config) => {
        placeSubdivisions = await geocode({ limit: 100, query: '', ...config.searchConfig });
        map.mapLibreMap.fitBounds(placeBBox());
        const geometries = await geometryData({ geometries: placeSubdivisions, zoom: 14 });
        geometryModule.applyConfig(config.geometryConfig);
        geometryModule.show(geometries);
    };

    const listenToUIEvents = async () => {
        const placeSelector = document.getElementById('sdk-example-placeSelector') as HTMLSelectElement;
        placeSelector.addEventListener('change', (event) =>
            updateMap(namedConfigs[(event.target as HTMLInputElement).value]),
        );

        const options = document.querySelectorAll<HTMLInputElement>('input[type=radio][name=layerOption]');
        options.forEach((option) => {
            option.addEventListener('change', () =>
                geometryModule.moveBeforeLayer(option.value as GeometryBeforeLayerConfig),
            );
        });

        const stylesSelector = document.querySelector('#sdk-example-mapStyles') as HTMLSelectElement;
        standardStyleIDs.forEach((id) => stylesSelector.add(new Option(id)));
        stylesSelector.addEventListener('change', (event) =>
            map.setStyle((event.target as HTMLOptionElement).value as StandardStyleID),
        );

        document
            .querySelector('#sdk-example-reCenter')
            ?.addEventListener('click', () => placeSubdivisions && map.mapLibreMap.fitBounds(placeBBox()));
    };

    await updateMap(namedConfigs.france);
    await listenToUIEvents();

    initTogglePanel();
})();

Purpose and Functionality

The Geometry Module serves as the primary interface for:

  • Displaying polygon geometries from TomTom services and custom data
  • Visualizing administrative boundaries such as countries, states, and cities
  • Rendering custom geographic shapes with configurable styling options
  • Managing geometry layers with visibility controls and interaction handling
  • Integrating geometry data from search results and external sources

Core Concepts

Geometry Data Types

The module supports various types of geographic geometries:

Supported Geometry Types:

  • Polygons: Closed shapes representing areas like administrative boundaries
  • MultiPolygons: Complex shapes with multiple disconnected areas
  • Administrative boundaries: Country, state, city, and district boundaries
  • Custom shapes: User-defined geographic areas and regions

Data Sources

Geometries can come from multiple sources:

  • TomTom Geometry Data Service: Official administrative boundaries and places
  • Search results: Geographic data from place searches
  • Custom GeoJSON: User-provided geometric data
  • External APIs: Third-party geographic data sources

Basic Geometry Display

Initializing Geometry Module

import { TomTomConfig } from '@tomtom-org/maps-sdk/core';
import { TomTomMap, GeometriesModule } from '@tomtom-org/maps-sdk/map';
// Configure SDK and create map
TomTomConfig.instance.put({ apiKey: 'YOUR_API_KEY' });
const map = new TomTomMap({ mapLibre: { container: 'map' } });
// Initialize geometry module with default styling
const geometryModule = await GeometriesModule.get(map);

Displaying Administrative Boundaries

import { geocode, geometryData } from '@tomtom-org/maps-sdk/services';
// Get geometry for a specific place
const place = (await geocode({ query: 'Amsterdam, Netherlands' })).features[0];
const geometryResponse = await geometryData({ geometries: [place] });
// Display the geometry on the map
geometryModule.show(geometryResponse);

Custom Styling Configuration

Fill and border are configured independently via fill and line. Each exposes concise curated fields for the common cases — fill: { color, opacity } and line: { color, width, opacity }:

// Initialize with custom styling
const geometryModule = await GeometriesModule.get(map, {
fill: {
color: '#007cbf', // Fill color for polygons
opacity: 0.3 // Fill transparency
},
line: {
color: '#005a8b', // Border color
width: 2, // Border width
opacity: 0.8 // Border transparency
},
beforeLayerConfig: 'lowestLabel' // Layer positioning (below all labels)
});

For border properties the curated fields don’t cover, the line.layer escape hatch accepts a partial MapLibre LineLayerSpecification (without id/source) and can set any line property — an inset/outset border (line-offset), a soft glow (line-blur), a dashed border (line-dasharray), a hollow casing (line-gap-width), line-cap, line-join, line-pattern, and more. The curated color/width/opacity fields take precedence over the same paint property set via layer:

const geometryModule = await GeometriesModule.get(map, {
line: {
color: '#00A65E',
width: 2,
layer: {
paint: {
'line-offset': 2, // Lateral offset in pixels (inset/outset border)
'line-blur': 4, // Edge blur in pixels (glow/halo effect)
'line-dasharray': [2, 2], // Dash pattern in line-width units ([dash, gap, …])
'line-gap-width': 3 // Hollow casing
},
layout: { 'line-cap': 'round' }
}
}
});

Advanced Geometry Features

Multiple Geometry Layers

// Create multiple geometry modules for different data sets
const countryGeometryModule = await GeometriesModule.get(map, {
fill: { color: '#ff6b6b', opacity: 0.2 },
line: { color: '#ff0000', width: 3 }
});
const cityGeometryModule = await GeometriesModule.get(map, {
fill: { color: '#4ecdc4', opacity: 0.4 },
line: { color: '#00a896', width: 2 }
});
// Display different geometry types
countryGeometryModule.show(countryBoundaries);
cityGeometryModule.show(cityBoundaries);

Dynamic Geometry Management

// Add and remove geometries dynamically
const geometryModule = await GeometriesModule.get(map);
// Show new geometry data
function displayGeometry(newGeometryData) {
geometryModule.clear(); // Clear existing geometries
geometryModule.show(newGeometryData);
}
// Toggle geometry visibility
let geometryVisible = true;
function toggleGeometry() {
if (geometryVisible) {
geometryModule.clear();
} else {
geometryModule.show(currentGeometryData);
}
geometryVisible = !geometryVisible;
}

Layer Positioning and Styling

A single beforeLayerConfig positions all geometry layers together. To place the fill and border at different points in the stack, pass the object form { fill, line } (or set beforeLayerConfig inside the fill / line sections):

const geometryModule = await GeometriesModule.get(map, {
fill: { color: '#87CEEB', opacity: 0.5 },
line: { color: '#4682B4', width: 1.5 },
// Fill slips below the road network while the border stays above the labels
beforeLayerConfig: { fill: 'lowestRoadLine', line: 'lowestLabel' }
});

Themed Geometry Display

The SDK supports three visual themes for polygon display:

ThemeEffect
'filled'Semi-transparent fill (default)
'outline'Transparent fill with a thick border
'inverted'Semi-transparent area outside the polygon

Setting theme at config level

The simplest way to apply a theme is via the theme option in GeometriesModuleConfig:

import { GeometriesModule } from '@tomtom-org/maps-sdk/map';
// Highlight "rest of the world" outside a country
const module = await GeometriesModule.get(map, {
theme: 'inverted',
fill: { color: 'black', opacity: 0.5 },
});
module.show(countryGeometry);

Individual features can override the config-level theme by setting theme in their own properties.

Using themedGeometryConfig for mixed themes

When features in the same layer need different themes, use themedGeometryConfig(palette?). It returns a config with MapLibre expressions that read each feature’s theme property and apply the appropriate style:

import { GeometriesModule, themedGeometryConfig } from '@tomtom-org/maps-sdk/map';
const module = await GeometriesModule.get(map, themedGeometryConfig('blues'));
// Features carry their own theme — styling adapts per feature
module.show({
type: 'FeatureCollection',
features: [
{ ...featureA, properties: { theme: 'filled', title: 'Zone A' } },
{ ...featureB, properties: { theme: 'outline', title: 'Zone B' } },
],
});

A center label is shown for each polygon whenever the feature carries a title property.

Color palettes

Both themedGeometryConfig and reachableRangeGeometryConfig accept a named palette as their first argument (defaulting to 'fadedRainbow'). The palette controls the fill colors assigned to successive polygon rings.

Available palettes: warm, browns, cold, fadedBlues, blues, greens, fadedGreenToBlue, blueToRed, greenToYellow, pastel, retro, contrastRetro, fadedRainbow, pastelRainbow.

import { themedGeometryConfig } from '@tomtom-org/maps-sdk/map';
// Use the 'retro' palette with filled theme (default)
const config = themedGeometryConfig('retro');
// Palette names are typed as ColorPaletteOptions

For reachable ranges specifically, use reachableRangeGeometryConfig which builds on themedGeometryConfig and additionally wires up label generation and the inverted-theme donut transform automatically. See Reachable Ranges.

Multiple Module Instances

You can create multiple independent instances of the Geometry module, each with its own configuration and styling. This is useful for displaying different geometry layers with distinct visual styles.

// Create separate instances for different geometry types
const countryBorders = await GeometriesModule.get(map, {
fill: { color: '#E74C3C', opacity: 0.2 },
line: { color: '#C0392B', width: 3 }
});
const cityBounds = await GeometriesModule.get(map, {
fill: { color: '#3498DB', opacity: 0.3 },
line: { color: '#2980B9', width: 2 }
});
// Each instance manages its own geometries independently
countryBorders.show(countryData);
cityBounds.show(cityData);

Reading Shown Data

Use getShown() to retrieve the geometries currently displayed on the map. This returns the exact data previously passed to show():

const shown = geometriesModule.getShown();
console.log(`Geometries: ${shown.geometry.features.length}`);

Services Integration

  • Geometry Data Service - Fetch detailed boundary and shape data for administrative areas and places
  • Search Services - Find places and administrative areas that have associated geometry data