Files
StructureHelper/StructureHelperCommon/Models/Shapes/Logics/PolygonGeometryUtils.cs
2025-10-26 22:19:25 +05:00

86 lines
2.7 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 ILinePolygonShape GetTransfromedPolygon(ILinePolygonShape polygon, double dx, double dy)
{
ILinePolygonShape newPolygon = new LinePolygonShape(Guid.Empty);
var updateLogic = new LinePolygonShapeUpdateStrategy();
updateLogic.Update(newPolygon, polygon);
foreach (var item in newPolygon.Vertices)
{
item.Point.X += dx;
item.Point.Y += dy;
}
return newPolygon;
}
public static bool DoPolygonsEdgesIntersect(ILinePolygonShape 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
}
}
}