using System.Collections; using System.Collections.Generic; using Godot; using System; using System.Linq; using TriangleNet.Geometry; using TriangleNet.Meshing; using TriangleNet.Voronoi; using TriangleNet.Topology.DCEL; namespace Rokojori { public class Voronoi2D { public class Edge { public int start; public int end; } public List cellPoints; public List boundaryPoints = new List(); public List cells = new List(); public List edges = new List(); public class Cell { public int index; public List neighbors = new List(); public List boundaries = new List(); protected Voronoi2D _voronoi2D; public Cell( Voronoi2D v, int index ) { _voronoi2D = v; this.index = index; } public List GetBoundaryPositions() { return boundaries.Map( b => _voronoi2D.boundaryPoints[ b ] ); } } public static Voronoi2D CreateFromCellPoints( List cellPoints ) { var polygon = new Polygon(); cellPoints.ForEach( c => polygon.Add( new TriangleNet.Geometry.Vertex( c.X, c.Y ) ) ); var v = new Voronoi2D(); v.cellPoints = cellPoints; var mesh = (TriangleNet.Mesh) polygon.Triangulate(); var voronoi = new StandardVoronoi( mesh ); var boundaryMap = new Dictionary(); var edgesMap = new Dictionary(); foreach ( var face in voronoi.Faces ) { var site = face.generator; var cell = new Cell( v, site.ID ); var edge = face.edge; if ( edge == null ) { continue; } var start = edge; AddEdge( cell, start, boundaryMap, edgesMap ); var it = start.next; while ( it != start && it != null ) { AddEdge( cell, it, boundaryMap, edgesMap ); it = it.next; } v.cells.Add( cell ); } for ( int i = 0; i < boundaryMap.Count; i++ ) { if ( ! boundaryMap.ContainsKey( i ) ) { RJLog.Log( "Invalid index for boundary", i ); continue; } v.boundaryPoints.Add( boundaryMap[ i ] ); } foreach ( var edge in edgesMap ) { v.edges.Add( edge.Value ); } return v; } static void AddEdge( Cell cell, HalfEdge halfEdge, Dictionary boundaryMap, Dictionary edgeMap ) { if ( halfEdge == null ) { return; } if ( ! boundaryMap.ContainsKey( halfEdge.origin.id ) ) { boundaryMap[ halfEdge.origin.id ] = new Vector2( (float) halfEdge.origin.x, (float) halfEdge.origin.y ); } var end = halfEdge.next; if ( end != null ) { int[] ids = [ halfEdge.origin.id, halfEdge.next.origin.id ]; if ( ids[ 0 ] > ids[ 1 ] ) { var b = ids[ 0 ]; ids[ 0 ] = ids[ 1 ]; ids[ 1 ] = b; } var edgeID = ids[ 0 ] + " " + ids[ 1 ]; if ( ! edgeMap.ContainsKey( edgeID ) ) { var edge = new Edge(); edge.start = halfEdge.origin.id; edge.end = halfEdge.next.origin.id; edgeMap[ edgeID ] = edge; } } cell.neighbors.Add( halfEdge.Twin.id ); cell.boundaries.Add( halfEdge.origin.id ); } } }