|
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
using NetTopologySuite.Geometries;
|
|
|
|
|
|
|
|
|
|
|
|
namespace FortAnalysis
|
|
|
|
|
|
{
|
|
|
|
|
|
public class PolygonSplit
|
|
|
|
|
|
{
|
|
|
|
|
|
// 找到自相交多边形的交点
|
|
|
|
|
|
private static List<Tuple<double, double>> FindIntersectionPoints(List<Tuple<double, double>> coordinates)
|
|
|
|
|
|
{
|
|
|
|
|
|
List<Tuple<double, double>> intersectionPoints = new List<Tuple<double, double>>();
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < coordinates.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var edge1Start = coordinates[i];
|
|
|
|
|
|
var edge1End = coordinates[(i + 1) % coordinates.Count];
|
|
|
|
|
|
|
|
|
|
|
|
for (int j = i + 2; j < coordinates.Count + i - 1; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var edge2Start = coordinates[j % coordinates.Count];
|
|
|
|
|
|
var edge2End = coordinates[(j + 1) % coordinates.Count];
|
|
|
|
|
|
|
|
|
|
|
|
var intersection = FindIntersection(edge1Start, edge1End, edge2Start, edge2End);
|
|
|
|
|
|
if (intersection != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
intersectionPoints.Add(intersection);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return intersectionPoints;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 找到两条边的交点
|
|
|
|
|
|
private static Tuple<double, double> FindIntersection(Tuple<double, double> p1, Tuple<double, double> p2, Tuple<double, double> p3, Tuple<double, double> p4)
|
|
|
|
|
|
{
|
|
|
|
|
|
double x1 = p1.Item1;
|
|
|
|
|
|
double y1 = p1.Item2;
|
|
|
|
|
|
double x2 = p2.Item1;
|
|
|
|
|
|
double y2 = p2.Item2;
|
|
|
|
|
|
double x3 = p3.Item1;
|
|
|
|
|
|
double y3 = p3.Item2;
|
|
|
|
|
|
double x4 = p4.Item1;
|
|
|
|
|
|
double y4 = p4.Item2;
|
|
|
|
|
|
|
|
|
|
|
|
double denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
|
|
|
|
|
|
|
|
|
|
|
|
if (Math.Abs(denominator) < double.Epsilon)
|
|
|
|
|
|
{
|
|
|
|
|
|
return null; // 平行或共线,无交点
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double x = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / denominator;
|
|
|
|
|
|
double y = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / denominator;
|
|
|
|
|
|
|
|
|
|
|
|
return new Tuple<double, double>(x, y);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 根据交点分割多边形集合
|
|
|
|
|
|
public static List<List<Coordinate>> SplitPolygons(List<List<Coordinate>> polygons, List<Coordinate> intersectionPoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
List<List<Coordinate>> splittedPolygons = new List<List<Coordinate>>();
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var polygon in polygons)
|
|
|
|
|
|
{
|
|
|
|
|
|
List<Coordinate> splittedPolygon = new List<Coordinate>(polygon);
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var intersectionPoint in intersectionPoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (IsInsidePolygon(intersectionPoint, polygon))
|
|
|
|
|
|
{
|
|
|
|
|
|
splittedPolygon.Add(intersectionPoint);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
splittedPolygon = splittedPolygon.OrderBy(p => Math.Atan2(p.Y - intersectionPoints[0].Y, p.X - intersectionPoints[0].X)).ToList();
|
|
|
|
|
|
splittedPolygons.Add(splittedPolygon);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return splittedPolygons;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 判断点是否在多边形内部
|
|
|
|
|
|
private static bool IsInsidePolygon(Coordinate point, List<Coordinate> polygon)
|
|
|
|
|
|
{
|
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
int n = polygon.Count;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < n; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var p1 = polygon[i];
|
|
|
|
|
|
var p2 = polygon[(i + 1) % n];
|
|
|
|
|
|
|
|
|
|
|
|
if (IsPointOnSegment(point, p1, p2))
|
|
|
|
|
|
{
|
|
|
|
|
|
return true; // 点在多边形的边上
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (point.Y > Math.Min(p1.Y, p2.Y) && point.Y <= Math.Max(p1.Y, p2.Y) && point.X <= Math.Max(p1.X, p2.X) && p1.Y != p2.Y)
|
|
|
|
|
|
{
|
|
|
|
|
|
double xIntersection = (point.Y - p1.Y) * (p2.X - p1.X) / (p2.Y - p1.Y) + p1.X;
|
|
|
|
|
|
if (p1.X == p2.X || point.X <= xIntersection)
|
|
|
|
|
|
{
|
|
|
|
|
|
count++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return count % 2 == 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 判断点是否在线段上
|
|
|
|
|
|
private static bool IsPointOnSegment(Coordinate point, Coordinate p1, Coordinate p2)
|
|
|
|
|
|
{
|
|
|
|
|
|
return Math.Abs(Distance(point, p1) + Distance(point, p2) - Distance(p1, p2)) < double.Epsilon;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 计算两个点之间的距离
|
|
|
|
|
|
private static double Distance(Coordinate p1, Coordinate p2)
|
|
|
|
|
|
{
|
|
|
|
|
|
double dx = p1.X - p2.X;
|
|
|
|
|
|
double dy = p1.Y - p2.Y;
|
|
|
|
|
|
return Math.Sqrt(dx * dx + dy * dy);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|