155 lines
3.4 KiB
C#
155 lines
3.4 KiB
C#
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<Vector2> cellPoints;
|
|
public List<Vector2> boundaryPoints = new List<Vector2>();
|
|
public List<Cell> cells = new List<Cell>();
|
|
public List<Edge> edges = new List<Edge>();
|
|
|
|
public class Cell
|
|
{
|
|
public int index;
|
|
public List<int> neighbors = new List<int>();
|
|
public List<int> boundaries = new List<int>();
|
|
|
|
protected Voronoi2D _voronoi2D;
|
|
|
|
public Cell( Voronoi2D v, int index )
|
|
{
|
|
_voronoi2D = v;
|
|
this.index = index;
|
|
}
|
|
|
|
public List<Vector2> GetBoundaryPositions()
|
|
{
|
|
return boundaries.Map( b => _voronoi2D.boundaryPoints[ b ] );
|
|
}
|
|
}
|
|
|
|
|
|
public static Voronoi2D CreateFromCellPoints( List<Vector2> 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<int,Vector2>();
|
|
var edgesMap = new Dictionary<string,Edge>();
|
|
|
|
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<int,Vector2> boundaryMap, Dictionary<string,Edge> 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 );
|
|
}
|
|
}
|
|
} |