public static void GrowByFaceAngle(TriMesh mesh) { Queue <TriMesh.Face> queue = new Queue <HalfEdgeMesh.Face>(); Vector3D[] normal = TriMeshUtil.ComputeNormalFace(mesh); foreach (var face in mesh.Faces) { if (face.Traits.SelectedFlag != 0) { queue.Enqueue(face); } } double k = 0.449; while (queue.Count != 0) { TriMesh.Face center = queue.Dequeue(); foreach (var round in center.Faces) { if (round.Traits.SelectedFlag == 0) { if (normal[center.Index].Dot(normal[round.Index]) > k) { round.Traits.SelectedFlag = center.Traits.SelectedFlag; queue.Enqueue(round); } } } } }
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(); } } }
public bool Backward() { if (this.index == 0) { return(false); } else { index--; EdgeContext ctx = this.method.Logs[this.index]; SplitVertex.Split(this.Mesh, ctx); 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.HalfEdge hf = left.FindHalfedgeTo(right); hf.Face.Traits.Normal = TriMeshUtil.ComputeNormalFace(hf.Face); hf.Opposite.Face.Traits.Normal = TriMeshUtil.ComputeNormalFace(hf.Opposite.Face); left.Traits.Normal = TriMeshUtil.ComputeNormalAreaWeight(left); right.Traits.Normal = TriMeshUtil.ComputeNormalAreaWeight(right); return(true); } }
public static void SetUpNormalFace(TriMesh mesh) { Vector3D[] normal = TriMeshUtil.ComputeNormalFace(mesh); for (int i = 0; i < mesh.Faces.Count; i++) { mesh.Faces[i].Traits.Normal = normal[i]; } }
Vector3D GetMoveVector(TriMesh.HalfEdge hf) { Vector3D normal = TriMeshUtil.ComputeNormalFace(hf.Face); Vector3D vec = hf.ToVertex.Traits.Position - hf.FromVertex.Traits.Position; Vector3D dir = normal.Cross(vec).Normalize(); return(dir * this.move); }
void CutInner(TriMesh.HalfEdge cur, TriMesh.HalfEdge next) { TriMesh.Vertex share1 = cur.FromVertex; TriMesh.Vertex share2 = next.ToVertex; TriMesh.Vertex mid = cur.ToVertex; Vector3D normal = TriMeshUtil.ComputeNormalFace(cur.Face); Vector3D vec = next.ToVertex.Traits.Position - cur.FromVertex.Traits.Position; Vector3D dir = normal.Cross(vec).Normalize(); TriMesh.Vertex v2 = TriMeshModify.VertexSplit(mid, share1, share2, mid.Traits.Position - dir * move, mid.Traits.Position + dir * move); TriMesh.HalfEdge hf = mid.FindHalfedgeTo(v2); TriMeshModify.RemoveEdge(hf.Edge); this.vertexMap.Add(mid, v2); }
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 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); }