74 lines
2.2 KiB
C#
74 lines
2.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Shapes;
|
|
|
|
namespace StructureHelperCommon.Models.Shapes
|
|
{
|
|
public static class PolygonGeometryUtils
|
|
{
|
|
public static bool DoPolygonsEdgesIntersect(IPolygonShape polygon)
|
|
{
|
|
var vertices = polygon.Vertices;
|
|
int n = vertices.Count;
|
|
|
|
if (n < 4)
|
|
return false; // Triangles cannot self-intersect
|
|
|
|
for (int i = 0; i < n; i++)
|
|
{
|
|
var a1 = vertices[i].Point;
|
|
var a2 = vertices[(i + 1) % n].Point;
|
|
|
|
for (int j = i + 1; j < n; j++)
|
|
{
|
|
var b1 = vertices[j].Point;
|
|
var b2 = vertices[(j + 1) % n].Point;
|
|
|
|
// Skip adjacent edges (they share a vertex)
|
|
if (AreAdjacent(i, j, n, polygon.IsClosed))
|
|
continue;
|
|
|
|
if (SegmentsIntersect(a1, a2, b1, b2))
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static bool AreAdjacent(int i, int j, int n, bool isClosed)
|
|
{
|
|
// Edges (i,i+1) and (j,j+1) are adjacent if:
|
|
if (j == i) return true;
|
|
if (j == i + 1) return true;
|
|
if (i == j + 1) return true;
|
|
|
|
// Special case: first and last edges in closed polygon
|
|
if (isClosed &&
|
|
((i == 0 && j == n - 1) || (j == 0 && i == n - 1)))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
private static bool SegmentsIntersect(IPoint2D p1, IPoint2D p2, IPoint2D q1, IPoint2D q2)
|
|
{
|
|
return (Orientation(p1, p2, q1) * Orientation(p1, p2, q2) < 0) &&
|
|
(Orientation(q1, q2, p1) * Orientation(q1, q2, p2) < 0);
|
|
}
|
|
|
|
private static int Orientation(IPoint2D a, IPoint2D b, IPoint2D c)
|
|
{
|
|
double val = (b.Y - a.Y) * (c.X - b.X) -
|
|
(b.X - a.X) * (c.Y - b.Y);
|
|
|
|
if (Math.Abs(val) < 1e-12) return 0; // Collinear
|
|
return (val > 0) ? 1 : -1; // Clockwise / Counter-clockwise
|
|
}
|
|
}
|
|
|
|
}
|