3种求点到线段最短距离的算法
来源:互联网 发布:淘宝网二手家具沙发 编辑:程序博客网 时间:2024/05/02 02:34
3种求点到线段最短距离的算法 [原]
(2006-08-05 13:31:00)http://blog.sina.com.cn/s/blog_4dacef8501000foz.html
前段时间做东西的时候,因为要用鼠标拾取线段,涉及到了求一个点到线段最短距离的算法问题。在网上找了半天,主要提供了两种算法,一种是经典型的,直接用高中的几何知道求,当然算法也巨复杂,要是用几万条线段的话可能计算起来够呛;另一种用矢量的方法,算法很简略,但是如果高数学得不好可能很难理解。后来我想能不能找一种又省时又易懂的算法,自己想了半天,竟然给我想到了一种,算法比矢量的还快,并且相当易懂~
下面把这3种算法贴出来,大家以后要是遇到这种问题可以参考一下:
//小虫原创,转载请说明出处:yjukh.blogcn.com
1.经典算法:
////////////////////////////////////////////////////////////////
//
//方法名:PointSegment
//方法说明:求一点到一线段距离
//参数:x1, y1,x2, y2 线段两端点坐标
//x, y 所求点坐标
//返回值:dbLength 两点间距
//
////////////////////////////////////////////////////////////////
doublePointSegment(const double x1, const double y1,const double x2,
constdouble y2, const double x, const double y)
{
doubledbLen1,dbLen2, dbLen3;
doubledbAng,dbAng1, dbAng2;
dbLen1= Distance(x, y, x1, y1);
if(EQ(0.0, dbLen1))
return0.0;
dbLen2= Distance(x, y, x2, y2);
if(EQ(0.0, dbLen2))
return0.0;
dbLen3=Distance(x1, y1, x2, y2);
if(EQ(0.0, dbLen3))
returndbLen1;
if(dbLen1 < dbLen2)
{
if(EQ(y1, y2))
{
if(x1 < x2)
dbAng1= 0.0;
else
dbAng1= PI;
}
else
{
dbAng1= acos((x2 - x1) / dbLen3);
if(y1 > y2)
dbAng1= 2 * PI - dbAng1;
}
dbAng2= acos((x - x1) / dbLen1);
if(y1 > y) dbAng2 = 2 * PI - dbAng2;
dbAng= dbAng2 - dbAng1;
if(dbAng < 0.0)
dbAng= - dbAng;
if(dbAng > PI)
dbAng= 2 * PI - dbAng;
if(dbAng > PI / 2)
returndbLen1;
elsereturn (dbLen1 * sin(dbAng));
}//小虫原创,转载请说明出处:yjukh.blogcn.com
else
{
if(EQ(y1, y2))
{
if(x1 < x2)
dbAng1= PI;
else
dbAng1= 0.0;
}
else
{
dbAng1= acos((x1 - x2) / dbLen3);
if(y2 > y1)
dbAng1= 2 * PI - dbAng1;
}
dbAng2= acos((x - x2) / dbLen2);
if(y2 > y)
dbAng2= 2 * PI - dbAng2;
dbAng= dbAng2 - dbAng1;
if(dbAng < 0.0)
dbAng= - dbAng;
if(dbAng > PI)
dbAng= 2 * PI - dbAng;
if(dbAng > PI / 2)
returndbLen2;
else
return(dbLen2 * sin(dbAng));
}
}
这种算法是直接用解析几何求的,光从程序上看就可以知道很复杂,所以不推荐。
2.矢量算法:
floatDistance(Point p1, Point p2) // 返回两点之间的距离
{
return (float)sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
floatDistanceLine(Point a, Point b, Point c) // a和b是线段的两个端点, c是检测点
{
Pointab = b - a;
Pointac = c-a;
floatf = ab * ac;
if(f<0) return Distance(a, c);
下面把这3种算法贴出来,大家以后要是遇到这种问题可以参考一下:
//小虫原创,转载请说明出处:yjukh.blogcn.com
1.经典算法:
////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////
double
const
{
doubledbLen1,
doubledbAng,
dbLen1
if
return
dbLen2
if
return
dbLen3=
if
return
if
{
if
{
if
dbAng1
else
dbAng1
}
else
{
dbAng1
if
dbAng1
}
dbAng2
if
dbAng
if
dbAng
if
dbAng
if
return
else
}//小虫原创,转载请说明出处:yjukh.blogcn.com
else
{
if
{
if
dbAng1
else
dbAng1
}
else
{
dbAng1
if
dbAng1
}
dbAng2
if
dbAng2
dbAng
if
dbAng
if
dbAng
if
return
else
return
}
}
这种算法是直接用解析几何求的,光从程序上看就可以知道很复杂,所以不推荐。
2.矢量算法:
float
{
}
float
{
Point
Point
float
if