星期三, 1月 20, 2010

求點到直線距離

好幾天沒寫部落格,剛好在某討論區看到C版本的點到線段距離的算法,趕快寫一篇PHP版本『點到直線』和『點到線段』的最短距離。這個方式是透過海倫公式求得面積之後,在透過面積 = 底 x 高 / 2的公式取得高(最短距離)。

問:在直角座標平面上 , P( - 4 , 3 ) 到直線 3x-4y=12 的距離為多少?

那麼,我們先找出在直線上的AB 任意兩點,把A(4,0),B (0,-3)和P( - 4 , 3 ) 連成一個三角形。





<?php
// 作標x,y 的 Value Object
class Point
{
    
public $x;
    
public $y;
}

// 取得兩點距離
class Distance
{
    
public static function get (Point $p1Point $p2)
    {
        return 
sqrt(($p1->$p2->x) * ($p1->$p2->x) + ($p1->$p2->y) * ($p1->$p2->y));
    }
}
// 點到直線距離
class NearestDistance
{
    
public static function get (Point $APoint $BPoint $P)
    {
        if (
$A == $P)  return 0// A 和 P 位置相同
        
if ($B == $P)  return 0// B 和 P 位置相同

        
$ap Distance::get($A$P); // A 到 P 的距離
        
$bp Distance::get($B$P); // B 到 P 的距離
        
$ab Distance::get($A$B); // A 到 B 的距離

        
if ($A == $B) return $ap// A 和 B 位置相同
 

        
$l = ($ap $bp $ab) / 2// 三邊周長的一半
        
$area sqrt($l * ($l $ap) * ($l $bp) * ($l $ab));  //求面積:海倫公式
        
return $area $ab// 面積 = 底 x 高 / 2  換言之  高 = 面積 * 2 / 底
    
}
}

$A = new Point();
$A->4;
$A->0;

$B = new Point();
$B->0;
$B->= -3;

$P = new Point();
$P->= -4;
$P->3;

$NearestDistance = new NearestDistance();
echo 
$NearestDistance->get($A$B$P);
// 7.2
?>


上面的程式碼中,是指直線,所以最短距離為垂直線段。若是求P到 AB兩點之線段最短距離的話,NearestDistance::get() 這個方法中,則必須加上額外的判斷:

if ($ap * $ap >= $bp * $bp + $ab * $ab) return $bp; // 大於 90 度
if ($bp * $bp >= $ap * $ap + $ab * $ab) return $ap; // 大於 90 度

當大於 90 度角,則取P點到A或B點兩條線最短的那條。

3 則留言:

我的意見