外包框運(yùn)算
在實(shí)際計(jì)算時,由于軌跡模塊涉及的對象(軌跡類型,或幾何類型)常常十分復(fù)雜,在分析時可能會使用計(jì)算較為簡單的矩形框?qū)ο竺枋霾樵兓蚝喕?jì)算。
在軌跡模塊,使用BoxNdf類型表示矩形框。
BoxNdf對象表示在時空中的一個多維立方體區(qū)域,其由x,y,z(空間),t(時間)
四個坐標(biāo)軸上的最小值和最大值表示。每個矩形框包含的維度可能不同,有的矩形框只記錄x、y維度信息,有些則可能記錄x,y,z,t四個維度的信息。
在查詢時,可以利用軌跡或幾何類型的外包矩形框來輔助查詢。例如下圖就是一條在x,y,t空間中的運(yùn)動的軌跡和它對應(yīng)的外包矩形框。
在Ganos Trajectory模塊中,使用BoxNDF類型表示外包框。對于軌跡、幾何類型,可以求得其外包框,也可以提取其在特定時間段的子外包框。
提取幾何類型的外包框,也可以在外包框上附加時間范圍(2000-01-01 00:00:10至02:13:20)。
WITH geom AS( SELECT ('POLYGON((12.7243236691148 4.35238368367118,12.9102992732078 1.49748113937676,12.5926592946053 1.67643963359296' || ',12.0197574747333 3.19258554889152,12.7243236691148 4.35238368367118))')::geometry a ) SELECT ST_MakeBox(a),ST_MakeBox(a,'2000-01-01 00:00:10'::timestamp, '2000-01-01 02:13:20'::timestamp) from geom;
提取軌跡類型的外包框,也可以提取軌跡在限定時間內(nèi)的子軌跡的外包框。
With traj AS ( Select ST_makeTrajectory( 'STPOINT', 'LINESTRING(0 0, 50 50, 100 100)'::geometry, tsrange('2000-01-01 00:00:00'::timestamp, '2000-01-01 00:01:40'::timestamp), '{"leafcount":3, "attributes":{ "velocity": {"type": "integer","length": 2,"nullable" : true,"value": [120,130,140]}, "accuracy": {"type": "float", "length": 4, "nullable" : false,"value": [120,130,140]}, "bearing": {"type": "float", "length": 8, "nullable" : false,"value": [120,130,140]}, "acceleration": {"type": "string", "length": 20, "nullable" : true,"value": ["120","130","140"]}, "active": {"type": "timestamp","nullable" : false,"value": ["Fri Jan 01 11:35:00 2010", "Fri Jan 01 12:35:00 2010", "Fri Jan 01 13:30:00 2010"]} }, "events": [{"2" : "Fri Jan 02 15:00:00 2010"}, {"3" : "Fri Jan 02 15:30:00 2010"}] }') a ) SELECT ST_MakeBox(a), ST_MakeBox(a,'1999-12-31 23:00:00'::timestamp, '2000-01-01 00:00:30'::timestamp) from traj;
在較為復(fù)雜的應(yīng)用場景中,對軌跡的處理時常分為兩步:
根據(jù)軌跡的外包框信息過濾掉大部分的無關(guān)數(shù)據(jù)。
對剩余的數(shù)據(jù)進(jìn)行精細(xì)處理。
例如,需要用軌跡間的LCSS相似度查找在某數(shù)據(jù)集中和一條查詢軌跡相似的軌跡,如果直接計(jì)算查詢軌跡和數(shù)據(jù)集中所有軌跡的LCSS相似度再進(jìn)行排序,則計(jì)算量會很大。
可以假設(shè)和查詢軌跡相似的軌跡必然與查詢軌跡的外包框相交,或是距離在一定范圍內(nèi),然后只計(jì)算符合條件的軌跡和查詢之間的相似度,得到一個近似的結(jié)果。
外包框相交:
-- 將軌跡SRID統(tǒng)一設(shè)置為4326 UPDATE trajectory_table SET traj = ST_SetSRID(traj,4326) WHERE ST_SRID(traj)!=4326; With query AS ( SELECT '{"trajectory":{"version":1,"type":"STPOINT","leafcount":3,"start_time":"2020-04-11 17:42:30","end_time":"2020-04-11 17:45:00","spatial":"SRID=4326;LINESTRING(114.35 39.28 4,114.36 39.28 4,114.35 39.29 4)","timeline":["2020-04-11 17:42:30","2020-04-11 17:43:30","2020-04-11 17:45:00"],"attributes":{"leafcount":3,"intensity":{"type":"integer","length":4,"nullable":true,"value":[80,30,50]}}}}'::trajectory q) SELECT ST_lcsDistance(traj, q, 500), trajectory_table.* FROM trajectory_table, query WHERE traj && q ORDER BY ST_lcsDistance(traj, q, 500);
外包框空間距離小于500米,時間距離小于1小時:
-- 將軌跡SRID統(tǒng)一設(shè)置為4326 UPDATE trajectory_table SET traj = ST_SetSRID(traj,4326) WHERE ST_SRID(traj)!=4326; With query AS ( SELECT '{"trajectory":{"version":1,"type":"STPOINT","leafcount":3,"start_time":"2020-04-11 17:42:30","end_time":"2020-04-11 17:45:00","spatial":"SRID=4326;LINESTRING(114.35 39.28 4,114.36 39.28 4,114.35 39.29 4)","timeline":["2020-04-11 17:42:30","2020-04-11 17:43:30","2020-04-11 17:45:00"],"attributes":{"leafcount":3,"intensity":{"type":"integer","length":4,"nullable":true,"value":[80,30,50]}}}}'::trajectory q) SELECT ST_lcsDistance(traj, q, 500), trajectory_table.* FROM trajectory_table, query WHERE traj && ST_ExpandTemporal(ST_ExpandSpatial(ST_MakeBox(q), 500/110000), 3600) ORDER BY ST_lcsDistance(traj, q, 500);
說明由于對軌跡調(diào)用ST_Buffer函數(shù)時無法使用traj列的索引,因此必須擴(kuò)展q,將q的外包框擴(kuò)大相應(yīng)距離。
由于軌跡使用經(jīng)緯度坐標(biāo),需要先將500米轉(zhuǎn)為經(jīng)緯度范圍,一經(jīng)緯度大約110km。一小時為3600秒。
常用外包框相交算子:
算子 | 說明 |
&& | 兩個對象的外包框在二維(x,y)上相交。 |
&/& | 兩個對象的外包框在三維(x,y,z)上相交。 |
&#& | 兩個對象的外包框在二維(x,y)和時間(t)上相交。 |
&/#& | 兩個對象的外包框在三維(x,y,z)和時間(t)上相交。 |
外包框算子支持軌跡類型(Trajectory)、幾何類型(Geometry)、外包框類型(BoxNDF)之間的運(yùn)算。
使用算子時,可以自動應(yīng)用之前創(chuàng)建的索引。例如如果在traj_col列上建立了索引,則使用traj_col && ST_MakeEnvelope(0,0,1,1)
時,就可以使用索引加速查詢。
在traj_col上進(jìn)行了其它操作,如ST_Buffer(traj_col),ST_Buffer(traj_col)&&ST_MakeEnvelope(0,0,1,1)
將無法使用索引。