Converter.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. // -----------------------------------------------------------------------
  2. // <copyright file="Converter.cs" company="">
  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. .Meshing
  9. {
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Linq;
  13. using Animation.TriangleNet.Geometry;
  14. using Animation.TriangleNet.Topology;
  15. using Animation.TriangleNet.Topology.DCEL;
  16. using HVertex = Animation.TriangleNet.Topology.DCEL.Vertex;
  17. using TVertex = Animation.TriangleNet.Geometry.Vertex;
  18. /// <summary>
  19. /// The Converter class provides methods for mesh reconstruction and conversion.
  20. /// </summary>
  21. internal static class Converter
  22. {
  23. #region Triangle mesh conversion
  24. /// <summary>
  25. /// Reconstruct a triangulation from its raw data representation.
  26. /// </summary>
  27. internal static Mesh ToMesh(Polygon polygon, IList<ITriangle> triangles)
  28. {
  29. return ToMesh(polygon, triangles.ToArray());
  30. }
  31. /// <summary>
  32. /// Reconstruct a triangulation from its raw data representation.
  33. /// </summary>
  34. internal static Mesh ToMesh(Polygon polygon, ITriangle[] triangles)
  35. {
  36. Otri tri = default(Otri);
  37. Osub subseg = default(Osub);
  38. int i = 0;
  39. int elements = triangles == null ? 0 : triangles.Length;
  40. int segments = polygon.Segments.Count;
  41. // TODO: Configuration should be a function argument.
  42. var mesh = new Mesh(new Configuration());
  43. mesh.TransferNodes(polygon.Points);
  44. mesh.regions.AddRange(polygon.Regions);
  45. mesh.behavior.useRegions = polygon.Regions.Count > 0;
  46. if (polygon.Segments.Count > 0)
  47. {
  48. mesh.behavior.Poly = true;
  49. mesh.holes.AddRange(polygon.Holes);
  50. }
  51. // Create the triangles.
  52. for (i = 0; i < elements; i++)
  53. {
  54. mesh.MakeTriangle(ref tri);
  55. }
  56. if (mesh.behavior.Poly)
  57. {
  58. mesh.insegments = segments;
  59. // Create the subsegments.
  60. for (i = 0; i < segments; i++)
  61. {
  62. mesh.MakeSegment(ref subseg);
  63. }
  64. }
  65. var vertexarray = SetNeighbors(mesh, triangles);
  66. SetSegments(mesh, polygon, vertexarray);
  67. return mesh;
  68. }
  69. /// <summary>
  70. /// Finds the adjacencies between triangles by forming a stack of triangles for
  71. /// each vertex. Each triangle is on three different stacks simultaneously.
  72. /// </summary>
  73. private static List<Otri>[] SetNeighbors(Mesh mesh, ITriangle[] triangles)
  74. {
  75. Otri tri = default(Otri);
  76. Otri triangleleft = default(Otri);
  77. Otri checktri = default(Otri);
  78. Otri checkleft = default(Otri);
  79. Otri nexttri;
  80. TVertex tdest, tapex;
  81. TVertex checkdest, checkapex;
  82. int[] corner = new int[3];
  83. int aroundvertex;
  84. int i;
  85. // Allocate a temporary array that maps each vertex to some adjacent triangle.
  86. var vertexarray = new List<Otri>[mesh.vertices.Count];
  87. // Each vertex is initially unrepresented.
  88. for (i = 0; i < mesh.vertices.Count; i++)
  89. {
  90. Otri tmp = default(Otri);
  91. tmp.tri = mesh.dummytri;
  92. vertexarray[i] = new List<Otri>(3);
  93. vertexarray[i].Add(tmp);
  94. }
  95. i = 0;
  96. // Read the triangles from the .ele file, and link
  97. // together those that share an edge.
  98. foreach (var item in mesh.triangles)
  99. {
  100. tri.tri = item;
  101. // Copy the triangle's three corners.
  102. for (int j = 0; j < 3; j++)
  103. {
  104. corner[j] = triangles[i].GetVertexID(j);
  105. if ((corner[j] < 0) || (corner[j] >= mesh.invertices))
  106. {
  107. Log.Instance.Error("Triangle has an invalid vertex index.", "MeshReader.Reconstruct()");
  108. throw new Exception("Triangle has an invalid vertex index.");
  109. }
  110. }
  111. // Read the triangle's attributes.
  112. tri.tri.label = triangles[i].Label;
  113. // TODO: VarArea
  114. if (mesh.behavior.VarArea)
  115. {
  116. tri.tri.area = triangles[i].Area;
  117. }
  118. // Set the triangle's vertices.
  119. tri.orient = 0;
  120. tri.SetOrg(mesh.vertices[corner[0]]);
  121. tri.SetDest(mesh.vertices[corner[1]]);
  122. tri.SetApex(mesh.vertices[corner[2]]);
  123. // Try linking the triangle to others that share these vertices.
  124. for (tri.orient = 0; tri.orient < 3; tri.orient++)
  125. {
  126. // Take the number for the origin of triangleloop.
  127. aroundvertex = corner[tri.orient];
  128. int index = vertexarray[aroundvertex].Count - 1;
  129. // Look for other triangles having this vertex.
  130. nexttri = vertexarray[aroundvertex][index];
  131. // Push the current triangle onto the stack.
  132. vertexarray[aroundvertex].Add(tri);
  133. checktri = nexttri;
  134. if (checktri.tri.id != Mesh.DUMMY)
  135. {
  136. tdest = tri.Dest();
  137. tapex = tri.Apex();
  138. // Look for other triangles that share an edge.
  139. do
  140. {
  141. checkdest = checktri.Dest();
  142. checkapex = checktri.Apex();
  143. if (tapex == checkdest)
  144. {
  145. // The two triangles share an edge; bond them together.
  146. tri.Lprev(ref triangleleft);
  147. triangleleft.Bond(ref checktri);
  148. }
  149. if (tdest == checkapex)
  150. {
  151. // The two triangles share an edge; bond them together.
  152. checktri.Lprev(ref checkleft);
  153. tri.Bond(ref checkleft);
  154. }
  155. // Find the next triangle in the stack.
  156. index--;
  157. nexttri = vertexarray[aroundvertex][index];
  158. checktri = nexttri;
  159. }
  160. while (checktri.tri.id != Mesh.DUMMY);
  161. }
  162. }
  163. i++;
  164. }
  165. return vertexarray;
  166. }
  167. /// <summary>
  168. /// Finds the adjacencies between triangles and subsegments.
  169. /// </summary>
  170. private static void SetSegments(Mesh mesh, Polygon polygon, List<Otri>[] vertexarray)
  171. {
  172. Otri checktri = default(Otri);
  173. Otri nexttri; // Triangle
  174. TVertex checkdest;
  175. Otri checkneighbor = default(Otri);
  176. Osub subseg = default(Osub);
  177. Otri prevlink; // Triangle
  178. TVertex tmp;
  179. TVertex sorg, sdest;
  180. bool notfound;
  181. //bool segmentmarkers = false;
  182. int boundmarker;
  183. int aroundvertex;
  184. int i;
  185. int hullsize = 0;
  186. // Prepare to count the boundary edges.
  187. if (mesh.behavior.Poly)
  188. {
  189. // Link the segments to their neighboring triangles.
  190. boundmarker = 0;
  191. i = 0;
  192. foreach (var item in mesh.subsegs.Values)
  193. {
  194. subseg.seg = item;
  195. sorg = polygon.Segments[i].GetVertex(0);
  196. sdest = polygon.Segments[i].GetVertex(1);
  197. boundmarker = polygon.Segments[i].Label;
  198. if ((sorg.id < 0 || sorg.id >= mesh.invertices) || (sdest.id < 0 || sdest.id >= mesh.invertices))
  199. {
  200. Log.Instance.Error("Segment has an invalid vertex index.", "MeshReader.Reconstruct()");
  201. throw new Exception("Segment has an invalid vertex index.");
  202. }
  203. // set the subsegment's vertices.
  204. subseg.orient = 0;
  205. subseg.SetOrg(sorg);
  206. subseg.SetDest(sdest);
  207. subseg.SetSegOrg(sorg);
  208. subseg.SetSegDest(sdest);
  209. subseg.seg.boundary = boundmarker;
  210. // Try linking the subsegment to triangles that share these vertices.
  211. for (subseg.orient = 0; subseg.orient < 2; subseg.orient++)
  212. {
  213. // Take the number for the destination of subsegloop.
  214. aroundvertex = subseg.orient == 1 ? sorg.id : sdest.id;
  215. int index = vertexarray[aroundvertex].Count - 1;
  216. // Look for triangles having this vertex.
  217. prevlink = vertexarray[aroundvertex][index];
  218. nexttri = vertexarray[aroundvertex][index];
  219. checktri = nexttri;
  220. tmp = subseg.Org();
  221. notfound = true;
  222. // Look for triangles having this edge. Note that I'm only
  223. // comparing each triangle's destination with the subsegment;
  224. // each triangle's apex is handled through a different vertex.
  225. // Because each triangle appears on three vertices' lists, each
  226. // occurrence of a triangle on a list can (and does) represent
  227. // an edge. In this way, most edges are represented twice, and
  228. // every triangle-subsegment bond is represented once.
  229. while (notfound && (checktri.tri.id != Mesh.DUMMY))
  230. {
  231. checkdest = checktri.Dest();
  232. if (tmp == checkdest)
  233. {
  234. // We have a match. Remove this triangle from the list.
  235. //prevlink = vertexarray[aroundvertex][index];
  236. vertexarray[aroundvertex].Remove(prevlink);
  237. // Bond the subsegment to the triangle.
  238. checktri.SegBond(ref subseg);
  239. // Check if this is a boundary edge.
  240. checktri.Sym(ref checkneighbor);
  241. if (checkneighbor.tri.id == Mesh.DUMMY)
  242. {
  243. // The next line doesn't insert a subsegment (because there's
  244. // already one there), but it sets the boundary markers of
  245. // the existing subsegment and its vertices.
  246. mesh.InsertSubseg(ref checktri, 1);
  247. hullsize++;
  248. }
  249. notfound = false;
  250. }
  251. index--;
  252. // Find the next triangle in the stack.
  253. prevlink = vertexarray[aroundvertex][index];
  254. nexttri = vertexarray[aroundvertex][index];
  255. checktri = nexttri;
  256. }
  257. }
  258. i++;
  259. }
  260. }
  261. // Mark the remaining edges as not being attached to any subsegment.
  262. // Also, count the (yet uncounted) boundary edges.
  263. for (i = 0; i < mesh.vertices.Count; i++)
  264. {
  265. // Search the stack of triangles adjacent to a vertex.
  266. int index = vertexarray[i].Count - 1;
  267. nexttri = vertexarray[i][index];
  268. checktri = nexttri;
  269. while (checktri.tri.id != Mesh.DUMMY)
  270. {
  271. // Find the next triangle in the stack before this
  272. // information gets overwritten.
  273. index--;
  274. nexttri = vertexarray[i][index];
  275. // No adjacent subsegment. (This overwrites the stack info.)
  276. checktri.SegDissolve(mesh.dummysub);
  277. checktri.Sym(ref checkneighbor);
  278. if (checkneighbor.tri.id == Mesh.DUMMY)
  279. {
  280. mesh.InsertSubseg(ref checktri, 1);
  281. hullsize++;
  282. }
  283. checktri = nexttri;
  284. }
  285. }
  286. mesh.hullsize = hullsize;
  287. }
  288. #endregion
  289. #region DCEL conversion
  290. internal static DcelMesh ToDCEL(Mesh mesh)
  291. {
  292. var dcel = new DcelMesh();
  293. var vertices = new HVertex[mesh.vertices.Count];
  294. var faces = new Face[mesh.triangles.Count];
  295. dcel.HalfEdges.Capacity = 2 * mesh.NumberOfEdges;
  296. mesh.Renumber();
  297. HVertex vertex;
  298. foreach (var v in mesh.vertices.Values)
  299. {
  300. vertex = new HVertex(v.x, v.y);
  301. vertex.id = v.id;
  302. vertex.label = v.label;
  303. vertices[v.id] = vertex;
  304. }
  305. // Maps a triangle to its 3 edges (used to set next pointers).
  306. var map = new List<HalfEdge>[mesh.triangles.Count];
  307. Face face;
  308. foreach (var t in mesh.triangles)
  309. {
  310. face = new Face(null);
  311. face.id = t.id;
  312. faces[t.id] = face;
  313. map[t.id] = new List<HalfEdge>(3);
  314. }
  315. Otri tri = default(Otri), neighbor = default(Otri);
  316. Animation.TriangleNet.Geometry.Vertex org, dest;
  317. int id, nid, count = mesh.triangles.Count;
  318. HalfEdge edge, twin, next;
  319. var edges = dcel.HalfEdges;
  320. // Count half-edges (edge ids).
  321. int k = 0;
  322. // Maps a vertex to its leaving boundary edge.
  323. var boundary = new Dictionary<int, HalfEdge>();
  324. foreach (var t in mesh.triangles)
  325. {
  326. id = t.id;
  327. tri.tri = t;
  328. for (int i = 0; i < 3; i++)
  329. {
  330. tri.orient = i;
  331. tri.Sym(ref neighbor);
  332. nid = neighbor.tri.id;
  333. if (id < nid || nid < 0)
  334. {
  335. face = faces[id];
  336. // Get the endpoints of the current triangle edge.
  337. org = tri.Org();
  338. dest = tri.Dest();
  339. // Create half-edges.
  340. edge = new HalfEdge(vertices[org.id], face);
  341. twin = new HalfEdge(vertices[dest.id], nid < 0 ? Face.Empty : faces[nid]);
  342. map[id].Add(edge);
  343. if (nid >= 0)
  344. {
  345. map[nid].Add(twin);
  346. }
  347. else
  348. {
  349. boundary.Add(dest.id, twin);
  350. }
  351. // Set leaving edges.
  352. edge.origin.leaving = edge;
  353. twin.origin.leaving = twin;
  354. // Set twin edges.
  355. edge.twin = twin;
  356. twin.twin = edge;
  357. edge.id = k++;
  358. twin.id = k++;
  359. edges.Add(edge);
  360. edges.Add(twin);
  361. }
  362. }
  363. }
  364. // Set next pointers for each triangle face.
  365. foreach (var t in map)
  366. {
  367. edge = t[0];
  368. next = t[1];
  369. if (edge.twin.origin.id == next.origin.id)
  370. {
  371. edge.next = next;
  372. next.next = t[2];
  373. t[2].next = edge;
  374. }
  375. else
  376. {
  377. edge.next = t[2];
  378. next.next = edge;
  379. t[2].next = next;
  380. }
  381. }
  382. // Resolve boundary edges.
  383. foreach (var e in boundary.Values)
  384. {
  385. e.next = boundary[e.twin.origin.id];
  386. }
  387. dcel.Vertices.AddRange(vertices);
  388. dcel.Faces.AddRange(faces);
  389. return dcel;
  390. }
  391. #endregion
  392. }
  393. }