不用三角函数求点到线段距离的算法解决思路

不用三角函数求点到线段距离的算法
自己想出来的,可能很多人已经会用,但希望对某些朋友有帮助。




C/C++ code

double GetPointDistance(CPoint p1, CPoint p2) 
{
 return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
float GetNearestDistance(CPoint PA, CPoint PB, CPoint P3)
{

//----------图2--------------------
 float a,b,c;
 a=GetPointDistance(PB,P3);
 if(a<=0.00001)
  return 0.0f;
 b=GetPointDistance(PA,P3);
 if(b<=0.00001)
  return 0.0f;
 c=GetPointDistance(PA,PB);
 if(c<=0.00001)
  return a;//如果PA和PB坐标相同,则退出函数,并返回距离
//------------------------------

 
 if(a*a>=b*b+c*c)//--------图3--------
  return b;
 if(b*b>=a*a+c*c)//--------图4-------
  return a;

 

//图1
 float l=(a+b+c)/2;     //周长的一半
 float s=sqrt(l*(l-a)*(l-b)*(l-c));  //海伦公式求面积
 return 2*s/c;
}





------解决方案--------------------
其实也可以直接用公式做啊.点到直线做垂线,再判断交点在不在线段上,不在的话再判断该点跟线段的两个端点的距离即可,在的话就算交点到该点的长度.(要注意除数为0的情况)
------解决方案--------------------
不用这么麻烦吧,使用点到直线的距离公式不就行了。
d=[A*x+B*y+C的绝对值]/[(A^2+B^2)的算术平方根]。
------解决方案--------------------
这个用海伦公式 需要用4次开方.

如果用点到直线距离公式只需要用1次开方.

速度差距不是一点两点.


数学学得太死板了.
------解决方案--------------------
原则上应该只需要一次开方,这个算法效率太低了。
数学上简化一下,贴下我随手写的算法
C/C++ code
float GetNearestDistance(CPoint PA, CPoint PB, CPoint P3)
{
    CPoint p1,p2;
    ASSERT(PA!=PB);//两点相等的话就不存在直线,没有意义
    p1 = PA-P3;//二维空间平移,p3成为原点
    p2 = PB-P3;
    float x,y,dis;  
    if (p1.y == p2.y)
    {
        dis = p1.y;
    }
    else if (p1.x == p2.x)
    {
        dis = p1.x;
    }
    else
    {     //计算直线与x轴y轴的交点
        x = (p2.x-p1.x)/(p1.y-p2.y)+p1.y;
        y = (p2.y-p1.y)/(p1.x-p2.x)+p1.x;
        float p1p2 = sqrt(x*x+y*y);
        if (p1p2<0.00001)
        {
            dis = 0;
        }
        else
        {
            dis = x*y/p1p2;
        }
    }
    return abs(dis);
}

------解决方案--------------------
这样做精度会有损失吧。
个人觉得不应该多算两点距离
比如判断点P是否在线段AB上
可以用斜率相等(K(AP) == K(AB)),而且可以转成乘积相减不用除。
也可以用|PA|+|PB| == |AB|,但觉得还是没有上面效率高。
------解决方案--------------------
效率太低了,向量才是王道,三点坐标(x0,y0)(x1,y1)(x2,y2),面积=((x1-x0)*(y2-y0)-(x2-x0)*(y1-y0))/2