1 | namespace MIConvexHull
|
---|
2 | {
|
---|
3 | using System;
|
---|
4 | using System.Collections.Generic;
|
---|
5 | using System.Linq;
|
---|
6 |
|
---|
7 | /// <summary>
|
---|
8 | /// A factory class for creating a Voronoi mesh.
|
---|
9 | /// </summary>
|
---|
10 | public static class VoronoiMesh
|
---|
11 | {
|
---|
12 | /// <summary>
|
---|
13 | /// Create the voronoi mesh.
|
---|
14 | /// </summary>
|
---|
15 | /// <typeparam name="TVertex"></typeparam>
|
---|
16 | /// <typeparam name="TCell"></typeparam>
|
---|
17 | /// <typeparam name="TEdge"></typeparam>
|
---|
18 | /// <param name="data"></param>
|
---|
19 | /// <returns></returns>
|
---|
20 | public static VoronoiMesh<TVertex, TCell, TEdge> Create<TVertex, TCell, TEdge>(IEnumerable<TVertex> data)
|
---|
21 | where TCell : TriangulationCell<TVertex, TCell>, new()
|
---|
22 | where TVertex : IVertex
|
---|
23 | where TEdge : VoronoiEdge<TVertex, TCell>, new()
|
---|
24 | {
|
---|
25 | return VoronoiMesh<TVertex, TCell, TEdge>.Create(data);
|
---|
26 | }
|
---|
27 |
|
---|
28 | /// <summary>
|
---|
29 | /// Create the voronoi mesh.
|
---|
30 | /// </summary>
|
---|
31 | /// <typeparam name="TVertex"></typeparam>
|
---|
32 | /// <param name="data"></param>
|
---|
33 | /// <returns></returns>
|
---|
34 | public static VoronoiMesh<TVertex, DefaultTriangulationCell<TVertex>, VoronoiEdge<TVertex, DefaultTriangulationCell<TVertex>>> Create<TVertex>(IEnumerable<TVertex> data)
|
---|
35 | where TVertex : IVertex
|
---|
36 | {
|
---|
37 | return VoronoiMesh<TVertex, DefaultTriangulationCell<TVertex>, VoronoiEdge<TVertex, DefaultTriangulationCell<TVertex>>>.Create(data);
|
---|
38 | }
|
---|
39 |
|
---|
40 | /// <summary>
|
---|
41 | /// Create the voronoi mesh.
|
---|
42 | /// </summary>
|
---|
43 | /// <param name="data"></param>
|
---|
44 | /// <returns></returns>
|
---|
45 | public static VoronoiMesh<DefaultVertex, DefaultTriangulationCell<DefaultVertex>, VoronoiEdge<DefaultVertex, DefaultTriangulationCell<DefaultVertex>>>
|
---|
46 | Create(IEnumerable<double[]> data)
|
---|
47 | {
|
---|
48 | var points = data.Select(p => new DefaultVertex { Position = p.ToArray() });
|
---|
49 | return VoronoiMesh<DefaultVertex, DefaultTriangulationCell<DefaultVertex>, VoronoiEdge<DefaultVertex, DefaultTriangulationCell<DefaultVertex>>>.Create(points);
|
---|
50 | }
|
---|
51 |
|
---|
52 | /// <summary>
|
---|
53 | /// Create the voronoi mesh.
|
---|
54 | /// </summary>
|
---|
55 | /// <typeparam name="TVertex"></typeparam>
|
---|
56 | /// <typeparam name="TCell"></typeparam>
|
---|
57 | /// <typeparam name="TEdge"></typeparam>
|
---|
58 | /// <param name="data"></param>
|
---|
59 | /// <returns></returns>
|
---|
60 | public static VoronoiMesh<TVertex, TCell, VoronoiEdge<TVertex, TCell>> Create<TVertex, TCell>(IEnumerable<TVertex> data)
|
---|
61 | where TVertex : IVertex
|
---|
62 | where TCell : TriangulationCell<TVertex, TCell>, new()
|
---|
63 | {
|
---|
64 | return VoronoiMesh<TVertex, TCell, VoronoiEdge<TVertex, TCell>>.Create(data);
|
---|
65 | }
|
---|
66 | }
|
---|
67 |
|
---|
68 | /// <summary>
|
---|
69 | /// A representation of a voronoi mesh.
|
---|
70 | /// </summary>
|
---|
71 | /// <typeparam name="TVertex"></typeparam>
|
---|
72 | /// <typeparam name="TCell"></typeparam>
|
---|
73 | /// <typeparam name="TEdge"></typeparam>
|
---|
74 | public class VoronoiMesh<TVertex, TCell, TEdge>
|
---|
75 | where TCell : TriangulationCell<TVertex, TCell>, new()
|
---|
76 | where TVertex : IVertex
|
---|
77 | where TEdge : VoronoiEdge<TVertex, TCell>, new()
|
---|
78 | {
|
---|
79 | /// <summary>
|
---|
80 | /// This is probably not needed, but might make things a tiny bit faster.
|
---|
81 | /// </summary>
|
---|
82 | class EdgeComparer : IEqualityComparer<TEdge>
|
---|
83 | {
|
---|
84 | public bool Equals(TEdge x, TEdge y)
|
---|
85 | {
|
---|
86 | return (x.Source == y.Source && x.Target == y.Target) || (x.Source == y.Target && x.Target == y.Source);
|
---|
87 | }
|
---|
88 |
|
---|
89 | public int GetHashCode(TEdge obj)
|
---|
90 | {
|
---|
91 | return obj.Source.GetHashCode() ^ obj.Target.GetHashCode();
|
---|
92 | }
|
---|
93 | }
|
---|
94 |
|
---|
95 | /// <summary>
|
---|
96 | /// Vertices of the diagram.
|
---|
97 | /// </summary>
|
---|
98 | public IEnumerable<TCell> Vertices { get; private set; }
|
---|
99 |
|
---|
100 | /// <summary>
|
---|
101 | /// Edges connecting the cells.
|
---|
102 | /// The same information can be retrieved Cells' Adjacency.
|
---|
103 | /// </summary>
|
---|
104 | public IEnumerable<TEdge> Edges { get; private set; }
|
---|
105 |
|
---|
106 | /// <summary>
|
---|
107 | /// Create a Voronoi diagram of the input data.
|
---|
108 | /// </summary>
|
---|
109 | /// <param name="data"></param>
|
---|
110 | public static VoronoiMesh<TVertex, TCell, TEdge> Create(IEnumerable<TVertex> data)
|
---|
111 | {
|
---|
112 | if (data == null) throw new ArgumentNullException("data can't be null");
|
---|
113 |
|
---|
114 | if (!(data is IList<TVertex>)) data = data.ToArray();
|
---|
115 |
|
---|
116 | var t = DelaunayTriangulation<TVertex, TCell>.Create(data);
|
---|
117 | var vertices = t.Cells;
|
---|
118 | var edges = new HashSet<TEdge>(new EdgeComparer());
|
---|
119 |
|
---|
120 | foreach (var f in vertices)
|
---|
121 | {
|
---|
122 | for (int i = 0; i < f.Adjacency.Length; i++)
|
---|
123 | {
|
---|
124 | var af = f.Adjacency[i];
|
---|
125 | if (af != null) edges.Add(new TEdge { Source = f, Target = af });
|
---|
126 | }
|
---|
127 | }
|
---|
128 |
|
---|
129 | return new VoronoiMesh<TVertex, TCell, TEdge>
|
---|
130 | {
|
---|
131 | Vertices = vertices,
|
---|
132 | Edges = edges.ToList()
|
---|
133 | };
|
---|
134 | }
|
---|
135 |
|
---|
136 | /// <summary>
|
---|
137 | /// Can only be created using a factory method.
|
---|
138 | /// </summary>
|
---|
139 | private VoronoiMesh()
|
---|
140 | {
|
---|
141 |
|
---|
142 | }
|
---|
143 | }
|
---|
144 | }
|
---|