Example #1
0
        private TriMesh.HalfEdge[] FindSaddleExtreme(TriMesh.Vertex v, bool maxOrMin)
        {
            List <TriMesh.HalfEdge> all = new List <HalfEdgeMesh.HalfEdge>();

            TriMesh.HalfEdge n2p = this.FindN2P(v);
            v.HalfEdge = n2p;
            List <TriMesh.HalfEdge> part = new List <HalfEdgeMesh.HalfEdge>();
            double mid = this.function[v.Index];

            foreach (TriMesh.HalfEdge hf in v.HalfEdges)
            {
                double round = this.function[hf.ToVertex.Index];
                if (this.Compare(round, mid, maxOrMin))
                {
                    part.Add(hf);
                }
                else
                {
                    if (part.Count != 0)
                    {
                        all.Add(this.FindExtreme(part, maxOrMin));
                    }
                    part.Clear();
                }
            }
            if (part.Count != 0)
            {
                all.Add(this.FindExtreme(part, maxOrMin));
            }
            return(all.ToArray());
        }
Example #2
0
        public static void InverseFace(TriMesh mesh)
        {
            List <TriMesh.Vertex[]> faces = new List <HalfEdgeMesh.Vertex[]>();

            foreach (TriMesh.Face face in mesh.Faces)
            {
                TriMesh.HalfEdge hf  = face.HalfEdge;
                TriMesh.Vertex[] arr = new TriMesh.Vertex[] {
                    hf.Next.ToVertex,
                    hf.ToVertex,
                    hf.FromVertex
                };
                faces.Add(arr);
            }
            TriMesh.Vertex[] vertices = new TriMesh.Vertex[mesh.Vertices.Count];
            for (int i = 0; i < mesh.Vertices.Count; i++)
            {
                vertices[i]          = mesh.Vertices[i];
                vertices[i].HalfEdge = null;
            }
            mesh.Clear();
            foreach (var v in vertices)
            {
                mesh.AppendToVertexList(v);
            }
            foreach (var face in faces)
            {
                mesh.Faces.AddTriangles(face);
            }
        }
Example #3
0
        /// <summary>
        /// 两端点都在边界上
        /// </summary>
        /// <param name="edge"></param>
        void CutBothBoundary(TriMesh.Edge edge)
        {
            TriMesh.HalfEdge   hf       = edge.HalfEdge0;
            TriMesh.HalfEdge[] leftArr  = this.GetToBoundaryAntiClockWise(hf);
            TriMesh.HalfEdge[] rightArr = this.GetToBoundaryClockWise(hf.Next);


            for (int i = 1; i < leftArr.Length; i++)
            {
                TriMeshModify.RemoveEdge(leftArr[i].Edge);
            }

            for (int i = 0; i < rightArr.Length; i++)
            {
                TriMeshModify.RemoveEdge(rightArr[i].Edge);
            }

            Vector3D vec = this.GetMoveVector(hf.Opposite);

            TriMesh.Vertex left  = this.Clone(hf.FromVertex, vec);
            TriMesh.Vertex right = this.Clone(hf.ToVertex, vec);

            for (int i = 2; i < leftArr.Length; i++)
            {
                this.mesh.Faces.AddTriangles(left, leftArr[i - 1].ToVertex, leftArr[i].ToVertex);
            }
            for (int i = 1; i < rightArr.Length; i++)
            {
                this.mesh.Faces.AddTriangles(right, rightArr[i].ToVertex, rightArr[i - 1].ToVertex);
            }
            this.mesh.Faces.AddTriangles(left, right, leftArr[1].ToVertex);
        }
Example #4
0
        private double GetAngle(Plane plane, TriMesh.HalfEdge hf)
        {
            Vector3D v   = hf.ToVertex.Traits.Position - hf.FromVertex.Traits.Position;
            double   cos = Math.Abs(plane.Normal.Dot(v.Normalize()));

            return(Math.Acos(cos) * 180 / Math.PI);
        }
Example #5
0
        public List <List <TriMesh.HalfEdge> > Append1RingBases(TriMesh mesh)
        {
            MapRow = new int[mesh.Vertices.Count];
            List <List <TriMesh.HalfEdge> > cycles = new List <List <HalfEdgeMesh.HalfEdge> >();

            foreach (TriMesh.Vertex vertex in mesh.Vertices)
            {
                if (vertex.OnBoundary)
                {
                    MapRow[vertex.Index] = -1;
                    continue;
                }

                List <TriMesh.HalfEdge> cycle = new List <HalfEdgeMesh.HalfEdge>();

                TriMesh.HalfEdge currentHf = vertex.HalfEdge;
                do
                {
                    cycle.Add(currentHf);

                    currentHf = currentHf.Opposite.Next;
                } while (currentHf != vertex.HalfEdge);

                MapRow[vertex.Index] = cycles.Count;

                cycles.Add(cycle);
            }

            return(cycles);
        }
Example #6
0
        public void PlaneCut(TriMesh.HalfEdge above, Vector3D normal, double maxAngle)
        {
            Plane plane = new Plane(above.Next.ToVertex.Traits.Position, normal);
            Nullable <Vector3D> point = this.Intersect(plane, above.Edge);
            double angle = this.GetAngle(plane, above);

            while (point != null && angle > maxAngle)
            {
                TriMesh.Vertex left   = above.FromVertex;
                TriMesh.Vertex right  = above.ToVertex;
                TriMesh.Vertex buttom = above.Opposite.Next.ToVertex;

                this.Cut(above, point.Value);

                if (above.Opposite.OnBoundary)
                {
                    break;
                }

                TriMesh.HalfEdge[] below = new[] { left.FindHalfedgeTo(buttom), buttom.FindHalfedgeTo(right) };
                foreach (var hf in below)
                {
                    point = this.Intersect(plane, hf.Edge);
                    if (point != null)
                    {
                        angle = this.GetAngle(plane, hf);
                        above = hf;
                        break;
                    }
                }
            }
        }
Example #7
0
 public static bool EdgeSwap(TriMesh.Edge edge)
 {
     if (edge.OnBoundary)
     {
         return(false);
     }
     //逆时针90度,左右变为下上
     TriMesh.HalfEdge hf1         = edge.HalfEdge0;
     TriMesh.HalfEdge hf2         = edge.HalfEdge1;
     TriMesh.Vertex   top         = hf1.ToVertex;
     TriMesh.Vertex   buttom      = hf2.ToVertex;
     TriMesh.HalfEdge topLeft     = hf1.Next;
     TriMesh.HalfEdge buttomLeft  = hf1.Previous;
     TriMesh.HalfEdge topRight    = hf2.Previous;
     TriMesh.HalfEdge buttomRight = hf2.Next;
     top.HalfEdge      = topLeft;
     buttom.HalfEdge   = buttomRight;
     hf1.ToVertex      = topLeft.ToVertex;
     hf2.ToVertex      = buttomRight.ToVertex;
     hf1.Face.HalfEdge = hf1;
     hf2.Face.HalfEdge = hf2;
     topLeft.Face      = hf2.Face;
     buttomRight.Face  = hf1.Face;
     ConnectHalfEdge(topLeft, hf2, topRight);
     ConnectHalfEdge(buttomRight, hf1, buttomLeft);
     return(true);
 }
Example #8
0
        public void RemoveCapWithSplit()
        {
            int count = 0;

            do
            {
                count = 0;
                for (int i = 0; i < this.mesh.HalfEdges.Count; i++)
                {
                    TriMesh.HalfEdge hf    = this.mesh.HalfEdges[i];
                    double           angle = TriMeshUtil.ComputeAngle(hf) / Math.PI * 180;
                    if (angle > this.capAngle)
                    {
                        Plane plane = this.GetPlane(hf);

                        Nullable <Vector3D> point = this.Intersect(plane, hf.Edge);
                        this.ShowIntersect(plane);

                        if (point != null)
                        {
                            this.Cut(hf, point.Value);
                            count++;
                        }
                        else
                        {
                            hf.Edge.Traits.SelectedFlag = 1;
                        }
                    }
                }
            } while (count != 0);
        }
Example #9
0
        TriMesh.Edge CreateNewEdge(TriMesh.Vertex from, TriMesh.Vertex to)
        {
            TriMesh mesh = (TriMesh)from.Mesh;

            // Create new edge
            TriMesh.Edge edge = new TriMesh.Edge();
            mesh.AppendToEdgeList(edge);
            // Create new halfedges
            TriMesh.HalfEdge hf0 = new TriMesh.HalfEdge();
            mesh.AppendToHalfedgeList(hf0);
            hf0.Opposite = new TriMesh.HalfEdge();
            mesh.AppendToHalfedgeList(hf0.Opposite);
            // Connect opposite halfedge to inner halfedge
            hf0.Opposite.Opposite = hf0;
            // Connect edge to halfedges
            edge.HalfEdge0 = hf0;
            // Connect halfedges to edge
            hf0.Edge          = edge;
            hf0.Opposite.Edge = edge;
            // Connect halfedges to vertices
            hf0.ToVertex          = to;
            hf0.Opposite.ToVertex = from;
            // Connect vertex to outgoing halfedge if it doesn't have one yet
            if (from.HalfEdge == null)
            {
                from.HalfEdge = hf0;
            }
            return(edge);
        }
Example #10
0
 void OuterHalfedgeBothOld(TriMesh.HalfEdge cur, TriMesh.HalfEdge next)
 {
     // Relink faces before adding new edges if they are in the way of a new face
     if (cur.Next != next)
     {
         TriMesh.HalfEdge closeHalfedge = cur.Opposite;
         // Find the closing halfedge of the opening opposite the opening halfedge i is on
         do
         {
             closeHalfedge = closeHalfedge.Previous.Opposite;
         } while (closeHalfedge.Face != null && closeHalfedge != next &&
                  closeHalfedge != cur.Opposite);
         if (closeHalfedge == next || closeHalfedge == cur.Opposite)
         {
             throw new BadTopologyException("Unable to find an opening to relink an existing face.");
         }
         TriMesh.HalfEdge openHalfedge = closeHalfedge.Previous;
         // Remove group of faces between two openings, close up gap to form one opening
         openHalfedge.Next = cur.Next;
         cur.Next.Previous = openHalfedge;
         // Insert group of faces into target opening
         next.Previous.Next     = closeHalfedge;
         closeHalfedge.Previous = next.Previous;
     }
 }
Example #11
0
 void OuterHalfedgeBothNew(TriMesh.HalfEdge cur, TriMesh.HalfEdge next, bool vertexIsUsed)
 {
     if (vertexIsUsed)  // Both edges are new and vertex has faces connected already
     {
         TriMesh.Vertex   vertex        = cur.ToVertex;
         TriMesh.HalfEdge closeHalfedge = null;
         // Find the closing halfedge of the first available opening
         foreach (TriMesh.HalfEdge h in vertex.HalfEdges)
         {
             if (h.Face == null)
             {
                 closeHalfedge = h;
                 break;
             }
         }
         TriMesh.HalfEdge openHalfedge = closeHalfedge.Previous;
         // Link new outer halfedges into this opening
         cur.Opposite.Previous  = openHalfedge;
         openHalfedge.Next      = cur.Opposite;
         next.Opposite.Next     = closeHalfedge;
         closeHalfedge.Previous = next.Opposite;
     }
     else
     {
         cur.Opposite.Previous = next.Opposite;
         next.Opposite.Next    = cur.Opposite;
     }
 }
Example #12
0
        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);
        }
Example #13
0
 public void SelectAngle(TriMesh.HalfEdge hf)
 {
     hf.Edge.Traits.SelectedFlag          = 1;
     hf.Previous.Edge.Traits.SelectedFlag = 1;
     hf.Next.Edge.Traits.SelectedFlag     = 1;
     hf.Next.ToVertex.Traits.SelectedFlag = 1;
 }
Example #14
0
        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);
            }
        }
Example #15
0
        private static void InsertEdge(TriMesh mesh, TriMesh.HalfEdge inner, TriMesh.HalfEdge outer)
        {
            //TriMesh.Edge left = new TriMesh.Edge();
            //left.HalfEdge0 = outer;
            //outer.Edge = left;
            //inner.Next.Edge = left;

            //TriMesh.Edge right = outer.Edge;
            //right.HalfEdge0 = inner;
            //inner.Edge = right;
            //outer.Opposite.Edge = right;

            //inner.Opposite = outer.Opposite;
            //inner.Next.Opposite = outer;
            //outer.Opposite.Opposite = inner;
            //outer.Opposite = inner.Next;
            inner.Opposite          = outer.Opposite;
            inner.Next.Opposite     = outer;
            outer.Opposite.Opposite = inner;
            outer.Opposite          = inner.Next;
            outer.Edge.HalfEdge0    = outer;

            TriMesh.Edge edge = new TriMesh.Edge();
            edge.HalfEdge0      = inner;
            inner.Edge          = edge;
            inner.Opposite.Edge = edge;
            inner.Next.Edge     = outer.Edge;

            mesh.AppendToEdgeList(edge);
        }
Example #16
0
        public static TriMesh.HalfEdge[] RetrieveBoundaryHalfEdgeByPatch(TriMesh mesh, bool[] selectedFlags)
        {
            List <TriMesh.HalfEdge> boundaryHFs = new List <TriMesh.HalfEdge>();

            TriMesh.HalfEdge start = GetStart(mesh, selectedFlags);
            if (start == null)
            {
                return(boundaryHFs.ToArray());
            }
            TriMesh.HalfEdge cur = start;
            do
            {
                do
                {
                    cur = cur.Next.Opposite;
                } while (!(selectedFlags[cur.Next.FromVertex.Index] &&
                           selectedFlags[cur.Next.ToVertex.Index]));

                do
                {
                    cur = cur.Next;
                    boundaryHFs.Add(cur);
                } while (cur.OnBoundary &&
                         selectedFlags[cur.Next.ToVertex.Index] &&
                         selectedFlags[cur.Next.FromVertex.Index]);
            } while (cur != start);

            return(boundaryHFs.ToArray());
        }
Example #17
0
        public static TriMesh.HalfEdge Split(TriMesh.HalfEdge hf, Vector3D v1Pos, Vector3D v2Pos)
        {
            TriMesh mesh = (TriMesh)hf.Mesh;

            List <TriMesh.HalfEdge> list = new List <HalfEdgeMesh.HalfEdge>();

            TriMesh.HalfEdge cur = hf;
            list.Add(cur);
            do
            {
                cur = cur.Opposite.Next;
                list.Add(cur);
            } while (cur.Opposite.Face != null && cur != hf);


            for (int i = 1; i < list.Count; i++)
            {
                TriMeshModify.RemoveEdge(list[i].Edge);
            }
            hf.FromVertex.Traits.Position = v1Pos;
            TriMesh.Vertex v2 = new HalfEdgeMesh.Vertex(new VertexTraits(v2Pos));
            mesh.AppendToVertexList(v2);

            for (int i = 1; i < list.Count; i++)
            {
                mesh.Faces.AddTriangles(list[i - 1].ToVertex, v2, list[i].ToVertex);
            }
            mesh.Faces.AddTriangles(list[0].ToVertex, hf.FromVertex, v2);
            return(hf.FromVertex.FindHalfedgeTo(v2));
        }
Example #18
0
        public static List <TriMesh.HalfEdge> RetrieveOneRingEdgeOfEdge(TriMesh.Edge edge)
        {
            TriMesh mesh = (TriMesh)edge.Mesh;
            List <TriMesh.HalfEdge> list = new List <TriMesh.HalfEdge>();

            TriMesh.HalfEdge hf0             = edge.HalfEdge0;
            TriMesh.HalfEdge currentHalfedge = hf0.Next.Opposite;
            while (currentHalfedge.Next.Opposite != hf0)
            {
                if (!currentHalfedge.OnBoundary)
                {
                    list.Add(currentHalfedge.Previous);
                }
                currentHalfedge = currentHalfedge.Next.Opposite;
            }
            ;
            TriMesh.HalfEdge hf1 = edge.HalfEdge1;
            currentHalfedge = hf1.Next.Opposite;
            while (currentHalfedge.Next.Opposite != hf1)
            {
                if (!currentHalfedge.OnBoundary)
                {
                    list.Add(currentHalfedge.Previous);
                }
                currentHalfedge = currentHalfedge.Next.Opposite;
            }
            ;
            return(list);
        }
Example #19
0
        /// <summary>
        /// 逆时针一圈
        /// </summary>
        /// <param name="mesh"></param>
        /// <param name="faceFlags"></param>
        /// <returns></returns>
        public static TriMesh.HalfEdge[] RetrieveRegionBoundaryHalfEdge(TriMesh mesh, bool[] faceFlags)
        {
            TriMesh.HalfEdge start = null;
            foreach (var hf in mesh.HalfEdges)
            {
                if (IsBoundary(hf, faceFlags))
                {
                    start = hf;
                    break;
                }
            }
            List <TriMesh.HalfEdge> list = new List <HalfEdgeMesh.HalfEdge>();

            TriMesh.HalfEdge cur = start;
            do
            {
                list.Add(cur);
                foreach (var hf in cur.ToVertex.HalfEdges)
                {
                    if (IsBoundary(hf, faceFlags))
                    {
                        cur = hf;
                        break;
                    }
                }
            } while (cur != start);
            return(list.ToArray());
        }
Example #20
0
        public static TriMesh.Vertex MergeEdge(TriMesh.Edge edge, Vector3D position)
        {
            TriMesh mesh = (TriMesh)edge.Mesh;

            TriMesh.Vertex   v0  = edge.Vertex0;
            TriMesh.Vertex   v1  = edge.Vertex1;
            TriMesh.HalfEdge hf0 = edge.HalfEdge0;
            TriMesh.HalfEdge hf1 = edge.HalfEdge1;

            v0.Traits.Position = position;

            foreach (var item in v1.HalfEdges)
            {
                //if (item.ToVertex != v0)
                {
                    item.Opposite.ToVertex = v0;
                }
            }

            MergeOneSide(hf0);
            MergeOneSide(hf1);

            mesh.RemoveVertex(v1);
            mesh.RemoveEdge(edge);
            v1.HalfEdge    = null;
            edge.HalfEdge0 = null;

            return(v0);
        }
Example #21
0
        public static void Split(TriMesh mesh, EdgeContext ctx)
        {
            TriMesh.Vertex left   = null;
            TriMesh.Vertex top    = null;
            TriMesh.Vertex bottom = null;

            foreach (var v in mesh.Vertices)
            {
                if (v.Index == ctx.Left)
                {
                    left = v;
                }
                else if (v.Index == ctx.Top)
                {
                    top = v;
                }
                else if (v.Index == ctx.Bottom)
                {
                    bottom = v;
                }
            }

            TriMesh.Vertex   right = TriMeshModify.VertexSplit(left, top, bottom, ctx.LeftPos, ctx.RightPos);
            TriMesh.HalfEdge hf    = left.FindHalfedgeTo(right);
            right.Index                     = ctx.Right;
            hf.Next.ToVertex.Index          = ctx.Top;
            hf.Opposite.Next.ToVertex.Index = ctx.Bottom;
        }
Example #22
0
        void ConnectHalfedge(TriMesh.HalfEdge cur, TriMesh.HalfEdge next, bool vertexIsUsed)
        {
            TriMesh mesh      = (TriMesh)cur.Mesh;
            bool    curIsNew  = cur.Next == null;
            bool    nextIsNew = next.Previous == null;

            // Outer halfedges
            if (curIsNew && nextIsNew)
            {
                this.OuterHalfedgeBothNew(cur, next, vertexIsUsed);
            }
            else if (curIsNew && !nextIsNew)  // This is new, next is old
            {
                cur.Opposite.Previous = next.Previous;
                next.Previous.Next    = cur.Opposite;
            }
            else if (!curIsNew && nextIsNew)  // This is old, next is new
            {
                cur.Next.Previous  = next.Opposite;
                next.Opposite.Next = cur.Next;
            }
            else
            {
                this.OuterHalfedgeBothOld(cur, next);
            }
            // Inner halfedges
            cur.Next      = next;
            next.Previous = cur;
        }
Example #23
0
        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);
        }
Example #24
0
        private Plane GetProjectivePlane(TriMesh.HalfEdge hf)
        {
            Vector3D p  = hf.Next.ToVertex.Traits.Position;
            Vector3D p1 = hf.FromVertex.Traits.Position;
            Vector3D p2 = hf.ToVertex.Traits.Position;

            return(new Plane(p, p2 - p1));
        }
Example #25
0
 private void Cut(TriMesh.HalfEdge above, Vector3D pos)
 {
     TriMesh.Vertex v1     = above.FromVertex;
     TriMesh.Vertex top    = above.Next.ToVertex;
     TriMesh.Vertex buttom = above.Opposite.Next.ToVertex;
     TriMesh.Vertex v2     = TriMeshModify.VertexSplit(v1,
                                                       top, buttom, v1.Traits.Position, pos);
     v2.Traits.SelectedFlag = 1;
 }
Example #26
0
        private static void MergeOneSide(TriMesh.HalfEdge hf)
        {
            TriMesh mesh = (TriMesh)hf.Mesh;

            if (hf.OnBoundary)
            {
                hf.ToVertex.HalfEdge = hf.Next;
                hf.Previous.Next     = hf.Next;
                hf.Next.Previous     = hf.Previous;
            }
            else
            {
                TriMesh.Edge     remain     = hf.Next.Edge;
                TriMesh.Edge     remove     = hf.Previous.Edge;
                TriMesh.HalfEdge outerLeft  = hf.Previous.Opposite;
                TriMesh.HalfEdge outerRight = hf.Next.Opposite;

                if (outerLeft.Next == outerRight || outerLeft.Previous == outerRight)
                {
                    outerLeft.Edge.Traits.SelectedFlag     = 1;
                    hf.FromVertex.Traits.SelectedFlag      = 1;
                    outerLeft.ToVertex.Traits.SelectedFlag = 1;
                    //throw new Exception();
                }

                remain.HalfEdge0 = outerRight;
                outerLeft.Edge   = remain;

                outerLeft.Opposite  = outerRight;
                outerRight.Opposite = outerLeft;

                hf.ToVertex.HalfEdge = outerRight.Next;
                //hf.ToVertex.HalfEdge = outerLeft;
                TriMesh.Vertex top = hf.Next.ToVertex;
                top.HalfEdge = outerRight;

                mesh.RemoveFace(hf.Face);
                mesh.RemoveHalfedge(hf.Previous);
                mesh.RemoveHalfedge(hf.Next);
                mesh.RemoveEdge(remove);

                hf.Previous.Previous = null;
                hf.Previous.Next     = null;
                hf.Previous.Opposite = null;
                hf.Next.Previous     = null;
                hf.Next.Next         = null;
                hf.Next.Opposite     = null;
                remove.HalfEdge0     = null;
            }
            mesh.RemoveHalfedge(hf);
            hf.ToVertex = null;
            hf.Next     = null;
            hf.Previous = null;
            hf.Opposite = null;
            hf.Face     = null;
        }
Example #27
0
 public static Triple <Vector3D> GetHalfEdgesVector(TriMesh.Face face)
 {
     TriMesh.HalfEdge hf = face.HalfEdge;
     return(new Triple <Vector3D>()
     {
         T0 = GetHalfEdgeVector(hf),
         T1 = GetHalfEdgeVector(hf.Next),
         T2 = GetHalfEdgeVector(hf.Previous)
     });
 }
Example #28
0
        private Plane GetBisectorPlane(TriMesh.HalfEdge hf)
        {
            Vector3D a  = hf.Next.ToVertex.Traits.Position;
            Vector3D b  = hf.FromVertex.Traits.Position;
            Vector3D c  = hf.ToVertex.Traits.Position;
            Vector3D v1 = a + (b + c - a * 2);
            Vector3D v2 = a + new Plane(a, b, c).Normal;

            return(new Plane(a, v1, v2));
        }
Example #29
0
 public static Triple <Vector3D> GetVerticesPosition(TriMesh.Face face)
 {
     TriMesh.HalfEdge hf = face.HalfEdge;
     return(new Triple <Vector3D>()
     {
         T0 = hf.ToVertex.Traits.Position,
         T1 = hf.Next.ToVertex.Traits.Position,
         T2 = hf.FromVertex.Traits.Position
     });
 }
Example #30
0
        public static double ComputeAngle(TriMesh.HalfEdge op)
        {
            double a = (op.FromVertex.Traits.Position - op.ToVertex.Traits.Position).Length();
            double b = (op.ToVertex.Traits.Position - op.Next.ToVertex.Traits.Position).Length();
            double c = (op.Next.ToVertex.Traits.Position - op.FromVertex.Traits.Position).Length();

            double angle = Math.Acos((b * b + c * c - a * a) / (2 * b * c));

            return(angle);
        }
Example #31
0
        private TriMesh.HalfEdge[] AddInnerTriangle(TriMesh mesh, TriMesh.Face face, params TriMesh.Vertex[] verteces)
        {
            mesh.Add(face);

            TriMesh.HalfEdge[] hfs = new TriMesh.HalfEdge[3];
            for (int i = 0; i < hfs.Length; i++)
            {
                hfs[i] = new TriMesh.HalfEdge();
                hfs[i].ToVertex = verteces[(i + 1) % hfs.Length];
                hfs[i].Face = face;
                mesh.AppendToHalfedgeList(hfs[i]);
            }
            face.HalfEdge = hfs[0];
            this.ConnectHalfEdge(hfs);
            return hfs;
        }
Example #32
0
        /// <summary>
        /// Adds a face to the mesh with the specified face traits.
        /// </summary>
        /// <param name="faceVertices">The vertices of the face in counterclockwise order.</param>
        /// <returns>The face created by this method.</returns>
        /// <exception cref="BadTopologyException">
        /// Thrown when fewer than three vertices are given or the vertices cannot form a valid face.
        /// </exception>
        /// <exception cref="ArgumentNullException">Thrown when a null vertex is given.</exception>
        public TriMesh.Face CreateFace(params TriMesh.Vertex[] faceVertices)
        {
            int n = faceVertices.Length;
            // Require at least 3 vertices
            if (n < 3)
            {
                throw new BadTopologyException("Cannot create a polygon with fewer than three vertices.");
            }
            TriMesh mesh = (TriMesh)faceVertices[0].Mesh;
            TriMesh.HalfEdge[] faceHalfedges = new TriMesh.HalfEdge[n];
            bool[] isUsedVertex = new bool[n]; 

            // Make sure input is (mostly) acceptable before making any changes to the mesh
            for (int i = 0; i < n; ++i)
            {
                int j = (i + 1) % n;
                faceHalfedges[i] = this.Validate(faceVertices[i], faceVertices[j]);
                isUsedVertex[i] = (faceVertices[i].HalfEdge != null); 
            }
            // Create face
            TriMesh.Face f = new TriMesh.Face(default(FaceTraits));
            mesh.AppendToFaceList(f);
            // Create new edges
            for (int i = 0; i < n; ++i)
            {
                int j = (i + 1) % n;
                if (faceHalfedges[i] == null)
                {
                    TriMesh.Edge newEdge = this.CreateNewEdge(faceVertices[i], faceVertices[j]);
                    faceHalfedges[i] = newEdge.HalfEdge0;
                }
                faceHalfedges[i].Face = f;
            }

            // Connect next/previous halfedges
            for (int i = 0; i < n; ++i)
            {
                int j = (i + 1) % n;
                this.ConnectHalfedge(faceHalfedges[i], faceHalfedges[j], isUsedVertex[j]);
            }
            // Connect face to an inner halfedge
            f.HalfEdge = faceHalfedges[0];
            return f;
        }
Example #33
0
        /// <summary>
        /// Adds a face to the mesh with the specified face traits.
        /// </summary>
        /// <param name="faceTraits">The custom traits for the face to add to the mesh.</param>
        /// <param name="faceVertices">The vertices of the face in counterclockwise order.</param>
        /// <returns>The face created by this method.</returns>
        /// <exception cref="BadTopologyException">
        /// Thrown when fewer than three vertices are given or the vertices cannot form a valid face.
        /// </exception>
        /// <exception cref="ArgumentNullException">Thrown when a null vertex is given.</exception>
        private static TriMesh.Face CreateFace(TriMesh mesh, params TriMesh.Vertex[] faceVertices)
        {
            int n = faceVertices.Length; 
            // Require at least 3 vertices
            if (n < 3)
            {
                throw new BadTopologyException("Cannot create a polygon with fewer than three vertices.");
            }  
            TriMesh.Edge e;
            TriMesh.Face f;
            TriMesh.HalfEdge[] faceHalfedges = new TriMesh.HalfEdge[n];
            bool[] isNewEdge = new bool[n], isUsedVertex = new bool[n]; 
            for (int i = 0; i < n; i++)
            {
                int j = (i + 1) % n; 
                faceHalfedges[i] = faceVertices[i].FindHalfedgeTo(faceVertices[j]);

            }

            // Make sure input is (mostly) acceptable before making any changes to the mesh
            for (int i = 0; i < n; ++i)
            {
                int j = (i + 1) % n; 
                if (faceVertices[i] == null)
                {
                    throw new ArgumentNullException("Can't add a null vertex to a face.");
                }
                if (!faceVertices[i].OnBoundary)
                { 
                    throw new BadTopologyException("Can't add an edge to a vertex on the interior of a mesh.");
                } 
                // Find existing halfedges for this face
                faceHalfedges[i] = faceVertices[i].FindHalfedgeTo(faceVertices[j]);
                isNewEdge[i] = (faceHalfedges[i] == null);
                isUsedVertex[i] = (faceVertices[i].HalfEdge != null); 
                if (!isNewEdge[i] && !faceHalfedges[i].OnBoundary)
                { 
                    throw new BadTopologyException("Can't add more than two faces to an edge.");
                }
            } 
            // Create face
            f = new TriMesh.Face(default(FaceTraits));
            mesh.AppendToFaceList(f); 
            // Create new edges
            for (int i = 0; i < n; ++i)
            {
                int j = (i + 1) % n; 
                if (isNewEdge[i])
                {
                    // Create new edge
                    e = new TriMesh.Edge();
                    mesh.AppendToEdgeList(e); 
                    // Create new halfedges
                    faceHalfedges[i] = new TriMesh.HalfEdge();
                    mesh.AppendToHalfedgeList(faceHalfedges[i]); 
                    faceHalfedges[i].Opposite = new TriMesh.HalfEdge();
                    mesh.AppendToHalfedgeList(faceHalfedges[i].Opposite); 
                    // Connect opposite halfedge to inner halfedge
                    faceHalfedges[i].Opposite.Opposite = faceHalfedges[i]; 
                    // Connect edge to halfedges
                    e.HalfEdge0 = faceHalfedges[i]; 
                    // Connect halfedges to edge
                    faceHalfedges[i].Edge = e;
                    faceHalfedges[i].Opposite.Edge = e; 
                    // Connect halfedges to vertices
                    faceHalfedges[i].ToVertex = faceVertices[j];
                    faceHalfedges[i].Opposite.ToVertex = faceVertices[i]; 
                    // Connect vertex to outgoing halfedge if it doesn't have one yet
                    if (faceVertices[i].HalfEdge == null)
                    {
                        faceVertices[i].HalfEdge = faceHalfedges[i];
                    }
                } 
                if (faceHalfedges[i].Face != null)
                {
                    throw new BadTopologyException("An inner halfedge already has a face assigned to it.");
                } 
                // Connect inner halfedge to face
                faceHalfedges[i].Face = f; 
            }

            // Connect next/previous halfedges
            for (int i = 0; i < n; ++i)
            {
                int j = (i + 1) % n;

                // Outer halfedges
                if (isNewEdge[i] && isNewEdge[j] && isUsedVertex[j])  // Both edges are new and vertex has faces connected already
                {
                    TriMesh.HalfEdge closeHalfedge = null; 
                    // Find the closing halfedge of the first available opening
                    foreach (TriMesh.HalfEdge h in faceVertices[j].HalfEdges)
                    {
                        if (h.Face == null)
                        {
                            closeHalfedge = h;
                            break;
                        }
                    } 
                    TriMesh.HalfEdge openHalfedge = closeHalfedge.Previous; 
                    // Link new outer halfedges into this opening
                    faceHalfedges[i].Opposite.Previous = openHalfedge;
                    openHalfedge.Next = faceHalfedges[i].Opposite;
                    faceHalfedges[j].Opposite.Next = closeHalfedge;
                    closeHalfedge.Previous = faceHalfedges[j].Opposite;
                }
                else if (isNewEdge[i] && isNewEdge[j])  // Both edges are new
                {
                    faceHalfedges[i].Opposite.Previous = faceHalfedges[j].Opposite;
                    faceHalfedges[j].Opposite.Next = faceHalfedges[i].Opposite;
                }
                else if (isNewEdge[i] && !isNewEdge[j])  // This is new, next is old
                {
                    faceHalfedges[i].Opposite.Previous = faceHalfedges[j].Previous;
                    faceHalfedges[j].Previous.Next = faceHalfedges[i].Opposite;
                }
                else if (!isNewEdge[i] && isNewEdge[j])  // This is old, next is new
                {
                    faceHalfedges[i].Next.Previous = faceHalfedges[j].Opposite;
                    faceHalfedges[j].Opposite.Next = faceHalfedges[i].Next;
                }
                // Relink faces before adding new edges if they are in the way of a new face
                else if (!isNewEdge[i] && !isNewEdge[j] && faceHalfedges[i].Next != faceHalfedges[j]) 
                {
                    TriMesh.HalfEdge closeHalfedge = faceHalfedges[i].Opposite; 
                    // Find the closing halfedge of the opening opposite the opening halfedge i is on
                    do
                    {
                        closeHalfedge = closeHalfedge.Previous.Opposite;
                    } while (closeHalfedge.Face != null && closeHalfedge != faceHalfedges[j] 
                             && closeHalfedge != faceHalfedges[i].Opposite); 
                    if (closeHalfedge == faceHalfedges[j] || closeHalfedge == faceHalfedges[i].Opposite)
                    {
                        throw new BadTopologyException("Unable to find an opening to relink an existing face.");
                    } 
                    TriMesh.HalfEdge openHalfedge = closeHalfedge.Previous; 
                    // Remove group of faces between two openings, close up gap to form one opening
                    openHalfedge.Next = faceHalfedges[i].Next;
                    faceHalfedges[i].Next.Previous = openHalfedge; 
                    // Insert group of faces into target opening
                    faceHalfedges[j].Previous.Next = closeHalfedge;
                    closeHalfedge.Previous = faceHalfedges[j].Previous;
                } 
                // Inner halfedges
                faceHalfedges[i].Next = faceHalfedges[j];
                faceHalfedges[j].Previous = faceHalfedges[i];
            }
            // Connect face to an inner halfedge
            f.HalfEdge = faceHalfedges[0];
            return f;
        }
Example #34
0
        public void MakeTheTopologyB(PolygonMesh dualMesh)
        {
            List<TriMesh.Vertex> boundaryVertices = new List<TriMesh.Vertex>();

            boundaryVertices = TriMeshUtil.RetrieveAllBoundaryVertex(mesh);
            foreach (TriMesh.Face face in mesh.Faces)
            {
                int index = face.Index;
                int baryVertexIndex = mesh.Edges.Count;
                int edgeVertexIndex;
                int faceIndex = index;
                TriMesh.Edge boundaryEdge = new TriMesh.Edge();
                TriMesh.HalfEdge tempHalfedge = new TriMesh.HalfEdge();
                TriMesh.Vertex vertex0 = mesh.Faces[index].GetVertex(0);
                TriMesh.Vertex vertex1 = mesh.Faces[index].GetVertex(1);
                TriMesh.Vertex vertex2 = mesh.Faces[index].GetVertex(2);
                TriMesh.HalfEdge halfedge0 = vertex0.FindHalfedgeTo(vertex1);
                TriMesh.HalfEdge halfedge1 = vertex1.FindHalfedgeTo(vertex2);
                TriMesh.HalfEdge halfedge2 = vertex2.FindHalfedgeTo(vertex0);
                TriMesh.HalfEdge boundaryHalfedge = new TriMesh.HalfEdge();
                tempHalfedge = halfedge0;
                
                edgeVertexIndex = halfedge0.Edge.Index;
                TriMesh.Vertex firstVertex = dualMesh.Vertices[baryVertexIndex + faceIndex];
                TriMesh.Vertex secondVertex = dualMesh.Vertices[edgeVertexIndex];
                if (firstVertex.FindHalfedgeTo(secondVertex) == null)
                {
                    List<TriMesh.Vertex> ringVertices = new List<TriMesh.Vertex>();
                    do
                    {
                        ringVertices.Add(dualMesh.Vertices[baryVertexIndex + faceIndex]);
                        ringVertices.Add(dualMesh.Vertices[edgeVertexIndex]);
                        if (tempHalfedge.Opposite.Next.Face != null)
                        {
                            tempHalfedge = tempHalfedge.Opposite.Next;
                            faceIndex = tempHalfedge.Face.Index;
                            edgeVertexIndex = tempHalfedge.Edge.Index;
                        }
                        else
                        {
                            tempHalfedge = tempHalfedge.Opposite.Next;
                            edgeVertexIndex = tempHalfedge.Edge.Index;
                            faceIndex = tempHalfedge.Opposite.Next.Face.Index;
                        }
                    } while (tempHalfedge != halfedge0);
                    TriMesh.Vertex[] newFaceVertices = new TriMesh.Vertex[ringVertices.Count];
                    for (int i = 0; i < ringVertices.Count; i++)
                    {
                        newFaceVertices[i] = ringVertices[i];
                    }
                    dualMesh.Faces.Add(newFaceVertices);
                }
                tempHalfedge = halfedge1;
                edgeVertexIndex = halfedge1.Edge.Index;
                firstVertex = dualMesh.Vertices[baryVertexIndex + faceIndex];
                secondVertex = dualMesh.Vertices[edgeVertexIndex];
                if (firstVertex.FindHalfedgeTo(secondVertex) == null)
                {
                    List<TriMesh.Vertex> ringVertices = new List<TriMesh.Vertex>();
                    do
                    {
                        ringVertices.Add(dualMesh.Vertices[baryVertexIndex + faceIndex]);
                        ringVertices.Add(dualMesh.Vertices[edgeVertexIndex]);
                        if (tempHalfedge.Opposite.Next != null)
                        {
                            tempHalfedge = tempHalfedge.Opposite.Next;
                            faceIndex = tempHalfedge.Face.Index;
                            edgeVertexIndex = tempHalfedge.Edge.Index;
                        }
                        else
                        {
                            continue;
                        }
                    } while (tempHalfedge != halfedge1);
                    TriMesh.Vertex[] newFaceVertices = new TriMesh.Vertex[ringVertices.Count];
                    for (int i = 0; i < ringVertices.Count; i++)
                    {
                        newFaceVertices[i] = ringVertices[i];

                    }
                    dualMesh.Faces.Add(newFaceVertices);
                }
                tempHalfedge = halfedge2;
                edgeVertexIndex = halfedge2.Edge.Index;
                firstVertex = dualMesh.Vertices[baryVertexIndex + faceIndex];
                secondVertex = dualMesh.Vertices[edgeVertexIndex];
                if (firstVertex.FindHalfedgeTo(secondVertex) == null)
                {
                    List<TriMesh.Vertex> ringVertices = new List<TriMesh.Vertex>();
                    do
                    {
                        ringVertices.Add(dualMesh.Vertices[baryVertexIndex + faceIndex]);
                        ringVertices.Add(dualMesh.Vertices[edgeVertexIndex]);
                        if (tempHalfedge.Opposite.Next != null)
                        {
                            tempHalfedge = tempHalfedge.Opposite.Next;
                            faceIndex = tempHalfedge.Face.Index;
                            edgeVertexIndex = tempHalfedge.Edge.Index;
                        }
                        else
                        {
                            continue;
                        }
                    } while (tempHalfedge != halfedge2);
                    TriMesh.Vertex[] newFaceVertices = new TriMesh.Vertex[ringVertices.Count];
                    for (int i = 0; i < ringVertices.Count; i++)
                    {
                        newFaceVertices[i] = ringVertices[i];

                    }
                    dualMesh.Faces.Add(newFaceVertices);
                }
            }
        }
Example #35
0
 TriMesh.Edge CreateNewEdge(TriMesh.Vertex from, TriMesh.Vertex to)
 {
     TriMesh mesh = (TriMesh)from.Mesh;
     // Create new edge
     TriMesh.Edge edge = new TriMesh.Edge();
     mesh.AppendToEdgeList(edge);
     // Create new halfedges
     TriMesh.HalfEdge hf0 = new TriMesh.HalfEdge();
     mesh.AppendToHalfedgeList(hf0);
     hf0.Opposite = new TriMesh.HalfEdge();
     mesh.AppendToHalfedgeList(hf0.Opposite);
     // Connect opposite halfedge to inner halfedge
     hf0.Opposite.Opposite = hf0;
     // Connect edge to halfedges
     edge.HalfEdge0 = hf0;
     // Connect halfedges to edge
     hf0.Edge = edge;
     hf0.Opposite.Edge = edge;
     // Connect halfedges to vertices
     hf0.ToVertex = to;
     hf0.Opposite.ToVertex = from;
     // Connect vertex to outgoing halfedge if it doesn't have one yet
     if (from.HalfEdge == null)
     {
         from.HalfEdge = hf0;
     }
     return edge;
 }
Example #36
0
        /// <summary>
        /// Computes principle curvatures on the vertices.
        /// </summary>
        /// <param name="cornerArea">A halfedge dynamic trait with face vertex angular areas.</param>
        /// <param name="pointArea">A vertex dynamic trait with vertex angular areas.</param>
        /// <remarks>
        /// Portions of this method are based on code from the C++ trimesh2 library
        /// (from TriMesh_curvature.cc).
        /// </remarks>
        public void ComputePrincipleCurvatures(TriMesh mesh,TriMesh.HalfedgeDynamicTrait<float> cornerArea, TriMesh.VertexDynamicTrait<float> pointArea)
        {
            // Add dynamic trait for principle curvature computation
            TriMesh.VertexDynamicTrait<float> curv = new TriMesh.VertexDynamicTrait<float>(mesh);

            // Initialize principle curvatures to zero
            foreach (TriMesh.Vertex v in mesh.Vertices)
            {
                v.Traits.MaxCurvature = 0.0f;
                v.Traits.MinCurvature = 0.0f;
            }

            // Initialize a coordinate system for each vertex
            foreach (TriMesh.Vertex v in mesh.Vertices)
            {
                if (Math.Sqrt(v.Traits.Normal.Length()) > 0.0f)    // Ignore isolated points
                {
                    // Vector that points from this vertex to an adjacent one
                    v.Traits.MaxCurvatureDirection = v.HalfEdge.ToVertex.Traits.Position - v.Traits.Position;
                    v.Traits.MaxCurvatureDirection.Normalize();

                    // Get a vector orthogonal to this vector and the vertex normal
                    v.Traits.MinCurvatureDirection = v.Traits.Normal.Cross(v.Traits.MaxCurvatureDirection);
                }
            }

            TriMesh.HalfEdge[] fh = new TriMesh.HalfEdge[3];
            TriMesh.Vertex[] fv = new TriMesh.Vertex[3];
            Vector3D[] e = new Vector3D[3];
            Vector3D t, b, dn, faceNormal;

            // Compute curvature for each face
            foreach (TriMesh.Face f in mesh.Faces)
            {
                // Get halfedges for this face
                fh[0] = f.HalfEdge;
                fh[1] = fh[0].Next;
                fh[2] = fh[1].Next;

                // Get vertices for this face
                fv[0] = fh[0].ToVertex;
                fv[1] = fh[1].ToVertex;
                fv[2] = fh[2].ToVertex;

                // Edge vectors
                e[0] = fv[2].Traits.Position - fv[1].Traits.Position;
                e[1] = fv[0].Traits.Position - fv[2].Traits.Position;
                e[2] = fv[1].Traits.Position - fv[0].Traits.Position;

                t = e[0];
                t.Normalize();

                faceNormal = e[0].Cross(e[1]);
                faceNormal.Normalize();

                b = faceNormal.Cross(t);
                b.Normalize();

                // Estimate curvature by variation of normals along edges
                float[] m = new float[3];
                float[,] w = new float[3, 3];

                for (int i = 0; i < 3; ++i)
                {
                    float u = (float)e[i].Dot(t);
                    float v = (float)e[i].Dot(b);

                    w[0, 0] += u * u;
                    w[0, 1] += u * v;
                    w[2, 2] += v * v;

                    dn = fv[(i + 2) % 3].Traits.Normal - fv[(i + 1) % 3].Traits.Normal;

                    float dnu = (float)dn.Dot(t);
                    float dnv = (float)dn.Dot(b);

                    m[0] += dnu * u;
                    m[1] += dnu * v + dnv * u;
                    m[2] += dnv * v;
                }

                w[1, 1] = w[0, 0] + w[2, 2];
                w[1, 2] = w[0, 1];

                // Least squares solution
                float[] diag = new float[3];
                if (Curvature.LdlTransposeDecomp(w, diag))
                {
                    Curvature.LdlTransposeSolveInPlace(w, diag, m);

                    // Adjust curvature for vertices of this face
                    for (int i = 0; i < 3; ++i)
                    {
                        float c1, c12, c2;
                        Curvature.ProjectCurvature(t, b, m[0], m[1], m[2], fv[i].Traits.MaxCurvatureDirection, fv[i].Traits.MinCurvatureDirection, out c1, out c12, out c2);

                        float weight = cornerArea[fh[i]] / pointArea[fv[i]];
                        fv[i].Traits.MaxCurvature += weight * c1;
                        curv[fv[i]] += weight * c12;
                        fv[i].Traits.MinCurvature += weight * c2;
                    }
                }
            }

            // Compute curvature for each vertex
            foreach (TriMesh.Vertex v in mesh.Vertices)
            {
                if (Math.Sqrt(v.Traits.Normal.Length()) > 0.0f)    // Ignore isolated points
                {
                    Curvature.DiagonalizeCurvature(v.Traits.MaxCurvatureDirection, v.Traits.MinCurvatureDirection, v.Traits.MaxCurvature, curv[v], v.Traits.MinCurvature, v.Traits.Normal,
                        out v.Traits.MaxCurvatureDirection, out v.Traits.MinCurvatureDirection, out v.Traits.MaxCurvature, out v.Traits.MinCurvature);
                }
            }
        }
Example #37
0
        public TriMesh.Vertex VertexSplit1(TriMesh.Vertex v, TriMesh.Vertex vshard1, TriMesh.Vertex vshard2, Vector3D v1Position, Vector3D v2Position, int v2FixedIndex)
        {
            //1.Get two group of verties
            TriMesh.HalfEdge[] processGroup = FindGroup(v, vshard1, vshard2);

            TriMesh mesh = (TriMesh)v.Mesh;
            TriMesh.Vertex v1 = null;
            TriMesh.Vertex v2 = null;
            TriMesh.Vertex newVertex = null;

            v1 = v;
            v.Traits.Position = v1Position;
            v2 = new TriMesh.Vertex();
            v2.Traits = new VertexTraits(Vector3D.Zero);
            newVertex = v2;
            newVertex.Traits.FixedIndex = v2FixedIndex;
            v2.Mesh = v.Mesh;
            v2.Traits.Position = v2Position;

            //2.Process the Topology
            TriMesh.HalfEdge hf1Origin = processGroup[0];
            TriMesh.HalfEdge hf2Origin = processGroup[processGroup.Length - 1];

            //Add new edge
            TriMesh.HalfEdge hf3 = new TriMesh.HalfEdge();
            TriMesh.HalfEdge hf3Oppsite = new TriMesh.HalfEdge();
            TriMesh.Edge edge = new TriMesh.Edge();

            hf3.Opposite = hf3Oppsite;
            hf3Oppsite.Opposite = hf3;

            edge.HalfEdge0 = hf3;
            edge.HalfEdge1 = hf3Oppsite;
            hf3.Edge = edge;
            hf3Oppsite.Edge = edge;

            hf3.ToVertex = v2;
            hf3Oppsite.ToVertex = v1;

            //Handle hf1Origin which is outter hafledge [INNER]
            TriMesh.HalfEdge hf1 = new TriMesh.HalfEdge();
            hf1.Opposite = hf1Origin;
            hf1.ToVertex = v1;

            TriMesh.HalfEdge hf1Other = new TriMesh.HalfEdge();
            hf1Other.Opposite = hf1Origin.Opposite;
            hf1Other.ToVertex = hf1Origin.ToVertex;

            hf1.Previous = hf1Other;
            hf1Other.Next = hf1;

            hf1.Next = hf3;
            hf3.Previous = hf1;
            hf1Other.Previous = hf3;
            hf3.Next = hf1Other;

            //Handle hf2Origin which is inner hafledge [INNER]
            TriMesh.HalfEdge hf2 = new TriMesh.HalfEdge();
            hf2.Opposite = hf2Origin;
            hf2.ToVertex = v2;

            TriMesh.HalfEdge hf2Other = new TriMesh.HalfEdge();
            hf2Other.Opposite = hf2Origin.Opposite;
            hf2Other.ToVertex = hf2Origin.ToVertex;

            hf2.Previous = hf2Other;
            hf2Other.Next = hf2;

            hf2.Next = hf3Oppsite;
            hf3Oppsite.Previous = hf2;
            hf2Other.Previous = hf3Oppsite;
            hf3Oppsite.Next = hf2Other;


            TriMesh.Face face1 = new TriMesh.Face();
            TriMesh.Face face2 = new TriMesh.Face();

            face1.HalfEdge = hf3;
            hf3.Face = face1;
            hf1.Face = face1;
            hf1Other.Face = face1;

            face2.HalfEdge = hf3Oppsite;
            hf3Oppsite.Face = face2;
            hf2.Face = face2;
            hf2Other.Face = face2;

            //Process the outside
            TriMesh.Edge edge1 = new TriMesh.Edge();
            TriMesh.HalfEdge hf1OriginOppsite = hf1Origin.Opposite;

            hf1Origin.Opposite = hf1;
            hf1.Edge = hf1Origin.Edge;

            hf1OriginOppsite.Opposite = hf1Other;
            hf1OriginOppsite.ToVertex = v2;
            hf1OriginOppsite.Edge = edge1;
            hf1Other.Edge = edge1;
            edge1.HalfEdge0 = hf1Other;
            edge1.HalfEdge1 = hf1OriginOppsite;

            TriMesh.Edge edge2 = new TriMesh.Edge();
            TriMesh.HalfEdge hf2OriginOppsite = hf2Origin.Opposite;

            hf2Origin.Opposite = hf2;
            hf2.Edge = hf2Origin.Edge;

            hf2OriginOppsite.Opposite = hf2Other;
            hf2OriginOppsite.ToVertex = v1;
            hf2OriginOppsite.Edge = edge2;
            hf2Other.Edge = edge2;
            edge2.HalfEdge0 = hf2Other;
            edge2.HalfEdge1 = hf2OriginOppsite;

            v1.HalfEdge = hf1Origin;
            v2.HalfEdge = hf2Origin;

            mesh.AppendToEdgeList(edge);
            mesh.AppendToEdgeList(edge1);
            mesh.AppendToEdgeList(edge2);
            mesh.AppendToFaceList(face1);
            mesh.AppendToFaceList(face2);
            mesh.AppendToHalfedgeList(hf1);
            mesh.AppendToHalfedgeList(hf1Other);
            mesh.AppendToHalfedgeList(hf2);
            mesh.AppendToHalfedgeList(hf2Other);
            mesh.AppendToHalfedgeList(hf3);
            mesh.AppendToHalfedgeList(hf3Oppsite);
            mesh.AppendToVertexList(newVertex);

            for (int i = 1; i < processGroup.Length - 1; i++)
            {
                processGroup[i].Opposite.ToVertex = newVertex;
            }


            //mesh.FixIndex();

            return newVertex;
        }
Example #38
0
        public static PrincipalCurvature[] ComputePrincipleCurvatures(TriMesh mesh, double[] CornerArea, double[] PointArea)
        {

            Vector3D[] vertexNormal = TriMeshUtil.ComputeNormalVertex(mesh);

            // Add dynamic trait for principle curvature computation
            double[] curv = new double[mesh.Vertices.Count];
            PrincipalCurvature[] pc = new PrincipalCurvature[mesh.Vertices.Count];

            // Initialize a coordinate system for each vertex
            foreach (TriMesh.Vertex v in mesh.Vertices)
            {
                pc[v.Index] = new PrincipalCurvature();
                // Vector that points from this vertex to an adjacent one
                pc[v.Index].maxDir = (v.HalfEdge.ToVertex.Traits.Position - v.Traits.Position).Cross(vertexNormal[v.Index]).Normalize();
                // Get a vector orthogonal to this vector and the vertex normal
                pc[v.Index].minDir = vertexNormal[v.Index].Cross(pc[v.Index].maxDir);
            }

            TriMesh.HalfEdge[] fh = new TriMesh.HalfEdge[3];
            TriMesh.Vertex[] fv = new TriMesh.Vertex[3];
            Vector3D[] e = new Vector3D[3];
            Vector3D t, b, dn, faceNormal;

            // Compute curvature for each face
            foreach (TriMesh.Face f in mesh.Faces)
            {
                // Get halfedges for this face
                fh[0] = f.HalfEdge;
                fh[1] = fh[0].Next;
                fh[2] = fh[1].Next;

                // Get vertices for this face
                fv[0] = fh[0].ToVertex;
                fv[1] = fh[1].ToVertex;
                fv[2] = fh[2].ToVertex;

                // Edge vectors
                e[0] = fv[2].Traits.Position - fv[1].Traits.Position;
                e[1] = fv[0].Traits.Position - fv[2].Traits.Position;
                e[2] = fv[1].Traits.Position - fv[0].Traits.Position;

                t = e[0];
                t.Normalize();

                faceNormal = e[0].Cross(e[1]);
                faceNormal.Normalize();

                b = faceNormal.Cross(t);
                b.Normalize();

                // Estimate curvature by variation of normals along edges
                double[] m = new double[3];
                double[,] w = new double[3, 3];

                for (int i = 0; i < 3; ++i)
                {
                    double u = e[i].Dot(t);
                    double v = e[i].Dot(b);

                    w[0, 0] += u * u;
                    w[0, 1] += u * v;
                    w[2, 2] += v * v;

                    dn = vertexNormal[fv[(i + 2) % 3].Index] - vertexNormal[fv[(i + 1) % 3].Index];

                    double dnu = dn.Dot(t);
                    double dnv = dn.Dot(b);

                    m[0] += dnu * u;
                    m[1] += dnu * v + dnv * u;
                    m[2] += dnv * v;
                }

                w[1, 1] = w[0, 0] + w[2, 2];
                w[1, 2] = w[0, 1];

                // Least squares solution
                double[] diag = new double[3];
                if (Transform.LdlTransposeDecomp(w, diag))
                {
                    Transform.LdlTransposeSolveInPlace(w, diag, m);

                    // Adjust curvature for vertices of this face
                    for (int i = 0; i < 3; ++i)
                    {
                        UV tb = new UV { U = t, V = b };
                        KUV mk = new KUV { U = m[0], UV = m[1], V = m[2] };
                        UV dst = new UV { U = pc[fv[i].Index].maxDir, V = pc[fv[i].Index].minDir };
                        KUV c = Transform.ProjectCurvature(tb, mk, dst);

                        double weight =  CornerArea[fh[i].Index] /  PointArea[fv[i].Index];
                        pc[fv[i].Index].max += weight * c.U;
                        curv[fv[i].Index] += weight * c.UV;
                        pc[fv[i].Index].min += weight * c.V;
                    }
                }
            }

            // Compute curvature for each vertex
            foreach (TriMesh.Vertex v in mesh.Vertices)
            {
                UV src = new UV { U = pc[v.Index].maxDir, V = pc[v.Index].minDir };
                KUV srcK = new KUV { U = pc[v.Index].max, UV = curv[v.Index], V = pc[v.Index].min };
                pc[v.Index] = Transform.DiagonalizeCurvature(src, srcK, vertexNormal[v.Index]);
            }

            return pc;
        }
Example #39
0
        public static Vector4D[] ComputeDCruv(TriMesh mesh, double[] CornerArea, double[] PointArea)
        {
            PrincipalCurvature[] PrincipalCurv = ComputePrincipleCurvatures(mesh, CornerArea, PointArea);

            Vector4D[] dcurv = new Vector4D[mesh.Vertices.Count];

            TriMesh.HalfEdge[] fh = new TriMesh.HalfEdge[3];
            TriMesh.Vertex[] fv = new TriMesh.Vertex[3];
            Vector3D[] e = new Vector3D[3];
            Vector3D t, b, faceNormal;

            // Compute curvature for each face
            foreach (TriMesh.Face f in mesh.Faces)
            {
                // Get halfedges for this face
                fh[0] = f.HalfEdge;
                fh[1] = fh[0].Next;
                fh[2] = fh[1].Next;

                // Get vertices for this face
                fv[0] = fh[0].ToVertex;
                fv[1] = fh[1].ToVertex;
                fv[2] = fh[2].ToVertex;

                // Edge vectors
                e[0] = fv[2].Traits.Position - fv[1].Traits.Position;
                e[1] = fv[0].Traits.Position - fv[2].Traits.Position;
                e[2] = fv[1].Traits.Position - fv[0].Traits.Position;

                t = e[0];
                t.Normalize();

                faceNormal = e[0].Cross(e[1]);

                b = faceNormal.Cross(t);
                b.Normalize();

                KUV[] fcurv = new KUV[3];
                for (int i = 0; i < 3; i++)
                {
                    PrincipalCurvature pc =  PrincipalCurv[fv[i].Index];
                    UV src = new UV { U = pc.maxDir, V = pc.minDir };
                    KUV mk = new KUV { U = pc.max, UV = 0, V = pc.min };
                    UV tb = new UV { U = t, V = b };
                    fcurv[i] = Transform.ProjectCurvature(src, mk, tb);
                }

                double[] m = new double[4];
                double[,] w = new double[4, 4];
                for (int i = 0; i < 3; i++)
                {
                    KUV prev = fcurv[(i + 2) % 3];
                    KUV next = fcurv[(i + 1) % 3];
                    KUV dfcurv = new KUV { U = prev.U - next.U, UV = prev.UV - next.UV, V = prev.V - next.V };
                    double u = e[i].Dot(t);
                    double v = e[i].Dot(b);
                    w[0, 0] += u * u;
                    w[0, 1] += u * v;
                    w[3, 3] += v * v;
                    m[0] += u * dfcurv.U;
                    m[1] += v * dfcurv.U + 2d * u * dfcurv.UV;
                    m[2] += 2d * v * dfcurv.UV + u * dfcurv.V;
                    m[3] += v * dfcurv.V;
                }
                w[1, 1] = 2d * w[0, 0] + w[3, 3];
                w[1, 2] = 2d * w[0, 1];
                w[2, 2] = w[0, 0] + 2d * w[3, 3];
                w[2, 3] = w[0, 1];

                double[] diag = new double[4];
                if (Transform.LdlTransposeDecomp(w, diag))
                {
                    Transform.LdlTransposeSolveInPlace(w, diag, m);
                    Vector4D d = new Vector4D(m);
                    // Adjust curvature for vertices of this face
                    for (int i = 0; i < 3; ++i)
                    {
                        UV tb = new UV { U = t, V = b };
                        
                        PrincipalCurvature pc =  PrincipalCurv[fv[i].Index];
                        UV dst = new UV { U = pc.maxDir, V = pc.minDir };
                        Vector4D c = Transform.ProjectDCurvature(tb, d, dst);

                        double weight =  CornerArea[fh[i].Index] / PointArea[fv[i].Index];
                        dcurv[fv[i].Index] += weight * d;
                    }
                }
            }

            return dcurv;
        }