Divise une trajectoire en un tableau de sous-trajectoires. Trois surcharges sont disponibles : division par géométrie, par règle et par index.
La fonction renvoie le type trajectory[]. Utilisez la fonction unnest() pour développer le résultat en lignes individuelles.
Syntaxe
trajectory[] ST_Split(trajectory traj, geometry geom, float8 radius_of_buffer);
trajectory[] ST_Split(trajectory traj, text config);
trajectory[] ST_Split(trajectory traj, int[] indexes);
Paramètres
| Paramètre | Type | Description |
|---|---|---|
traj |
trajectory | Trajectoire à diviser. |
geom |
geometry | Objet géométrique servant de limite de division. Seuls les types Point et MultiPoint sont pris en charge. |
radius_of_buffer |
float8 | Rayon de la zone tampon autour de la géométrie Point, exprimé en mètres. La trajectoire est divisée lorsqu'elle traverse une limite de cette zone tampon. |
config |
text | Chaîne JSON spécifiant une seule règle de division. Consultez la section Règles de division. |
indexes |
int[] | Index des points où effectuer la division. Les index commencent à 0. |
Fonctionnement
Division par géométrie
Indiquez une géométrie de type Point ou MultiPoint ainsi qu'un rayon de zone tampon. La fonction construit une zone tampon circulaire autour de chaque point et divise la trajectoire à chaque intersection avec la limite de cette zone.

Si aucune partie de la trajectoire n'intersecte une zone tampon, aucune division n'a lieu et la fonction renvoie la trajectoire d'origine sans modification.
Division par règle
Transmettez une chaîne JSON contenant exactement une clé de règle. Le comportement varie selon la famille de règles :
Les règles **
cut_point.*** effectuent la division au niveau de points d'échantillonnage spécifiques (point B dans le diagramme).Les règles **
cut_edge.*** divisent la trajectoire au niveau d'arêtes spécifiques (point C dans le diagramme).Les règles **
drop_edge.*** suppriment entièrement les arêtes correspondantes. Utilisez ces règles pour nettoyer le bruit des données de trajectoire, par exemple en supprimant les segments très longs causés par une perte de signal GPS ou des sauts de position importants.

Règles de division
| Règle | Type de valeur | Description |
|---|---|---|
cut_point.max_point |
Entier positif | Divise tous les N points d'échantillonnage. |
cut_point.even_divide |
Entier positif | Divise en N parties égales. Si la trajectoire comporte moins d'arêtes que N, chaque arête devient une sous-trajectoire distincte. |
cut_edge.time_interval |
Plage de temps positive | Divise à intervalles de temps réguliers. Vous pouvez éventuellement spécifier une heure de référence : "1 hour, 2000-01-01". |
cut_edge.geohash |
Entier pair positif | Divise de sorte que chaque sous-trajectoire tienne dans une cellule de grille Geohash à la précision spécifiée. Les données de trajectoire doivent utiliser des coordonnées latitude/longitude. |
drop_edge.temporal_length |
Plage de temps | Supprime les arêtes dont la durée dépasse la valeur spécifiée. |
drop_edge.spatial_distance_2d |
Nombre à virgule flottante | Supprime les arêtes dont la distance euclidienne 2D dépasse la valeur spécifiée. Si toutes les arêtes dépassent le seuil, la fonction renvoie {}. |
Division par index
Transmettez un tableau d'index de points. Pour n index fournis, la fonction renvoie n-1 sous-trajectoires. Il n'est pas nécessaire d'inclure les points de début et de fin de la trajectoire dans le tableau d'index.
Exemples
Configuration des données d'exemple
CREATE TABLE tr_split_traj (id integer, traj trajectory);
INSERT INTO tr_split_traj VALUES (
3,
ST_MakeTrajectory(
'STPOINT'::leaftype,
st_geomfromtext('LINESTRING(99.027 29.7555,99.313 29.9975,99.852 30.0745,104.879 35.0795,105.044 35.1235,105.187 35.0685,109.906 35.0795,110.071 35.1675,110.192 35.0355,110.544 35.0245,111.017 34.8045)', 4326),
ARRAY[
'2010-01-01 14:30'::timestamp,
'2010-01-01 15:00','2010-01-01 15:10','2010-01-01 15:20',
'2010-01-01 15:30','2010-01-01 15:40','2010-01-01 15:50',
'2010-01-01 16:00','2010-01-01 16:10','2010-01-01 16:20',
'2010-01-01 16:30'
],
'{"leafcount":11,"attributes":{"velocity":{"type":"integer","length":2,"nullable":true,"value":[120,130,140,150,160,170,180,190,200,210,220]}}}'
)
);
Division par géométrie
Divisez la trajectoire chaque fois qu'elle passe à moins de 23 000 mètres de n'importe quel point dans MULTIPOINT(100 30, 105 35, 110 35). Cette opération produit 4 sous-trajectoires.
SELECT id, unnest(st_split(traj, st_geomfromtext('MULTIPOINT(100 30,105 35,110 35)'), 23000)) AS subtraj
FROM tr_split_traj;
id | subtraj
----+--------
3 | {"trajectory":{"version":1,"type":"STPOINT","leafcount":3,"start_time":"Fri Jan 01 14:30:00 2010","end_time":"Fri Jan 01 15:10:00 2010",...}}
3 | {"trajectory":{"version":1,"type":"STPOINT","leafcount":2,"start_time":"Fri Jan 01 15:10:00 2010","end_time":"Fri Jan 01 15:20:00 2010",...}}
3 | {"trajectory":{"version":1,"type":"STPOINT","leafcount":2,"start_time":"Fri Jan 01 15:40:00 2010","end_time":"Fri Jan 01 15:50:00 2010",...}}
3 | {"trajectory":{"version":1,"type":"STPOINT","leafcount":3,"start_time":"Fri Jan 01 16:10:00 2010","end_time":"Fri Jan 01 16:30:00 2010",...}}
(4 rows)
Cas limite : si la valeur de radius_of_buffer est trop petite pour que la trajectoire intersecte une zone tampon, aucune division ne se produit et la fonction renvoie la trajectoire d'origine sous forme d'un tableau à un seul élément.
Division par règle
Les exemples suivants utilisent tous la même trajectoire de 19 points définie inline.
WITH traj AS (
SELECT '{"trajectory":{"version":1,"type":"STPOINT","leafcount":19,"start_time":"2000-01-01 00:01:19.067179","end_time":"2000-01-01 03:24:25.946085","spatial":"LINESTRING(-100 -100 -100,-88.8925775739675 -86.6512698383691 -92.3767832526937,-79.6904716538265 -80.6515727923252 -84.2357598245144,-75.8435507711644 -73.7572890928326 -80.5007370118983,-70.6238425321256 -67.8213750167439 -74.5733173238113,-61.6014582272619 -61.0636760429479 -67.9874239303172,-56.1098577060426 -54.4264591250879 -64.5007972046733,-46.9800617334743 -49.4026757289345 -61.6160059720278,-41.7122942996211 -46.3224360072054 -56.5283147455193,-35.5646221285375 -38.1688933617746 -49.2775720101781,-31.7230528349367 -33.6970051738123 -44.1693710885011,-23.1585765127093 -26.5895827477798 -40.6539742602035,-16.7020264320696 -21.6133877349397 -37.3055470525287,-12.1044529232507 -14.1236051704424 -28.2295028120279,-3.77185660181567 -7.74744770256802 -24.3842111621052,0.488159407706304 -3.68223926316326 -19.9478872027248,6.33406881305078 4.54123636645575 -15.0410129944794,15.6666049417108 10.5611746329814 -11.2770220567472,14 11 -10)","timeline":["2000-01-01 00:01:19.067179","2000-01-01 00:12:36.116007","2000-01-01 00:23:53.164835","2000-01-01 00:35:10.213663","2000-01-01 00:46:27.262491","2000-01-01 00:57:44.311319","2000-01-01 01:09:01.360147","2000-01-01 01:20:18.408975","2000-01-01 01:31:35.457803","2000-01-01 01:42:52.506631","2000-01-01 01:54:09.555459","2000-01-01 02:05:26.604287","2000-01-01 02:16:43.653115","2000-01-01 02:28:00.701943","2000-01-01 02:39:17.750771","2000-01-01 02:50:34.799599","2000-01-01 03:01:51.848427","2000-01-01 03:13:08.897255","2000-01-01 03:24:25.946085"]}}'::trajectory AS a
)
**cut_point.max_point — division tous les 4 points (produit 5 sous-trajectoires)**
-- append to the WITH block above
SELECT unnest(ST_split(a, '{"cut_point.max_point":4}')) FROM traj;
-- Result: 5 rows, leafcount 5/5/5/5/3
**cut_point.max_point — division tous les 10 points (produit 2 sous-trajectoires)**
SELECT ST_split(a, '{"cut_point.max_point":10}') FROM traj;
-- Result: 1 row containing an array of 2 sub-trajectories, leafcount 10/10
**cut_point.max_point — division tous les 3 points (produit 7 sous-trajectoires)**
SELECT ST_split(a, '{"cut_point.max_point":3}') FROM traj;
-- Result: 1 row containing an array of 7 sub-trajectories, leafcount 3/4/4/4/4/4/2
**cut_point.even_divide — division en 100 parties égales**
Étant donné que la trajectoire ne comporte que 18 arêtes (19 points) et que 18 < 100, chaque arête devient sa propre sous-trajectoire. Le résultat est un tableau de 18 sous-trajectoires, chacune ayant un leafcount de 2.
SELECT ST_split(a, '{"cut_point.even_divide":100}') FROM traj;
-- Result: 1 row containing an array of 18 sub-trajectories
**cut_edge.geohash — division par précision Geohash 2 (produit 4 sous-trajectoires)**
SELECT ST_split(a, '{"cut_edge.geohash":2}') FROM traj;
-- Result: 1 row containing an array of 4 sub-trajectories
**cut_edge.geohash — division par précision Geohash 20 (produit 19 sous-trajectoires)**
SELECT ST_split(a, '{"cut_edge.geohash":20}') FROM traj;
-- Result: 1 row containing an array of 19 sub-trajectories
**drop_edge.spatial_distance_2d — suppression des arêtes de plus de 13 (produit 1 sous-trajectoire)**
SELECT ST_split(a, '{"drop_edge.spatial_distance_2d":13}') FROM traj;
-- Result: 1 sub-trajectory with leafcount 18 (first long edge removed)
**drop_edge.spatial_distance_2d — suppression des arêtes de plus de 10 (produit 7 sous-trajectoires)**
SELECT ST_split(a, '{"drop_edge.spatial_distance_2d":10}') FROM traj;
-- Result: array of 7 sub-trajectories
**drop_edge.spatial_distance_2d — seuil de 1 (toutes les arêtes supprimées)**
Lorsque le seuil est inférieur à la longueur de toutes les arêtes, chaque arête est supprimée et la fonction renvoie un tableau vide.
SELECT ST_split(a, '{"drop_edge.spatial_distance_2d":1}') FROM traj;
-- Result: {}
**cut_edge.time_interval — division toutes les 50 minutes (produit 5 sous-trajectoires)**
SELECT ST_split(a, '{"cut_edge.time_interval":"50 minute"}') FROM traj;
-- Result: array of 5 sub-trajectories
**cut_edge.time_interval — division toutes les heures avec ancrage au 2000-01-01 (produit 4 sous-trajectoires)**
Utilisez unnest() pour développer le tableau en lignes individuelles.
SELECT unnest(ST_split(a, '{"cut_edge.time_interval":"1 hour, 2000-01-01"}')) FROM traj;
-- Result: 4 rows covering 00:01–01:00, 01:00–02:00, 02:00–03:00, 03:00–03:24
Division par index
3 index — 2 sous-trajectoires
SELECT unnest(ST_split(a, '{1,3,5}'::int[])) FROM traj;
-- Result: 2 rows
-- Sub-trajectory 1: points at indexes 1–3 (start_time 00:12:36, end_time 00:35:10)
-- Sub-trajectory 2: points at indexes 3–5 (start_time 00:35:10, end_time 00:57:44)
6 index (avec doublons et points limites) — 4 sous-trajectoires
Les valeurs d'index en double et les index limites explicites (0 et leafcount-1) sont acceptés. Après déduplication et tri, 5 points de division uniques produisent 4 sous-trajectoires.
SELECT unnest(ST_split(a, '{0}'::int[] || '{0,1,3,5}'::int[] || ST_leafcount(a) - 1)) FROM traj;
-- Result: 4 rows