ToB企服应用市场:ToB评测及商务社交产业平台

标题: [CSharpTips]判断两条线段是否相交 [打印本页]

作者: 张国伟    时间: 2022-9-16 17:18
标题: [CSharpTips]判断两条线段是否相交
判断两条线段是否相交
主要用到了通过向量积的正负判断两个向量位置关系
向量a×向量b(×为向量叉乘),若结果小于0,表示向量b在向量a的顺时针方向;若结果大于0,表示向量b在向量a的逆时针方向;若等于0,表示向量a与向量b平行
主要代码参考自文末链接,但是他并没有给出跨立检验函数的具体内容,因此补充了一下放在下面
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Windows;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace lineTest
  8. {
  9.     class Program
  10.     {
  11.         public struct Point
  12.         {
  13.             public double X;
  14.             public double Y;
  15.             public Point(double x, double y)
  16.             {
  17.                 X = x;
  18.                 Y = y;
  19.             }
  20.         }
  21.         static void Main(string[] args)
  22.         {
  23.             Point a = new Point(0, 0);
  24.             Point b = new Point(100, 100);
  25.             Point c = new Point(100,0);
  26.             Point d = new Point(50,49);
  27.             var result = IsIntersect(a, b, c, d);
  28.         }
  29.         public static Point? GetIntersection(Point lineAStart, Point lineAEnd, Point lineBStart, Point lineBEnd)
  30.         {
  31.             double x1 = lineAStart.X, y1 = lineAStart.Y;
  32.             double x2 = lineAEnd.X, y2 = lineAEnd.Y;
  33.             double x3 = lineBStart.X, y3 = lineBStart.Y;
  34.             double x4 = lineBEnd.X, y4 = lineBEnd.Y;
  35.             //equations of the form x=c (two vertical lines)
  36.             if (x1 == x2 && x3 == x4 && x1 == x3)
  37.             {
  38.                 return null;
  39.             }
  40.             //equations of the form y=c (two horizontal lines)
  41.             if (y1 == y2 && y3 == y4 && y1 == y3)
  42.             {
  43.                 return null;
  44.             }
  45.             //equations of the form x=c (two vertical lines)
  46.             if (x1 == x2 && x3 == x4)
  47.             {
  48.                 return null;
  49.             }
  50.             //equations of the form y=c (two horizontal lines)
  51.             if (y1 == y2 && y3 == y4)
  52.             {
  53.                 return null;
  54.             }
  55.             double x, y;
  56.             if (x1 == x2)
  57.             {
  58.                 double m2 = (y4 - y3) / (x4 - x3);
  59.                 double c2 = -m2 * x3 + y3;
  60.                 x = x1;
  61.                 y = c2 + m2 * x1;
  62.             }
  63.             else if (x3 == x4)
  64.             {
  65.                 double m1 = (y2 - y1) / (x2 - x1);
  66.                 double c1 = -m1 * x1 + y1;
  67.                 x = x3;
  68.                 y = c1 + m1 * x3;
  69.             }
  70.             else
  71.             {
  72.                 //compute slope of line 1 (m1) and c2
  73.                 double m1 = (y2 - y1) / (x2 - x1);
  74.                 double c1 = -m1 * x1 + y1;
  75.                 //compute slope of line 2 (m2) and c2
  76.                 double m2 = (y4 - y3) / (x4 - x3);
  77.                 double c2 = -m2 * x3 + y3;
  78.                 x = (c1 - c2) / (m2 - m1);
  79.                 y = c2 + m2 * x;
  80.             }
  81.             if (IsInsideLine(lineAStart, lineAEnd, x, y) &&
  82.                 IsInsideLine(lineBStart, lineBEnd, x, y))
  83.             {
  84.                 return new Point(x, y);
  85.             }
  86.             //return default null (no intersection)
  87.             return null;
  88.         }
  89.         private static bool IsInsideLine(Point start, Point end, double x, double y)
  90.         {
  91.             return ((x >= start.X && x <= end.X)
  92.                 || (x >= end.Y && x <= start.Y))
  93.                 && ((y >= start.Y && y <= end.Y)
  94.                     || (y >= end.Y && y <= start.Y));
  95.         }
  96.         public static bool IsIntersect(Point p1, Point p2, Point q1, Point q2)
  97.         {
  98.             //排斥试验,判断p1p2在q1q2为对角线的矩形区之外
  99.             if (Math.Max(p1.X, p2.X) < Math.Min(q1.X, q2.X))
  100.             {//P1P2中最大的X比Q1Q2中的最小X还要小,说明P1P2在Q1Q2的最左点的左侧,不可能相交。
  101.                 return false;
  102.             }
  103.             if (Math.Min(p1.X, p2.X) > Math.Max(q1.X, q2.X))
  104.             {//P1P2中最小的X比Q1Q2中的最大X还要大,说明P1P2在Q1Q2的最右点的右侧,不可能相交。
  105.                 return false;
  106.             }
  107.             if (Math.Max(p1.Y, p2.Y) < Math.Min(q1.Y, q2.Y))
  108.             {//P1P2中最大的Y比Q1Q2中的最小Y还要小,说明P1P2在Q1Q2的最低点的下方,不可能相交。
  109.                 return false;
  110.             }
  111.             if (Math.Min(p1.Y, p2.Y) > Math.Max(q1.Y, q2.Y))
  112.             {//P1P2中最小的Y比Q1Q2中的最大Y还要大,说明P1P2在Q1Q2的最高点的上方,不可能相交。
  113.                 return false;
  114.             }
  115.             //跨立试验
  116.             var crossP1P2Q1 = VectorCross(p1, p2, q1);
  117.             var crossP1Q2P2 = VectorCross(p1, q2, p2);
  118.             var crossQ1Q2P1 = VectorCross(q1, q2, p1);
  119.             var crossQ1P2Q2 = VectorCross(q1, p2, q2);
  120.             bool isIntersect = (crossP1P2Q1 * crossP1Q2P2 >= 0) && (crossQ1Q2P1 * crossQ1P2Q2 >= 0);
  121.             return isIntersect;
  122.         }
  123.         private static double VectorCross(Point p1, Point p2, Point p3)
  124.         {
  125.             Vector vectorP1 = new Vector(p1.X, p1.Y);
  126.             Vector vectorP2 = new Vector(p2.X, p2.Y);
  127.             Vector vectorP3 = new Vector(p3.X, p3.Y);
  128.             Vector vectorP1P2 = Vector.Subtract(vectorP2, vectorP1);
  129.             Vector vectorP1P3 = Vector.Subtract(vectorP3, vectorP1);
  130.             return Vector.CrossProduct(vectorP1P2, vectorP1P3);
  131.         }
  132.     }
  133. }
复制代码
 
参考
https://blog.csdn.net/weixin_33973609/article/details/93580049
https://www.cnblogs.com/tuyang1129/p/9390376.html

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4