public static void TransformationRotation(List <TriMesh.Vertex> vertice, Vector3D rotation, bool local) { Vector3D center = Vector3D.Zero; Matrix4D m = Matrix4D.Identity(); if (local) { center = TriMeshUtil.GetCenter(vertice); Matrix4D moveC = ComputeMatrixMove(ref center); center.Negate(); Matrix4D moveCReverse = ComputeMatrixMove(ref center); Matrix4D r = ComputeMatrixRotation(rotation); m = moveCReverse * r * moveC; } else { m = ComputeMatrixRotation(rotation); } TransformationVertex(vertice, m); }
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 double[] SetColor(string item, TriMesh mesh, CriteriaInfo criteriaInfo) { TriMeshUtil.ClearMeshColor(mesh); double[] value = null; if (item == "DehidraAngleMin") { value = ColorEdgeByDihedralAngle(mesh, criteriaInfo.DehidraAngleMin, criteriaInfo.DehidraAngleMax); } if (item == "DehidraAngleMax") { value = ColorEdgeByDihedralAngle(mesh, criteriaInfo.DehidraAngleMin, criteriaInfo.DehidraAngleMax); } if (item == "GaussinMin") { value = ColorVertexByGaussin(mesh, criteriaInfo.GaussinMin, criteriaInfo.GaussinMax); } if (item == "GaussinMax") { value = ColorVertexByGaussin(mesh, criteriaInfo.GaussinMin, criteriaInfo.GaussinMax); } if (item == "MeanCurvatureMax") { value = ColorVertexByMeanCurvature(mesh, criteriaInfo.MeanCurvatureMin, criteriaInfo.MeanCurvatureMax); } if (item == "MeanCurvatureMin") { value = ColorVertexByMeanCurvature(mesh, criteriaInfo.MeanCurvatureMin, criteriaInfo.MeanCurvatureMax); } return(value); }
public SparseMatrix BuildMatrixMeanCurvature(TriMesh mesh) { int n = mesh.Vertices.Count; SparseMatrix L = BuildLaplaceMatrixCotBasic(mesh); double[] voronoiArea = TriMeshUtil.ComputeAreaVoronoi(mesh); for (int i = 0; i < n; i++) { double sum = 0; foreach (SparseMatrix.Element e in L.Rows[i]) { e.value = e.value / (voronoiArea[e.i] * 4); } foreach (SparseMatrix.Element e in L.Rows[i]) { sum += e.value; } L.AddValueTo(i, i, -sum); } L.SortElement(); return(L); }
public CurvaturePG07(TriMesh mesh) { this.mesh = mesh; this.K = new Vector3D[this.mesh.Vertices.Count]; this.Mean = new double[this.mesh.Vertices.Count]; this.Normal = new Vector3D[this.mesh.Vertices.Count]; this.PrincipalCurv = new PrincipalCurvature[this.mesh.Vertices.Count]; foreach (var v in this.mesh.Vertices) { double mixedArea = TriMeshUtil.ComputeAreaMixed(v); this.K[v.Index] = ComputeK(v, mixedArea); this.Mean[v.Index] = ComputeMeanCurvature(this.K[v.Index]); this.Normal[v.Index] = ComputeNormal(this.K[v.Index]); } foreach (var v in this.mesh.Vertices) { this.PrincipalCurv[v.Index] = this.ComputePrincipalCurvature(v); } }
SparseMatrixQuaternion BuildEigenValueProblem(double[] rho) { int nV = mesh.Vertices.Count; SparseMatrixQuaternion E = new SparseMatrixQuaternion(nV, nV); int[] Indices = new int[3]; foreach (TriMesh.Face face in mesh.Faces) { double A = TriMeshUtil.ComputeAreaFace(face); double a = -1 / (4 * A); double b = rho[face.Index] / 6; double c = A * rho[face.Index] * rho[face.Index] / 9; Indices[0] = face.GetVertex(0).Index; Indices[1] = face.GetVertex(1).Index; Indices[2] = face.GetVertex(2).Index; Quaternion[] e = new Quaternion[3]; for (int i = 0; i < 3; i++) { Vector3D eV = mesh.Vertices[Indices[(i + 2) % 3]].Traits.Position - mesh.Vertices[Indices[(i + 1) % 3]].Traits.Position; e[i] = new Quaternion(eV, 0); } for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { Quaternion q = a * e[i] * e[j] + b * (e[j] - e[i]) + c; E[Indices[i], Indices[j]] += q; } } } return(E); }
private void InitCurvatureInfoGrid() { this.dataGridViewCurvature.Rows.Clear(); double[] curvature = TriMeshUtil.ComputeGaussianCurvature(Mesh); double[] meanCurv = TriMeshUtil.ComputeMeanCurvature(Mesh); PrincipalCurvature[] basic = TriMeshUtil.ComputePricipalCurvature(Mesh); PrincipalCurvature[] pg = TriMeshUtil.ComputePricipalCurvaturePG07(Mesh); CurvatureLib.Init(Mesh); PrincipalCurvature[] ccc = CurvatureLib.ComputeCurvature(); for (int i = 0; i < curvature.Length; i++) { this.dataGridViewCurvature.Rows.Add(i, curvature[i], meanCurv[i], ccc[i].max, ccc[i].min, pg[i].max, pg[i].min); } }
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 SparseMatrix BuildMatrixMass(TriMesh mesh) { int n = mesh.Vertices.Count; SparseMatrix L = new SparseMatrix(n, n); for (int i = 0; i < mesh.Edges.Count; i++) { double face0area = 0; double face1area = 0; if (mesh.Edges[i].Face0 != null) { face0area = TriMeshUtil.ComputeAreaFace(mesh.Edges[i].Face0); } if (mesh.Edges[i].Face1 != null) { face1area = TriMeshUtil.ComputeAreaFace(mesh.Edges[i].Face1); } L.AddValueTo(mesh.Edges[i].Vertex0.Index, mesh.Edges[i].Vertex1.Index, (face0area + face1area) / 12); L.AddValueTo(mesh.Edges[i].Vertex1.Index, mesh.Edges[i].Vertex0.Index, (face0area + face1area) / 12); } for (int i = 0; i < n; i++) { double sum = 0; foreach (SparseMatrix.Element e in L.Rows[i]) { sum += e.value; } L.AddValueTo(i, i, sum); } L.SortElement(); return(L); }
public void DrawFaceNormal(TriMesh mesh) { OpenGLManager.Instance.SetColor(GlobalSetting.DisplaySetting.NormalColor); double avgLength = TriMeshUtil.ComputeEdgeAvgLength(mesh); avgLength *= GlobalSetting.DisplaySetting.NormalLength; foreach (TriMesh.Face item in mesh.Faces) { double x = (item.GetVertex(0).Traits.Position.x + item.GetVertex(1).Traits.Position.x + item.GetVertex(2).Traits.Position.x) / 3; double y = (item.GetVertex(0).Traits.Position.y + item.GetVertex(1).Traits.Position.y + item.GetVertex(2).Traits.Position.y) / 3; double z = (item.GetVertex(0).Traits.Position.z + item.GetVertex(1).Traits.Position.z + item.GetVertex(2).Traits.Position.z) / 3; Vector3D normal = item.Traits.Normal.Normalize() * avgLength; GL.Begin(BeginMode.Lines); GL.Vertex3(x, y, z); GL.Vertex3(x + normal.x, y + normal.y, z + normal.z); GL.End(); } }
public TriMesh AddSelectionEdge(TriMesh mesh, int index) { List <TriMesh> sel = new List <TriMesh>(); for (int i = 0; i < mesh.Edges.Count; i++) { if (mesh.Edges[i].Traits.SelectedFlag == index) { TriMesh selV = TriMeshIO.FromObjFile(ConfigShape.Instance.EdgeFile); TriMeshUtil.ScaleToUnit(selV, 1); TriMeshUtil.ScaleToUnit(selV, ConfigShape.Instance.Scale); Vector3D direction = mesh.Edges[i].Vertex1.Traits.Position - mesh.Edges[i].Vertex0.Traits.Position; Vector3D loc = (mesh.Edges[i].Vertex1.Traits.Position + mesh.Edges[i].Vertex0.Traits.Position) / 2; Matrix4D scale = TriMeshUtil.ComputeMatrixScale(direction.Length() / ConfigShape.Instance.Scale, 1d, 1d); // TriMeshUtil.TransformationRotation(selV, direction); TriMeshUtil.TransformationScale(selV, scale); TriMeshUtil.TransformRoatationV(selV, direction, Vector3D.UnitX); //TriMeshUtil.TransformRotationX(selV, direction.x); //TriMeshUtil.TransformRotationY(selV, direction.y); //TriMeshUtil.TransformRotationZ(selV, direction.z); TriMeshUtil.TransformationMove(selV, loc); sel.Add(selV); } } TriMesh result = TriMeshUtil.Combine(sel); result.FileName = Path.GetFileNameWithoutExtension(mesh.FileName) + "-E-" + index.ToString(); TriMeshUtil.SetUpVertexNormal(result, EnumNormal.AreaWeight); return(result); }
public DenseMatrixDouble InitWithTrivalHolonmy(SparseMatrixDouble Laplace, TriMesh mesh) { DenseMatrixDouble b = new DenseMatrixDouble(mesh.Vertices.Count, 1); double[] tempSingularities = new double[mesh.Vertices.Count]; for (int i = 0; i < tempSingularities.Length; i++) { tempSingularities[i] = 0; } foreach (KeyValuePair <TriMesh.Vertex, double> pair in Singularities) { int index = pair.Key.Index; double value = pair.Value; tempSingularities[index] = value; } double[] GuassianCurvs = TriMeshUtil.ComputeGaussianCurvatureIntegrated(mesh); foreach (TriMesh.Vertex v in mesh.Vertices) { double value = 0; if (!v.OnBoundary) { value -= GuassianCurvs[v.Index]; value += 2 * Math.PI * tempSingularities[v.Index]; } b[v.Index, 0] = value; } DenseMatrixDouble u = LinearSystemGenericByLib.Instance.SolveLinerSystem(ref Laplace, ref b); return(u); }
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 Dictionary <string, string> BuildMeshInfo(TriMesh mesh) { Dictionary <string, string> meshinfo = new Dictionary <string, string>(); meshinfo.Add("Verties", mesh.Vertices.Count.ToString()); meshinfo.Add("Edges", mesh.Edges.Count.ToString()); meshinfo.Add("Faces", mesh.Faces.Count.ToString()); meshinfo.Add("Elur Formula For Genus=0", "V-E+F = 2"); meshinfo.Add("General Elur Formula on Genus !=0", "V-E+F=2(C-G)-B, C is Component Number,G is Genus Number,B is boundary Number"); meshinfo.Add("Elur Characteristic is ", "2(C-G)-B or V-E+F"); meshinfo.Add("Elur Characteristic on Current Mesh", "V-E+F = " + mesh.Vertices.Count.ToString() + " - " + mesh.Edges.Count.ToString() + " + " + mesh.Faces.Count.ToString() + " = " + CountEulerCharacteristic(mesh).ToString()); meshinfo.Add("Component", CountComponents(mesh, false).ToString()); meshinfo.Add("Boundary Number", TriMeshUtil.CountBoundary(mesh).ToString()); meshinfo.Add("Genus", "G=-((V-E+F)+B)/2+C"); meshinfo.Add("Genus on Current mesh", CountGenus(mesh).ToString()); meshinfo.Add("Total Gaussian Curvature is ", TriMeshUtil.ComputeTotalGaussianCurvarture(mesh).ToString()); meshinfo.Add("Gaussian-Bonnet Theroem", "2*PI*(V-E+F) = SUM(Gaussian Curvature)"); meshinfo.Add("Current Gaussian-Bonnet Theroem", "2*PI*(V-E+F)=" + "2 x 3.1415 x " + CountEulerCharacteristic(mesh).ToString() + " = " + (Math.PI * 2 * CountEulerCharacteristic(mesh)) + " ??= " + TriMeshUtil.ComputeTotalGaussianCurvarture(mesh) ); meshinfo.Add("Average Area", TriMeshUtil.ComputeAreaAverage(mesh).ToString()); meshinfo.Add("Volume", TriMeshUtil.ComputeVolume(mesh).ToString()); meshinfo.Add("Total Area", TriMeshUtil.ComputeAreaTotal(mesh).ToString()); return(meshinfo); }
public static void BoundaryExpand(TriMesh mesh) { double length = TriMeshUtil.ComputeEdgeAvgLength(mesh); List <List <TriMesh.HalfEdge> > holes = TriMeshUtil.RetrieveBoundaryEdgeAll(mesh); foreach (var hole in holes) { TriMesh.Vertex[] arr = new HalfEdgeMesh.Vertex[hole.Count]; for (int i = 0; i < hole.Count; i++) { Vector3D normal = Vector3D.UnitX; if (hole[i].Opposite.Face != null) { normal = TriMeshUtil.ComputeNormalFace(hole[i].Opposite.Face); } Vector3D toPos = hole[i].ToVertex.Traits.Position; Vector3D fromPos = hole[i].FromVertex.Traits.Position; Vector3D hfDir = toPos - fromPos; Vector3D hfMid = (toPos + fromPos) / 2; Vector3D pos = hfMid + normal.Cross(hfDir).Normalize() * length; arr[i] = mesh.Vertices.Add(new VertexTraits(pos)); } for (int i = 0; i < hole.Count; i++) { int next = (i + 1) % hole.Count; TriMesh.Face face = mesh.Faces.Add(arr[i], hole[i].ToVertex, hole[next].ToVertex); face.Traits.SelectedFlag = 1; face = mesh.Faces.Add(arr[i], hole[next].ToVertex, arr[next]); face.Traits.SelectedFlag = 1; } } }
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(); } }
protected Vector3D[] ComputeVectorField(DenseMatrixDouble u, TriMesh mesh) { Vector3D[] vectors = new Vector3D[mesh.Faces.Count]; foreach (TriMesh.Face f in mesh.Faces) { if (f.OnBoundary) { continue; } TriMesh.HalfEdge hij = f.HalfEdge; TriMesh.HalfEdge hjk = hij.Next; TriMesh.HalfEdge hki = hjk.Next; TriMesh.Vertex vi = hij.FromVertex; TriMesh.Vertex vj = hjk.FromVertex; TriMesh.Vertex vk = hki.FromVertex; double ui = u[vi.Index, 0]; double uj = u[vj.Index, 0]; double uk = u[vk.Index, 0]; Vector3D eijL = RotatedEdge(hij); Vector3D ejkL = RotatedEdge(hjk); Vector3D ekiL = RotatedEdge(hki); double area = TriMeshUtil.ComputeAreaFaceTwo(f); Vector3D x = 0.5 * (ui * ejkL + uj * ekiL + uk * eijL) / area; vectors[f.Index] = -x.Normalize(); } return(vectors); }
public void Run() { TriMeshUtil.TransformationRotation(GlobalData.Instance.TriMesh, new Vector3D(0, 0, 0.001d)); }
private void scaleToUnitToolStripMenuItem_Click(object sender, EventArgs e) { TriMeshUtil.ScaleToUnit(Mesh, 0.9); OnChanged(EventArgs.Empty); }
private void moveToCenterToolStripMenuItem_Click(object sender, EventArgs e) { TriMeshUtil.MoveToCenter(Mesh); OnChanged(EventArgs.Empty); }
private void reverseToolStripMenuItem_Click(object sender, EventArgs e) { TriMeshUtil.SelectedVertexReverse(Mesh); TriMeshUtil.GroupVertice(Mesh); OnChanged(EventArgs.Empty); }
private void randomToolStripMenuItem_Click(object sender, EventArgs e) { TriMeshUtil.SelectedVertexRandom(Mesh, ConfigMeshOP.Instance.RandomSelect); OnChanged(EventArgs.Empty); }
protected double GetValue(TriMesh.Vertex v) { return(TriMeshUtil.ComputeGaussianCurvature(v)); }
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 static double ComputePerimeter(TriMesh.Face face) { Triple <Vector3D> t = TriMeshUtil.GetHalfEdgesVector(face); return(t.T0.Length() + t.T1.Length() + t.T2.Length()); }
public static void RegionGrow(TriMesh mesh) { Vector3D[] normal = TriMeshUtil.ComputeNormalFace(mesh); double[] area = TriMeshUtil.ComputeAreaFace(mesh); SortedList <double, TriMesh.Face> sort = new SortedList <double, HalfEdgeMesh.Face>(); foreach (var center in mesh.Faces) { List <double> list = new List <double>(); double sum = 0; foreach (var round in center.Faces) { double l = (normal[round.Index] - normal[center.Index]).Length();// * area[round.Index]); sum += l; list.Add(l); } sum /= list.Count; double d = 0; foreach (var item in list) { d += Math.Pow(item - sum, 2); } d /= list.Count; if (sum < 1 && d < 0.1) { sort.Add(sum, center); } } Stack <TriMesh.Face> stack = new Stack <HalfEdgeMesh.Face>(); Dictionary <int, Cluster> dict = new Dictionary <int, Cluster>(); double k = 1; int flag = 0; do { if (stack.Count == 0) { bool run = false; if (flag > 100) { return; } for (int i = flag; i < sort.Count; i++) { TriMesh.Face next = sort.Values[i]; if (next.Traits.SelectedFlag == 0) { flag++; next.Traits.SelectedFlag = (byte)flag; stack.Push(next); dict[flag] = new Cluster(); dict[flag].Add(normal[sort.Values[i].Index]); run = true; break; } } if (!run) { return; } } TriMesh.Face center = stack.Pop(); foreach (var round in center.Faces) { if (round.Traits.SelectedFlag == 0 && (normal[round.Index] - normal[center.Index]).Length() < k && (normal[round.Index] - dict[flag].Center).Length() < k) { dict[flag].Add(normal[round.Index]); round.Traits.SelectedFlag = (byte)flag; stack.Push(round); } } } while (true); }
private void InitVertexInfo() { this.dataGridViewVertex.Rows.Clear(); foreach (TriMesh.Vertex vertex in Mesh.Vertices) { this.dataGridViewVertex.Rows.Add(vertex.Index, vertex.Traits.Position.x, vertex.Traits.Position.y, vertex.Traits.Position.z); } foreach (TriMesh.Face face in Mesh.Faces) { this.dataGridViewFace.Rows.Add(face.Index, face.GetVertex(0).Index, face.GetVertex(1).Index, face.GetVertex(2).Index, TriMeshUtil.ComputeAreaFace(face)); } foreach (TriMesh.Edge edge in Mesh.Edges) { string face0 = "null"; string face1 = "null"; if (edge.Face0 != null) { face0 = edge.Face0.Index.ToString(); } if (edge.Face1 != null) { face1 = edge.Face1.Index.ToString(); } this.dataGridViewEdge.Rows.Add(edge.Index, edge.Vertex0.Index, edge.Vertex1.Index, face0, face1, TriMeshUtil.ComputeEdgeLength(edge), TriMeshUtil.ComputeDihedralAngle(edge) / 3.14 * 180); } }
private void faceBySplitLineToolStripMenuItem_Click(object sender, EventArgs e) { TriMeshUtil.ShowMeshPatchColor(Mesh); OnChanged(EventArgs.Empty); }
public static EdgeContext Merge(TriMesh.Edge edge) { Vector3D position = TriMeshUtil.GetMidPoint(edge); return(Merge(edge, position)); }
public void Run() { Stopwatch clock = new Stopwatch(); clock.Start(); double step = 0.01; DECMeshDouble decMesh = new DECMeshDouble(mesh); SparseMatrixDouble laplace = decMesh.Laplace; SparseMatrixDouble star0 = decMesh.HodgeStar0Form; SparseMatrixDouble star1 = decMesh.HodgeStar1Form; SparseMatrixDouble d0 = decMesh.ExteriorDerivative0Form; SparseMatrixDouble L = d0.Transpose() * star1 * d0; SparseMatrixDouble A = star0 + step * L; A.WriteToFile("A.ma"); double[] xs = new double[mesh.Vertices.Count]; double[] ys = new double[mesh.Vertices.Count]; double[] zs = new double[mesh.Vertices.Count]; foreach (TriMesh.Vertex v in mesh.Vertices) { xs[v.Index] = v.Traits.Position.x; ys[v.Index] = v.Traits.Position.y; zs[v.Index] = v.Traits.Position.z; } double[] rhs1 = star0 * xs; double[] rhs2 = star0 * ys; double[] rhs3 = star0 * zs; //SparseMatrix.WriteVectorToFile("xs.ve", rhs1); //SparseMatrix.WriteVectorToFile("ys.ve", rhs2); //SparseMatrix.WriteVectorToFile("zs.ve", rhs3); DenseMatrixDouble rhsx = new DenseMatrixDouble(mesh.Vertices.Count, 1); DenseMatrixDouble rhsy = new DenseMatrixDouble(mesh.Vertices.Count, 1); DenseMatrixDouble rhsz = new DenseMatrixDouble(mesh.Vertices.Count, 1); for (int i = 0; i < mesh.Vertices.Count; i++) { rhsx[i, 0] = rhs1[i]; rhsy[i, 0] = rhs2[i]; rhsz[i, 0] = rhs3[i]; } DenseMatrixDouble newX = LinearSystemGenericByLib.Instance.SolveLinerSystem(ref A, ref rhsx); DenseMatrixDouble newY = LinearSystemGenericByLib.Instance.SolveLinerSystem(ref A, ref rhsy); DenseMatrixDouble newZ = LinearSystemGenericByLib.Instance.SolveLinerSystem(ref A, ref rhsz); foreach (TriMesh.Vertex v in mesh.Vertices) { v.Traits.Position.x = newX[v.Index, 0]; v.Traits.Position.y = newY[v.Index, 0]; v.Traits.Position.z = newZ[v.Index, 0]; } TriMeshUtil.ScaleToUnit(mesh, 1.0f); TriMeshUtil.MoveToCenter(mesh); clock.Stop(); decimal micro = clock.Elapsed.Ticks / 10m; Console.WriteLine("Total time cost:{0}", micro); }