若是直接写个“高大上”的定义结果每每是一脸懵逼的,也不知道为何要定义这么一个概念。其实线性参考技术在咱们生活中是很是常见的,好比打开高德,百度地图的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 來源:简书 简书著做权归做者全部,任何形式的转载都请联系做者得到受权并注明出处。