點到線段最短距離的運算與點到直線的最短距離的運算二者之間存在一定的差別题暖,即求點到線段最短距離時需要考慮參考點在沿線段方向的投影點是否在線段上找蜜,若在線段上才可采用點到直線距離公式谷暮,如圖1所示蔗喂。
圖1(a)最短距離為點P與其在線段AB上投影C之間的線段PC
(b)最短距離為點P與端點B(或A)所構成的線段PB(或PA)
具體算法主要有以下三種:
該算法直接用高中時所學習到的解析幾何知識對點到線段的距離進行求解缚俏。其基本思想是先判斷點在線段端點绵疲、點在線上等等的特殊情況答毫,逐步的由特殊到一般呛伴,當忽略點在線段上的特殊情況時勃痴,判斷點到線段方向的垂線是否落在線段上的方法是通過比較橫縱坐標的方式來判斷,最后把不同的判斷情況用不同的幾何方式來進行處理計算得出結果热康。
由上面敘述的基本思路可以知道這種算法雖然很容易理解和接受沛申,但從算法的實用性的角度分析還是有很大的缺點的,首先是算法復雜姐军,計算量巨大铁材,大量的比較判斷、距離計算庶弃、角度計算等等衫贬,實際應用中往往是需要求由大量線段組成的折線到某點的最短距離,如此用這樣的算法計算量是不能想象的歇攻。其次經典算法中使用的一些簡化運算的函數不利于語言的重新包裝固惯,如果想換編程語言的話,就比較麻煩了缴守。
該方法主要是先判斷投影點是否在線段上,投影點在線段延長線上時屡穗,最短距離長度為點到端點的線段長度贴捡;當投影點在線段上時,先使用海倫公式計算三角形面積村砂,再計算出三角形的高烂斋,即為最短距離。
運用面積算法求解點到線段最短距離思路很清晰础废,也很容易理解汛骂。從效率方面考慮,比如需要多次計算平方评腺、根號帘瞭,這對于大量數據進行運算是負擔很重的。求面積就必須把三條邊長全部求出蒿讥,并且用到的海倫公式也需要進行開方運算蝶念,計算過程顯得繁瑣抛腕。
矢量算法過程清晰媒殉,如果具有一定的空間幾何基礎担敌,則是解決此類問題時應優(yōu)先考慮的方法。當需要計算的數據量很大時适袜,這種方式優(yōu)勢明顯柄错。
由于矢量具有方向性,故一些方向的判斷直接根據其正負號就可以得知苦酱,使得其中的一些問題得以很簡單的解決售貌。
用此方法考慮,我們只需要找到向量在
方向上的投影疫萤,具體如下:
上面的是方向上的單位向量颂跨,其意義是給所求向量確定方向。是的兩個向量的內積扯饶,且恒削,其中θ為向量AP與AB之間的夾角。是向量長度尾序。
那么即為上圖中線段AC的長度值钓丰,不帶有方向性。此數值與上述表征方向的整體構成有大小每币、有方向的新向量携丁,即為在方向上的投影向量,C為投影點兰怠。
根據得到的梦鉴,由向量的方向性可知:如果情況是上圖(a)所示,那么0<r<1揭保,;如果是如圖(b)所示的情況肥橙,那么r>=1,;如果是如圖(c)所示的情況,那么得到r≤0;
特殊情況如點在線段上秸侣、點在端點存筏、點在線段延長線上等等的情況全部適用于此公式,只是作為特殊情況出現(xiàn)味榛,無需另作討論方篮。這也是矢量算法思想的優(yōu)勢所在。
故根據r值的不同励负,最短距離
C#代碼為:
publicstaticdoublePointToSegDist(doublex,doubley,doublex1,doubley1,doublex2,doubley2)
{
doublecross?=?(x2?-?x1)?*?(x?-?x1)?+?(y2?-?y1)?*?(y?-?y1);
if(cross?<=?0)returnMath.Sqrt((x?-?x1)?*?(x?-?x1)?+?(y?-?y1)?*?(y?-?y1));
doubled2?=?(x2?-?x1)?*?(x2?-?x1)?+?(y2?-?y1)?*?(y2?-?y1);
if(cross?>=?d2)returnMath.Sqrt((x?-?x2)?*?(x?-?x2)?+?(y?-?y2)?*?(y?-?y2));
doubler?=?cross?/?d2;
doublepx?=?x1?+?(x2?-?x1)?*?r;
doublepy?=?y1?+?(y2?-?y1)?*?r;
returnMath.Sqrt((x?-?px)?*?(x?-?px)?+?(py?-?y1)?*?(py?-?y1));
}
后記:編程考驗的不光是寫代碼的能力,更多的是對一個問題的優(yōu)質解決方法匕得,點到線段最短距離的求解继榆,在數學上可能就是一個公式的問題巾表,編程是深究起來卻有如此巧妙的解決方法,記錄本文方法略吨,更多的是對以后學習的一個啟發(fā)集币!
return?Math.Sqrt((x-px)*(x-px)+(py-y)*(py-y))