Divide uma trajetória em um array de subtrajetórias. Há três sobrecargas disponíveis: divisão por geometria, divisão por regra e divisão por índice.
A função retorna trajectory[]. Use unnest() para expandir o resultado em linhas individuais.
Sintaxe
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);
Parâmetros
|
Parâmetro |
Tipo |
Descrição |
|
|
trajectory |
A trajetória a dividir. |
|
|
geometry |
O objeto de geometria usado como limite de divisão. Apenas Point e MultiPoint são suportados. |
|
|
float8 |
O raio do buffer ao redor da geometria Point, em metros. A trajetória se divide onde cruza o limite do buffer. |
|
|
text |
Uma string JSON que especifica uma regra de divisão. Consulte Regras de divisão. |
|
|
int[] |
Os índices dos pontos onde dividir. Os índices começam em 0. |
Funcionamento
Divisão por geometria
Forneça uma geometria Point ou MultiPoint e um raio de buffer. A função cria um buffer circular ao redor de cada ponto e divide a trajetória sempre que ela cruzar o limite desse buffer.

Caso nenhuma parte da trajetória intercepte algum buffer, a divisão não ocorre e a função retorna a trajetória original sem alterações.
Divisão por regra
Informe uma string JSON contendo exatamente uma chave de regra. O comportamento varia conforme a família da regra:
As regras **
cut_point.*** dividem em pontos de amostragem específicos (ponto B no diagrama).As regras **
cut_edge.*** dividem em arestas específicas (ponto C no diagrama).As regras **
drop_edge.*** removem totalmente as arestas correspondentes. Use estas regras para limpar ruídos dos dados de trajetória, como a remoção de segmentos muito longos causados por perda de sinal GPS ou grandes saltos posicionais.

Regras de divisão
|
Regra |
Tipo de valor |
Descrição |
|
|
Inteiro positivo |
Divide a cada N pontos de amostragem. |
|
|
Inteiro positivo |
Divide em N partes iguais. Se a trajetória tiver menos arestas que N, cada aresta se torna sua própria subtrajetória. |
|
|
Intervalo de tempo positivo |
Divide em intervalos de tempo regulares. Opcionalmente, especifique um tempo âncora: |
|
|
Inteiro par positivo |
Divide de modo que cada subtrajetória fique dentro de uma célula de grade Geohash na precisão especificada. Os dados da trajetória devem usar coordenadas de latitude/longitude. |
|
|
Intervalo de tempo |
Remove arestas com duração superior à especificada. |
|
|
Ponto flutuante |
Remove arestas maiores que a distância euclidiana 2D especificada. Se todas as arestas excederem o limiar, retorna |
Divisão por índice
Forneça um array de índices de pontos. Dado n índices, a função retorna n-1 subtrajetórias. Não é necessário incluir os pontos inicial e final da trajetória no array de índices.
Exemplos
Preparar dados de exemplo
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]}}}'
)
);
Divisão por geometria
Divida a trajetória sempre que ela passar a menos de 23.000 metros de qualquer ponto em MULTIPOINT(100 30, 105 35, 110 35). Isso gera 4 subtrajetórias.
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)
Caso extremo: Se radius_of_buffer for pequeno demais para que a trajetória intercepte alguma zona de buffer, nenhuma divisão ocorre e a função retorna a trajetória original como um array de elemento único.
Divisão por regra
Os exemplos abaixo usam a mesma trajetória de 19 pontos definida 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 — dividir a cada 4 pontos (gera 5 subtrajetórias)**
-- 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 — dividir a cada 10 pontos (gera 2 subtrajetórias)**
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 — dividir a cada 3 pontos (gera 7 subtrajetórias)**
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 — dividir em 100 partes iguais**
Como a trajetória possui apenas 18 arestas (19 pontos) e 18 < 100, cada aresta se torna sua própria subtrajetória. O resultado é um array com 18 subtrajetórias, cada uma com leafcount 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 — dividir por precisão Geohash 2 (gera 4 subtrajetórias)**
SELECT ST_split(a, '{"cut_edge.geohash":2}') FROM traj;
-- Result: 1 row containing an array of 4 sub-trajectories
**cut_edge.geohash — dividir por precisão Geohash 20 (gera 19 subtrajetórias)**
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 — remover arestas maiores que 13 (gera 1 subtrajetória)**
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 — remover arestas maiores que 10 (gera 7 subtrajetórias)**
SELECT ST_split(a, '{"drop_edge.spatial_distance_2d":10}') FROM traj;
-- Result: array of 7 sub-trajectories
**drop_edge.spatial_distance_2d — limiar de 1 (todas as arestas removidas)**
Quando o limiar é menor que o comprimento de todas as arestas, cada aresta é removida e a função retorna um array vazio.
SELECT ST_split(a, '{"drop_edge.spatial_distance_2d":1}') FROM traj;
-- Result: {}
**cut_edge.time_interval — dividir a cada 50 minutos (gera 5 subtrajetórias)**
SELECT ST_split(a, '{"cut_edge.time_interval":"50 minute"}') FROM traj;
-- Result: array of 5 sub-trajectories
**cut_edge.time_interval — dividir a cada 1 hora com âncora em 2000-01-01 (gera 4 subtrajetórias)**
Use unnest() para expandir o array em linhas individuais.
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
Divisão por índice
3 índices — 2 subtrajetórias
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 índices (com duplicatas e pontos de limite) — 4 subtrajetórias
Valores de índice duplicados e índices de limite explícitos (0 e leafcount-1) são aceitos. Após a deduplicação e ordenação, 5 pontos de divisão únicos geram 4 subtrajetórias.
SELECT unnest(ST_split(a, '{0}'::int[] || '{0,1,3,5}'::int[] || ST_leafcount(a) - 1)) FROM traj;
-- Result: 4 rows