前言
判断多边形是否相交是计算几何中的一个重要问题。这个问题在图形学、地理信息系统、计算机视觉等领域都有广泛的应用。下面介绍判断多边形相交的基本概念、方法和实现步骤。
判断多边形是否相交的算法有多种,今天这里介绍的是Separate Axis Theorem(SAT)的算法原理。
关于SAT的概念
分离轴定理(Separating Axis Theorem, SAT)是一种用于检测两个凸多边形是否相交的有效方法。根据该定理,如果存在一种直线(分离轴),使得两个多边形在该直线上的投影不重叠,则这两个多边形不相交。反之,如果所有投影都重叠,则这两个多边形相交。
SAT 算法步骤
- 计算每个多边形的边向量:对于多边形的每一条边,计算其法向量(即垂直于边的向量)。
- 投影多边形到法向量:对所有顶点进行投影,找到两个多边形在这个法向量上的最小和最大值。
- 检查重叠:如果投影有重叠,则继续检查其他法向量。如果找到任何一个法向量的投影不重叠,则这两个多边形不相交。
完整代码
以下是一个实现SAT用于判断两个2D凸多边形是否相交的示例代码
using System;
using System.Collections.Generic;
using System.Linq;
public class Vector
{
public float X { get; }
public float Y { get; }
public Vector(float x, float y)
{
X = x;
Y = y;
}
public static Vector operator -(Vector a, Vector b)
{
return new Vector(a.X - b.X, a.Y - b.Y);
}
public static float Dot(Vector a, Vector b)
{
return a.X * b.X + a.Y * b.Y;
}
public static Vector Perpendicular(Vector v)
{
return new Vector(-v.Y, v.X); // 顺时针旋转90度
}
}
public class Polygon
{
public List<Vector> Vertices { get; }
public Polygon(List<Vector> vertices)
{
Vertices = vertices;
}
public List<Vector> GetEdges()
{
List<Vector> edges = new List<Vector>();
for (int i = 0; i < Vertices.Count; i++)
{
Vector start = Vertices[i];
Vector end = Vertices[(i + 1) % Vertices.Count];
edges.Add(end - start);
}
return edges;
}
public List<Vector> GetNormals()
{
List<Vector> normals = new List<Vector>();
foreach (Vector edge in GetEdges())
{
normals.Add(Vector.Perpendicular(edge));
}
return normals;
}
public (float min, float max) ProjectOntoAxis(Vector axis)
{
float min = float.MaxValue;
float max = float.MinValue;
foreach (Vector vertex in Vertices)
{
float projection = Vector.Dot(vertex, axis);
min = Math.Min(min, projection);
max = Math.Max(max, projection);
}
return (min, max);
}
}
public static class SAT
{
public static bool ArePolygonsIntersecting(Polygon polyA, Polygon polyB)
{
foreach (Vector normal in polyA.GetNormals())
{
if (!IsProjectionOverlapping(polyA, polyB, normal))
return false;
}
foreach (Vector normal in polyB.GetNormals())
{
if (!IsProjectionOverlapping(polyA, polyB, normal))
return false;
}
return true; // 如果在所有轴投影上都有重叠,则多边形相交
}
private static bool IsProjectionOverlapping(Polygon polyA, Polygon polyB, Vector axis)
{
var (aMin, aMax) = polyA.ProjectOntoAxis(axis);
var (bMin, bMax) = polyB.ProjectOntoAxis(axis);
return aMax >= bMin && bMax >= aMin; // 重叠条件
}
}
public class Program
{
public static void Main(string[] args)
{
// 定义两个多边形
Polygon polyA = new Polygon(new List<Vector>
{
new Vector(1, 1),
new Vector(3, 1),
new Vector(3, 3),
new Vector(1, 3)
});
Polygon polyB = new Polygon(new List<Vector>
{
new Vector(2, 2),
new Vector(4, 2),
new Vector(4, 4),
new Vector(2, 4)
});
bool isIntersecting = SAT.ArePolygonsIntersecting(polyA, polyB);
Console.WriteLine("Polygons intersect: " + isIntersecting);
}
}
代码解释:
- Vector 类:表示一个二维向量,提供向量相减、点积和垂直操作的方法。
- Polygon 类:表示一个多边形,包含顶点列表。其方法包括获得边、法向量和投影到给定轴上。
- SAT 类:包含用于检测两个多边形是否相交的逻辑:
ArePolygonsIntersecting` 方法会对每个多边形的法向量进行重叠检。
IsProjectionOverlapping` 方法检查两个多边形在投影轴上的重叠情况。
- Program 类:在 `Main` 方法中创建两个多边形并检查它们是否相交。
使用说明:
此代码演示了如何使用分离轴定理检测两个凸多边形的相交情况。在实际应用中,您可能需要将其扩展到处理凹多边形,或添加更多功能。对于凹多边形的处理,可以先将其细分为多个凸多边形进行检测。
更多学习内容,可关注公众号:

以上内容为个人测试过程的记录,供大家参考。
内容如有错欢迎批评指正,谢谢!!!!

5801

被折叠的 条评论
为什么被折叠?



