VoronoiBase.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. // -----------------------------------------------------------------------
  2. // <copyright file="VoronoiBase.cs">
  3. // Original Triangle code by Jonathan Richard Shewchuk, http://www.cs.cmu.edu/~quake/triangle.html
  4. // Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
  5. // </copyright>
  6. // -----------------------------------------------------------------------
  7. namespace UnityEngine.U2D.Animation.TriangleNet
  8. .Voronoi
  9. {
  10. using System.Collections.Generic;
  11. using Animation.TriangleNet.Topology;
  12. using Animation.TriangleNet.Geometry;
  13. using Animation.TriangleNet.Topology.DCEL;
  14. using Vertex = Animation.TriangleNet.Topology.DCEL.Vertex;
  15. /// <summary>
  16. /// The Voronoi diagram is the dual of a pointset triangulation.
  17. /// </summary>
  18. internal abstract class VoronoiBase : DcelMesh
  19. {
  20. protected IPredicates predicates;
  21. protected IVoronoiFactory factory;
  22. // List of infinite half-edges, i.e. half-edges that start at circumcenters of triangles
  23. // which lie on the domain boundary.
  24. protected List<HalfEdge> rays;
  25. /// <summary>
  26. /// Initializes a new instance of the <see cref="VoronoiBase" /> class.
  27. /// </summary>
  28. /// <param name="mesh">Triangle mesh.</param>
  29. /// <param name="factory">Voronoi object factory.</param>
  30. /// <param name="predicates">Geometric predicates implementation.</param>
  31. /// <param name="generate">If set to true, the constuctor will call the Generate
  32. /// method, which builds the Voronoi diagram.</param>
  33. protected VoronoiBase(Mesh mesh, IVoronoiFactory factory, IPredicates predicates,
  34. bool generate)
  35. : base(false)
  36. {
  37. this.factory = factory;
  38. this.predicates = predicates;
  39. if (generate)
  40. {
  41. Generate(mesh);
  42. }
  43. }
  44. /// <summary>
  45. /// Generate the Voronoi diagram from given triangle mesh..
  46. /// </summary>
  47. /// <param name="mesh"></param>
  48. /// <param name="bounded"></param>
  49. protected void Generate(Mesh mesh)
  50. {
  51. mesh.Renumber();
  52. base.edges = new List<HalfEdge>();
  53. this.rays = new List<HalfEdge>();
  54. // Allocate space for Voronoi diagram.
  55. var vertices = new Vertex[mesh.triangles.Count + mesh.hullsize];
  56. var faces = new Face[mesh.vertices.Count];
  57. if (factory == null)
  58. {
  59. factory = new DefaultVoronoiFactory();
  60. }
  61. factory.Initialize(vertices.Length, 2 * mesh.NumberOfEdges, faces.Length);
  62. // Compute triangles circumcenters.
  63. var map = ComputeVertices(mesh, vertices);
  64. // Create all Voronoi faces.
  65. foreach (var vertex in mesh.vertices.Values)
  66. {
  67. faces[vertex.id] = factory.CreateFace(vertex);
  68. }
  69. ComputeEdges(mesh, vertices, faces, map);
  70. // At this point all edges are computed, but the (edge.next) pointers aren't set.
  71. ConnectEdges(map);
  72. base.vertices = new List<Vertex>(vertices);
  73. base.faces = new List<Face>(faces);
  74. }
  75. /// <summary>
  76. /// Compute the Voronoi vertices (the circumcenters of the triangles).
  77. /// </summary>
  78. /// <returns>An empty map, which will map all vertices to a list of leaving edges.</returns>
  79. protected List<HalfEdge>[] ComputeVertices(Mesh mesh, Vertex[] vertices)
  80. {
  81. Otri tri = default(Otri);
  82. double xi = 0, eta = 0;
  83. Vertex vertex;
  84. Point pt;
  85. int id;
  86. // Maps all vertices to a list of leaving edges.
  87. var map = new List<HalfEdge>[mesh.triangles.Count];
  88. // Compue triangle circumcenters
  89. foreach (var t in mesh.triangles)
  90. {
  91. id = t.id;
  92. tri.tri = t;
  93. pt = predicates.FindCircumcenter(tri.Org(), tri.Dest(), tri.Apex(), ref xi, ref eta);
  94. vertex = factory.CreateVertex(pt.x, pt.y);
  95. vertex.id = id;
  96. vertices[id] = vertex;
  97. map[id] = new List<HalfEdge>();
  98. }
  99. return map;
  100. }
  101. /// <summary>
  102. /// Compute the edges of the Voronoi diagram.
  103. /// </summary>
  104. /// <param name="mesh"></param>
  105. /// <param name="vertices"></param>
  106. /// <param name="faces"></param>
  107. /// <param name="map">Empty vertex map.</param>
  108. protected void ComputeEdges(Mesh mesh, Vertex[] vertices, Face[] faces, List<HalfEdge>[] map)
  109. {
  110. Otri tri, neighbor = default(Otri);
  111. Animation.TriangleNet.Geometry.Vertex org, dest;
  112. double px, py;
  113. int id, nid, count = mesh.triangles.Count;
  114. Face face, neighborFace;
  115. HalfEdge edge, twin;
  116. Vertex vertex, end;
  117. // Count infinte edges (vertex id for their endpoints).
  118. int j = 0;
  119. // Count half-edges (edge ids).
  120. int k = 0;
  121. // To loop over the set of edges, loop over all triangles, and look at the
  122. // three edges of each triangle. If there isn't another triangle adjacent
  123. // to the edge, operate on the edge. If there is another adjacent triangle,
  124. // operate on the edge only if the current triangle has a smaller id than
  125. // its neighbor. This way, each edge is considered only once.
  126. foreach (var t in mesh.triangles)
  127. {
  128. id = t.id;
  129. tri.tri = t;
  130. for (int i = 0; i < 3; i++)
  131. {
  132. tri.orient = i;
  133. tri.Sym(ref neighbor);
  134. nid = neighbor.tri.id;
  135. if (id < nid || nid < 0)
  136. {
  137. // Get the endpoints of the current triangle edge.
  138. org = tri.Org();
  139. dest = tri.Dest();
  140. face = faces[org.id];
  141. neighborFace = faces[dest.id];
  142. vertex = vertices[id];
  143. // For each edge in the triangle mesh, there's a corresponding edge
  144. // in the Voronoi diagram, i.e. two half-edges will be created.
  145. if (nid < 0)
  146. {
  147. // Unbounded edge, direction perpendicular to the boundary edge,
  148. // pointing outwards.
  149. px = dest.y - org.y;
  150. py = org.x - dest.x;
  151. end = factory.CreateVertex(vertex.x + px, vertex.y + py);
  152. end.id = count + j++;
  153. vertices[end.id] = end;
  154. edge = factory.CreateHalfEdge(end, face);
  155. twin = factory.CreateHalfEdge(vertex, neighborFace);
  156. // Make (face.edge) always point to an edge that starts at an infinite
  157. // vertex. This will allow traversing of unbounded faces.
  158. face.edge = edge;
  159. face.bounded = false;
  160. map[id].Add(twin);
  161. rays.Add(twin);
  162. }
  163. else
  164. {
  165. end = vertices[nid];
  166. // Create half-edges.
  167. edge = factory.CreateHalfEdge(end, face);
  168. twin = factory.CreateHalfEdge(vertex, neighborFace);
  169. // Add to vertex map.
  170. map[nid].Add(edge);
  171. map[id].Add(twin);
  172. }
  173. vertex.leaving = twin;
  174. end.leaving = edge;
  175. edge.twin = twin;
  176. twin.twin = edge;
  177. edge.id = k++;
  178. twin.id = k++;
  179. this.edges.Add(edge);
  180. this.edges.Add(twin);
  181. }
  182. }
  183. }
  184. }
  185. /// <summary>
  186. /// Connect all edges of the Voronoi diagram.
  187. /// </summary>
  188. /// <param name="map">Maps all vertices to a list of leaving edges.</param>
  189. protected virtual void ConnectEdges(List<HalfEdge>[] map)
  190. {
  191. int length = map.Length;
  192. // For each half-edge, find its successor in the connected face.
  193. foreach (var edge in this.edges)
  194. {
  195. var face = edge.face.generator.id;
  196. // The id of the dest vertex of current edge.
  197. int id = edge.twin.origin.id;
  198. // The edge origin can also be an infinite vertex. Sort them out
  199. // by checking the id.
  200. if (id < length)
  201. {
  202. // Look for the edge that is connected to the current face. Each
  203. // Voronoi vertex has degree 3, so this loop is actually O(1).
  204. foreach (var next in map[id])
  205. {
  206. if (next.face.generator.id == face)
  207. {
  208. edge.next = next;
  209. break;
  210. }
  211. }
  212. }
  213. }
  214. }
  215. protected override IEnumerable<IEdge> EnumerateEdges()
  216. {
  217. var edges = new List<IEdge>(this.edges.Count / 2);
  218. foreach (var edge in this.edges)
  219. {
  220. var twin = edge.twin;
  221. // Report edge only once.
  222. if (twin == null)
  223. {
  224. edges.Add(new Edge(edge.origin.id, edge.next.origin.id));
  225. }
  226. else if (edge.id < twin.id)
  227. {
  228. edges.Add(new Edge(edge.origin.id, twin.origin.id));
  229. }
  230. }
  231. return edges;
  232. }
  233. }
  234. }