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

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

                                                                           若是您以爲本文確實幫助了您,能夠微信掃一掃,進行小額的打賞和鼓勵,謝謝 ^_^

                                    

相關文章
相關標籤/搜索