namespace MIConvexHull
{
using System;
using System.Collections.Generic;
using System.Linq;
///
/// A factory class for creating a Voronoi mesh.
///
public static class VoronoiMesh
{
///
/// Create the voronoi mesh.
///
///
///
///
///
///
public static VoronoiMesh Create(IEnumerable data)
where TCell : TriangulationCell, new()
where TVertex : IVertex
where TEdge : VoronoiEdge, new()
{
return VoronoiMesh.Create(data);
}
///
/// Create the voronoi mesh.
///
///
///
///
public static VoronoiMesh, VoronoiEdge>> Create(IEnumerable data)
where TVertex : IVertex
{
return VoronoiMesh, VoronoiEdge>>.Create(data);
}
///
/// Create the voronoi mesh.
///
///
///
public static VoronoiMesh, VoronoiEdge>>
Create(IEnumerable data)
{
var points = data.Select(p => new DefaultVertex { Position = p.ToArray() });
return VoronoiMesh, VoronoiEdge>>.Create(points);
}
///
/// Create the voronoi mesh.
///
///
///
///
///
///
public static VoronoiMesh> Create(IEnumerable data)
where TVertex : IVertex
where TCell : TriangulationCell, new()
{
return VoronoiMesh>.Create(data);
}
}
///
/// A representation of a voronoi mesh.
///
///
///
///
public class VoronoiMesh
where TCell : TriangulationCell, new()
where TVertex : IVertex
where TEdge : VoronoiEdge, new()
{
///
/// This is probably not needed, but might make things a tiny bit faster.
///
class EdgeComparer : IEqualityComparer
{
public bool Equals(TEdge x, TEdge y)
{
return (x.Source == y.Source && x.Target == y.Target) || (x.Source == y.Target && x.Target == y.Source);
}
public int GetHashCode(TEdge obj)
{
return obj.Source.GetHashCode() ^ obj.Target.GetHashCode();
}
}
///
/// Vertices of the diagram.
///
public IEnumerable Vertices { get; private set; }
///
/// Edges connecting the cells.
/// The same information can be retrieved Cells' Adjacency.
///
public IEnumerable Edges { get; private set; }
///
/// Create a Voronoi diagram of the input data.
///
///
public static VoronoiMesh Create(IEnumerable data)
{
if (data == null) throw new ArgumentNullException("data can't be null");
if (!(data is IList)) data = data.ToArray();
var t = DelaunayTriangulation.Create(data);
var vertices = t.Cells;
var edges = new HashSet(new EdgeComparer());
foreach (var f in vertices)
{
for (int i = 0; i < f.Adjacency.Length; i++)
{
var af = f.Adjacency[i];
if (af != null) edges.Add(new TEdge { Source = f, Target = af });
}
}
return new VoronoiMesh
{
Vertices = vertices,
Edges = edges.ToList()
};
}
///
/// Can only be created using a factory method.
///
private VoronoiMesh()
{
}
}
}