判断两条轨迹是否重合的思路(存储过程描述)

文章版权由做者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/算法

1.背景

假设有两条轨迹,一条是预约轨迹,一条是实际轨迹,分别为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

2.不考虑方向性的算法实现

2.1进一步简化问题

这里,首先咱们将问题进一步简化,即如何判断一个点是否落在两个点组成的线的容差范围内,距离描述为:a点、b点两个计划点,c点为实际点,如今要判断c点是否在a点和b点链接成的直线的容差范围内。设计

2.2解决简化问题的思路

我将解决步骤分为三步。分别为: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。

2.3实现判断点是否在线范围内(使用存储过程)

利用海伦公式求点到线段的距离。

传递的参数中。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;

2.4实现整个流程

先查询获得整个预约线路的坐标,再查询出须要判断的点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; 

 

3.考虑方向性的算法的实现

若是轨迹的对比还考虑方向性,即线路a-b-c-d与线路a-c-b-d是不一样,其实,此时只须要用一个变量来标记每一次吻合时,数组已经对比到的地方,下次对比时应该从标记处开始后推就能实现方向性问题了。

 

                                                                           -----欢迎转载,但保留版权,请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/

                                                                           若是您以为本文确实帮助了您,能够微信扫一扫,进行小额的打赏和鼓励,谢谢 ^_^

                                    

相关文章
相关标签/搜索