public static bool EdgeSwap(TriMesh.Edge edge) { if (edge.OnBoundary) { return(false); } //逆时针90度,左右变为下上 TriMesh.HalfEdge hf1 = edge.HalfEdge0; TriMesh.HalfEdge hf2 = edge.HalfEdge1; TriMesh.Vertex top = hf1.ToVertex; TriMesh.Vertex buttom = hf2.ToVertex; TriMesh.HalfEdge topLeft = hf1.Next; TriMesh.HalfEdge buttomLeft = hf1.Previous; TriMesh.HalfEdge topRight = hf2.Previous; TriMesh.HalfEdge buttomRight = hf2.Next; top.HalfEdge = topLeft; buttom.HalfEdge = buttomRight; hf1.ToVertex = topLeft.ToVertex; hf2.ToVertex = buttomRight.ToVertex; hf1.Face.HalfEdge = hf1; hf2.Face.HalfEdge = hf2; topLeft.Face = hf2.Face; buttomRight.Face = hf1.Face; ConnectHalfEdge(topLeft, hf2, topRight); ConnectHalfEdge(buttomRight, hf1, buttomLeft); return(true); }
protected override void BeforeMerge(TriMesh.Edge edge) { base.BeforeMerge(edge); TriMesh.Vertex v1 = edge.Vertex0; TriMesh.Vertex v2 = edge.Vertex1; vertexMatrix[v1] += vertexMatrix[v2]; }
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 bool Forward() { if (this.index < this.method.Logs.Count) { EdgeContext ctx = this.method.Logs[this.index]; TriMesh.Vertex left = null; TriMesh.Vertex right = null; foreach (var v in this.Mesh.Vertices) { if (v.Index == ctx.Left) { left = v; } else if (v.Index == ctx.Right) { right = v; } } TriMesh.Edge edge = left.FindEdgeTo(right); MergeEdge.Merge(edge, ctx.MidPos); index++; return(true); } else { int r = this.method.Run(this.Mesh.Faces.Count - 1); index += r; return(false); } }
/// <summary> /// 两端点都在边界上 /// </summary> /// <param name="edge"></param> void CutBothBoundary(TriMesh.Edge edge) { TriMesh.HalfEdge hf = edge.HalfEdge0; TriMesh.HalfEdge[] leftArr = this.GetToBoundaryAntiClockWise(hf); TriMesh.HalfEdge[] rightArr = this.GetToBoundaryClockWise(hf.Next); for (int i = 1; i < leftArr.Length; i++) { TriMeshModify.RemoveEdge(leftArr[i].Edge); } for (int i = 0; i < rightArr.Length; i++) { TriMeshModify.RemoveEdge(rightArr[i].Edge); } Vector3D vec = this.GetMoveVector(hf.Opposite); TriMesh.Vertex left = this.Clone(hf.FromVertex, vec); TriMesh.Vertex right = this.Clone(hf.ToVertex, vec); for (int i = 2; i < leftArr.Length; i++) { this.mesh.Faces.AddTriangles(left, leftArr[i - 1].ToVertex, leftArr[i].ToVertex); } for (int i = 1; i < rightArr.Length; i++) { this.mesh.Faces.AddTriangles(right, rightArr[i].ToVertex, rightArr[i - 1].ToVertex); } this.mesh.Faces.AddTriangles(left, right, leftArr[1].ToVertex); }
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); }
public static List <TriMesh.HalfEdge> RetrieveOneRingEdgeOfEdge(TriMesh.Edge edge) { TriMesh mesh = (TriMesh)edge.Mesh; List <TriMesh.HalfEdge> list = new List <TriMesh.HalfEdge>(); TriMesh.HalfEdge hf0 = edge.HalfEdge0; TriMesh.HalfEdge currentHalfedge = hf0.Next.Opposite; while (currentHalfedge.Next.Opposite != hf0) { if (!currentHalfedge.OnBoundary) { list.Add(currentHalfedge.Previous); } currentHalfedge = currentHalfedge.Next.Opposite; } ; TriMesh.HalfEdge hf1 = edge.HalfEdge1; currentHalfedge = hf1.Next.Opposite; while (currentHalfedge.Next.Opposite != hf1) { if (!currentHalfedge.OnBoundary) { list.Add(currentHalfedge.Previous); } currentHalfedge = currentHalfedge.Next.Opposite; } ; return(list); }
public static TriMesh.Vertex MergeEdge(TriMesh.Edge edge, Vector3D position) { TriMesh mesh = (TriMesh)edge.Mesh; TriMesh.Vertex v0 = edge.Vertex0; TriMesh.Vertex v1 = edge.Vertex1; TriMesh.HalfEdge hf0 = edge.HalfEdge0; TriMesh.HalfEdge hf1 = edge.HalfEdge1; v0.Traits.Position = position; foreach (var item in v1.HalfEdges) { //if (item.ToVertex != v0) { item.Opposite.ToVertex = v0; } } MergeOneSide(hf0); MergeOneSide(hf1); mesh.RemoveVertex(v1); mesh.RemoveEdge(edge); v1.HalfEdge = null; edge.HalfEdge0 = null; return(v0); }
protected Vector3D Transport(Vector3D wI, TriMesh.Face faceI, TriMesh.Face faceJ, double angle) { /* * triangles i and j according to the following labels: * * b * /|\ * / | \ * / | \ * / | \ * c i | j d \ | / \ | / \ | / \|/ \ a \ */ //Find Shared edge IJ TriMesh.HalfEdge sharedEdgeI = null; TriMesh.HalfEdge sharedEdgeJ = null; TriMesh.Edge sharedEdge = null; foreach (TriMesh.HalfEdge edgeI in faceI.Halfedges) { foreach (TriMesh.HalfEdge edgeJ in faceJ.Halfedges) { if (edgeI.Opposite == edgeJ) { sharedEdge = edgeI.Edge; sharedEdgeI = edgeI; sharedEdgeJ = edgeJ; break; } } } if (sharedEdge == null) { throw new Exception("Error"); } //Find vertex correspondent to figure above Vector3D av = sharedEdgeI.FromVertex.Traits.Position; Vector3D bv = sharedEdgeJ.FromVertex.Traits.Position; Vector3D cv = sharedEdgeI.Next.ToVertex.Traits.Position; Vector3D dv = sharedEdgeJ.Next.ToVertex.Traits.Position; //Compute the basis Matrix3D Ei = Orthogonalize(bv - av, cv - av); Matrix3D Ej = Orthogonalize(bv - av, bv - dv); //Build Rotate Matrix between two Faces Matrix3D rotateMatrix = Matrix3D.Rotate(angle); Vector3D wj = (Ej * rotateMatrix * Ei.Inverse() * wI); return(wj); }
public static void ShowOneRingVertexOfEdge(TriMesh.Edge edge) { foreach (var item in RetrieveOneRingVertexOfEdge(edge)) { item.Traits.SelectedFlag = 8; item.Traits.Color = RetrieveResult.Instance.VertexResult; } }
private static void MergeOneSide(TriMesh.HalfEdge hf) { TriMesh mesh = (TriMesh)hf.Mesh; if (hf.OnBoundary) { hf.ToVertex.HalfEdge = hf.Next; hf.Previous.Next = hf.Next; hf.Next.Previous = hf.Previous; } else { TriMesh.Edge remain = hf.Next.Edge; TriMesh.Edge remove = hf.Previous.Edge; TriMesh.HalfEdge outerLeft = hf.Previous.Opposite; TriMesh.HalfEdge outerRight = hf.Next.Opposite; if (outerLeft.Next == outerRight || outerLeft.Previous == outerRight) { outerLeft.Edge.Traits.SelectedFlag = 1; hf.FromVertex.Traits.SelectedFlag = 1; outerLeft.ToVertex.Traits.SelectedFlag = 1; //throw new Exception(); } remain.HalfEdge0 = outerRight; outerLeft.Edge = remain; outerLeft.Opposite = outerRight; outerRight.Opposite = outerLeft; hf.ToVertex.HalfEdge = outerRight.Next; //hf.ToVertex.HalfEdge = outerLeft; TriMesh.Vertex top = hf.Next.ToVertex; top.HalfEdge = outerRight; mesh.RemoveFace(hf.Face); mesh.RemoveHalfedge(hf.Previous); mesh.RemoveHalfedge(hf.Next); mesh.RemoveEdge(remove); hf.Previous.Previous = null; hf.Previous.Next = null; hf.Previous.Opposite = null; hf.Next.Previous = null; hf.Next.Next = null; hf.Next.Opposite = null; remove.HalfEdge0 = null; } mesh.RemoveHalfedge(hf); hf.ToVertex = null; hf.Next = null; hf.Previous = null; hf.Opposite = null; hf.Face = null; }
public static List <TriMesh.Vertex> RetrieveOneRingVertexOfEdge(TriMesh.Edge edge) { List <TriMesh.HalfEdge> oneRingEdges = RetrieveOneRingEdgeOfEdge(edge); List <TriMesh.Vertex> oneRingVertice = new List <TriMesh.Vertex>(); for (int i = 0; i < oneRingEdges.Count; i++) { oneRingVertice.Add(oneRingEdges[i].ToVertex); } return(oneRingVertice); }
public bool EdgeCollapse(TriMesh.Edge edge) { if (this.EdgeCanCollapse(edge) && TriMeshModify.IsMergeable(edge)) { TriMeshModify.MergeEdge(edge); return(true); } else { return(false); } }
protected override double GetValue(TriMesh.Edge edge) { Vector3D n0 = this.traits.VertexAreaWeightNormal[edge.Vertex0.Index]; Vector3D n1 = this.traits.VertexAreaWeightNormal[edge.Vertex1.Index]; double angle = Math.Acos(n0.Dot(n1)); if (angle < 0) { throw new Exception(); } return(angle * this.traits.EdgeLength[edge.Index]); }
public bool EdgeFlip(TriMesh.Edge edge) { if (this.EdgeCanFlip(edge)) { TriMeshModify.EdgeSwap(edge); return(true); } else { return(false); } }
public static bool Contains(TriMesh.Edge edge, Vector3D v) { Vector3D from = edge.Vertex0.Traits.Position; Vector3D to = edge.Vertex1.Traits.Position; Vector3D dir = (from - to).Normalize(); double length = (from - to).Length(); return(((v - to).Normalize() - dir).Length() < 0.0001f); //return (v - to).Normalize() == dir && // (v - from).Length() < length && // (v - to).Length() < length; }
public static void RemoveEdge(TriMesh.Edge edge) { TriMesh mesh = (TriMesh)edge.Mesh; if (edge.HalfEdge0.Next == edge.HalfEdge1) { //TriMesh.HalfEdge hf = edge.Vertex0.HalfEdge; //hf.Previous.Next = hf.Opposite.Next; //hf.Next.Previous = hf.Previous; //edge.Vertex1.HalfEdge = hf.Previous; edge.HalfEdge0.Previous.Next = edge.HalfEdge1.Next; edge.HalfEdge1.Next.Previous = edge.HalfEdge0.Previous; edge.Vertex1.HalfEdge = edge.HalfEdge0.Previous; edge.Vertex0.HalfEdge = null; } else if (edge.HalfEdge1.Next == edge.HalfEdge0) { //TriMesh.HalfEdge hf = edge.Vertex1.HalfEdge; //hf.Previous.Next = hf.Opposite.Next; //hf.Next.Previous = hf.Previous; //edge.Vertex0.HalfEdge = hf.Previous; edge.HalfEdge1.Previous.Next = edge.HalfEdge0.Next; edge.HalfEdge0.Next.Previous = edge.HalfEdge1.Previous; edge.Vertex0.HalfEdge = edge.HalfEdge1.Previous; edge.Vertex1.HalfEdge = null; } else { edge.HalfEdge0.Next.Previous = edge.HalfEdge1.Previous; edge.HalfEdge0.Previous.Next = edge.HalfEdge1.Next; edge.HalfEdge1.Next.Previous = edge.HalfEdge0.Previous; edge.HalfEdge1.Previous.Next = edge.HalfEdge0.Next; edge.HalfEdge0.ToVertex.HalfEdge = edge.HalfEdge0.Next; edge.HalfEdge1.ToVertex.HalfEdge = edge.HalfEdge1.Next; edge.HalfEdge0.Next.Face = null; edge.HalfEdge0.Previous.Face = null; edge.HalfEdge1.Next.Face = null; edge.HalfEdge1.Previous.Face = null; if (edge.Face0 != null) { mesh.RemoveFace(edge.Face0); } if (edge.Face1 != null) { mesh.RemoveFace(edge.Face1); } } mesh.RemoveHalfedge(edge.HalfEdge1); mesh.RemoveHalfedge(edge.HalfEdge0); mesh.RemoveEdge(edge); }
public bool EdgeCanCollapse(TriMesh.Edge edge) { if (edge.Vertex0.OnBoundary || edge.Vertex1.OnBoundary) { return(false); } int left = edge.Vertex1.HalfEdgeCount; int right = edge.Vertex0.HalfEdgeCount; int top = edge.HalfEdge0.Next.ToVertex.HalfEdgeCount; int bottom = edge.HalfEdge1.Next.ToVertex.HalfEdgeCount; return(left + right < 12 && top > 5 && bottom > 5); }
protected virtual void SelectByPoint() { int minIndex = SelectVertexByPoint(false); if (curVertex != -1) { TriMesh.Edge edge = TriMeshUtil.FindEdge(mesh.Vertices[curVertex], mesh.Vertices[minIndex]); if (edge != null) { edge.Traits.SelectedFlag = 1; } } curVertex = minIndex; }
public bool EdgeCanFlip(TriMesh.Edge edge) { if (edge.OnBoundary) { return(false); } int left = edge.Vertex1.HalfEdgeCount; int right = edge.Vertex0.HalfEdgeCount; int top = edge.HalfEdge0.Next.ToVertex.HalfEdgeCount; int bottom = edge.HalfEdge1.Next.ToVertex.HalfEdgeCount; double dot = this.GetNormal(edge.Face0).Dot(this.GetNormal(edge.Face1)); return(left > 5 && right > 5 && top < 7 && bottom < 7 && dot > 0.95); }
public void ClusterVertexs(TriMesh.Vertex[] vertices, Vector3D position) { Queue <TriMesh.Edge> connectedEdge = new Queue <TriMesh.Edge>(); Dictionary <TriMesh.Edge, bool> processedFlag = new Dictionary <HalfEdgeMesh.Edge, bool>(); foreach (TriMesh.Vertex v in vertices) { foreach (TriMesh.HalfEdge hf in v.HalfEdges) { foreach (TriMesh.Vertex vx in vertices) { if (hf.ToVertex == vx && !processedFlag.ContainsKey(hf.Edge)) { connectedEdge.Enqueue(hf.Edge); processedFlag[hf.Edge] = true; } } } } int n = 0; while (connectedEdge.Count > 0) { TriMesh.Edge e = connectedEdge.Dequeue(); if (e.HalfEdge0 == null || e.HalfEdge1 == null) { continue; } if (TriMeshModify.IsMergeable(e)) { TriMeshModify.MergeEdge(e, position); n = 0; } else { connectedEdge.Enqueue(e); n++; if (n > connectedEdge.Count) { break; } ; } } }
public static TriMesh.Vertex MergeTriangle(TriMesh.Face face, Vector3D pos) { TriMesh.Edge edge1 = face.HalfEdge.Edge; TriMesh.Edge edge2 = face.HalfEdge.Next.Edge; TriMesh.Vertex v = MergeEdge(edge1, pos); if (IsMergeable(edge2)) { v = MergeEdge(edge2, pos); } else { edge2.Traits.SelectedFlag = 1; } return(v); }
/// <summary> /// Adds a face to the mesh with the specified face traits. /// </summary> /// <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> public TriMesh.Face CreateFace(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 mesh = (TriMesh)faceVertices[0].Mesh; TriMesh.HalfEdge[] faceHalfedges = new TriMesh.HalfEdge[n]; bool[] isUsedVertex = new bool[n]; // 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; faceHalfedges[i] = this.Validate(faceVertices[i], faceVertices[j]); isUsedVertex[i] = (faceVertices[i].HalfEdge != null); } // Create face TriMesh.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 (faceHalfedges[i] == null) { TriMesh.Edge newEdge = this.CreateNewEdge(faceVertices[i], faceVertices[j]); faceHalfedges[i] = newEdge.HalfEdge0; } faceHalfedges[i].Face = f; } // Connect next/previous halfedges for (int i = 0; i < n; ++i) { int j = (i + 1) % n; this.ConnectHalfedge(faceHalfedges[i], faceHalfedges[j], isUsedVertex[j]); } // Connect face to an inner halfedge f.HalfEdge = faceHalfedges[0]; return(f); }
public static double ComputeDihedralAngle(TriMesh.Edge edge) { TriMesh.Face f1 = edge.Face0; TriMesh.Face f2 = edge.Face1; if (f1 != null && f2 != null) { Vector3D f1Normal = ComputeNormalFace(f1).Normalize(); Vector3D f2Normal = ComputeNormalFace(f2).Normalize(); double cosa = f1Normal.Dot(f2Normal) / (f1Normal.Length() * f2Normal.Length()); return(Math.Acos(cosa)); } else { return(0); } }
public static Nullable <Vector3D> Intersect(Plane plane, TriMesh.Edge edge, double threshold) { Vector3D p1 = edge.Vertex0.Traits.Position; Vector3D p2 = edge.Vertex1.Traits.Position; double d1 = GetDistance(plane, p1); double d2 = GetDistance(plane, p2); if (Math.Abs(d1) > threshold && Math.Abs(d2) > threshold && d1 * d2 < 0) { d1 = Math.Abs(d1); d2 = Math.Abs(d2); return(p1 + (p2 - p1) * d1 / (d1 + d2)); } else { return(null); } }
public static EdgeContext Merge(TriMesh.Edge edge, Vector3D position) { TriMesh mesh = (TriMesh)edge.Mesh; EdgeContext context = new EdgeContext() { LeftPos = edge.Vertex0.Traits.Position, MidPos = position, RightPos = edge.Vertex1.Traits.Position, Left = edge.Vertex0.Index, Right = edge.Vertex1.Index, Top = edge.HalfEdge1.Next.ToVertex.Index, Bottom = edge.HalfEdge0.Next.ToVertex.Index, }; TriMeshModify.MergeEdge(edge); return(context); }
/// <summary> /// cut后部分边的index改变,src是按照cut前边的index顺序,dst是按照cut后的 /// </summary> /// <param name="src"></param> /// <returns></returns> public double[] MapEdgeValue(double[] src) { double[] dst = new double[this.mesh.Edges.Count]; for (int i = 0; i < this.EdgeStore.Length; i++) { VertexPair pair = this.EdgeStore[i]; TriMesh.Edge edge = pair.Src.FindEdgeTo(pair.Dst); TriMesh.Edge other = this.GetOtherEdge(pair.Src, pair.Dst); if (edge != null) { dst[edge.Index] = src[i]; } if (other != null) { dst[other.Index] = src[i]; } } return(dst); }
private void InsertEdge(TriMesh mesh, TriMesh.Edge edge, TriMesh.HalfEdge inner, TriMesh.HalfEdge outer) { TriMesh.Edge left = 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; mesh.Add(edge); }
/// <summary> /// 这里有时候有bug,原因不明 /// </summary> /// <param name="v1"></param> /// <param name="v2"></param> /// <returns></returns> public TriMesh.Edge GetOtherEdge(TriMesh.Vertex v1, TriMesh.Vertex v2) { TriMesh.Vertex[] arr1 = this.GetAllCascade(v1); TriMesh.Vertex[] arr2 = this.GetAllCascade(v2); foreach (var item1 in arr1) { foreach (var item2 in arr2) { if (item1 != v1 || item2 != v2) { TriMesh.Edge edge = item1.FindEdgeTo(item2); if (edge != null) { return(edge); } } } } return(null); }
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); }
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; }
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; }
public void MakeTheTopologyB(PolygonMesh dualMesh) { List<TriMesh.Vertex> boundaryVertices = new List<TriMesh.Vertex>(); boundaryVertices = TriMeshUtil.RetrieveAllBoundaryVertex(mesh); foreach (TriMesh.Face face in mesh.Faces) { int index = face.Index; int baryVertexIndex = mesh.Edges.Count; int edgeVertexIndex; int faceIndex = index; TriMesh.Edge boundaryEdge = new TriMesh.Edge(); TriMesh.HalfEdge tempHalfedge = new TriMesh.HalfEdge(); TriMesh.Vertex vertex0 = mesh.Faces[index].GetVertex(0); TriMesh.Vertex vertex1 = mesh.Faces[index].GetVertex(1); TriMesh.Vertex vertex2 = mesh.Faces[index].GetVertex(2); TriMesh.HalfEdge halfedge0 = vertex0.FindHalfedgeTo(vertex1); TriMesh.HalfEdge halfedge1 = vertex1.FindHalfedgeTo(vertex2); TriMesh.HalfEdge halfedge2 = vertex2.FindHalfedgeTo(vertex0); TriMesh.HalfEdge boundaryHalfedge = new TriMesh.HalfEdge(); tempHalfedge = halfedge0; edgeVertexIndex = halfedge0.Edge.Index; TriMesh.Vertex firstVertex = dualMesh.Vertices[baryVertexIndex + faceIndex]; TriMesh.Vertex secondVertex = dualMesh.Vertices[edgeVertexIndex]; if (firstVertex.FindHalfedgeTo(secondVertex) == null) { List<TriMesh.Vertex> ringVertices = new List<TriMesh.Vertex>(); do { ringVertices.Add(dualMesh.Vertices[baryVertexIndex + faceIndex]); ringVertices.Add(dualMesh.Vertices[edgeVertexIndex]); if (tempHalfedge.Opposite.Next.Face != null) { tempHalfedge = tempHalfedge.Opposite.Next; faceIndex = tempHalfedge.Face.Index; edgeVertexIndex = tempHalfedge.Edge.Index; } else { tempHalfedge = tempHalfedge.Opposite.Next; edgeVertexIndex = tempHalfedge.Edge.Index; faceIndex = tempHalfedge.Opposite.Next.Face.Index; } } while (tempHalfedge != halfedge0); TriMesh.Vertex[] newFaceVertices = new TriMesh.Vertex[ringVertices.Count]; for (int i = 0; i < ringVertices.Count; i++) { newFaceVertices[i] = ringVertices[i]; } dualMesh.Faces.Add(newFaceVertices); } tempHalfedge = halfedge1; edgeVertexIndex = halfedge1.Edge.Index; firstVertex = dualMesh.Vertices[baryVertexIndex + faceIndex]; secondVertex = dualMesh.Vertices[edgeVertexIndex]; if (firstVertex.FindHalfedgeTo(secondVertex) == null) { List<TriMesh.Vertex> ringVertices = new List<TriMesh.Vertex>(); do { ringVertices.Add(dualMesh.Vertices[baryVertexIndex + faceIndex]); ringVertices.Add(dualMesh.Vertices[edgeVertexIndex]); if (tempHalfedge.Opposite.Next != null) { tempHalfedge = tempHalfedge.Opposite.Next; faceIndex = tempHalfedge.Face.Index; edgeVertexIndex = tempHalfedge.Edge.Index; } else { continue; } } while (tempHalfedge != halfedge1); TriMesh.Vertex[] newFaceVertices = new TriMesh.Vertex[ringVertices.Count]; for (int i = 0; i < ringVertices.Count; i++) { newFaceVertices[i] = ringVertices[i]; } dualMesh.Faces.Add(newFaceVertices); } tempHalfedge = halfedge2; edgeVertexIndex = halfedge2.Edge.Index; firstVertex = dualMesh.Vertices[baryVertexIndex + faceIndex]; secondVertex = dualMesh.Vertices[edgeVertexIndex]; if (firstVertex.FindHalfedgeTo(secondVertex) == null) { List<TriMesh.Vertex> ringVertices = new List<TriMesh.Vertex>(); do { ringVertices.Add(dualMesh.Vertices[baryVertexIndex + faceIndex]); ringVertices.Add(dualMesh.Vertices[edgeVertexIndex]); if (tempHalfedge.Opposite.Next != null) { tempHalfedge = tempHalfedge.Opposite.Next; faceIndex = tempHalfedge.Face.Index; edgeVertexIndex = tempHalfedge.Edge.Index; } else { continue; } } while (tempHalfedge != halfedge2); TriMesh.Vertex[] newFaceVertices = new TriMesh.Vertex[ringVertices.Count]; for (int i = 0; i < ringVertices.Count; i++) { newFaceVertices[i] = ringVertices[i]; } dualMesh.Faces.Add(newFaceVertices); } } }
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; }
/// <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; }