public Vector3D ComputeFaceNormals(TriMesh.Face f) { Vector3D p0 = f.GetVertex(0).Traits.Position; Vector3D p1 = f.GetVertex(1).Traits.Position; Vector3D p2 = f.GetVertex(2).Traits.Position; return((p1 - p0).Cross(p2 - p0).Normalize()); }
public Vector3D[] ComputeVectorField(double initAngle) { Vector3D[] vectorFields = new Vector3D[mesh.Faces.Count]; bool[] visitedFlags = new bool[mesh.Faces.Count]; for (int i = 0; i < visitedFlags.Length; i++) { visitedFlags[i] = false; } //Find a initial root to expend TriMesh.Face rootFace = mesh.Faces[0]; var v1 = rootFace.GetVertex(0); var v3 = rootFace.GetVertex(2); var v2 = rootFace.GetVertex(1); Vector3D w0 = (rootFace.GetVertex(2).Traits.Position - rootFace.GetVertex(0).Traits.Position).Normalize(); //Init transpot Vector3D av = v1.Traits.Position; Vector3D bv = v2.Traits.Position; Vector3D cv = v3.Traits.Position; Matrix3D Ei = Orthogonalize(bv - av, cv - av); Vector3D w0i = (Ei * Matrix3D.Rotate(initAngle) * Ei.Inverse() * w0); vectorFields[rootFace.Index] = w0i; visitedFlags[rootFace.Index] = true; //Recurse all faces Queue <TriMesh.Face> queue = new Queue <HalfEdgeMesh.Face>(); queue.Enqueue(rootFace); int ii = 0; while (queue.Count > 0) { TriMesh.Face currentFace = queue.Dequeue(); Vector3D wI = vectorFields[currentFace.Index]; foreach (TriMesh.Face neighbor in currentFace.Faces) { if (visitedFlags[neighbor.Index] == false) { Vector3D wj = Transport2(wI, currentFace, neighbor); vectorFields[neighbor.Index] = wj; queue.Enqueue(neighbor); visitedFlags[neighbor.Index] = true; } } ii++; } return(vectorFields); }
//face area public static double ComputeAreaFaceTwo(TriMesh.Face face) { Vector3D v1 = new Vector3D(face.GetVertex(0).Traits.Position.x, face.GetVertex(0).Traits.Position.y, face.GetVertex(0).Traits.Position.z); Vector3D v2 = new Vector3D(face.GetVertex(1).Traits.Position.x, face.GetVertex(1).Traits.Position.y, face.GetVertex(1).Traits.Position.z); Vector3D v3 = new Vector3D(face.GetVertex(2).Traits.Position.x, face.GetVertex(2).Traits.Position.y, face.GetVertex(2).Traits.Position.z); double a = Math.Sqrt((v1.x - v2.x) * (v1.x - v2.x) + (v1.y - v2.y) * (v1.y - v2.y) + (v1.z - v2.z) * (v1.z - v2.z)); double b = Math.Sqrt((v3.x - v2.x) * (v3.x - v2.x) + (v3.y - v2.y) * (v3.y - v2.y) + (v3.z - v2.z) * (v3.z - v2.z)); double c = Math.Sqrt((v1.x - v3.x) * (v1.x - v3.x) + (v1.y - v3.y) * (v1.y - v3.y) + (v1.z - v3.z) * (v1.z - v3.z)); double p = (a + b + c) / 2; double area = Math.Sqrt(p * (p - a) * (p - b) * (p - c)); return(area); }
public static double ComputeInradius(TriMesh.Face face) { Vector3D a = face.GetVertex(0).Traits.Position; Vector3D b = face.GetVertex(1).Traits.Position; Vector3D c = face.GetVertex(2).Traits.Position; double u = (a - b).Length(); double v = (b - c).Length(); double w = (c - a).Length(); return(0.5 * Math.Sqrt(((u + v - w) * (w + u - v) * (v + w - u)) / (u + v + w))); }
public static List <double> ComputeAngle(TriMesh.Face face) { List <double> angles = new List <double>(); double angle1 = ComputeAngle(face.GetVertex(0).HalfEdge); double angle2 = ComputeAngle(face.GetVertex(1).HalfEdge); double angle3 = ComputeAngle(face.GetVertex(2).HalfEdge); angles.Add(angle1); angles.Add(angle2); angles.Add(angle3); return(angles); }
//public void ComputeFrameAngles(double initialAngle) //{ // TreeNode<TriMesh.Face> Root = transportTree.Root; // Queue<TreeNode<HalfEdgeMesh.Face>> queue = new Queue<TreeNode<HalfEdgeMesh.Face>>(); // queue.Enqueue(transportTree.Root); // bool[] processedFlag = new bool[Mesh.Faces.Count]; // while (queue.Count != 0) // { // TreeNode<HalfEdgeMesh.Face> currentFaceNode = queue.Dequeue(); // TriMesh.HalfEdge startHf = currentFaceNode.Attribute.HalfEdge; // TriMesh.HalfEdge currentHf = startHf; // do // { // TriMesh.Face neighborFace = currentHf.Opposite.Face; // TransportData td = transDatas[currentHf.Index]; // td.alphaJ = td.alphaI + td.delta - td.sign * td.omega; // currentHf = currentHf.Next; // } while (currentHf != startHf); // } //} //public void UpdateAngles(int initAngle) //{ // TriMesh.Face faceTransport = Mesh.Faces[3]; // FaceAngle[faceTransport.Index] = initAngle; // Queue<TriMesh.Face> queue = new Queue<TriMesh.Face>(); // queue.Enqueue(faceTransport); // bool[] processedFlag = new bool[Mesh.Faces.Count]; // while (queue.Count != 0) // { // TriMesh.Face currentFace = queue.Dequeue(); // TriMesh.HalfEdge startHf = currentFace.HalfEdge; // TriMesh.HalfEdge currentHf = startHf; // double currentDelta = Deltas[currentFace.Index]; // do // { // TriMesh.Face neighborFace = currentHf.Opposite.Face; // if (processedFlag[neighborFace.Index] == false && // neighborFace != faceTransport && // !neighborFace.OnBoundary // ) // { // processedFlag[neighborFace.Index] = true; // queue.Enqueue(neighborFace); // double delta = ComputeParallTransport(currentDelta, currentHf); // Deltas[neighborFace.Index] = delta; // double omega = EdgeTheta[currentHf.Edge.Index]; // double sign = currentHf.FromVertex.Index > currentHf.ToVertex.Index ? -1 : 1; // FaceAngle[neighborFace.Index] = FaceAngle[currentFace.Index] + delta - sign * omega; // } // currentHf = currentHf.Next; // } while (currentHf != startHf); // } //} //public void AppendDirectionalConstraints(TriMesh mesh, List<List<TriMesh.HalfEdge>> cycles) //{ // transDatas = new TransportData[mesh.HalfEdges.Count]; // TriMesh.Face faceTransport = mesh.Faces[3]; // transportTree = new DynamicTree<HalfEdgeMesh.Face>(); // transportTree.Root = new TreeNode<HalfEdgeMesh.Face>(faceTransport); // Queue<TreeNode<HalfEdgeMesh.Face>> queue = new Queue<TreeNode<HalfEdgeMesh.Face>>(); // queue.Enqueue(transportTree.Root); // bool[] processedFlag = new bool[mesh.Faces.Count]; // while (queue.Count != 0) // { // TreeNode<HalfEdgeMesh.Face> currentFaceNode = queue.Dequeue(); // TriMesh.HalfEdge startHf = currentFaceNode.Attribute.HalfEdge; // TriMesh.HalfEdge currentHf = startHf; // do // { // TriMesh.Face neighborFace = currentHf.Opposite.Face; // if (processedFlag[neighborFace.Index] == false && // neighborFace != faceTransport && // !neighborFace.OnBoundary // ) // { // TreeNode<HalfEdgeMesh.Face> neighNode = new TreeNode<HalfEdgeMesh.Face>(neighborFace); // processedFlag[neighborFace.Index] = true; // currentFaceNode.AddChild(neighNode); // queue.Enqueue(neighNode); // TransportData td = new TransportData(); // td.delta = ComputeParallTransport(0, currentHf); // td.sign = currentHf.FromVertex.Index > currentHf.ToVertex.Index ? 1 : -1; // td.omega = EdgeTheta[currentHf.Edge.Index]; // td.alphaI = FaceAngle[currentHf.Face.Index]; // td.alphaJ = FaceAngle[currentHf.Opposite.Face.Index]; // transDatas[currentHf.Index] = td; // Deltas[currentHf.Face.Index] = td.delta; // } // currentHf = currentHf.Next; // } while (currentHf != startHf); // } //} public Vector3D[] ComputeVectorField(double initAngle) { Vector3D[] vectorFields = new Vector3D[Mesh.Faces.Count]; bool[] visitedFlags = new bool[Mesh.Faces.Count]; for (int i = 0; i < visitedFlags.Length; i++) { visitedFlags[i] = false; } //Find a initial root to expend TriMesh.Face rootFace = Mesh.Faces[0]; var v1 = rootFace.GetVertex(0); var v3 = rootFace.GetVertex(2); var v2 = rootFace.GetVertex(1); Vector3D w0 = (rootFace.GetVertex(2).Traits.Position - rootFace.GetVertex(0).Traits.Position).Normalize(); //Init transpot Vector3D av = v1.Traits.Position; Vector3D bv = v2.Traits.Position; Vector3D cv = v3.Traits.Position; Matrix3D Ei = Orthogonalize(bv - av, cv - av); Vector3D w0i = (Ei * Matrix3D.Rotate(initAngle) * Ei.Inverse() * w0); vectorFields[rootFace.Index] = w0i; visitedFlags[rootFace.Index] = true; //Recurse all faces Queue <TriMesh.Face> queue = new Queue <HalfEdgeMesh.Face>(); queue.Enqueue(rootFace); int ii = 0; while (queue.Count > 0) { TriMesh.Face currentFace = queue.Dequeue(); Vector3D wI = vectorFields[currentFace.Index]; TriMesh.HalfEdge cuHe = currentFace.HalfEdge; do { TriMesh.Face neighbor = cuHe.Opposite.Face; if (neighbor == null) { cuHe = cuHe.Next; continue; } if (visitedFlags[neighbor.Index] == false) { double angle = EdgeTheta[cuHe.Edge.Index]; int i = cuHe.FromVertex.Index; int j = cuHe.ToVertex.Index; if (i > j) { angle = -angle; } Vector3D wj = Transport(wI, currentFace, neighbor, angle); vectorFields[neighbor.Index] = wj; queue.Enqueue(neighbor); visitedFlags[neighbor.Index] = true; } cuHe = cuHe.Next; } while (cuHe != currentFace.HalfEdge); ii++; } return(vectorFields); }