点到线段距离(向量 delphi)(zt)

在二维/三维图形学系统当中,线段的拾取是一个经常使用的功能

如何根据鼠标点来判断线段是否被选择了,最主要的方法之一是通过点到线段的最小距离来判定的

无论二维还是三维情况下,使用点到直线的距离公式似乎是最直接的选择

但是不要忘记点到直线公式计算的是点和直线之间的关系,而不是点和线段之间的关系

需要额外的判断,点在线段上的投影点是否位于线段内部,是才可以采用点到直线的公式,否则就不能

算法如下

class Point

float Distance(Point p1, Point p2); // 返回两点之间的距离

float DistanceLine(Point a, Point b, Point c) // a和b是线段的两个端点, c是检测点

{

       Point ab = b - a;

      Point ac = c-a;

      float f = ab * ac;//向量点乘

      if (f<0) return Distance(a, c);

      float d = ab * ab;

     if ( f>d) return Distance(a, c);

    f = f/d;

     Point D = a + f *ab;   // c在ab线段上的投影点

    return Distance(a, D);

}

这个算法计算量很少,在现在流行配置的计算机基本上在当中1秒钟可以检测出上百万个线段

这个是检测一个点和一个线段之间的最短距离的

对于一个系统当中存在大量的线段需要检测的时候,应该把线段按照区域划分成组,建立一个包围盒

先检测点是否在包围盒内部,然后再进入组内检测具体的线段。

///

c语言版

用点乘求点到线段的距离
2007年09月12日 星期三 10:33

//网上搜的一个算法,自己改了改。激动的是终于看到了点乘的用途。

#include <cstdio>
#include <cmath>

struct POINT
{
double x,y;
void Offset(POINT A) //相对A偏移
{
   x=x+A.x;
   y=y+A.y;
}
POINT   operator - ( POINT &A )
{
   POINT X;
   X.x = x-A.x;
   X.y = y-A.y;
   return X;
}
};

double Dist(POINT A, POINT B,bool sqr=1)
{
     double x = A.x - B.x;
     double y = A.y - B.y;
if(sqr)
   return sqrt(x*x+y*y);
else
   return x*x + y*y;
}

double Pnt2SegmentDist(POINT A, POINT B, POINT C)
{
     POINT AB = B - A; //向量AB
     POINT AC = C - A;
     double r = AB.x * AC.x + AB.y * AC.y;//AB与AC的点乘积
     r /= Dist(A,B,0);//AC在AB上的投影比上AB。调用Dist(),不开方

     //若C的投影在AB外
     if(r < 0)
         return Dist(A, C);//调用Dist(),开方
     if(r > 1)
         return Dist(B, C);

     //若C的投影在AB之间
     POINT D = AB;
     D.x *= r;
     D.y *= r;//因为AB是向量,所以可以这样做。得到AC在AB上的投影向量。
     D.Offset(A);//点D的绝对坐标
     return Dist(C, D);
}


int main()
{
// freopen("a.txt","r",stdin);
POINT A,B,C;
while(scanf("%lf%lf%lf%lf%lf%lf",&A.x,&A.y,&B.x,&B.y,&C.x,&C.y)!=EOF)
{
   printf("%lf/n",Pnt2LineDist(A,B,C));
}
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值