| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- // -----------------------------------------------------------------------
- // <copyright file="AdjacencyMatrix.cs" company="">
- // Original Matlab code by John Burkardt, Florida State University
- // Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
- // </copyright>
- // -----------------------------------------------------------------------
- namespace UnityEngine.U2D.Animation.TriangleNet
- .Tools
- {
- using System;
- /// <summary>
- /// The adjacency matrix of the mesh.
- /// </summary>
- internal class AdjacencyMatrix
- {
- // Number of adjacency entries.
- int nnz;
- // Pointers into the actual adjacency structure adj. Information about row k is
- // stored in entries pcol(k) through pcol(k+1)-1 of adj. Size: N + 1
- int[] pcol;
- // The adjacency structure. For each row, it contains the column indices
- // of the nonzero entries. Size: nnz
- int[] irow;
- /// <summary>
- /// Gets the number of columns (nodes of the mesh).
- /// </summary>
- public readonly int N;
- /// <summary>
- /// Gets the column pointers.
- /// </summary>
- public int[] ColumnPointers
- {
- get { return pcol; }
- }
- /// <summary>
- /// Gets the row indices.
- /// </summary>
- public int[] RowIndices
- {
- get { return irow; }
- }
- public AdjacencyMatrix(Mesh mesh)
- {
- this.N = mesh.vertices.Count;
- // Set up the adj_row adjacency pointer array.
- this.pcol = AdjacencyCount(mesh);
- this.nnz = pcol[N];
- // Set up the adj adjacency array.
- this.irow = AdjacencySet(mesh, this.pcol);
- SortIndices();
- }
- public AdjacencyMatrix(int[] pcol, int[] irow)
- {
- this.N = pcol.Length - 1;
- this.nnz = pcol[N];
- this.pcol = pcol;
- this.irow = irow;
- if (pcol[0] != 0)
- {
- throw new ArgumentException("Expected 0-based indexing.", "pcol");
- }
- if (irow.Length < nnz)
- {
- throw new ArgumentException();
- }
- }
- /// <summary>
- /// Computes the bandwidth of an adjacency matrix.
- /// </summary>
- /// <returns>Bandwidth of the adjacency matrix.</returns>
- public int Bandwidth()
- {
- int band_hi;
- int band_lo;
- int col;
- int i, j;
- band_lo = 0;
- band_hi = 0;
- for (i = 0; i < N; i++)
- {
- for (j = pcol[i]; j < pcol[i + 1]; j++)
- {
- col = irow[j];
- band_lo = Math.Max(band_lo, i - col);
- band_hi = Math.Max(band_hi, col - i);
- }
- }
- return band_lo + 1 + band_hi;
- }
- #region Adjacency matrix
- /// <summary>
- /// Counts adjacencies in a triangulation.
- /// </summary>
- /// <remarks>
- /// This routine is called to count the adjacencies, so that the
- /// appropriate amount of memory can be set aside for storage when
- /// the adjacency structure is created.
- ///
- /// The triangulation is assumed to involve 3-node triangles.
- ///
- /// Two nodes are "adjacent" if they are both nodes in some triangle.
- /// Also, a node is considered to be adjacent to itself.
- /// </remarks>
- int[] AdjacencyCount(Mesh mesh)
- {
- int n = N;
- int n1, n2, n3;
- int tid, nid;
- int[] pcol = new int[n + 1];
- // Set every node to be adjacent to itself.
- for (int i = 0; i < n; i++)
- {
- pcol[i] = 1;
- }
- // Examine each triangle.
- foreach (var tri in mesh.triangles)
- {
- tid = tri.id;
- n1 = tri.vertices[0].id;
- n2 = tri.vertices[1].id;
- n3 = tri.vertices[2].id;
- // Add edge (1,2) if this is the first occurrence, that is, if
- // the edge (1,2) is on a boundary (nid <= 0) or if this triangle
- // is the first of the pair in which the edge occurs (tid < nid).
- nid = tri.neighbors[2].tri.id;
- if (nid < 0 || tid < nid)
- {
- pcol[n1] += 1;
- pcol[n2] += 1;
- }
- // Add edge (2,3).
- nid = tri.neighbors[0].tri.id;
- if (nid < 0 || tid < nid)
- {
- pcol[n2] += 1;
- pcol[n3] += 1;
- }
- // Add edge (3,1).
- nid = tri.neighbors[1].tri.id;
- if (nid < 0 || tid < nid)
- {
- pcol[n3] += 1;
- pcol[n1] += 1;
- }
- }
- // We used PCOL to count the number of entries in each column.
- // Convert it to pointers into the ADJ array.
- for (int i = n; i > 0; i--)
- {
- pcol[i] = pcol[i - 1];
- }
- pcol[0] = 0;
- for (int i = 1; i <= n; i++)
- {
- pcol[i] = pcol[i - 1] + pcol[i];
- }
- return pcol;
- }
- /// <summary>
- /// Sets adjacencies in a triangulation.
- /// </summary>
- /// <remarks>
- /// This routine can be used to create the compressed column storage
- /// for a linear triangle finite element discretization of Poisson's
- /// equation in two dimensions.
- /// </remarks>
- int[] AdjacencySet(Mesh mesh, int[] pcol)
- {
- int n = this.N;
- int[] col = new int[n];
- // Copy of the adjacency rows input.
- Array.Copy(pcol, col, n);
- int i, nnz = pcol[n];
- // Output list, stores the actual adjacency information.
- int[] list = new int[nnz];
- // Set every node to be adjacent to itself.
- for (i = 0; i < n; i++)
- {
- list[col[i]] = i;
- col[i] += 1;
- }
- int n1, n2, n3; // Vertex numbers.
- int tid, nid; // Triangle and neighbor id.
- // Examine each triangle.
- foreach (var tri in mesh.triangles)
- {
- tid = tri.id;
- n1 = tri.vertices[0].id;
- n2 = tri.vertices[1].id;
- n3 = tri.vertices[2].id;
- // Add edge (1,2) if this is the first occurrence, that is, if
- // the edge (1,2) is on a boundary (nid <= 0) or if this triangle
- // is the first of the pair in which the edge occurs (tid < nid).
- nid = tri.neighbors[2].tri.id;
- if (nid < 0 || tid < nid)
- {
- list[col[n1]++] = n2;
- list[col[n2]++] = n1;
- }
- // Add edge (2,3).
- nid = tri.neighbors[0].tri.id;
- if (nid < 0 || tid < nid)
- {
- list[col[n2]++] = n3;
- list[col[n3]++] = n2;
- }
- // Add edge (3,1).
- nid = tri.neighbors[1].tri.id;
- if (nid < 0 || tid < nid)
- {
- list[col[n1]++] = n3;
- list[col[n3]++] = n1;
- }
- }
- return list;
- }
- public void SortIndices()
- {
- int k1, k2, n = N;
- int[] list = this.irow;
- // Ascending sort the entries for each column.
- for (int i = 0; i < n; i++)
- {
- k1 = pcol[i];
- k2 = pcol[i + 1];
- Array.Sort(list, k1, k2 - k1);
- }
- }
- #endregion
- }
- }
|