AdjacencyMatrix.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. // -----------------------------------------------------------------------
  2. // <copyright file="AdjacencyMatrix.cs" company="">
  3. // Original Matlab code by John Burkardt, Florida State University
  4. // Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
  5. // </copyright>
  6. // -----------------------------------------------------------------------
  7. namespace UnityEngine.U2D.Animation.TriangleNet
  8. .Tools
  9. {
  10. using System;
  11. /// <summary>
  12. /// The adjacency matrix of the mesh.
  13. /// </summary>
  14. internal class AdjacencyMatrix
  15. {
  16. // Number of adjacency entries.
  17. int nnz;
  18. // Pointers into the actual adjacency structure adj. Information about row k is
  19. // stored in entries pcol(k) through pcol(k+1)-1 of adj. Size: N + 1
  20. int[] pcol;
  21. // The adjacency structure. For each row, it contains the column indices
  22. // of the nonzero entries. Size: nnz
  23. int[] irow;
  24. /// <summary>
  25. /// Gets the number of columns (nodes of the mesh).
  26. /// </summary>
  27. public readonly int N;
  28. /// <summary>
  29. /// Gets the column pointers.
  30. /// </summary>
  31. public int[] ColumnPointers
  32. {
  33. get { return pcol; }
  34. }
  35. /// <summary>
  36. /// Gets the row indices.
  37. /// </summary>
  38. public int[] RowIndices
  39. {
  40. get { return irow; }
  41. }
  42. public AdjacencyMatrix(Mesh mesh)
  43. {
  44. this.N = mesh.vertices.Count;
  45. // Set up the adj_row adjacency pointer array.
  46. this.pcol = AdjacencyCount(mesh);
  47. this.nnz = pcol[N];
  48. // Set up the adj adjacency array.
  49. this.irow = AdjacencySet(mesh, this.pcol);
  50. SortIndices();
  51. }
  52. public AdjacencyMatrix(int[] pcol, int[] irow)
  53. {
  54. this.N = pcol.Length - 1;
  55. this.nnz = pcol[N];
  56. this.pcol = pcol;
  57. this.irow = irow;
  58. if (pcol[0] != 0)
  59. {
  60. throw new ArgumentException("Expected 0-based indexing.", "pcol");
  61. }
  62. if (irow.Length < nnz)
  63. {
  64. throw new ArgumentException();
  65. }
  66. }
  67. /// <summary>
  68. /// Computes the bandwidth of an adjacency matrix.
  69. /// </summary>
  70. /// <returns>Bandwidth of the adjacency matrix.</returns>
  71. public int Bandwidth()
  72. {
  73. int band_hi;
  74. int band_lo;
  75. int col;
  76. int i, j;
  77. band_lo = 0;
  78. band_hi = 0;
  79. for (i = 0; i < N; i++)
  80. {
  81. for (j = pcol[i]; j < pcol[i + 1]; j++)
  82. {
  83. col = irow[j];
  84. band_lo = Math.Max(band_lo, i - col);
  85. band_hi = Math.Max(band_hi, col - i);
  86. }
  87. }
  88. return band_lo + 1 + band_hi;
  89. }
  90. #region Adjacency matrix
  91. /// <summary>
  92. /// Counts adjacencies in a triangulation.
  93. /// </summary>
  94. /// <remarks>
  95. /// This routine is called to count the adjacencies, so that the
  96. /// appropriate amount of memory can be set aside for storage when
  97. /// the adjacency structure is created.
  98. ///
  99. /// The triangulation is assumed to involve 3-node triangles.
  100. ///
  101. /// Two nodes are "adjacent" if they are both nodes in some triangle.
  102. /// Also, a node is considered to be adjacent to itself.
  103. /// </remarks>
  104. int[] AdjacencyCount(Mesh mesh)
  105. {
  106. int n = N;
  107. int n1, n2, n3;
  108. int tid, nid;
  109. int[] pcol = new int[n + 1];
  110. // Set every node to be adjacent to itself.
  111. for (int i = 0; i < n; i++)
  112. {
  113. pcol[i] = 1;
  114. }
  115. // Examine each triangle.
  116. foreach (var tri in mesh.triangles)
  117. {
  118. tid = tri.id;
  119. n1 = tri.vertices[0].id;
  120. n2 = tri.vertices[1].id;
  121. n3 = tri.vertices[2].id;
  122. // Add edge (1,2) if this is the first occurrence, that is, if
  123. // the edge (1,2) is on a boundary (nid <= 0) or if this triangle
  124. // is the first of the pair in which the edge occurs (tid < nid).
  125. nid = tri.neighbors[2].tri.id;
  126. if (nid < 0 || tid < nid)
  127. {
  128. pcol[n1] += 1;
  129. pcol[n2] += 1;
  130. }
  131. // Add edge (2,3).
  132. nid = tri.neighbors[0].tri.id;
  133. if (nid < 0 || tid < nid)
  134. {
  135. pcol[n2] += 1;
  136. pcol[n3] += 1;
  137. }
  138. // Add edge (3,1).
  139. nid = tri.neighbors[1].tri.id;
  140. if (nid < 0 || tid < nid)
  141. {
  142. pcol[n3] += 1;
  143. pcol[n1] += 1;
  144. }
  145. }
  146. // We used PCOL to count the number of entries in each column.
  147. // Convert it to pointers into the ADJ array.
  148. for (int i = n; i > 0; i--)
  149. {
  150. pcol[i] = pcol[i - 1];
  151. }
  152. pcol[0] = 0;
  153. for (int i = 1; i <= n; i++)
  154. {
  155. pcol[i] = pcol[i - 1] + pcol[i];
  156. }
  157. return pcol;
  158. }
  159. /// <summary>
  160. /// Sets adjacencies in a triangulation.
  161. /// </summary>
  162. /// <remarks>
  163. /// This routine can be used to create the compressed column storage
  164. /// for a linear triangle finite element discretization of Poisson's
  165. /// equation in two dimensions.
  166. /// </remarks>
  167. int[] AdjacencySet(Mesh mesh, int[] pcol)
  168. {
  169. int n = this.N;
  170. int[] col = new int[n];
  171. // Copy of the adjacency rows input.
  172. Array.Copy(pcol, col, n);
  173. int i, nnz = pcol[n];
  174. // Output list, stores the actual adjacency information.
  175. int[] list = new int[nnz];
  176. // Set every node to be adjacent to itself.
  177. for (i = 0; i < n; i++)
  178. {
  179. list[col[i]] = i;
  180. col[i] += 1;
  181. }
  182. int n1, n2, n3; // Vertex numbers.
  183. int tid, nid; // Triangle and neighbor id.
  184. // Examine each triangle.
  185. foreach (var tri in mesh.triangles)
  186. {
  187. tid = tri.id;
  188. n1 = tri.vertices[0].id;
  189. n2 = tri.vertices[1].id;
  190. n3 = tri.vertices[2].id;
  191. // Add edge (1,2) if this is the first occurrence, that is, if
  192. // the edge (1,2) is on a boundary (nid <= 0) or if this triangle
  193. // is the first of the pair in which the edge occurs (tid < nid).
  194. nid = tri.neighbors[2].tri.id;
  195. if (nid < 0 || tid < nid)
  196. {
  197. list[col[n1]++] = n2;
  198. list[col[n2]++] = n1;
  199. }
  200. // Add edge (2,3).
  201. nid = tri.neighbors[0].tri.id;
  202. if (nid < 0 || tid < nid)
  203. {
  204. list[col[n2]++] = n3;
  205. list[col[n3]++] = n2;
  206. }
  207. // Add edge (3,1).
  208. nid = tri.neighbors[1].tri.id;
  209. if (nid < 0 || tid < nid)
  210. {
  211. list[col[n1]++] = n3;
  212. list[col[n3]++] = n1;
  213. }
  214. }
  215. return list;
  216. }
  217. public void SortIndices()
  218. {
  219. int k1, k2, n = N;
  220. int[] list = this.irow;
  221. // Ascending sort the entries for each column.
  222. for (int i = 0; i < n; i++)
  223. {
  224. k1 = pcol[i];
  225. k2 = pcol[i + 1];
  226. Array.Sort(list, k1, k2 - k1);
  227. }
  228. }
  229. #endregion
  230. }
  231. }