All Products
Search
Document Center

PolarDB:ST_MapMatching

Last Updated:Mar 28, 2026

Snaps GPS traces or geometric line objects to a road network and returns the matched road geometry. Use this function to turn noisy, imprecise location data into clean paths that follow actual roads.

Syntax

geometry ST_MapMatching(text wsname, geometry geom, text options);
geometry ST_MapMatching(text wsname, trajectory traj, text options);

Parameters

ParameterDescription
wsnameThe name of the workspace containing the road network data.
geomThe geometric line object to match against the road network.
trajThe trajectory object to match against the road network.
optionsA JSON string specifying the matching algorithm and its parameters.

Return values

Returns the road geometric objects that correspond to the input geometric objects or trajectories. The returned geometry follows the actual road network rather than the raw input coordinates.

Usage notes

  • The input can be a geometric line object (geom) or a trajectory object (traj).

  • When the input is a trajectory object, only the geometry within the trajectory is matched. The trajectory's attribute information is not included in the output.

  • The returned geometry is a new object constructed from matched road segments — it is not a subset of the input geometry.

Example

This example creates a road network, builds a workspace, then runs map matching on a GPS trace.

Step 1: Prepare road network data

Create the road network table and insert road segment data:

CREATE TABLE network (
    fid    bigint,                              -- Unique identifier of the road segment
    source bigint,                              -- Start node identifier
    target bigint,                              -- End node identifier
    cost   double precision,                    -- Road weight (not currently used)
    geom   public.geometry(LineString, 4326)    -- Road segment geometry
);

INSERT INTO network(fid, source, target, cost, geom) VALUES
    (1,  1,  2,  1, ST_GeomFromText('LINESTRING(2 1,2 0)')),
    (2,  2,  1,  1, ST_GeomFromText('LINESTRING(2 0,2 1)')),
    (3,  3,  1,  1, ST_GeomFromText('LINESTRING(3 1,2 1)')),
    (4,  4,  3,  1, ST_GeomFromText('LINESTRING(4 1,3 1)')),
    (5,  1,  5,  1, ST_GeomFromText('LINESTRING(2 1,2 2)')),
    (6,  5,  1,  1, ST_GeomFromText('LINESTRING(2 2,2 1)')),
    (7,  3,  6,  1, ST_GeomFromText('LINESTRING(3 1,3 2)')),
    (8,  7,  8,  1, ST_GeomFromText('LINESTRING(0 2,1 2)')),
    (9,  8,  7,  1, ST_GeomFromText('LINESTRING(1 2,0 2)')),
    (10, 5,  8,  3, ST_GeomFromText('LINESTRING(2 2,1 2)')),
    (11, 8,  5,  3, ST_GeomFromText('LINESTRING(1 2,2 2)')),
    (12, 6,  5,  1, ST_GeomFromText('LINESTRING(3 2,2 2)')),
    (13, 5,  6,  1, ST_GeomFromText('LINESTRING(2 2,3 2)')),
    (14, 6,  9,  1, ST_GeomFromText('LINESTRING(3 2,4 2)')),
    (15, 9,  6,  1, ST_GeomFromText('LINESTRING(4 2,3 2)')),
    (16, 10, 5,  1, ST_GeomFromText('LINESTRING(2 3,2 2)')),
    (17, 5,  10, 1, ST_GeomFromText('LINESTRING(2 2,2 3)')),
    (18, 6,  11, 1, ST_GeomFromText('LINESTRING(3 2,3 3)')),
    (19, 10, 11, 1, ST_GeomFromText('LINESTRING(2 3,3 3)')),
    (20, 11, 12, 1, ST_GeomFromText('LINESTRING(3 3,4 3)')),
    (21, 13, 10, 1, ST_GeomFromText('LINESTRING(2 4,2 3)')),
    (22, 10, 13, 1, ST_GeomFromText('LINESTRING(2 3,2 4)')),
    (23, 9,  12, 1, ST_GeomFromText('LINESTRING(4 2,4 3)')),
    (24, 12, 9,  1, ST_GeomFromText('LINESTRING(4 3,4 2)')),
    (25, 9,  4,  1, ST_GeomFromText('LINESTRING(4 2,4 1)')),
    (26, 4,  9,  1, ST_GeomFromText('LINESTRING(4 1,4 2)')),
    (27, 14, 15, 1, ST_GeomFromText('LINESTRING(0.5 3.5,2 3.5)')),
    (28, 15, 14, 1, ST_GeomFromText('LINESTRING(2 3.5,0.5 3.5)')),
    (29, 16, 17, 1, ST_GeomFromText('LINESTRING(3.5 4,3.5 2.3)')),
    (30, 17, 16, 1, ST_GeomFromText('LINESTRING(3.5 2.3,3.5 4)'));

Create a workspace from the road network table:

SELECT st_createworkspace('mm_ws_test1', 'SELECT fid, source, target, geom FROM network');

Step 2: Run map matching

Match a GPS trace against the road network:

SELECT ST_AsText(
    ST_MapMatching(
        'mm_ws_test',
        ST_GeomFromText('LINESTRING(4.15 1.6,3.47 0.92,2.4 0.92,2.14 1.53,2.14 2.57,2.49 2.98)'),
        '{"algorithm":"stmatch","k":4,"r":0.25,"e":0.5}'::text
    )
);

Expected output:

geom
----------------------------------------------
 LINESTRING(4 1.6,4 1,3 1,2 1,2 2,2 3,2.49 3)
(1 row)

The input trace (shown in the image below as a series of GPS points) is snapped to the nearest matching road segments, producing a clean path that follows the road network.

image