判斷兩條軌跡是否重合的思路(存儲過程描述)


文章版權由作者李曉暉和博客園共有,若轉載請於明顯處標明出處: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/

                                                                           如果您覺得本文確實幫助了您,可以微信掃一掃,進行小額的打賞和鼓勵,謝謝 ^_^

                                    

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM