/// <summary> /// Solves the linear system A * x = b, where A is the original matrix (before the factorization), /// b = <paramref name="rhsVector"/> and x is the solution vector, which will be returned. /// </summary> /// <param name="rhsVector"> /// The right hand side vector. Its <see cref="IIndexable1D.Length"/> must be equal to /// <see cref="Matrices.IIndexable2D.NumRows"/> of the original matrix A. /// </param> /// Thrown if the length of <paramref name="rhsVector"/> is different than <see cref="Matrices.IIndexable2D.NumRows"/> /// of the original matrix A. /// </exception> public static Vector SolveLinearSystem(this ITriangulation triangulation, Vector rhsVector) { var solution = Vector.CreateZero(triangulation.Order); triangulation.SolveLinearSystem(rhsVector, solution); return(solution); }
public DelaunayTriangulationManager(ICoordinateValidator cv, ITriangulation triangulator) { _triangulator = triangulator; this.x = cv.getX(); this.y = cv.getY(); this.z_as_fxy = cv.get_Z_as_fxy(); }
public void visualizeEdges(ITriangulation <Vector3Vertex, DefaultTriangulationCell <Vector3Vertex> > triangulation) { /* * * foreach (var edge in voronoiMesh.Edges) * { * calculateCircumsphere * var from = edge.Source.Circumcenter; * var to = edge.Target.Circumcenter; * drawingCanvas.Children.Add(new Line { X1 = from.X, Y1 = from.Y, X2 = to.X, Y2 = to.Y, Stroke = Brushes.Black }); * } * * foreach (var cell in voronoiMesh.Vertices) * { * for (int i = 0; i < 3; i++) * { * if (cell.Adjacency[i] == null) * { * var from = cell.Circumcenter; * var t = cell.Vertices.Where((_, j) => j != i).ToArray(); * var factor = 100 * IsLeft(t[0].ToPoint(), t[1].ToPoint(), from) * IsLeft(t[0].ToPoint(), t[1].ToPoint(), Center(cell)); * var dir = new Point(0.5 * (t[0].Position[0] + t[1].Position[0]), 0.5 * (t[0].Position[1] + t[1].Position[1])) - from; * var to = from + factor * dir; * drawingCanvas.Children.Add(new Line { X1 = from.X, Y1 = from.Y, X2 = to.X, Y2 = to.Y, Stroke = Brushes.Black }); * } * } * } * * ShowVertices(Vertices); * drawingCanvas.Children.Add(new Rectangle { Width = drawingCanvas.ActualWidth, Height = drawingCanvas.ActualHeight, Stroke = Brushes.Black, StrokeThickness = 3 }); * } */ // visualize foreach (var cell in triangulation.Cells) { for (int i = 0; i < cell.Adjacency.Length; i++) { var F = cell.Adjacency[i]; int sharedBoundaries = 0; // vertices shared with F: for (int j = 0; j < cell.Vertices.Length; j++) { if (i != j) { sharedBoundaries++; //cell.Vertices[j] } } Debug.Log("Shared vertices: " + sharedBoundaries); } // drawLine(lastPos, vertex.toVector3(), ColorAssistant.getQualitativeColor(0)); } }
/// <summary> /// Provide new values for the vertices that constitute the triangles of the specified face. /// </summary> /// <param name="face">The face whose triangle vertices should be udpated.</param> /// <param name="triangulation">The triangulation method used for converting faces to triangles.</param> /// <remarks> /// <para>This method will update the vertex attribute values for this face, but will not /// immediately push these changes to the mesh itself. Instead, it will simply mark the /// relevant submesh as dirty. Call <see cref="RebuildMesh"/>() in order to commit all /// changes and apply them to the mesh.</para> /// /// <para>The <paramref name="triangulation"/> parameter is expected to match the kind of /// triangulation used when first creating the dynamic mesh, but is permitted to set the /// vertex attributes however it likes. That is, the number of triangles generated for /// each face and the vertex indices used by each of these triangles cannot change, only /// vertex attributes. Not all vertex attributes need or are always expected to be /// changed either. In many cases, simply changing normals or uvs, for example, is /// all that is needed, and all other vertex attribute values can remain the same.</para> /// </remarks> public void RebuildFace(Topology.Face face, ITriangulation triangulation) { var submesh = _submeshes[_faceSubmeshIndices[face.index]]; var vertexAttributeArrays = GetIndexedVertexAttributeArrays(submesh, _faceFirstVertexIndices[face.index]); triangulation.RebuildFace(face, vertexAttributeArrays); submesh.isDirty = true; }
/// <summary> /// Ring:划分Delaunay三角网,结果保存于tsData /// </summary> /// <param name="depth">深度</param> /// <param name="interpolateFunc">插值函数</param> public void MeshRing( double depth, Func <IList <Point>, double, double, double, double> interpolateFunc) { try { triangulations = Triangulation.CreateDelaunay(this.allVerticesList); this.TsData.VerticesList = new List <Point3D>(this.allVerticesList.Count); this.TsData.TriLinksList = new List <TriLink>(this.triangulations.Cells.Count()); // 以Dict记录三角形的编号 int num = 1; foreach (var cell in this.triangulations.Cells) { for (int i = 0; i < 3; ++i) { var v = cell.Vertices[i]; if (!this.vertexnumDictionary.ContainsKey(v)) { this.vertexnumDictionary.Add(v, num++); } } // 根据编号写ts的TriLinksList this.TsData.TriLinksList.Add(new TriLink { VertexA = this.vertexnumDictionary[cell.Vertices[0]], VertexB = this.vertexnumDictionary[cell.Vertices[1]], VertexC = this.vertexnumDictionary[cell.Vertices[2]] }); } // 写ts的VerticesList, 并插值Z foreach (var kv in this.vertexnumDictionary.OrderBy(n => n.Value)) { var vPos = kv.Key.Position; var x = vPos[0]; var y = vPos[1]; var z = interpolateFunc(this.edgeVerticesList, depth, x, y); this.TsData.VerticesList.Add(new Point3D(x, y, z)); } } catch (Exception ex) { MessageBox.Show(ex.Message); return; } }
public void visualizeVertices(ITriangulation <Vector3Vertex, DefaultTriangulationCell <Vector3Vertex> > triangulation) { // visualize foreach (var cell in triangulation.Cells) { foreach (var vertex in cell.Vertices) { GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); sphere.transform.position = vertex.toVector3(); sphere.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f); sphere.transform.SetParent(_delaunay.transform); setColor(sphere, ColorAssistant.getQualitativeColor(0)); } } }
/// <summary> /// Creates a dynamic mesh instance for the given faces, using the specified vertex attributes and triangulation object to construct the vertex data and triangles. /// </summary> /// <param name="faces">The faces for which to generate triangle meshes.</param> /// <param name="vertexAttributes">The types of vertex data to include in the meshes, such as position, color, and normal.</param> /// <param name="triangulation">The object which is responsible for turning each individual face into triangles with a mesh.</param> /// <param name="maxVerticesPerSubmesh">The maximum number of vertices allowed per submesh. Defaults to Unity's built-in maximum of 65534.</param> /// <returns>A dynamic mesh instance created from the given faces and triangulation.</returns> public static DynamicMesh Create(IEnumerable <Topology.Face> faces, VertexAttributes vertexAttributes, ITriangulation triangulation, int maxVerticesPerSubmesh = 65534) { var dynamicMesh = CreateInstance <DynamicMesh>(); dynamicMesh._vertexAttributes = vertexAttributes; dynamicMesh._maxVerticesPerSubmesh = maxVerticesPerSubmesh; dynamicMesh.Initialize(new IEnumerable <Topology.Face>[] { faces }, triangulation); return(dynamicMesh); }
private void Initialize(IEnumerable <IEnumerable <Topology.Face> > faceGroups, ITriangulation triangulation) { int maxFaceIndex = -1; var dynamicFaceSubmeshIndicesArray = new int[65536]; var dynamicFaceFirstVertexIndicesArray = new int[65536]; _cachedIndexedVertexAttributeArrays = new IndexedVertexAttributeArrays(); var submeshList = new List <Submesh>(); var vertexAttributeArrays = new DynamicVertexAttributeArrays(_vertexAttributes, _maxVerticesPerSubmesh); var triangleIndices = new List <int>(); foreach (var faceGroup in faceGroups) { foreach (var face in faceGroup) { var vertexCount = triangulation.GetVertexCount(face); if (vertexAttributeArrays.index + vertexCount > _maxVerticesPerSubmesh) { triangulation.FinalizeSubmesh(submeshList.Count); submeshList.Add(new Submesh(vertexAttributeArrays, triangleIndices)); vertexAttributeArrays.Reset(); triangleIndices.Clear(); } maxFaceIndex = Mathf.Max(maxFaceIndex, face.index); SetGrowableArrayElement(ref dynamicFaceSubmeshIndicesArray, face.index, submeshList.Count); SetGrowableArrayElement(ref dynamicFaceFirstVertexIndicesArray, face.index, vertexAttributeArrays.index); vertexAttributeArrays.Grow(vertexCount); triangulation.BuildFace(face, vertexAttributeArrays, triangleIndices); } if (vertexAttributeArrays.index > 0) { triangulation.FinalizeSubmesh(submeshList.Count); submeshList.Add(new Submesh(vertexAttributeArrays, triangleIndices)); vertexAttributeArrays.Reset(); triangleIndices.Clear(); } } _submeshes = submeshList.ToArray(); var faceCount = maxFaceIndex + 1; _faceSubmeshIndices = new int[faceCount]; _faceFirstVertexIndices = new int[faceCount]; Array.Copy(dynamicFaceSubmeshIndicesArray, _faceSubmeshIndices, faceCount); Array.Copy(dynamicFaceFirstVertexIndicesArray, _faceFirstVertexIndices, faceCount); }
/// <summary> /// Calculates the Schur complement of M/C = S = A - B^T * inv(C) * B, where M = [A B; B^T C]. /// This method constructs inv(C) * B one column at a time and uses that column to calculate the superdiagonal /// entries of the corresponding column of B^T * inv(C) * B. /// </summary> public static SymmetricMatrix CalcSchurComplementSymmetric(SymmetricMatrix A, CscMatrix B, ITriangulation inverseC) { //TODO: Unfortunately this cannot take advantage of MKL for CSC^T * vector. double[] valuesB = B.RawValues; int[] rowIndicesB = B.RawRowIndices; int[] colOffsetsB = B.RawColOffsets; var S = SymmetricMatrix.CreateZero(A.Order); for (int j = 0; j < B.NumColumns; ++j) { // column j of (inv(C) * B) = inv(C) * column j of B Vector colB = B.GetColumn(j); double[] colInvCB = inverseC.SolveLinearSystem(colB).RawData; // column j of (B^T * inv(C) * B) = B^T * column j of (inv(C) * B) // However we only need the superdiagonal part of this column. // Thus we only multiply the rows i of B^T (stored as columns i of B) with i <= j. for (int i = 0; i <= j; ++i) { double dot = 0.0; int colStart = colOffsetsB[i]; //inclusive int colEnd = colOffsetsB[i + 1]; //exclusive for (int k = colStart; k < colEnd; ++k) { dot += valuesB[k] * colInvCB[rowIndicesB[k]]; } // Perform the subtraction S = A - (B^T * inv(C) * B) for the current (i, j) int indexS = S.Find1DIndex(i, j); S.RawData[indexS] = A.RawData[indexS] - dot; } } return(S); }