点、线、面之间最短距离求法

该文介绍了几种几何计算问题的解决方案,包括通过两点定义的直线上的点到给定点的最短距离算法,点到平面的最小距离计算,二维空间中两线段的交点判断,以及三维空间中两条直线的最短距离计算。这些算法在图形学、游戏开发和几何建模等领域有广泛应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、点到线最短距离

通过两个点P1(x1,y1)和P2(x2,y2)定义的直线方程为:P=P1 + u(P2-P1)。

 点P3(x3,y3),离线段P最短距离,即(P3-P)dot(P2-P1)=0

代入直线方程:[P3-P1-u(P2-P1)] dot (P2-P1) = 0

得到u:

 则:最短距离相交的(x,y):
                x = x1 + u(x2-x1)

                y = y1 + u(y2-y1)

 public static double distanceToSegment(Point2D p1, Point2D p2, Point2D p3) {

	final double xDelta = p2.getX() - p1.getX();
	final double yDelta = p2.getY() - p1.getY();

	if ((xDelta == 0) && (yDelta == 0)) {
	    throw new IllegalArgumentException("p1 和p2 不能同一个点");
	}

	final double u = ((p3.getX() - p1.getX()) * xDelta + (p3.getY() - p1.getY()) * yDelta) / (xDelta * xDelta + yDelta * yDelta);

	final Point2D closestPoint;
	if (u < 0) {
	    closestPoint = p1;
	} else if (u > 1) {
	    closestPoint = p2;
	} else {
	    closestPoint = new Point2D.Double(p1.getX() + u * xDelta, p1.getY() + u * yDelta);
	}

	return closestPoint.distance(p3);
    }

2、点到平面最小距离

设点Pa = (xa,ya,za)。Pa到平面法线的投影。即最短距离

3、二维两线段的交点

 两直线方程为  :Pa = P1 + Ua(P2-P1), Pb = P3 + Ub(P4 - P3)

求解 Pa = Pb  得:

x1 + Ua (x2-x1) = x3 + Ub (x4-x3)  和   y1 + Ua(y2-y1) = y3 +Ub (y4-y3) 

Ua和Ub 分别为:


 

 则交点(x, y)为:x = x1 + Ua (x2-x1),y = y1 + Ua(y2-y1)

 public static bool DoLinesIntersect(Line L1, Line L2, ref Point ptIntersection)
      {      
         double d =
            (L2.Y2 - L2.Y1) * (L1.X2 - L1.X1)
            -
            (L2.X2 - L2.X1) * (L1.Y2 - L1.Y1);

         //n_a and n_b are calculated as seperate values for readability
         double n_a =
            (L2.X2 - L2.X1) * (L1.Y1 - L2.Y1)
            -
            (L2.Y2 - L2.Y1) * (L1.X1 - L2.X1);

         double n_b =
            (L1.X2 - L1.X1) * (L1.Y1 - L2.Y1)
            -
            (L1.Y2 - L1.Y1) * (L1.X1 - L2.X1);

        
         if (d == 0)
            return false;

         double ua = n_a / d;
         double ub = n_b / d;
        
         if (ua >= 0d && ua <= 1d && ub >= 0d && ub <= 1d)
         {
            ptIntersection.X = L1.X1 + (ua * (L1.X2 - L1.X1));
            ptIntersection.Y = L1.Y1 + (ua * (L1.Y2 - L1.Y1));
            return true;
         }
         return false;
      }

4、 3D中两条直线最短距离

 P a = P 1 + mua (P2 - P1),P b = P 3 + mub (P4 - P3)

则:(Pa - Pb) dot (P2 - P1) = 0,(Pa - Pb) dot (P4 - P3) = 0

即:( P1 - P3 + mua (P2 - P1) - mub (P4 - P3) ) dot (P2 - P1) = 0

( P1 - P3 + mua (P2 - P1) - mub (P4 - P3) ) dot (P4 - P3) = 0

public static bool CalculateLineLineIntersection(Vector3 line1Point1, Vector3 line1Point2, 
	Vector3 line2Point1, Vector3 line2Point2, out Vector3 resultSegmentPoint1, out Vector3 resultSegmentPoint2)
{

   resultSegmentPoint1 = Vector3.Empty;
   resultSegmentPoint2 = Vector3.Empty;
 
   Vector3 p1 = line1Point1;
   Vector3 p2 = line1Point2;
   Vector3 p3 = line2Point1;
   Vector3 p4 = line2Point2;
   Vector3 p13 = p1 - p3;
   Vector3 p43 = p4 - p3;
 
   if (p43.LengthSq() < Math.Epsilon) {
      return false;
   }
   Vector3 p21 = p2 - p1;
   if (p21.LengthSq() < Math.Epsilon) {
      return false;
   }
 
   double d1343 = p13.X * (double)p43.X + (double)p13.Y * p43.Y + (double)p13.Z * p43.Z;
   double d4321 = p43.X * (double)p21.X + (double)p43.Y * p21.Y + (double)p43.Z * p21.Z;
   double d1321 = p13.X * (double)p21.X + (double)p13.Y * p21.Y + (double)p13.Z * p21.Z;
   double d4343 = p43.X * (double)p43.X + (double)p43.Y * p43.Y + (double)p43.Z * p43.Z;
   double d2121 = p21.X * (double)p21.X + (double)p21.Y * p21.Y + (double)p21.Z * p21.Z;
 
   double denom = d2121 * d4343 - d4321 * d4321;
   if (Math.Abs(denom) < Math.Epsilon) {
      return false;
   }
   double numer = d1343 * d4321 - d1321 * d4343;
 
   double mua = numer / denom;
   double mub = (d1343 + d4321 * (mua)) / d4343;
 
   resultSegmentPoint1.X = (float)(p1.X + mua * p21.X);
   resultSegmentPoint1.Y = (float)(p1.Y + mua * p21.Y);
   resultSegmentPoint1.Z = (float)(p1.Z + mua * p21.Z);
   resultSegmentPoint2.X = (float)(p3.X + mub * p43.X);
   resultSegmentPoint2.Y = (float)(p3.Y + mub * p43.Y);
   resultSegmentPoint2.Z = (float)(p3.Z + mub * p43.Z);

   return true;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值