トラジェクトリをサブトラジェクトリの配列に分割します。3 種類のオーバーロードが利用可能です:ジオメトリによる分割、ルールによる分割、およびインデックスによる分割。
この関数は trajectory[] を返します。unnest() を使用して、結果を個別の行に展開してください。
構文
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);パラメーター
| パラメーター | 型 | 説明 |
|---|---|---|
traj | trajectory | 分割対象のトラジェクトリです。 |
geom | geometry | 分割境界として使用されるジオメトリ オブジェクトです。Point および MultiPoint のみがサポートされます。 |
radius_of_buffer | float8 | Point ジオメトリ周辺のバッファー半径(単位:メートル)です。トラジェクトリは、バッファー境界を横切る箇所で分割されます。 |
config | text | 分割ルールを 1 つ指定する JSON 文字列です。詳細については、「分割ルール」をご参照ください。 |
indexes | int[] | 分割を行うポイントのインデックスです。インデックスは 0 から始まります。 |
仕組み
ジオメトリによる分割
Point または MultiPoint ジオメトリとバッファー半径を指定します。この関数は各ポイント周囲に環状バッファを構築し、トラジェクトリがバッファー境界を横切る箇所で分割を行います。

トラジェクトリのいずれの部分もバッファーと交差しない場合、分割は行われず、元のトラジェクトリが変更されずに返されます。
ルールによる分割
正確に 1 つのルール キーを含む JSON 文字列を指定します。動作はルール ファミリーによって異なります:
cut_point.*ルール:特定のサンプリング ポイント(図中のポイント B)で分割します。cut_edge.*ルール:特定のエッジ(図中のポイント C)で分割します。drop_edge.*ルール:該当するエッジを完全に削除します。GPS 信号の損失や大きな位置ジャンプなどにより生じるノイズをトラジェクトリ データから除去する際に使用します(例:非常に長いセグメントの削除)。

分割ルール
| ルール | 値の型 | 説明 |
|---|---|---|
cut_point.max_point | 正の整数 | N 個ごとのサンプリング ポイントで分割します。 |
cut_point.even_divide | 正の整数 | N 等分に分割します。トラジェクトリのエッジ数が N より少ない場合、各エッジが個別のサブトラジェクトリになります。 |
cut_edge.time_interval | 正の時間範囲 | 一定の時間間隔で分割します。任意でアンカー時刻を指定できます(例:"1 hour, 2000-01-01")。 |
cut_edge.geohash | 正の偶数 | 指定された精度で Geohash グリッド セル内に収まるよう、各サブトラジェクトリを分割します。トラジェクトリ データは緯度/経度座標を使用している必要があります。 |
drop_edge.temporal_length | 時間範囲 | 指定された持続時間より長いエッジを削除します。 |
drop_edge.spatial_distance_2d | 浮動小数点数 | 指定された 2 次元ユークリッド距離より長いエッジを削除します。すべてのエッジがしきい値より長い場合、{} を返します。 |
インデックスによる分割
ポイントのインデックスの配列を指定します。n 個のインデックスを指定すると、n−1 個のサブトラジェクトリが返されます。トラジェクトリの開始点および終了点は、インデックス配列に含める必要はありません。
例
サンプルデータの準備
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]}}}'
)
);ジオメトリによる分割
MULTIPOINT(100 30, 105 35, 110 35) の各ポイントから 23,000 メートル以内を通過する箇所でトラジェクトリを分割します。この操作により、4 個のサブトラジェクトリが生成されます。
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)エッジケース:radius_of_buffer が小さすぎてトラジェクトリがどのバッファー領域とも交差しない場合、分割は行われず、関数は元のトラジェクトリを 1 要素の配列として返します。
ルールによる分割
以下の例では、すべて同一の 19 ポイント トラジェクトリ(インライン定義)を使用します。
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 — 4 ポイントごとに分割(5 個のサブトラジェクトリを生成)
-- 上記の WITH 句に追加
SELECT unnest(ST_split(a, '{"cut_point.max_point":4}')) FROM traj;
-- 結果:5 行、leafcount が 5/5/5/5/3cut_point.max_point — 10 ポイントごとに分割(2 個のサブトラジェクトリを生成)
SELECT ST_split(a, '{"cut_point.max_point":10}') FROM traj;
-- 結果:1 行(2 個のサブトラジェクトリを含む配列)、leafcount が 10/10cut_point.max_point — 3 ポイントごとに分割(7 個のサブトラジェクトリを生成)
SELECT ST_split(a, '{"cut_point.max_point":3}') FROM traj;
-- 結果:1 行(7 個のサブトラジェクトリを含む配列)、leafcount が 3/4/4/4/4/4/2cut_point.even_divide — 100 等分
トラジェクトリには 18 個のエッジ(19 ポイント)しか存在しないため、18 < 100 となります。このため、各エッジが個別のサブトラジェクトリになります。結果は leafcount が 2 のサブトラジェクトリ 18 個を含む配列です。
SELECT ST_split(a, '{"cut_point.even_divide":100}') FROM traj;
-- 結果:1 行(18 個のサブトラジェクトリを含む配列)cut_edge.geohash — Geohash 精度 2 で分割(4 個のサブトラジェクトリを生成)
SELECT ST_split(a, '{"cut_edge.geohash":2}') FROM traj;
-- 結果:1 行(4 個のサブトラジェクトリを含む配列)cut_edge.geohash — Geohash 精度 20 で分割(19 個のサブトラジェクトリを生成)
SELECT ST_split(a, '{"cut_edge.geohash":20}') FROM traj;
-- 結果:1 行(19 個のサブトラジェクトリを含む配列)drop_edge.spatial_distance_2d — 13 より長いエッジを削除(1 個のサブトラジェクトリを生成)
SELECT ST_split(a, '{"drop_edge.spatial_distance_2d":13}') FROM traj;
-- 結果:leafcount が 18 のサブトラジェクトリ 1 個(最初の長いエッジが削除済み)drop_edge.spatial_distance_2d — 10 より長いエッジを削除(7 個のサブトラジェクトリを生成)
SELECT ST_split(a, '{"drop_edge.spatial_distance_2d":10}') FROM traj;
-- 結果:7 個のサブトラジェクトリを含む配列drop_edge.spatial_distance_2d — しきい値を 1 に設定(すべてのエッジが削除される)
しきい値がすべてのエッジ長より小さい場合、すべてのエッジが削除され、関数は空の配列を返します。
SELECT ST_split(a, '{"drop_edge.spatial_distance_2d":1}') FROM traj;
-- 結果:{}cut_edge.time_interval — 50 分ごとに分割(5 個のサブトラジェクトリを生成)
SELECT ST_split(a, '{"cut_edge.time_interval":"50 minute"}') FROM traj;
-- 結果:5 個のサブトラジェクトリを含む配列cut_edge.time_interval — 2000-01-01 をアンカー時刻として 1 時間ごとに分割(4 個のサブトラジェクトリを生成)
unnest() を使用して、配列を個別の行に展開します。
SELECT unnest(ST_split(a, '{"cut_edge.time_interval":"1 hour, 2000-01-01"}')) FROM traj;
-- 結果:00:01–01:00、01:00–02:00、02:00–03:00、03:00–03:24 をカバーする 4 行インデックスによる分割
3 個のインデックス → 2 個のサブトラジェクトリ
SELECT unnest(ST_split(a, '{1,3,5}'::int[])) FROM traj;
-- 結果:2 行
-- サブトラジェクトリ 1:インデックス 1–3 のポイント(start_time 00:12:36、end_time 00:35:10)
-- サブトラジェクトリ 2:インデックス 3–5 のポイント(start_time 00:35:10、end_time 00:57:44)6 個のインデックス(重複および境界ポイントを含む)→ 4 個のサブトラジェクトリ
重複したインデックス値および明示的な境界インデックス(0 および leafcount−1)は許容されます。重複排除およびソート後、5 個のユニークな分割ポイントから 4 個のサブトラジェクトリが生成されます。
SELECT unnest(ST_split(a, '{0}'::int[] || '{0,1,3,5}'::int[] || ST_leafcount(a) - 1)) FROM traj;
-- 結果:4 行