DebugWriter.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // -----------------------------------------------------------------------
  2. // <copyright file="DebugWriter.cs" company="">
  3. // Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
  4. // </copyright>
  5. // -----------------------------------------------------------------------
  6. namespace UnityEngine.U2D.Animation.TriangleNet
  7. .IO
  8. {
  9. using System;
  10. using System.Globalization;
  11. using System.IO;
  12. using System.IO.Compression;
  13. using System.Text;
  14. using Animation.TriangleNet.Topology;
  15. using Animation.TriangleNet.Geometry;
  16. /// <summary>
  17. /// Writes a the current mesh into a text file.
  18. /// </summary>
  19. /// <remarks>
  20. /// File format:
  21. ///
  22. /// num_nodes
  23. /// id_1 nx ny mark
  24. /// ...
  25. /// id_n nx ny mark
  26. ///
  27. /// num_segs
  28. /// id_1 p1 p2 mark
  29. /// ...
  30. /// id_n p1 p2 mark
  31. ///
  32. /// num_tris
  33. /// id_1 p1 p2 p3 n1 n2 n3
  34. /// ...
  35. /// id_n p1 p2 p3 n1 n2 n3
  36. /// </remarks>
  37. class DebugWriter
  38. {
  39. static NumberFormatInfo nfi = CultureInfo.InvariantCulture.NumberFormat;
  40. int iteration;
  41. string session;
  42. StreamWriter stream;
  43. string tmpFile;
  44. int[] vertices;
  45. int triangles;
  46. #region Singleton pattern
  47. private static readonly DebugWriter instance = new DebugWriter();
  48. // Explicit static constructor to tell C# compiler
  49. // not to mark type as beforefieldinit
  50. static DebugWriter() {}
  51. private DebugWriter() {}
  52. internal static DebugWriter Session
  53. {
  54. get
  55. {
  56. return instance;
  57. }
  58. }
  59. #endregion
  60. /// <summary>
  61. /// Start a new session with given name.
  62. /// </summary>
  63. /// <param name="name">Name of the session (and output files).</param>
  64. public void Start(string session)
  65. {
  66. this.iteration = 0;
  67. this.session = session;
  68. if (this.stream != null)
  69. {
  70. throw new Exception("A session is active. Finish before starting a new.");
  71. }
  72. this.tmpFile = Path.GetTempFileName();
  73. this.stream = new StreamWriter(tmpFile);
  74. }
  75. /// <summary>
  76. /// Write complete mesh to file.
  77. /// </summary>
  78. public void Write(Mesh mesh, bool skip = false)
  79. {
  80. this.WriteMesh(mesh, skip);
  81. this.triangles = mesh.Triangles.Count;
  82. }
  83. /// <summary>
  84. /// Finish this session.
  85. /// </summary>
  86. public void Finish()
  87. {
  88. this.Finish(session + ".mshx");
  89. }
  90. private void Finish(string path)
  91. {
  92. if (stream != null)
  93. {
  94. stream.Flush();
  95. stream.Dispose();
  96. stream = null;
  97. string header = "#!N" + this.iteration + Environment.NewLine;
  98. using (var gzFile = new FileStream(path, FileMode.Create))
  99. {
  100. using (var gzStream = new GZipStream(gzFile, CompressionMode.Compress, false))
  101. {
  102. byte[] bytes = Encoding.UTF8.GetBytes(header);
  103. gzStream.Write(bytes, 0, bytes.Length);
  104. // TODO: read with stream
  105. bytes = File.ReadAllBytes(tmpFile);
  106. gzStream.Write(bytes, 0, bytes.Length);
  107. }
  108. }
  109. File.Delete(this.tmpFile);
  110. }
  111. }
  112. private void WriteGeometry(IPolygon geometry)
  113. {
  114. stream.WriteLine("#!G{0}", this.iteration++);
  115. }
  116. private void WriteMesh(Mesh mesh, bool skip)
  117. {
  118. // Mesh may have changed, but we choose to skip
  119. if (triangles == mesh.triangles.Count && skip)
  120. {
  121. return;
  122. }
  123. // Header line
  124. stream.WriteLine("#!M{0}", this.iteration++);
  125. Vertex p1, p2, p3;
  126. if (VerticesChanged(mesh))
  127. {
  128. HashVertices(mesh);
  129. // Number of vertices.
  130. stream.WriteLine("{0}", mesh.vertices.Count);
  131. foreach (var v in mesh.vertices.Values)
  132. {
  133. // Vertex number, x and y coordinates and marker.
  134. stream.WriteLine("{0} {1} {2} {3}", v.id, v.x.ToString(nfi), v.y.ToString(nfi), v.label);
  135. }
  136. }
  137. else
  138. {
  139. stream.WriteLine("0");
  140. }
  141. // Number of segments.
  142. stream.WriteLine("{0}", mesh.subsegs.Count);
  143. Osub subseg = default(Osub);
  144. subseg.orient = 0;
  145. foreach (var item in mesh.subsegs.Values)
  146. {
  147. if (item.hash <= 0)
  148. {
  149. continue;
  150. }
  151. subseg.seg = item;
  152. p1 = subseg.Org();
  153. p2 = subseg.Dest();
  154. // Segment number, indices of its two endpoints, and marker.
  155. stream.WriteLine("{0} {1} {2} {3}", subseg.seg.hash, p1.id, p2.id, subseg.seg.boundary);
  156. }
  157. Otri tri = default(Otri), trisym = default(Otri);
  158. tri.orient = 0;
  159. int n1, n2, n3, h1, h2, h3;
  160. // Number of triangles.
  161. stream.WriteLine("{0}", mesh.triangles.Count);
  162. foreach (var item in mesh.triangles)
  163. {
  164. tri.tri = item;
  165. p1 = tri.Org();
  166. p2 = tri.Dest();
  167. p3 = tri.Apex();
  168. h1 = (p1 == null) ? -1 : p1.id;
  169. h2 = (p2 == null) ? -1 : p2.id;
  170. h3 = (p3 == null) ? -1 : p3.id;
  171. // Triangle number, indices for three vertices.
  172. stream.Write("{0} {1} {2} {3}", tri.tri.hash, h1, h2, h3);
  173. tri.orient = 1;
  174. tri.Sym(ref trisym);
  175. n1 = trisym.tri.hash;
  176. tri.orient = 2;
  177. tri.Sym(ref trisym);
  178. n2 = trisym.tri.hash;
  179. tri.orient = 0;
  180. tri.Sym(ref trisym);
  181. n3 = trisym.tri.hash;
  182. // Neighboring triangle numbers.
  183. stream.WriteLine(" {0} {1} {2}", n1, n2, n3);
  184. }
  185. }
  186. private bool VerticesChanged(Mesh mesh)
  187. {
  188. if (vertices == null || mesh.Vertices.Count != vertices.Length)
  189. {
  190. return true;
  191. }
  192. int i = 0;
  193. foreach (var v in mesh.Vertices)
  194. {
  195. if (v.id != vertices[i++])
  196. {
  197. return true;
  198. }
  199. }
  200. return false;
  201. }
  202. private void HashVertices(Mesh mesh)
  203. {
  204. if (vertices == null || mesh.Vertices.Count != vertices.Length)
  205. {
  206. vertices = new int[mesh.Vertices.Count];
  207. }
  208. int i = 0;
  209. foreach (var v in mesh.Vertices)
  210. {
  211. vertices[i++] = v.id;
  212. }
  213. }
  214. }
  215. }