protected Vector3D Transport(Vector3D wI, TriMesh.Face faceI, TriMesh.Face faceJ, double angle) { /* * triangles i and j according to the following labels: * * b * /|\ * / | \ * / | \ * / | \ * c i | j d \ | / \ | / \ | / \|/ \ a \ */ //Find Shared edge IJ TriMesh.HalfEdge sharedEdgeI = null; TriMesh.HalfEdge sharedEdgeJ = null; TriMesh.Edge sharedEdge = null; foreach (TriMesh.HalfEdge edgeI in faceI.Halfedges) { foreach (TriMesh.HalfEdge edgeJ in faceJ.Halfedges) { if (edgeI.Opposite == edgeJ) { sharedEdge = edgeI.Edge; sharedEdgeI = edgeI; sharedEdgeJ = edgeJ; break; } } } if (sharedEdge == null) { throw new Exception("Error"); } //Find vertex correspondent to figure above Vector3D av = sharedEdgeI.FromVertex.Traits.Position; Vector3D bv = sharedEdgeJ.FromVertex.Traits.Position; Vector3D cv = sharedEdgeI.Next.ToVertex.Traits.Position; Vector3D dv = sharedEdgeJ.Next.ToVertex.Traits.Position; //Compute the basis Matrix3D Ei = Orthogonalize(bv - av, cv - av); Matrix3D Ej = Orthogonalize(bv - av, bv - dv); //Build Rotate Matrix between two Faces Matrix3D rotateMatrix = Matrix3D.Rotate(angle); Vector3D wj = (Ej * rotateMatrix * Ei.Inverse() * wI); return(wj); }
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); }
//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); }