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

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

1.背景

假设有两条轨迹,一条是预定轨迹,一条是实际轨迹,分别为L1、L2。L1由点(A1、A2、A3、...、AN)组成,L2由(B1、B2、B3、…、BM)组成。现在给出了一个容差范围,即L2上的点能与L1这条预定路线的垂直容差范围Range,求L2上满足要求的实际点。

这个需求我们实际可以分为两种情况来考虑,一种是此需求单纯的仅仅是要求得到与L1能有一定匹配度的点。但是,如果我们深入分析,会发现L1作为一条线,其本身是有方向性的,如果我们还将线的方向性考虑进来,即L2的点不仅要在与L1的Range范围内,还要此时的点的前进趋势与L1是相同的。

当然,我们通过AGS或者GeoServer之类的NA服务是可以实现最邻路径生成的方法的,这个方法我们留在我的从底层谈WebGIS的设计实现系列中跟大家一起探讨。这里我要跟大家讨论一种效率更高的方法,直接通过数据库的存储过程来实现。

我在上面提到的两种情况(不考虑方向性和考虑方向性),这两者是层层递进的。我们首先考虑如何通过不考虑方向性来解决。然后再进一步探讨如果有方向性,我们该用什么思路去实现。

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

2.1进一步简化问题

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

2.2解决简化问题的思路

我将解决步骤分为三步。分别为:1.粗略判断;2.判断是否落在线外;3.垂线判断。

详细过程便是:

A.粗略判断,c点和a点以及b点的连线是否在容差范围内,即ac或者bc是否在容差范围内。如果是,返回true。否则,进一步判断。

B.判断c点是否在ab直线的外侧,即c点到ab的垂足在ab的延长线上(如果是这种情况,只给一个容差范围是很难确定是否符合标准的,需要多个与容差有关的参数,比如水平容差和垂直容差等,为了简化,此种情况下,直接返回false)。如果垂足在ab上,则进行下一步。

C.算出c点到ab的垂线距离d。判断d是否在容差范围内,如果在,返回true;否则,返回false。

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

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

传递的参数中。x0、y0、x1、y1为预定轨迹的两个坐标(P0,P1),x2、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/

                                                                           如果您觉得本文确实帮助了您,可以微信扫一扫,进行小额的打赏和鼓励,谢谢 ^_^

                                    

 

时间: 2024-10-26 12:55:23

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

select-在两个应用,两条连接的情况下mysql存储过程是否是同步的执行的?

问题描述 在两个应用,两条连接的情况下mysql存储过程是否是同步的执行的? CREATE DEFINER = `root`@`%` PROCEDURE `NewProc`() begin drop table if exists tem_request; create temporary table tem_request select RequestID,SaleCycleID,StationID from s_betrequest where requestStatus = 0 limit

javascript判断两个IP地址是否在同一个网段的实现思路_javascript技巧

1)基本思路: 要判断两个IP地址是否在同一个网段,将它们的IP地址分别与子网掩码做与运算,得到的结果为网络号,如果网络号相同,就在同一子网,否则,不在同一子网. 2)具体实现: 复制代码 代码如下: /** * [isEqualIPAddress 判断两个IP地址是否在同一个网段] * @param {[String]} addr1 [地址一] * @param {[String]} addr2 [地址二] * @param {[String]} mask [子网掩码] * @return {

IOS开发:Unity3D根据动态的两个轨迹点绘制面详解

 开发:Unity3D根据动态的两个轨迹点绘制面详解-"> 暂时我们先忽略Z轴(这样在平面中看得更清楚),假设Z轴坐标都为0.假设游戏中有两个轨迹点在动态的增加与改变,最后将这两个点改变的轨迹拼接起来就是它们生成的面.如上图所示,第一个点的轨迹是" 3,4,5,6,7" 第二个点的轨迹是"2,1,10,9,8" .这两个点的长度是可变的,前提是他们两个的数量必需完全一样.接着,如下图所示,我们将这些点两两相连起来,目前一共形成了8个三角形面(可根据两

控件界面-ScrollerNumberPicker 默认显示时 两条均被选中

问题描述 ScrollerNumberPicker 默认显示时 两条均被选中 默认显示是这种效果: 怎样让它固定显示选中一条啊? 这个 SrollerNumberPicker.java 是从网上找的 控件类 ,代码可能有点多,我贴到下面,希望大神能帮忙看看... 解决方案 自己解决掉了,原因是onMesure里根据父控件获取宽高,高度这样设置就不会再有这个问题: itemNumber * unitHeight 解决方案二: public class ScrollerNumberPicker ex

编程-Java 三目运算符 判断两个对象是否为空

问题描述 Java 三目运算符 判断两个对象是否为空 //住院非空,对住院进行处理,住院不为空,判断门诊是否为非空,对门诊进行处理 //zyyzjymx!=null?f1(zyyzjymx):mzzdjymx!=null?f1(mzzdjymx):null; 不会写代码... 思路如上 求大神解决~ 解决方案 zyyzjymx!=null?(f1(zyyzjymx)):(mzzdjymx!=null?f1(mzzdjymx):null); 解决方案二: 你的条件写错了吧?住院非空和住院不为空 不

拷贝-求代码 用C++控制台 写判断两个文档是否一样,不一样,进行覆盖。

问题描述 求代码 用C++控制台 写判断两个文档是否一样,不一样,进行覆盖. 求代码 用C++控制台 写判断两个文档是否一样,不一样,进行覆盖. 要求打开文件后,在内存中比较 ,谢谢大神 解决方案 提供个思路,随便搜一搜就能解决的,计算文档的md5,如果完全一致,那就一样,不一致,直接覆盖好了 解决方案二: #include <stdio.h> #include <stdlib.h> void main() { FILE *fp1,*fp2; char fn1[]="t1

c#利用webservice和wcf对oracle数据库增删改查,并判断两种方法的效率

问题描述 c#利用webservice和wcf对oracle数据库增删改查,并判断两种方法的效率 初学者,以前没有接触过webservice和wcf.现在遇到一个这样的项目,请大家给予帮助,提供源码,思路都行.当然,最好是代码了,亲,帮一个忙呗~ 解决方案 ws相对简单,WCF就是一把大牛刀,虽然很好,但是你要是杀鸡就得不偿失了.你是了解MVC的话,通信可以试试WebAPI.例子网上到处都是的

C++将二叉树转为双向链表及判断两个链表是否相交_C 语言

把二叉查找树转变成排序的双向链表例如: 转换成双向链表 4=6=8=10=12=14=16 struct BSTreeNode { int m_nValue; // value of node BSTreeNode *m_pLeft; // left child of node BSTreeNode *m_pRight; // right child of node }; 首先阐述下二叉排序树: 它首先要是一棵二元树,在这基础上它或者是一棵空树:或者是具有下列性质的二元树: (1)若左子树不空,

钱明:软件定义存储,要学会“两条腿走路”

今年8月,钱明先生正式出任凯翔科技代理CEO,主持业务运营.8月2日,钱明先生接受了记者的专访. 钱明:软件定义存储,要学会"两条腿走路" 软件定义存储和超融合 谈到市场的判断,钱明先生指出,从大的概念来说,云存储.软件定义存储和超融合都是采用分布式存储的架构,都具有Scale Out特征,但在特点上还是不尽相同. "云存储是一个更加笼统的概念,包括软件定义存储和超融合存储,尽管都采用x86服务器,但侧重点有所不同."钱明说. 钱明表示:很多时候,国内将云存储.软件