RT,简单地几何学知识。这个函数只考虑了二维空间的求交。
GetInterBetweenTwoLines函数即为求交点函数。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GeometryTestConsole
{
class Program
{
public struct DPoint3d
{
public double X, Y, Z;
public DPoint3d(double x, double y, double z) { X = x; Y = y; Z = z; }
}
/// <summary>
/// 求一个线段与另一个线段的交点
/// </summary>
/// <param name="line1S"></param>
/// <param name="line1E"></param>
/// <param name="line2S"></param>
/// <param name="line2E"></param>
/// <param name="interPoint"></param>
/// <returns>-1:不存在交点;1:存在一个交点;2:存在无穷多个交点(重合或部分重合)</returns>
private static int GetInterBetweenTwoLines(DPoint3d line1S, DPoint3d line1E,
DPoint3d line2S, DPoint3d line2E, ref DPoint3d interPoint)
{
int status = -1;
// 判断两条直线各自的矩形包围盒的X与Y的值范围
double line1Xmin = line1S.X < line1E.X ? line1S.X : line1E.X,
line1Xmax = line1S.X > line1E.X ? line1S.X : line1E.X,
line1Ymin = line1S.Y < line1E.Y ? line1S.Y : line1E.Y,
line1Ymax = line1S.Y > line1E.Y ? line1S.Y : line1E.Y,
line2Xmin = line2S.X < line2E.X ? line2S.X : line2E.X,
line2Xmax = line2S.X > line2E.X ? line2S.X : line2E.X,
line2Ymin = line2S.Y < line2E.Y ? line2S.Y : line2E.Y,
line2Ymax = line2S.Y > line2E.Y ? line2S.Y : line2E.Y;
if (line1S.X - line1E.X == 0)
{
// 两条线都垂直于X轴
if (line2S.X - line2E.X == 0)
{
if (line1S.X != line2S.X) status = -1;
else if ((line1Ymin > line2Ymax) || (line1Ymax < line2Ymin)) status = -1;
else if (line1Ymin == line2Ymax)
{
interPoint = new DPoint3d(line1S.X, line1Ymin, line1S.Z); status = 1;
}
else if (line1Ymax == line2Ymin)
{
interPoint = new DPoint3d(line1S.X, line1Ymax, line1S.Z); status = 1;
}
else status = 2;
}
// line1垂直于X轴,line2不垂直于X轴
else
{
double slope = (line2S.Y - line2E.Y) / (line2S.X - line2E.X);
double offset = line2S.Y - slope * line2S.X;
double newX = line1S.X, newY = slope * newX + offset;
if (newX >= line2Xmin && newX <= line2Xmax && newY >= line1Ymin && newY <= line1Ymax
&& newY >= line2Ymin && newY <= line2Ymax)
{
interPoint = new DPoint3d(newX, newY, line1S.Z); status = 1;
}
}
}
else
{
// line1不垂直于X轴,line2垂直于X轴
if (line2S.X - line2E.X == 0)
{
double slope = (line1S.Y - line1E.Y) / (line1S.X - line1E.X);
double offset = line1S.Y - slope * line1S.X;
double newX = line2S.X, newY = slope * newX + offset;
if (newX >= line1Xmin && newX <= line1Xmax && newY >= line1Ymin && newY <= line1Ymax
&& newY >= line2Ymin && newY <= line2Ymax)
{
interPoint = new DPoint3d(newX, newY, line2S.Z); status = 1;
}
}
// line1和line2都不垂直于X轴
else
{
double slope1 = (line1S.Y - line1E.Y) / (line1S.X - line1E.X);
double offset1 = line1S.Y - slope1 * line1S.X;
double slope2 = (line2S.Y - line2E.Y) / (line2S.X - line2E.X);
double offset2 = line2S.Y - slope2 * line2S.X;
// 如果两条直线平行
if (slope1 == slope2)
{
if (offset1 != offset2) status = -1;
else if (line1Xmax == line2Xmin)
{
interPoint = new DPoint3d(line1Xmax, line1Xmax * slope1 + offset1, line1S.Z); status = 1;
}
else if (line1Xmin == line2Xmax)
{
interPoint = new DPoint3d(line1Xmin, line1Xmin * slope1 + offset1, line1S.Z); status = 1;
}
else if (line1Xmax < line2Xmin || line1Xmin > line2Xmax) status = -1;
else status = 2;
}
else
{
double newX = (offset2 - offset1) / (slope1 - slope2), newY = newX * slope1 + offset1;
if (newX >= line1Xmin && newX <= line1Xmax && newX >= line2Xmin && newX <= line2Xmax)
{
interPoint = new DPoint3d(newX, newY, line1S.Z); status = 1;
}
}
}
}
return status;
}
static void Main(string[] args)
{
DPoint3d point1S = new DPoint3d(1, 1, 0), point1E = new DPoint3d(3, 3, 0),
point2S = new DPoint3d(4, 4, 0), point2E = new DPoint3d(5, 5, 0);
DPoint3d interPoint = new DPoint3d();
int type = GetInterBetweenTwoLines(point1S, point1E, point2S, point2E, ref interPoint);
}
}
}