public static void RepaireHoleTwo(List <TriMesh.Vertex> hole) { TriMesh mesh = (TriMesh)hole[0].Mesh; Vector3D center = Vector3D.Zero; for (int i = 0; i < hole.Count; i++) { center += hole[i].Traits.Position; } center /= hole.Count; TriMesh.Vertex vertex = mesh.Vertices.Add(new VertexTraits(center)); if (hole.Count >= 3) { TriMesh.Vertex[] faceVertices = new TriMesh.Vertex[3]; for (int i = 0; i < hole.Count; i++) { faceVertices[0] = vertex; faceVertices[1] = hole[i]; faceVertices[2] = hole[(i + 1) % hole.Count]; mesh.Faces.AddTriangles(faceVertices); } } TriMeshUtil.FixIndex(mesh); }
public void Init() { TriMeshUtil.FixIndex(mesh); int vc = mesh.Vertices.Count; int ec = mesh.Edges.Count; int fc = mesh.Faces.Count; this.EdgeLength = new double[ec]; this.FaceArea = new double[fc]; this.FaceNormal = new Vector3D[fc]; this.VertexAreaSum = new double[ec]; this.VertexAreaWeightNormal = new Vector3D[vc]; this.VertexDiscreteCurvature = new double[vc]; foreach (var edge in this.mesh.Edges) { this.UpdateLength(edge); } foreach (var face in this.mesh.Faces) { this.UpdateAreaAndNormal(face); } foreach (var v in this.mesh.Vertices) { this.UpdateAreaWeightNormal(v); this.UpdateVertexDiscreteCurvature(v); } }
public static void RepaireOneHole(TriMesh mesh) { List <TriMesh.Vertex> hole = TriMeshUtil.RetrieveBoundarySingle(mesh); RepaireHole(hole); TriMeshUtil.FixIndex(mesh); }
private void removeToolStripMenuItem1_Click(object sender, EventArgs e) { var enhance = new TriMeshEnhancement(Mesh); enhance.RemoveCapWithPlane(); TriMeshUtil.FixIndex(Mesh); TriMeshUtil.SetUpNormalVertex(Mesh); }
public TriMesh SubdivisionSelectedLoop() { TriMesh loopedMesh = ChangeTopologyLoopSelected(Mesh); ChangeGeometryLoopSelected(Mesh, loopedMesh); TriMeshUtil.FixIndex(loopedMesh); return(loopedMesh); }
private void showToolStripMenuItem1_Click(object sender, EventArgs e) { var enhance = new TriMeshEnhancement(Mesh); enhance.PlaneCutTest(); TriMeshUtil.FixIndex(Mesh); TriMeshUtil.SetUpNormalVertex(Mesh); }
private void simplify567ToolStripMenuItem_Click(object sender, EventArgs e) { Test567 test = new Test567(Mesh); test.CollapseAll(this.faceCount); TriMeshUtil.FixIndex(Mesh); TriMeshUtil.SetUpNormalVertex(Mesh); OnChanged(EventArgs.Empty); }
public TriMesh SubdivisonSqrt3() { TriMesh sqrt = ChangeTopologyInit(Mesh); ChangeGeometrySqrt3(Mesh, sqrt); TriMeshUtil.FixIndex(sqrt); return(sqrt); }
public static void RemoveSelectedFaces(TriMesh mesh) { List <TriMesh.Face> selected = TriMeshUtil.RetrieveSelectedFace(mesh); for (int i = 0; i < selected.Count; i++) { RemoveFace(selected[i]); } TriMeshUtil.FixIndex(mesh); }
private void removeToolStripMenuItem_Click(object sender, EventArgs e) { var enhance = new TriMeshEnhancement(Mesh); enhance.RemoveCapWithSplit(); TriMeshUtil.FixIndex(Mesh); TriMeshUtil.SetUpNormalVertex(Mesh); OnChanged(EventArgs.Empty); }
public static void RemoveTwoRingOfVertex(TriMesh mesh) { List <TriMesh.Vertex> selected = TriMeshUtil.RetrieveSelectedVertex(mesh); for (int i = 0; i < selected.Count; i++) { RemoveTwoRingOfVertex(selected[i]); } TriMeshUtil.FixIndex(mesh); }
public static void RemoveOneRingOfEdge(TriMesh mesh) { List <TriMesh.Edge> selected = TriMeshUtil.RetrieveSelectedEdge(mesh); for (int i = 0; i < selected.Count; i++) { RemoveOneRingOfEdge(selected[i]); } TriMeshUtil.FixIndex(mesh); }
public static void RepaireAllHole(TriMesh mesh) { List <List <TriMesh.Vertex> > holes = TriMeshUtil.RetrieveBoundaryAllVertex(mesh); for (int i = 0; i < holes.Count; i++) { RepaireHoleTwo(holes[i]); } TriMeshUtil.FixIndex(mesh); }
public static void RepaireHole(List <TriMesh.Vertex> hole) { TriMesh mesh = (TriMesh)hole[0].Mesh; if (hole.Count >= 3) { mesh.Faces.AddTriangles(hole.ToArray()); } TriMeshUtil.FixIndex(mesh); }
public static int Simplify(TriMesh mesh, EnumSimplicationType type, int preservedFace) { int i = 0; switch (type) { case EnumSimplicationType.CornerCutting: CornerCuttingSimplication corner = new CornerCuttingSimplication(mesh); i = corner.Run(preservedFace); break; case EnumSimplicationType.LengthAngle: LengthAndAngleSimplication lenghtAngle = new LengthAndAngleSimplication(mesh); i = lenghtAngle.Run(preservedFace); break; case EnumSimplicationType.MinCurvature: MinCurvatureSimplication minCurvature = new MinCurvatureSimplication(mesh); i = minCurvature.Run(preservedFace); break; case EnumSimplicationType.QEM: QEMSimplication qem = new QEMSimplication(mesh); i = qem.Run(preservedFace); break; case EnumSimplicationType.ShortEdge: ShortEdgeSimplication shortedge = new ShortEdgeSimplication(mesh); i = shortedge.Run(preservedFace); break; case EnumSimplicationType.SmallFace: SmallFaceSimplication smallFace = new SmallFaceSimplication(mesh); i = smallFace.Run(preservedFace); break; case EnumSimplicationType.SquareVolume: SquareVolumeSimplication squareVolume = new SquareVolumeSimplication(mesh); i = squareVolume.Run(preservedFace); break; case EnumSimplicationType.SurfaceFitting: SurfaceFittingSimplication surfaceFitting = new SurfaceFittingSimplication(mesh); i = surfaceFitting.Run(preservedFace); break; } TriMeshUtil.FixIndex(mesh); TriMeshUtil.SetUpNormalVertex(mesh); return(i); }
private void Cut_Click(object sender, EventArgs e) { TriMeshModify.ComputeSelectedEdgeFromColor(Mesh); double move = TriMeshUtil.ComputeEdgeAvgLength(Mesh) * 0.1; TriMeshEdgeCutFromBoundary cut = new TriMeshEdgeCutFromBoundary(Mesh); cut.Cut(move); TriMeshUtil.ClearMeshColor(Mesh); TriMeshUtil.ShowBoundary(Mesh); TriMeshUtil.FixIndex(Mesh); TriMeshUtil.SetUpNormalVertex(Mesh); OnChanged(EventArgs.Empty); }
private void remove567ToolStripMenuItem_Click(object sender, EventArgs e) { Test567 test = new Test567(Mesh); this.faceCount = test.Mesh.Faces.Count; test.Step3(); test.Step4(); test.Subdivision(); test.StepGT7(); TriMeshUtil.FixIndex(Mesh); TriMeshUtil.SetUpNormalVertex(Mesh); OnChanged(EventArgs.Empty); }
public static void RepairSimpleHoles(TriMesh mesh) { List <List <TriMesh.HalfEdge> > holes = TriMeshUtil.RetrieveBoundaryEdgeAll(mesh); foreach (List <TriMesh.HalfEdge> hole in holes) { for (int i = 2; i < hole.Count; i++) { mesh.Faces.AddTriangles(hole[0].ToVertex, hole[i - 1].ToVertex, hole[i].ToVertex); } } TriMeshUtil.FixIndex(mesh); }
public static void RepairHole(TriMesh mesh) { List <TriMesh.Vertex> hole = new List <TriMesh.Vertex>(); hole = TriMeshUtil.RetrieveBoundarySingle(mesh); TriMesh.Vertex[] faceVertices = new TriMesh.Vertex[3]; for (int i = 0; i < hole.Count - 2; i++) { faceVertices[0] = mesh.Vertices[hole[0].Index]; faceVertices[1] = mesh.Vertices[hole[i + 1].Index]; faceVertices[2] = mesh.Vertices[hole[i + 2].Index]; mesh.Faces.AddTriangles(faceVertices); } TriMeshUtil.FixIndex(mesh); }
public static void MergeTriangle(TriMesh mesh) { for (int i = 0; i < mesh.Faces.Count; i++) { if (mesh.Faces[i].Traits.SelectedFlag != 0) { if (IsMergeable(mesh.Faces[i])) { MergeTriangle(mesh.Faces[i]); i = Math.Max(0, i - 3); } else { mesh.Faces[i].Traits.SelectedFlag = 1; } } } TriMeshUtil.FixIndex(mesh); TriMeshUtil.SetUpNormalVertex(mesh); }
public static void VertexSplit(TriMesh mesh) { List <TriMesh.Vertex> newvertex = new List <HalfEdgeMesh.Vertex>(); for (int i = 0; i < mesh.Vertices.Count; i++) { if (mesh.Vertices[i].Traits.SelectedFlag != 0) { TriMesh.Vertex vertex = VertexSplit(mesh.Vertices[i]); newvertex.Add(vertex); } } foreach (TriMesh.Vertex vertex in newvertex) { vertex.Traits.selectedFlag = 1; } TriMeshUtil.FixIndex(mesh); TriMeshUtil.SetUpNormalVertex(mesh); }
public void ClusterProcess() { for (int x = 0; x < Xcount; x++) { for (int y = 0; y < Ycount; y++) { for (int z = 0; z < Zcount; z++) { TriMesh.Vertex[] group = FindVerticesInRange(x * cubeWeight + startX, y * cubeWeight + startY, z * cubeWeight + startZ); if (group.Length != 0) { Vector3D avg = AvgOfCluster(group); ClusterVertexs(group, avg); } } } } TriMeshUtil.FixIndex(mesh); }
public void Cut(Plane plane) { this.plane = plane; this.list = new List <Triangle>(); this.cutPoint = new Dictionary <int, CutPoint>(); foreach (var hf in this.mesh.HalfEdges) { this.CutHalfEdge(hf); } foreach (var face in this.mesh.Faces) { this.CutFace(face); } List <TriMesh.Edge> edges = new List <HalfEdgeMesh.Edge>(); foreach (var hf in this.mesh.HalfEdges) { if (this.cutPoint.ContainsKey(hf.Index)) { edges.Add(hf.Edge); } } foreach (var item in edges) { TriMeshModify.RemoveEdge(item); } foreach (var item in this.list) { this.mesh.Faces.AddTriangles(item.V1, item.V2, item.V3); } TriMeshUtil.FixIndex(mesh); TriMeshUtil.SetUpNormalVertex(mesh); }
public static void RepairComplexHole(TriMesh mesh) { List <TriMesh.Vertex> hole = new List <TriMesh.Vertex>(); TriMesh.Vertex[] faceVertices = new TriMesh.Vertex[3]; while (true)//此循环只限单洞修补 { //计算边界边的平均值 #region 计算边界边的平均值 hole = TriMeshUtil.RetrieveBoundarySingle(mesh); double aver_l = 0; double[] edgeLength = new double[hole.Count]; for (int i = 0; i < hole.Count; i++) { if (i == hole.Count - 1) { edgeLength[i] = Math.Sqrt(Math.Pow(hole[i].Traits.Position.x - hole[0].Traits.Position.x, 2) + Math.Pow(hole[i].Traits.Position.y - hole[0].Traits.Position.y, 2) + Math.Pow(hole[i].Traits.Position.z - hole[0].Traits.Position.z, 2)); break; } edgeLength[i] = Math.Sqrt(Math.Pow(hole[i].Traits.Position.x - hole[i + 1].Traits.Position.x, 2) + Math.Pow(hole[i].Traits.Position.y - hole[i + 1].Traits.Position.y, 2) + Math.Pow(hole[i].Traits.Position.z - hole[i + 1].Traits.Position.z, 2)); } for (int i = 0; i < hole.Count; i++) { aver_l += edgeLength[i]; } aver_l = aver_l / hole.Count; #endregion hole = TriMeshUtil.RetrieveBoundarySingle(mesh); //计算角度值 #region 计算角度值 double[] angle = new double[hole.Count]; double a = 0, b = 0, c = 0; for (int i = 0; i < hole.Count; i++) { if (i == 0) { a = Math.Sqrt(Math.Pow(hole[hole.Count - 1].Traits.Position.x - hole[i + 1].Traits.Position.x, 2) + Math.Pow(hole[hole.Count - 1].Traits.Position.y - hole[i + 1].Traits.Position.y, 2) + Math.Pow(hole[hole.Count - 1].Traits.Position.z - hole[i + 1].Traits.Position.z, 2)); b = Math.Sqrt(Math.Pow(hole[i].Traits.Position.x - hole[i + 1].Traits.Position.x, 2) + Math.Pow(hole[i].Traits.Position.y - hole[i + 1].Traits.Position.y, 2) + Math.Pow(hole[i].Traits.Position.z - hole[i + 1].Traits.Position.z, 2)); c = Math.Sqrt(Math.Pow(hole[hole.Count - 1].Traits.Position.x - hole[i].Traits.Position.x, 2) + Math.Pow(hole[hole.Count - 1].Traits.Position.y - hole[i].Traits.Position.y, 2) + Math.Pow(hole[hole.Count - 1].Traits.Position.z - hole[i].Traits.Position.z, 2)); angle[i] = Math.Acos((b * b + c * c - a * a) / (2 * b * c)); } else if (i == hole.Count - 1) { a = Math.Sqrt(Math.Pow(hole[i - 1].Traits.Position.x - hole[0].Traits.Position.x, 2) + Math.Pow(hole[i - 1].Traits.Position.y - hole[0].Traits.Position.y, 2) + Math.Pow(hole[i - 1].Traits.Position.z - hole[0].Traits.Position.z, 2)); b = Math.Sqrt(Math.Pow(hole[i].Traits.Position.x - hole[0].Traits.Position.x, 2) + Math.Pow(hole[i].Traits.Position.y - hole[0].Traits.Position.y, 2) + Math.Pow(hole[i].Traits.Position.z - hole[0].Traits.Position.z, 2)); c = Math.Sqrt(Math.Pow(hole[i - 1].Traits.Position.x - hole[i].Traits.Position.x, 2) + Math.Pow(hole[i - 1].Traits.Position.y - hole[i].Traits.Position.y, 2) + Math.Pow(hole[i - 1].Traits.Position.z - hole[i].Traits.Position.z, 2)); angle[i] = Math.Acos((b * b + c * c - a * a) / (2 * b * c)); } else { a = Math.Sqrt(Math.Pow(hole[i - 1].Traits.Position.x - hole[i + 1].Traits.Position.x, 2) + Math.Pow(hole[i - 1].Traits.Position.y - hole[i + 1].Traits.Position.y, 2) + Math.Pow(hole[i - 1].Traits.Position.z - hole[i + 1].Traits.Position.z, 2)); b = Math.Sqrt(Math.Pow(hole[i].Traits.Position.x - hole[i + 1].Traits.Position.x, 2) + Math.Pow(hole[i].Traits.Position.y - hole[i + 1].Traits.Position.y, 2) + Math.Pow(hole[i].Traits.Position.z - hole[i + 1].Traits.Position.z, 2)); c = Math.Sqrt(Math.Pow(hole[i - 1].Traits.Position.x - hole[i].Traits.Position.x, 2) + Math.Pow(hole[i - 1].Traits.Position.y - hole[i].Traits.Position.y, 2) + Math.Pow(hole[i - 1].Traits.Position.z - hole[i].Traits.Position.z, 2)); angle[i] = Math.Acos((b * b + c * c - a * a) / (2 * b * c)); } } #endregion //取得最小的角度 #region 取得最小的角度 int min = 0; for (int i = 0; i < hole.Count - 1; i++) { if (angle[i] < angle[i + 1]) { min = i; } else { min = i + 1; } } #endregion //求最小角度对应的边长 #region 求最小角度对应的边长 double temp = 0; if (min == hole.Count - 1) { temp = Math.Sqrt(Math.Pow(hole[min - 1].Traits.Position.x - hole[0].Traits.Position.x, 2) + Math.Pow(hole[min - 1].Traits.Position.y - hole[0].Traits.Position.y, 2) + Math.Pow(hole[min - 1].Traits.Position.z - hole[0].Traits.Position.z, 2)); } else if (min == 0) { temp = Math.Sqrt(Math.Pow(hole[hole.Count - 1].Traits.Position.x - hole[min + 1].Traits.Position.x, 2) + Math.Pow(hole[hole.Count - 1].Traits.Position.y - hole[min + 1].Traits.Position.y, 2) + Math.Pow(hole[hole.Count - 1].Traits.Position.z - hole[min + 1].Traits.Position.z, 2)); } else { temp = Math.Sqrt(Math.Pow(hole[min - 1].Traits.Position.x - hole[min + 1].Traits.Position.x, 2) + Math.Pow(hole[min - 1].Traits.Position.y - hole[min + 1].Traits.Position.y, 2) + Math.Pow(hole[min - 1].Traits.Position.z - hole[min + 1].Traits.Position.z, 2)); } #endregion //判断最小角对应的边与平均边界边长,并进行修补 #region 判断最小角对应的边与平均边界边长,并进行修补 if (temp > aver_l) { if (min == hole.Count - 1) { faceVertices[0] = mesh.Vertices[hole[min].Index]; faceVertices[1] = mesh.Vertices[hole[0].Index]; faceVertices[2] = mesh.Vertices[hole[min - 1].Index]; mesh.Faces.AddTriangles(faceVertices); } else if (min == 0) { faceVertices[0] = mesh.Vertices[hole[min].Index]; faceVertices[1] = mesh.Vertices[hole[min + 1].Index]; faceVertices[2] = mesh.Vertices[hole[hole.Count - 1].Index]; mesh.Faces.AddTriangles(faceVertices); } else { faceVertices[0] = mesh.Vertices[hole[min].Index]; faceVertices[1] = mesh.Vertices[hole[min + 1].Index]; faceVertices[2] = mesh.Vertices[hole[min - 1].Index]; mesh.Faces.AddTriangles(faceVertices); } } else { if (min == hole.Count - 1) { Vector3D midPosition; midPosition = (hole[min - 1].Traits.Position + hole[0].Traits.Position) / 2; mesh.Vertices.Add(new VertexTraits(midPosition.x, midPosition.y, midPosition.z)); faceVertices[0] = mesh.Vertices[hole[min].Index]; faceVertices[1] = mesh.Vertices[mesh.Vertices.Count - 1]; faceVertices[2] = mesh.Vertices[hole[min - 1].Index]; mesh.Faces.AddTriangles(faceVertices); faceVertices[0] = mesh.Vertices[hole[min].Index]; faceVertices[1] = mesh.Vertices[hole[0].Index]; faceVertices[2] = mesh.Vertices[mesh.Vertices.Count - 1]; mesh.Faces.AddTriangles(faceVertices); } else if (min == 0) { Vector3D midPosition; midPosition = (hole[hole.Count - 1].Traits.Position + hole[min + 1].Traits.Position) / 2; mesh.Vertices.Add(new VertexTraits(midPosition.x, midPosition.y, midPosition.z)); faceVertices[0] = mesh.Vertices[hole[min].Index]; faceVertices[1] = mesh.Vertices[mesh.Vertices.Count - 1]; faceVertices[2] = mesh.Vertices[hole[hole.Count - 1].Index]; mesh.Faces.AddTriangles(faceVertices); faceVertices[0] = mesh.Vertices[hole[min].Index]; faceVertices[1] = mesh.Vertices[hole[min + 1].Index]; faceVertices[2] = mesh.Vertices[mesh.Vertices.Count - 1]; mesh.Faces.AddTriangles(faceVertices); } else { Vector3D midPosition; midPosition = (hole[min - 1].Traits.Position + hole[min + 1].Traits.Position) / 2; mesh.Vertices.Add(new VertexTraits(midPosition.x, midPosition.y, midPosition.z)); faceVertices[0] = mesh.Vertices[hole[min].Index]; faceVertices[1] = mesh.Vertices[mesh.Vertices.Count - 1]; faceVertices[2] = mesh.Vertices[hole[min - 1].Index]; mesh.Faces.AddTriangles(faceVertices); faceVertices[0] = mesh.Vertices[hole[min].Index]; faceVertices[1] = mesh.Vertices[hole[min + 1].Index]; faceVertices[2] = mesh.Vertices[mesh.Vertices.Count - 1]; mesh.Faces.AddTriangles(faceVertices); } } #endregion //更新边界点,并判断空洞是否完整 #region 更新边界点,并判断空洞是否完整 TriMeshUtil.FixIndex(mesh); hole = TriMeshUtil.RetrieveBoundarySingle(mesh); if (hole.Count < 3) { break; } #endregion } }
public VertexMap Cut(double move) { this.vertexMap = new VertexMap(this.mesh); this.edgeQueue = new Queue <VertexPair>(); this.move = move; foreach (var edge in this.mesh.Edges) { if (edge.Traits.SelectedFlag != 0) { this.edgeQueue.Enqueue(new VertexPair(edge.Vertex0, edge.Vertex1)); } } bool boundary = false; foreach (var edge in this.edgeQueue) { if (edge.Src.OnBoundary || edge.Dst.OnBoundary) { boundary = true; break; } } if (!boundary) { this.CutStart(); } int count = 1; while (this.edgeQueue.Count != 0 && count < this.edgeQueue.Count) { VertexPair pair = this.edgeQueue.Dequeue(); TriMesh.Edge edge = pair.Src.FindEdgeTo(pair.Dst); if (edge != null) { if (this.Cut(edge)) { count = 0; } else { this.edgeQueue.Enqueue(pair); count++; } } else { TriMesh.Vertex[] map1 = this.vertexMap.GetOther(pair.Src, false); TriMesh.Vertex[] map2 = this.vertexMap.GetOther(pair.Dst, false); for (int m = 0; m < map1.Length; m++) { this.edgeQueue.Enqueue(new VertexPair(map1[m], pair.Dst)); } for (int n = 0; n < map2.Length; n++) { this.edgeQueue.Enqueue(new VertexPair(pair.Src, map2[n])); } for (int m = 0; m < map1.Length; m++) { for (int n = 0; n < map2.Length; n++) { this.edgeQueue.Enqueue(new VertexPair(map1[m], map2[n])); } } count = 0; } } TriMeshUtil.FixIndex(mesh); return(this.vertexMap); }