namespace CandyboxPlugin.Voronoi { public class DelaunayTriangulator { private double MaxX { get; set; } private double MaxY { get; set; } private IEnumerable border; public void GenerateBorder(double maxX, double maxY) { MaxX = maxX; MaxY = maxY; // TODO make more beautiful var point0 = new VoronoiPoint(0, 0); var point1 = new VoronoiPoint(0, MaxY); var point2 = new VoronoiPoint(MaxX, MaxY); var point3 = new VoronoiPoint(MaxX, 0); var points = new List() { point0, point1, point2, point3 }; var tri1 = new Triangle(point0, point1, point2); var tri2 = new Triangle(point0, point2, point3); border = new List() { tri1, tri2 }; } public IEnumerable BowyerWatson(IEnumerable points) { //var supraTriangle = GenerateSupraTriangle(); var triangulation = new HashSet(border); foreach (var point in points) { var badTriangles = FindBadTriangles(point, triangulation); var polygon = FindHoleBoundaries(badTriangles); foreach (var triangle in badTriangles) { foreach (var vertex in triangle.Vertices) { vertex.AdjacentTriangles.Remove(triangle); } } triangulation.RemoveWhere(o => badTriangles.Contains(o)); foreach (var edge in polygon.Where(possibleEdge => possibleEdge.Point1 != point && possibleEdge.Point2 != point)) { var triangle = new Triangle(point, edge.Point1, edge.Point2); triangulation.Add(triangle); } } return triangulation; } private List FindHoleBoundaries(ISet badTriangles) { var edges = new List(); foreach (var triangle in badTriangles) { edges.Add(new Edge(triangle.Vertices[0], triangle.Vertices[1])); edges.Add(new Edge(triangle.Vertices[1], triangle.Vertices[2])); edges.Add(new Edge(triangle.Vertices[2], triangle.Vertices[0])); } var grouped = edges.GroupBy(o => o); var boundaryEdges = edges.GroupBy(o => o).Where(o => o.Count() == 1).Select(o => o.First()); return boundaryEdges.ToList(); } private ISet FindBadTriangles(VoronoiPoint point, HashSet triangles) { var badTriangles = triangles.Where(o => o.IsPointInsideCircumcircle(point)); return new HashSet(badTriangles); } } }