文章版权由做者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/。算法
假设有两条轨迹,一条是预约轨迹,一条是实际轨迹,分别为L一、L2。L1由点(A一、A二、A三、...、AN)组成,L2由(B一、B二、B三、…、BM)组成。如今给出了一个容差范围,即L2上的点能与L1这条预约路线的垂直容差范围Range,求L2上知足要求的实际点。数据库
这个需求咱们实际能够分为两种状况来考虑,一种是此需求单纯的仅仅是要求获得与L1能有必定匹配度的点。可是,若是咱们深刻分析,会发现L1做为一条线,其自己是有方向性的,若是咱们还将线的方向性考虑进来,即L2的点不只要在与L1的Range范围内,还要此时的点的前进趋势与L1是相同的。数组
固然,咱们经过AGS或者GeoServer之类的NA服务是能够实现最邻路径生成的方法的,这个方法咱们留在个人从底层谈WebGIS的设计实现系列中跟你们一块儿探讨。这里我要跟你们讨论一种效率更高的方法,直接经过数据库的存储过程来实现。微信
我在上面提到的两种状况(不考虑方向性和考虑方向性),这二者是层层递进的。咱们首先考虑如何经过不考虑方向性来解决。而后再进一步探讨若是有方向性,咱们该用什么思路去实现。oop
这里,首先咱们将问题进一步简化,即如何判断一个点是否落在两个点组成的线的容差范围内,距离描述为:a点、b点两个计划点,c点为实际点,如今要判断c点是否在a点和b点链接成的直线的容差范围内。设计
我将解决步骤分为三步。分别为:1.粗略判断;2.判断是否落在线外;3.垂线判断。rest
详细过程即是:blog
A.粗略判断,c点和a点以及b点的连线是否在容差范围内,即ac或者bc是否在容差范围内。若是是,返回true。不然,进一步判断。get
B.判断c点是否在ab直线的外侧,即c点到ab的垂足在ab的延长线上(若是是这种状况,只给一个容差范围是很难肯定是否符合标准的,须要多个与容差有关的参数,好比水平容差和垂直容差等,为了简化,此种状况下,直接返回false)。若是垂足在ab上,则进行下一步。博客
C.算出c点到ab的垂线距离d。判断d是否在容差范围内,若是在,返回true;不然,返回false。
利用海伦公式求点到线段的距离。
传递的参数中。x0、y0、x一、y1为预约轨迹的两个坐标(P0,P1),x二、y2为第三个坐标(实际位置S)的坐标, fRange为比对距离,return 0 超出,return 1未超出。
function getNearestDistance(x0 in number,y0 in number,x1 in number,y1 in number,x2 in number,y2 in number,fRange in number := 1,distance out number) return integer is
fa number(15,3);
fb number(15,3);
fc number(15,3);
fl number(15,3);
fs number(15,3);
begin
fa := sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
fb := sqrt((x0-x2)*(x0-x2)+(y0-y2)*(y0-y2));
fc := sqrt((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1));
if fa < fRange then --当fa边长度小于警告距离时
distance := fa;
return 1;
end if;
if fb < fRange then --当fb边长度小于警告距离时
distance := fb;
return 1;
end if;
if fc < 0.01 then --当轨迹的两个坐标点重合时
return 0;
end if;
if(fa*fa>=fb*fb+fc*fc) then --P0处角度为(钝(直)角),垂足在外
distance := fb;
return 0;
end if;
if(fb*fb>=fa*fa+fc*fc) then – P1处角度为(钝(直)角),垂足在外
distance := fa;
return 0;
end if;
--利用海伦公式求垂直距离
fl := (fa+fb+fc)/2; --周长的一半
fs := sqrt(fl*(fl-fa)*(fl-fb)*(fl-fc)); --海伦公式求面积,也能够用矢量求
distance := 2*fs/fc;
if distance < fRance then
return 1;
end if;
return 0;
end;
先查询获得整个预约线路的坐标,再查询出须要判断的点S,遍历整个预约线路判断S是否在整个线路的某条线段的容差范围内。
再查询出实际线路中的第二个实际点,重复上面的过程。
第一个过程的实现以下:
isOutOfRanceErr := 1;
open rs2 for select a.X,a.Y,b.X,b.Y,c.预警距离 from 坐标点表 a, 坐标点表 b, 轨迹表 c where a.轨迹ID=b.轨迹ID and a.轨迹ID = c.轨迹ID and a.坐标ID+1=b.坐标ID order by a.轨迹ID,a.坐标ID;
loop
Fetch rs2 into fP0X,fP0Y,fP1X,fP1Y,fToleRance;
Exit when rs%Notfound;
dummy := getNearestDistance(fP0X,fP0Y,fP1X,fP1Y,fCoordinateX,fCoordinateY,fToleRance,fDistance);
if dummy = 1 then
isOutOfRanceErr := 0;
exit;
end if;
end loop;
close rs2;
若是轨迹的对比还考虑方向性,即线路a-b-c-d与线路a-c-b-d是不一样,其实,此时只须要用一个变量来标记每一次吻合时,数组已经对比到的地方,下次对比时应该从标记处开始后推就能实现方向性问题了。
-----欢迎转载,但保留版权,请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/
若是您以为本文确实帮助了您,能够微信扫一扫,进行小额的打赏和鼓励,谢谢 ^_^