private static void InsertEdge(TriMesh mesh, TriMesh.HalfEdge inner, TriMesh.HalfEdge outer) { //TriMesh.Edge left = new TriMesh.Edge(); //left.HalfEdge0 = outer; //outer.Edge = left; //inner.Next.Edge = left; //TriMesh.Edge right = outer.Edge; //right.HalfEdge0 = inner; //inner.Edge = right; //outer.Opposite.Edge = right; //inner.Opposite = outer.Opposite; //inner.Next.Opposite = outer; //outer.Opposite.Opposite = inner; //outer.Opposite = inner.Next; inner.Opposite = outer.Opposite; inner.Next.Opposite = outer; outer.Opposite.Opposite = inner; outer.Opposite = inner.Next; outer.Edge.HalfEdge0 = outer; TriMesh.Edge edge = new TriMesh.Edge(); edge.HalfEdge0 = inner; inner.Edge = edge; inner.Opposite.Edge = edge; inner.Next.Edge = outer.Edge; mesh.AppendToEdgeList(edge); }
TriMesh.Edge CreateNewEdge(TriMesh.Vertex from, TriMesh.Vertex to) { TriMesh mesh = (TriMesh)from.Mesh; // Create new edge TriMesh.Edge edge = new TriMesh.Edge(); mesh.AppendToEdgeList(edge); // Create new halfedges TriMesh.HalfEdge hf0 = new TriMesh.HalfEdge(); mesh.AppendToHalfedgeList(hf0); hf0.Opposite = new TriMesh.HalfEdge(); mesh.AppendToHalfedgeList(hf0.Opposite); // Connect opposite halfedge to inner halfedge hf0.Opposite.Opposite = hf0; // Connect edge to halfedges edge.HalfEdge0 = hf0; // Connect halfedges to edge hf0.Edge = edge; hf0.Opposite.Edge = edge; // Connect halfedges to vertices hf0.ToVertex = to; hf0.Opposite.ToVertex = from; // Connect vertex to outgoing halfedge if it doesn't have one yet if (from.HalfEdge == null) { from.HalfEdge = hf0; } return(edge); }
public static TriMesh.Vertex VertexSplit(TriMesh.Vertex v1, TriMesh.Vertex share1, TriMesh.Vertex share2, Vector3D v1Position, Vector3D v2Position, int fixedIndex) { TriMesh.HalfEdge[] hfs = FindGroup(v1, share1, share2); TriMesh mesh = (TriMesh)v1.Mesh; v1.Traits.Position = v1Position; v1.HalfEdge = hfs[0]; TriMesh.Vertex v2 = new TriMesh.Vertex(); v2.Traits = new VertexTraits(v2Position); v2.Traits.FixedIndex = fixedIndex; v2.HalfEdge = hfs[1]; mesh.AppendToVertexList(v2); for (int i = 0; i < hfs.Length - 1; i++) { hfs[i].Opposite.ToVertex = v2; } TriMesh.HalfEdge[] triangle1 = AddInnerTriangle(mesh, v1, v2, share1); InsertEdge(mesh, triangle1[1], hfs[0]); TriMesh.HalfEdge[] triangle2 = AddInnerTriangle(mesh, v2, v1, share2); InsertEdge(mesh, triangle2[1], hfs[hfs.Length - 1]); TriMesh.Edge edge = new TriMesh.Edge(); edge.HalfEdge0 = triangle1[0]; triangle1[0].Edge = edge; triangle2[0].Edge = edge; triangle1[0].Opposite = triangle2[0]; triangle2[0].Opposite = triangle1[0]; mesh.AppendToEdgeList(edge); return(v2); }
/// <summary> /// Adds a face to the mesh with the specified face traits. /// </summary> /// <param name="faceTraits">The custom traits for the face to add to the mesh.</param> /// <param name="faceVertices">The vertices of the face in counterclockwise order.</param> /// <returns>The face created by this method.</returns> /// <exception cref="BadTopologyException"> /// Thrown when fewer than three vertices are given or the vertices cannot form a valid face. /// </exception> /// <exception cref="ArgumentNullException">Thrown when a null vertex is given.</exception> private static TriMesh.Face CreateFace(TriMesh mesh, params TriMesh.Vertex[] faceVertices) { int n = faceVertices.Length; // Require at least 3 vertices if (n < 3) { throw new BadTopologyException("Cannot create a polygon with fewer than three vertices."); } TriMesh.Edge e; TriMesh.Face f; TriMesh.HalfEdge[] faceHalfedges = new TriMesh.HalfEdge[n]; bool[] isNewEdge = new bool[n], isUsedVertex = new bool[n]; for (int i = 0; i < n; i++) { int j = (i + 1) % n; faceHalfedges[i] = faceVertices[i].FindHalfedgeTo(faceVertices[j]); } // Make sure input is (mostly) acceptable before making any changes to the mesh for (int i = 0; i < n; ++i) { int j = (i + 1) % n; if (faceVertices[i] == null) { throw new ArgumentNullException("Can't add a null vertex to a face."); } if (!faceVertices[i].OnBoundary) { throw new BadTopologyException("Can't add an edge to a vertex on the interior of a mesh."); } // Find existing halfedges for this face faceHalfedges[i] = faceVertices[i].FindHalfedgeTo(faceVertices[j]); isNewEdge[i] = (faceHalfedges[i] == null); isUsedVertex[i] = (faceVertices[i].HalfEdge != null); if (!isNewEdge[i] && !faceHalfedges[i].OnBoundary) { throw new BadTopologyException("Can't add more than two faces to an edge."); } } // Create face f = new TriMesh.Face(default(FaceTraits)); mesh.AppendToFaceList(f); // Create new edges for (int i = 0; i < n; ++i) { int j = (i + 1) % n; if (isNewEdge[i]) { // Create new edge e = new TriMesh.Edge(); mesh.AppendToEdgeList(e); // Create new halfedges faceHalfedges[i] = new TriMesh.HalfEdge(); mesh.AppendToHalfedgeList(faceHalfedges[i]); faceHalfedges[i].Opposite = new TriMesh.HalfEdge(); mesh.AppendToHalfedgeList(faceHalfedges[i].Opposite); // Connect opposite halfedge to inner halfedge faceHalfedges[i].Opposite.Opposite = faceHalfedges[i]; // Connect edge to halfedges e.HalfEdge0 = faceHalfedges[i]; // Connect halfedges to edge faceHalfedges[i].Edge = e; faceHalfedges[i].Opposite.Edge = e; // Connect halfedges to vertices faceHalfedges[i].ToVertex = faceVertices[j]; faceHalfedges[i].Opposite.ToVertex = faceVertices[i]; // Connect vertex to outgoing halfedge if it doesn't have one yet if (faceVertices[i].HalfEdge == null) { faceVertices[i].HalfEdge = faceHalfedges[i]; } } if (faceHalfedges[i].Face != null) { throw new BadTopologyException("An inner halfedge already has a face assigned to it."); } // Connect inner halfedge to face faceHalfedges[i].Face = f; } // Connect next/previous halfedges for (int i = 0; i < n; ++i) { int j = (i + 1) % n; // Outer halfedges if (isNewEdge[i] && isNewEdge[j] && isUsedVertex[j]) // Both edges are new and vertex has faces connected already { TriMesh.HalfEdge closeHalfedge = null; // Find the closing halfedge of the first available opening foreach (TriMesh.HalfEdge h in faceVertices[j].HalfEdges) { if (h.Face == null) { closeHalfedge = h; break; } } TriMesh.HalfEdge openHalfedge = closeHalfedge.Previous; // Link new outer halfedges into this opening faceHalfedges[i].Opposite.Previous = openHalfedge; openHalfedge.Next = faceHalfedges[i].Opposite; faceHalfedges[j].Opposite.Next = closeHalfedge; closeHalfedge.Previous = faceHalfedges[j].Opposite; } else if (isNewEdge[i] && isNewEdge[j]) // Both edges are new { faceHalfedges[i].Opposite.Previous = faceHalfedges[j].Opposite; faceHalfedges[j].Opposite.Next = faceHalfedges[i].Opposite; } else if (isNewEdge[i] && !isNewEdge[j]) // This is new, next is old { faceHalfedges[i].Opposite.Previous = faceHalfedges[j].Previous; faceHalfedges[j].Previous.Next = faceHalfedges[i].Opposite; } else if (!isNewEdge[i] && isNewEdge[j]) // This is old, next is new { faceHalfedges[i].Next.Previous = faceHalfedges[j].Opposite; faceHalfedges[j].Opposite.Next = faceHalfedges[i].Next; } // Relink faces before adding new edges if they are in the way of a new face else if (!isNewEdge[i] && !isNewEdge[j] && faceHalfedges[i].Next != faceHalfedges[j]) { TriMesh.HalfEdge closeHalfedge = faceHalfedges[i].Opposite; // Find the closing halfedge of the opening opposite the opening halfedge i is on do { closeHalfedge = closeHalfedge.Previous.Opposite; } while (closeHalfedge.Face != null && closeHalfedge != faceHalfedges[j] && closeHalfedge != faceHalfedges[i].Opposite); if (closeHalfedge == faceHalfedges[j] || closeHalfedge == faceHalfedges[i].Opposite) { throw new BadTopologyException("Unable to find an opening to relink an existing face."); } TriMesh.HalfEdge openHalfedge = closeHalfedge.Previous; // Remove group of faces between two openings, close up gap to form one opening openHalfedge.Next = faceHalfedges[i].Next; faceHalfedges[i].Next.Previous = openHalfedge; // Insert group of faces into target opening faceHalfedges[j].Previous.Next = closeHalfedge; closeHalfedge.Previous = faceHalfedges[j].Previous; } // Inner halfedges faceHalfedges[i].Next = faceHalfedges[j]; faceHalfedges[j].Previous = faceHalfedges[i]; } // Connect face to an inner halfedge f.HalfEdge = faceHalfedges[0]; return(f); }
public TriMesh.Vertex VertexSplit1(TriMesh.Vertex v, TriMesh.Vertex vshard1, TriMesh.Vertex vshard2, Vector3D v1Position, Vector3D v2Position, int v2FixedIndex) { //1.Get two group of verties TriMesh.HalfEdge[] processGroup = FindGroup(v, vshard1, vshard2); TriMesh mesh = (TriMesh)v.Mesh; TriMesh.Vertex v1 = null; TriMesh.Vertex v2 = null; TriMesh.Vertex newVertex = null; v1 = v; v.Traits.Position = v1Position; v2 = new TriMesh.Vertex(); v2.Traits = new VertexTraits(Vector3D.Zero); newVertex = v2; newVertex.Traits.FixedIndex = v2FixedIndex; v2.Mesh = v.Mesh; v2.Traits.Position = v2Position; //2.Process the Topology TriMesh.HalfEdge hf1Origin = processGroup[0]; TriMesh.HalfEdge hf2Origin = processGroup[processGroup.Length - 1]; //Add new edge TriMesh.HalfEdge hf3 = new TriMesh.HalfEdge(); TriMesh.HalfEdge hf3Oppsite = new TriMesh.HalfEdge(); TriMesh.Edge edge = new TriMesh.Edge(); hf3.Opposite = hf3Oppsite; hf3Oppsite.Opposite = hf3; edge.HalfEdge0 = hf3; edge.HalfEdge1 = hf3Oppsite; hf3.Edge = edge; hf3Oppsite.Edge = edge; hf3.ToVertex = v2; hf3Oppsite.ToVertex = v1; //Handle hf1Origin which is outter hafledge [INNER] TriMesh.HalfEdge hf1 = new TriMesh.HalfEdge(); hf1.Opposite = hf1Origin; hf1.ToVertex = v1; TriMesh.HalfEdge hf1Other = new TriMesh.HalfEdge(); hf1Other.Opposite = hf1Origin.Opposite; hf1Other.ToVertex = hf1Origin.ToVertex; hf1.Previous = hf1Other; hf1Other.Next = hf1; hf1.Next = hf3; hf3.Previous = hf1; hf1Other.Previous = hf3; hf3.Next = hf1Other; //Handle hf2Origin which is inner hafledge [INNER] TriMesh.HalfEdge hf2 = new TriMesh.HalfEdge(); hf2.Opposite = hf2Origin; hf2.ToVertex = v2; TriMesh.HalfEdge hf2Other = new TriMesh.HalfEdge(); hf2Other.Opposite = hf2Origin.Opposite; hf2Other.ToVertex = hf2Origin.ToVertex; hf2.Previous = hf2Other; hf2Other.Next = hf2; hf2.Next = hf3Oppsite; hf3Oppsite.Previous = hf2; hf2Other.Previous = hf3Oppsite; hf3Oppsite.Next = hf2Other; TriMesh.Face face1 = new TriMesh.Face(); TriMesh.Face face2 = new TriMesh.Face(); face1.HalfEdge = hf3; hf3.Face = face1; hf1.Face = face1; hf1Other.Face = face1; face2.HalfEdge = hf3Oppsite; hf3Oppsite.Face = face2; hf2.Face = face2; hf2Other.Face = face2; //Process the outside TriMesh.Edge edge1 = new TriMesh.Edge(); TriMesh.HalfEdge hf1OriginOppsite = hf1Origin.Opposite; hf1Origin.Opposite = hf1; hf1.Edge = hf1Origin.Edge; hf1OriginOppsite.Opposite = hf1Other; hf1OriginOppsite.ToVertex = v2; hf1OriginOppsite.Edge = edge1; hf1Other.Edge = edge1; edge1.HalfEdge0 = hf1Other; edge1.HalfEdge1 = hf1OriginOppsite; TriMesh.Edge edge2 = new TriMesh.Edge(); TriMesh.HalfEdge hf2OriginOppsite = hf2Origin.Opposite; hf2Origin.Opposite = hf2; hf2.Edge = hf2Origin.Edge; hf2OriginOppsite.Opposite = hf2Other; hf2OriginOppsite.ToVertex = v1; hf2OriginOppsite.Edge = edge2; hf2Other.Edge = edge2; edge2.HalfEdge0 = hf2Other; edge2.HalfEdge1 = hf2OriginOppsite; v1.HalfEdge = hf1Origin; v2.HalfEdge = hf2Origin; mesh.AppendToEdgeList(edge); mesh.AppendToEdgeList(edge1); mesh.AppendToEdgeList(edge2); mesh.AppendToFaceList(face1); mesh.AppendToFaceList(face2); mesh.AppendToHalfedgeList(hf1); mesh.AppendToHalfedgeList(hf1Other); mesh.AppendToHalfedgeList(hf2); mesh.AppendToHalfedgeList(hf2Other); mesh.AppendToHalfedgeList(hf3); mesh.AppendToHalfedgeList(hf3Oppsite); mesh.AppendToVertexList(newVertex); for (int i = 1; i < processGroup.Length - 1; i++) { processGroup[i].Opposite.ToVertex = newVertex; } //mesh.FixIndex(); return(newVertex); }
/// <summary> /// Adds a face to the mesh with the specified face traits. /// </summary> /// <param name="faceTraits">The custom traits for the face to add to the mesh.</param> /// <param name="faceVertices">The vertices of the face in counterclockwise order.</param> /// <returns>The face created by this method.</returns> /// <exception cref="BadTopologyException"> /// Thrown when fewer than three vertices are given or the vertices cannot form a valid face. /// </exception> /// <exception cref="ArgumentNullException">Thrown when a null vertex is given.</exception> private static TriMesh.Face CreateFace(TriMesh mesh, params TriMesh.Vertex[] faceVertices) { int n = faceVertices.Length; // Require at least 3 vertices if (n < 3) { throw new BadTopologyException("Cannot create a polygon with fewer than three vertices."); } TriMesh.Edge e; TriMesh.Face f; TriMesh.HalfEdge[] faceHalfedges = new TriMesh.HalfEdge[n]; bool[] isNewEdge = new bool[n], isUsedVertex = new bool[n]; for (int i = 0; i < n; i++) { int j = (i + 1) % n; faceHalfedges[i] = faceVertices[i].FindHalfedgeTo(faceVertices[j]); } // Make sure input is (mostly) acceptable before making any changes to the mesh for (int i = 0; i < n; ++i) { int j = (i + 1) % n; if (faceVertices[i] == null) { throw new ArgumentNullException("Can't add a null vertex to a face."); } if (!faceVertices[i].OnBoundary) { throw new BadTopologyException("Can't add an edge to a vertex on the interior of a mesh."); } // Find existing halfedges for this face faceHalfedges[i] = faceVertices[i].FindHalfedgeTo(faceVertices[j]); isNewEdge[i] = (faceHalfedges[i] == null); isUsedVertex[i] = (faceVertices[i].HalfEdge != null); if (!isNewEdge[i] && !faceHalfedges[i].OnBoundary) { throw new BadTopologyException("Can't add more than two faces to an edge."); } } // Create face f = new TriMesh.Face(default(FaceTraits)); mesh.AppendToFaceList(f); // Create new edges for (int i = 0; i < n; ++i) { int j = (i + 1) % n; if (isNewEdge[i]) { // Create new edge e = new TriMesh.Edge(); mesh.AppendToEdgeList(e); // Create new halfedges faceHalfedges[i] = new TriMesh.HalfEdge(); mesh.AppendToHalfedgeList(faceHalfedges[i]); faceHalfedges[i].Opposite = new TriMesh.HalfEdge(); mesh.AppendToHalfedgeList(faceHalfedges[i].Opposite); // Connect opposite halfedge to inner halfedge faceHalfedges[i].Opposite.Opposite = faceHalfedges[i]; // Connect edge to halfedges e.HalfEdge0 = faceHalfedges[i]; // Connect halfedges to edge faceHalfedges[i].Edge = e; faceHalfedges[i].Opposite.Edge = e; // Connect halfedges to vertices faceHalfedges[i].ToVertex = faceVertices[j]; faceHalfedges[i].Opposite.ToVertex = faceVertices[i]; // Connect vertex to outgoing halfedge if it doesn't have one yet if (faceVertices[i].HalfEdge == null) { faceVertices[i].HalfEdge = faceHalfedges[i]; } } if (faceHalfedges[i].Face != null) { throw new BadTopologyException("An inner halfedge already has a face assigned to it."); } // Connect inner halfedge to face faceHalfedges[i].Face = f; } // Connect next/previous halfedges for (int i = 0; i < n; ++i) { int j = (i + 1) % n; // Outer halfedges if (isNewEdge[i] && isNewEdge[j] && isUsedVertex[j]) // Both edges are new and vertex has faces connected already { TriMesh.HalfEdge closeHalfedge = null; // Find the closing halfedge of the first available opening foreach (TriMesh.HalfEdge h in faceVertices[j].HalfEdges) { if (h.Face == null) { closeHalfedge = h; break; } } TriMesh.HalfEdge openHalfedge = closeHalfedge.Previous; // Link new outer halfedges into this opening faceHalfedges[i].Opposite.Previous = openHalfedge; openHalfedge.Next = faceHalfedges[i].Opposite; faceHalfedges[j].Opposite.Next = closeHalfedge; closeHalfedge.Previous = faceHalfedges[j].Opposite; } else if (isNewEdge[i] && isNewEdge[j]) // Both edges are new { faceHalfedges[i].Opposite.Previous = faceHalfedges[j].Opposite; faceHalfedges[j].Opposite.Next = faceHalfedges[i].Opposite; } else if (isNewEdge[i] && !isNewEdge[j]) // This is new, next is old { faceHalfedges[i].Opposite.Previous = faceHalfedges[j].Previous; faceHalfedges[j].Previous.Next = faceHalfedges[i].Opposite; } else if (!isNewEdge[i] && isNewEdge[j]) // This is old, next is new { faceHalfedges[i].Next.Previous = faceHalfedges[j].Opposite; faceHalfedges[j].Opposite.Next = faceHalfedges[i].Next; } // Relink faces before adding new edges if they are in the way of a new face else if (!isNewEdge[i] && !isNewEdge[j] && faceHalfedges[i].Next != faceHalfedges[j]) { TriMesh.HalfEdge closeHalfedge = faceHalfedges[i].Opposite; // Find the closing halfedge of the opening opposite the opening halfedge i is on do { closeHalfedge = closeHalfedge.Previous.Opposite; } while (closeHalfedge.Face != null && closeHalfedge != faceHalfedges[j] && closeHalfedge != faceHalfedges[i].Opposite); if (closeHalfedge == faceHalfedges[j] || closeHalfedge == faceHalfedges[i].Opposite) { throw new BadTopologyException("Unable to find an opening to relink an existing face."); } TriMesh.HalfEdge openHalfedge = closeHalfedge.Previous; // Remove group of faces between two openings, close up gap to form one opening openHalfedge.Next = faceHalfedges[i].Next; faceHalfedges[i].Next.Previous = openHalfedge; // Insert group of faces into target opening faceHalfedges[j].Previous.Next = closeHalfedge; closeHalfedge.Previous = faceHalfedges[j].Previous; } // Inner halfedges faceHalfedges[i].Next = faceHalfedges[j]; faceHalfedges[j].Previous = faceHalfedges[i]; } // Connect face to an inner halfedge f.HalfEdge = faceHalfedges[0]; return f; }