public void DrawTrivialConnection(TriMesh mesh, Vector3D[] faceVectors, int N) { double eps = 1e-3; double perAngle = 2 * Math.PI / N; for (int i = 0; i < mesh.Faces.Count; i++) { Vector3D vector = Vector3D.Normalize(faceVectors[i]); TriMesh.Face face = mesh.Faces[i]; Vector3D center = TriMeshUtil.GetMidPoint(face); Vector3D normal = TriMeshUtil.ComputeNormalFace(face); double inradius = TriMeshUtil.ComputeInradius(face); Quaternion rotate = Quaternion.RotationAxis(normal, perAngle); Quaternion v = new Quaternion(vector, 0); for (int j = 0; j < N; j++) { Vector3D a = center + inradius * v.ImagePart; //Vector3D b = center - inradius * v.ImagePart; v = rotate * v * rotate.Conjugate(); GL.Begin(BeginMode.Lines); GL.Vertex3(a.x, a.y, a.z); GL.Vertex3(center.x, center.y, center.z); GL.End(); } } }
private TriMesh ChangeTopologyLoop(TriMesh sourceMesh) { TriMesh newMesh = new TriMesh(); newMesh.Clear(); vMap = new HalfEdgeMesh.Vertex[sourceMesh.Vertices.Count]; eMap = new HalfEdgeMesh.Vertex[sourceMesh.Edges.Count]; foreach (var v in sourceMesh.Vertices) { vMap[v.Index] = newMesh.Vertices.Add(new VertexTraits(v.Traits.Position)); } foreach (var edge in sourceMesh.Edges) { eMap[edge.Index] = newMesh.Vertices.Add( new VertexTraits(TriMeshUtil.GetMidPoint(edge))); } foreach (TriMesh.Face face in sourceMesh.Faces) { foreach (var hf in face.Halfedges) { newMesh.Faces.AddTriangles(eMap[hf.Edge.Index], vMap[hf.ToVertex.Index], eMap[hf.Next.Edge.Index]); } newMesh.Faces.AddTriangles( eMap[face.HalfEdge.Previous.Edge.Index], eMap[face.HalfEdge.Edge.Index], eMap[face.HalfEdge.Next.Edge.Index]); } return(newMesh); }
public static void KMean(TriMesh mesh) { Dictionary <int, Cluster> dict = new Dictionary <int, Cluster>(); Queue <TriMesh.Face> queue = new Queue <HalfEdgeMesh.Face>(); foreach (var face in mesh.Faces) { if (face.Traits.SelectedFlag != 0) { dict[face.Traits.SelectedFlag] = new Cluster(); dict[face.Traits.SelectedFlag].Add(TriMeshUtil.GetMidPoint(face)); queue.Enqueue(face); } } while (queue.Count != 0) { TriMesh.Face center = queue.Dequeue(); foreach (var round in center.Faces) { if (round.Traits.SelectedFlag == 0) { int index = GetNearest(round, dict); dict[index].Add(TriMeshUtil.GetMidPoint(round)); round.Traits.SelectedFlag = (byte)index; queue.Enqueue(round); } } } }
private TriMesh ChangeTopologyInit(TriMesh sourceMesh) { TriMesh mesh = new TriMesh(); vMap = new HalfEdgeMesh.Vertex[sourceMesh.Vertices.Count]; faceMap = new HalfEdgeMesh.Vertex[sourceMesh.Faces.Count]; foreach (var face in sourceMesh.Faces) { faceMap[face.Index] = mesh.Vertices.Add( new VertexTraits(TriMeshUtil.GetMidPoint(face))); } foreach (var v in sourceMesh.Vertices) { vMap[v.Index] = mesh.Vertices.Add(new VertexTraits(v.Traits.Position)); foreach (var hf in v.HalfEdges) { if (hf.Face != null && hf.Opposite.Face != null) { mesh.Faces.AddTriangles(faceMap[hf.Face.Index], vMap[v.Index], faceMap[hf.Opposite.Face.Index]); } } } foreach (var hf in sourceMesh.HalfEdges) { if (hf.Face == null) { mesh.Faces.AddTriangles(vMap[hf.ToVertex.Index], vMap[hf.FromVertex.Index], faceMap[hf.Opposite.Face.Index]); } } return(mesh); }
public static PolygonMesh BuildDual(TriMesh mesh, EnumDual type) { TriMeshModify.RepaireAllHole(mesh); PolygonMesh.Vertex[] faceMap = new HalfEdgeMesh.Vertex[mesh.Faces.Count]; PolygonMesh.Vertex[] edgeMap = new HalfEdgeMesh.Vertex[mesh.Edges.Count]; PolygonMesh pm = new PolygonMesh(); foreach (var face in mesh.Faces) { Vector3D center = Vector3D.Zero; switch (type) { case EnumDual.DualA: center = TriMeshUtil.GetMidPoint(face); break; case EnumDual.DualB: TriMesh.Vertex vertex0 = face.GetVertex(0); TriMesh.Vertex vertex1 = face.GetVertex(1); TriMesh.Vertex vertex2 = face.GetVertex(2); Triangle triangle = new Triangle(vertex0.Traits.Position, vertex1.Traits.Position, vertex2.Traits.Position); center = triangle.ComputeCircumCenter(); break; default: break; } PolygonMesh.Vertex v = new HalfEdgeMesh.Vertex(new VertexTraits(center)); faceMap[face.Index] = v; pm.AppendToVertexList(v); } foreach (var edge in mesh.Edges) { VertexTraits trait = new VertexTraits(TriMeshUtil.GetMidPoint(edge)); PolygonMesh.Vertex v = new HalfEdgeMesh.Vertex(trait); edgeMap[edge.Index] = v; pm.AppendToVertexList(v); } foreach (var v in mesh.Vertices) { List <PolygonMesh.Vertex> list = new List <HalfEdgeMesh.Vertex>(); foreach (var hf in v.HalfEdges) { list.Add(faceMap[hf.Face.Index]); list.Add(edgeMap[hf.Edge.Index]); } list.Reverse(); pm.Faces.Add(list.ToArray()); } return(pm); }
public void Subdivision() { /* /\ /\ * / \ /__\ * / \ /\ /\ * / \ /__\/__\ * / \ /\ /\ /\ * /__________\ /__\/__\/__\ * * 为了让每个顶点周围都有它专属的一圈价为6的点,把每个三角形拆成9个 */ TriMesh copy = TriMeshIO.Clone(this.mesh); this.mesh.Clear(); TriMesh.Vertex[] faceMap = new HalfEdgeMesh.Vertex[copy.Faces.Count]; TriMesh.Vertex[] hfMap = new HalfEdgeMesh.Vertex[copy.HalfEdges.Count]; foreach (var v in copy.Vertices) { this.mesh.Vertices.Add(new VertexTraits(v.Traits.Position)); } foreach (var face in copy.Faces) { faceMap[face.Index] = this.mesh.Vertices.Add(new VertexTraits(TriMeshUtil.GetMidPoint(face))); } foreach (var hf in copy.HalfEdges) { Vector3D pos = hf.FromVertex.Traits.Position * 2 / 3 + hf.ToVertex.Traits.Position * 1 / 3; hfMap[hf.Index] = this.mesh.Vertices.Add(new VertexTraits(pos)); } foreach (var face in copy.Faces) { foreach (var hf in face.Halfedges) { this.mesh.Faces.AddTriangles(faceMap[face.Index], hfMap[hf.Index], hfMap[hf.Opposite.Index]); this.mesh.Faces.AddTriangles(faceMap[face.Index], hfMap[hf.Opposite.Index], hfMap[hf.Next.Index]); } } foreach (var v in copy.Vertices) { foreach (var hf in v.HalfEdges) { if (hf.Face != null) { this.mesh.Faces.AddTriangles(this.mesh.Vertices[v.Index], hfMap[hf.Index], hfMap[hf.Previous.Opposite.Index]); } } } }
static int GetNearest(TriMesh.Face face, Dictionary <int, Cluster> dict) { Vector3D center = TriMeshUtil.GetMidPoint(face); int nearestIndex = -1; double nearest = double.MaxValue; foreach (var item in dict) { double dist = Vector3D.Distance(center, item.Value.Center); if (dist < nearest) { nearestIndex = item.Key; nearest = dist; } } return(nearestIndex); }
public List <TriMesh.Edge> BuildCoTree(DynamicTree <TriMesh.Face> cotree) { if (cotree == null) { return(null); } List <TriMesh.Edge> cotreeMarks = new List <HalfEdgeMesh.Edge>(); Vector3D[] bycenters = new Vector3D[mesh.Faces.Count]; cotreeMarks = new List <HalfEdgeMesh.Edge>(); TreeNode <TriMesh.Face> currentCoNode = cotree.Root; Queue <TreeNode <TriMesh.Face> > coQueue = new Queue <TreeNode <TriMesh.Face> >(); coQueue.Enqueue(currentCoNode); do { currentCoNode = coQueue.Dequeue(); bycenters[currentCoNode.Attribute.Index] = TriMeshUtil.GetMidPoint(currentCoNode.Attribute); TreeNode <TriMesh.Face> currentChild = currentCoNode.LeftMostChild; while (currentChild != null) { //Mark edge TriMesh.Face f1 = currentCoNode.Attribute; TriMesh.Face f2 = currentChild.Attribute; foreach (TriMesh.HalfEdge hf in f1.Halfedges) { if (hf.Opposite.Face == f2) { cotreeMarks.Add(hf.Edge); break; } } coQueue.Enqueue(currentChild); currentChild = currentChild.RightSibling; } } while (coQueue.Count > 0); return(cotreeMarks); }
protected Vector3D GetPos1(TriMesh.HalfEdge hf) { Vector3D from = hf.FromVertex.Traits.Position; Vector3D to = hf.ToVertex.Traits.Position; Vector3D l = to - from; Vector3D[] vi = this.GetV(hf); Vector3D[] vj = this.GetV(hf.Opposite); Vector3D c1 = Vector3D.Zero; Vector3D c2 = Vector3D.Zero; for (int i = 0; i < vi.Length - 1; i++) { c1 += (vi[i] - from).Cross(vi[i + 1] - from); } for (int i = 0; i < vj.Length - 1; i++) { c2 += (vj[i + 1] - to).Cross(vj[i] - to); } Matrix4D m = Matrix4D.ZeroMatrix; m.Row1 = new Vector4D(c1 - c2, to.Dot(c2) - from.Dot(c1)); m.Row2 = new Vector4D(l.y, -l.x, 0d, to.y * l.x - to.x * l.y); m.Row3 = new Vector4D(l.z, 0d, -l.x, to.z * l.x - to.x * l.z); m.Row4 = new Vector4D(0d, 0d, 0d, 1d); Vector3D pos = Vector3D.Zero; double det = Util.Solve(ref m, ref pos); if (det == 0) { pos = TriMeshUtil.GetMidPoint(hf.Edge); } else { double vo1 = c1.Dot(pos - from); double vo2 = c2.Dot(pos - to); } return(pos); }
public void DrawTreeCotree(List <TriMesh.Edge> treeMarks, List <TriMesh.Edge> cotreeMarks) { OpenGLManager.Instance.SetColor(System.Drawing.Color.Green); //Draw Tree foreach (TriMesh.Edge item in treeMarks) { GL.Begin(BeginMode.Lines); Vector3D a = item.Vertex0.Traits.Position; Vector3D b = item.Vertex1.Traits.Position; GL.Vertex3(a.x, a.y, a.z); GL.Vertex3(b.x, b.y, b.z); GL.End(); } OpenGLManager.Instance.SetColor(System.Drawing.Color.Red); //Draw CoTree foreach (TriMesh.Edge item in cotreeMarks) { Vector3D a = TriMeshUtil.GetMidPoint(item.Face0); Vector3D b = TriMeshUtil.GetMidPoint(item.Face1); Vector3D centerOfEdge = (item.Vertex0.Traits.Position + item.Vertex1.Traits.Position) / 2; GL.Begin(BeginMode.Lines); GL.Vertex3(a.x, a.y, a.z); GL.Vertex3(centerOfEdge.x, centerOfEdge.y, centerOfEdge.z); GL.End(); GL.Begin(BeginMode.Lines); GL.Vertex3(centerOfEdge.x, centerOfEdge.y, centerOfEdge.z); GL.Vertex3(b.x, b.y, b.z); GL.End(); } }
private ErrorPair GetErrorPair(TriMesh.Face face) { Matrix4D m1 = this.GetVolumeMatrix(face); if (m1[1] != m1[4] || m1[2] != m1[8] || m1[6] != m1[9] || m1[3] != m1[12] || m1[7] != m1[13] || m1[11] != m1[14] ) { throw new Exception("Matrix m1 is not symmetric"); } Matrix4D m2 = Matrix4D.ZeroMatrix; for (int i = 0; i <= 11; i++) { m2[i] = m1[i]; } m2[12] = 0; m2[13] = 0; m2[14] = 0; m2[15] = 1; Vector3D newPos = Vector3D.Zero; double det = Util.Solve(ref m2, ref newPos); if (det == 0) { newPos = TriMeshUtil.GetMidPoint(face); } double error = this.GetError(m1, newPos); return(new ErrorPair() { Pos = newPos, Error = error }); }
public static EdgeContext Merge(TriMesh.Edge edge) { Vector3D position = TriMeshUtil.GetMidPoint(edge); return(Merge(edge, position)); }
protected virtual Vector3D GetPos(TriMesh.Face target) { return(TriMeshUtil.GetMidPoint(target)); }
protected override Vector3D GetPos(TriMesh.Face target) { return(TriMeshUtil.GetMidPoint(target)); //return this.faceError[target.Index].Pos; }
protected Vector3D GetPos(TriMesh.HalfEdge hf) { return(TriMeshUtil.GetMidPoint(hf.Edge)); }
public void DrawGenerators(TriMesh mesh, List <List <TriMesh.HalfEdge> > Generators) { if (Generators == null) { return; } Vector3D[] bycenters = new Vector3D[mesh.Faces.Count]; foreach (TriMesh.Face face in mesh.Faces) { bycenters[face.Index] = TriMeshUtil.GetMidPoint(face); } bool[] edgeFlags = new bool[mesh.Edges.Count]; int i = 0; System.Drawing.Color color = System.Drawing.Color.Orange; foreach (List <TriMesh.HalfEdge> loop in Generators) { switch (i) { case 1: color = System.Drawing.Color.Green; break; case 2: color = System.Drawing.Color.Red; break; case 3: color = System.Drawing.Color.Purple; break; default: color = System.Drawing.Color.Orange; break; } OpenGLManager.Instance.SetColor(color); foreach (TriMesh.HalfEdge loopItem in loop) { TriMesh.Edge edge = loopItem.Edge; if (edgeFlags[edge.Index] == false) { Vector3D a = bycenters[edge.Face0.Index]; Vector3D b = bycenters[edge.Face1.Index]; Vector3D centerOfEdge = (edge.Vertex0.Traits.Position + edge.Vertex1.Traits.Position) / 2; GL.Begin(BeginMode.Lines); GL.Vertex3(a.x, a.y, a.z); GL.Vertex3(centerOfEdge.x, centerOfEdge.y, centerOfEdge.z); GL.End(); GL.Begin(BeginMode.Lines); GL.Vertex3(centerOfEdge.x, centerOfEdge.y, centerOfEdge.z); GL.Vertex3(b.x, b.y, b.z); GL.End(); } edgeFlags[edge.Index] = true; } i++; } }
private TriMesh ChangeTopologyLoopSelected(TriMesh sourceMesh) { TriMesh newMesh = new TriMesh(); newMesh.Clear(); vMap = new HalfEdgeMesh.Vertex[sourceMesh.Vertices.Count]; eMap = new HalfEdgeMesh.Vertex[Mesh.Edges.Count]; foreach (var v in sourceMesh.Vertices) { vMap[v.Index] = newMesh.Vertices.Add(new VertexTraits(v.Traits.Position)); } foreach (var edge in sourceMesh.Edges) { if (edge.Vertex0.Traits.SelectedFlag != 0 && edge.Vertex1.Traits.SelectedFlag != 0) { eMap[edge.Index] = newMesh.Vertices.Add(new VertexTraits(TriMeshUtil.GetMidPoint(edge))); } } foreach (TriMesh.Face face in sourceMesh.Faces) { List <TriMesh.HalfEdge> list = new List <HalfEdgeMesh.HalfEdge>(); foreach (var hf in face.Halfedges) { if (hf.ToVertex.Traits.SelectedFlag != 0 && hf.FromVertex.Traits.SelectedFlag != 0) { list.Add(hf); } } switch (list.Count) { case 0: newMesh.Faces.AddTriangles( vMap[face.GetVertex(0).Index], vMap[face.GetVertex(1).Index], vMap[face.GetVertex(2).Index]); break; case 1: TriMesh.HalfEdge h = list[0]; newMesh.Faces.AddTriangles( eMap[h.Edge.Index], vMap[h.ToVertex.Index], vMap[h.Next.ToVertex.Index]); newMesh.Faces.AddTriangles( eMap[h.Edge.Index], vMap[h.Next.ToVertex.Index], vMap[h.FromVertex.Index]); break; case 3: foreach (var hf in face.Halfedges) { newMesh.Faces.AddTriangles(eMap[hf.Edge.Index], vMap[hf.ToVertex.Index], eMap[hf.Next.Edge.Index]); } newMesh.Faces.AddTriangles( eMap[face.HalfEdge.Previous.Edge.Index], eMap[face.HalfEdge.Edge.Index], eMap[face.HalfEdge.Next.Edge.Index]); break; default: break; } } return(newMesh); }
public static TriMesh.Vertex MergeTriangle(TriMesh.Face face) { Vector3D pos = TriMeshUtil.GetMidPoint(face); return(MergeTriangle(face, pos)); }