若是直接寫個「高大上」的定義結果每每是一臉懵逼的,也不知道爲何要定義這麼一個概念。其實線性參考技術在咱們生活中是很是常見的,好比打開高德,百度地圖的App,查看實時路況,道路被不一樣路況的顏色動態分段顯示了;高速中發生交通事故,電視廣播中經常對地點描述爲「距離xx高速入口xx千米處」,地圖是能很是精確的定位到這個地點的。生活中的兩個例子的說明,其實他們的規律都是針對圖形數據爲線(LineString)的一種GIS應用。
線性參考必定要有線,線上必定要有權重值(也叫測量值M),上一段路況的測量值M就是路段上的傳感器發送回來的車流通行速度,交通事故的測量值就是道路的實際距離。不一樣的測量值能作不一樣的事,以下圖所示:html
不一樣權重值.pngnode
在不改變道路數據前提下,使用不一樣的維度(測量值M),分段展現不一樣的業務場景。sql
轉回嚴肅的工程技術範疇,我我的對線性參考總結包括如下幾個要素:數據庫
沿線距離.pngide
以PostGIS2.4.0版本說明,經過查看API,能夠發現對線性參考核心三要素是所有支持的,本章節具體闡述。函數
PostGIS支持LineString,MultiLineString類型,能夠將路網,河網,電網等各類LineString數據導入數據庫。徹底支持。oop
ST_AddMeasure:用於對線性數添加測量值。
函數定義:post
geometry ST_AddMeasure(geometry geom_mline, float8 measure_start, float8 measure_end);
參數說明:傳入一個線圖形,設置其起點測量值,終點測量值,返回一個創建了測量值的圖形。
使用示例:測試
SELECT ST_AsText(ST_AddMeasure(ST_GeomFromText('LINESTRING(1 0, 2 0, 4 0)'),10,40)) As ewelev;; ewelev ---------------------------------------- LINESTRINGM(1 0 10,2 0 20,4 0 40)
PostGIS提供了ST_LocateBetween與ST_LocateBetweenElevations方式對帶測量值的線進行動態分段提取,其中ST_LocateBetweenElevations是支持三維,四維數據的,簡單的就以ST_LocateBetween(這個是用於對二維進行動態分段的)函數說明。
ST_LocateBetween:二維線動態分段函數。
函數定義:ui
geometry ST_LocateBetween(geometry geomA, float8 measure_start, float8 measure_end, float8 offset);
參數說明:傳入一個已創建測量值的線圖形,選擇一個起始測量M值與一個終點測量M值,返回測量值在這個區間內的動態截取線段圖形。
至於offset,看了官網說明,也不知道是幹嗎用的,請熟悉的朋友留言指點。
使用示例:
SELECT ST_AsText(the_geom) FROM (SELECT ST_LocateBetween( ST_GeomFromText('MULTILINESTRING M ((1 2 3, 3 4 2, 9 4 3), (1 2 3, 5 4 5))'),1.5, 3) As the_geom) As foo; ------------------------------------------------------------------------------------ GEOMETRYCOLLECTION M (LINESTRING M (1 2 3,3 4 2,9 4 3),POINT M (1 2 3))
草圖示意圖.png
要求截取M值在1.5到3之間的圖形,上圖中(1 2 3, 3 4 2, 9 4 3)都知足,(1 2 3, 5 4 5)只有起點知足,因此輸出結果符合預期。
ST_LocateAlong:事件定位函數,已知測量值,計算線性數據上的幾何定位。
函數定義:
geometry ST_LocateAlong(geometry ageom_with_measure, float8 a_measure, float8 offset);
參數說明:傳入一個已創建測量值的線圖形,任意設置一個測量M值,返回該M值對應在線性數據上的幾何位置。(如前文高速事故以這種事件點形式描述)。
使用說明:
SELECT ST_AsText((ST_Dump(the_geom)).geom) FROM (SELECT ST_LocateAlong( ST_GeomFromText('MULTILINESTRINGM((1 2 3, 3 4 2, 9 4 3), (1 2 3, 5 4 5))'),2.5) As the_geom) As foo; st_asewkt --------------- POINT M (2 3 2.5) POINT M (6 4 2.5)
草圖示意圖.png
ST_InterpolatePoint:與ST_LocateAlong函數相反,計算線性數據上任意一點位置的測量M值。
函數定義:
float8 ST_InterpolatePoint(geometry line, geometry point);
參數說明:輸入創建測量值M的line與已知線上的一點point,返回這個point點對應的測量值M的value。
使用說明:
SELECT ST_InterpolatePoint('LINESTRING M (0 0 0, 10 0 20)', 'POINT(5 5)'); st_interpolatepoint --------------------- 10
以上幾個函數,是線性參考應用場景中所必需的,主要解決如何給線性數據添加測量值,如何定位,如何反算,如何動態獲取。PostGIS線性參考章節剩餘幾個函數都是純圖形計算的。
ST_LineInterpolatePoint:geometry ST_LineInterpolatePoint(geometry a_linestring, float8 a_fraction)
說明:輸入LineString圖形與一個分割百分比數,返回LineString從起點到終點之間任意一個0-1之間的百分比數a_fraction所處的點圖形。
示例:
route=# select ST_AsText(ST_LineInterpolatePoint(ST_GeomFromText('LineString(0 0,10 10)'),0.5)); st_astext ------------ POINT(5 5) (1 行記錄) route=# select ST_AsText(ST_LineInterpolatePoint(ST_GeomFromText('LineString(0 0,10 10)'),0.3)); st_astext ------------ POINT(3 3) (1 行記錄)
ST_LineLocatePoint: float8 ST_LineLocatePoint(geometry a_linestring, geometry a_point)
說明:輸入LineString圖形與線上任意一個Point(並不是線的node節點,而是這個點確定與線相交(intersects)),返回LineString從起點到終點之間任意一個0-1之間的百分比數a_fraction。
示例:
route=# select ST_LineLocatePoint(ST_GeomFromText('LineString(0 0,10 10)'),ST_GeomFromText('Point(5 5)')); st_linelocatepoint -------------------- 0.5 (1 行記錄)
ST_LineSubstring:geometry ST_LineSubstring(geometry a_linestring, float8 startfraction, float8 endfraction);
說明:輸入LineString圖形與起點停靠值s_f與終點停靠值e_f,返回停靠值之間的線段,若是s_f是0,e_f是1,結果就是完整的線的自己。
示例:
select ST_AsText(ST_LineSubstring(ST_GeomFromText('LINESTRING(0 0, 10 10)'),0.5,1)); ---------------------------------------------------- LINESTRING(5 5,10 10)
本章節我製做了一批測試數據模擬一些實際應用。場景模擬是:武漢軍運會重點保障線路之一的「武漢火車站--江夏運動員村「,相關部門爲了增強掌握道路通行狀況,在該條線路上安裝了不少rfid監控傳感設備,實時上傳該路段的道路通行速度。監管部門設置速度區間,如35-45區間路段是紅色,45-55區間路段顯示黃色,55-75區間路段是綠色。
rfid數據.png
道路與monitor圖形.png
數據處理步驟方案是:
如下數據處理腳本,根據監控點對路段進行了切割打斷,每個segment路段,起點終點都是一個傳感器的位置,在創建線性參考的時候,只須要把segment的起點終點測量值M設置爲對應的傳感器的speed便可。
do language plpgsql $$ DECLARE rec record; route_line geometry; initinfo boolean:=true; start_fraction float; end_fraction float; line geometry; speed_s numeric; speed_e numeric; BEGIN --提取出重點線路的圖形 select geom from routes limit 1 into route_line; initinfo:=true; for rec in select t1.gid,t1.speed,t1.geom from rfid_monitor t1 order by t1.gid loop if(initinfo=true) then initinfo:=false; --起點百分比 start_fraction:=ST_LineLocatePoint(route_line,rec.geom); end_fraction:=start_fraction; speed_s:=rec.speed; speed_e:=rec.speed; else speed_s:=speed_e; speed_e:=rec.speed; start_fraction:=end_fraction; end_fraction:=ST_LineLocatePoint(route_line,rec.geom); line:=ST_LineSubstring(route_line,start_fraction,end_fraction); --子路段提取,創建線性參考 insert into substring_road(seg,geom) values(rec.gid,ST_AddMeasure(line,speed_s,speed_e)); end if; end loop; end; $$;
查詢下子路段數據並可視化下:
創建測量值.png
到這這一步,數據都處理完了,都創建了M值了。應用系統根據配置,動態顯示就可使用了。
根據速度動態分段:
select ST_LocateBetween(geom,35,45) geom,'紅色' as color from substring_road union select ST_LocateBetween(geom,45,55) geom,'黃色' as color from substring_road union select ST_LocateBetween(geom,55,75) geom,'綠色' as color from substring_road;
查詢結果可視化以下:
動態分段渲染.png
[ArcGIS線性參考幫助文檔][1]
[1]: http://desktop.arcgis.com/zh-cn/arcmap/10.3/guide-books/linear-referencing/what-is-linear-referencing.htm
[PostGIS線性參考開發文檔][2]
[2]: http://postgis.net/docs/manual-2.4/reference.html#Linear_Referencing
做者:遙想公瑾當年 連接:https://www.jianshu.com/p/4916b85bea65 來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。