79 lines
2.9 KiB
C#
79 lines
2.9 KiB
C#
namespace CandyboxPlugin.Voronoi
|
|
{
|
|
public class DelaunayTriangulator
|
|
{
|
|
private double MaxX { get; set; }
|
|
private double MaxY { get; set; }
|
|
private IEnumerable<Triangle> 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<VoronoiPoint>() { point0, point1, point2, point3 };
|
|
var tri1 = new Triangle(point0, point1, point2);
|
|
var tri2 = new Triangle(point0, point2, point3);
|
|
border = new List<Triangle>() { tri1, tri2 };
|
|
|
|
|
|
}
|
|
|
|
public IEnumerable<Triangle> BowyerWatson(IEnumerable<VoronoiPoint> points)
|
|
{
|
|
//var supraTriangle = GenerateSupraTriangle();
|
|
var triangulation = new HashSet<Triangle>(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<Edge> FindHoleBoundaries(ISet<Triangle> badTriangles)
|
|
{
|
|
var edges = new List<Edge>();
|
|
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<Triangle> FindBadTriangles(VoronoiPoint point, HashSet<Triangle> triangles)
|
|
{
|
|
var badTriangles = triangles.Where(o => o.IsPointInsideCircumcircle(point));
|
|
return new HashSet<Triangle>(badTriangles);
|
|
}
|
|
}
|
|
} |