예제 #1
0
        //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);
        }
예제 #2
0
        public static void KMean(TriMesh mesh)
        {
            Dictionary <int, Cluster> dict  = new Dictionary <int, Cluster>();
            Queue <TriMesh.Face>      queue = new Queue <HalfEdgeMesh.Face>();

            foreach (var face in mesh.Faces)
            {
                if (face.Traits.SelectedFlag != 0)
                {
                    dict[face.Traits.SelectedFlag] = new Cluster();
                    dict[face.Traits.SelectedFlag].Add(TriMeshUtil.GetMidPoint(face));
                    queue.Enqueue(face);
                }
            }

            while (queue.Count != 0)
            {
                TriMesh.Face center = queue.Dequeue();
                foreach (var round in center.Faces)
                {
                    if (round.Traits.SelectedFlag == 0)
                    {
                        int index = GetNearest(round, dict);
                        dict[index].Add(TriMeshUtil.GetMidPoint(round));
                        round.Traits.SelectedFlag = (byte)index;
                        queue.Enqueue(round);
                    }
                }
            }
        }
예제 #3
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);
        }
예제 #4
0
        public static TriMesh Combine(List <TriMesh> meshes)
        {
            TriMesh combine = new TriMesh();

            foreach (TriMesh mesh in meshes)
            {
                if (mesh != null)
                {
                    TriMesh.Vertex[] arr = new TriMesh.Vertex[mesh.Vertices.Count];
                    foreach (TriMesh.Vertex v in mesh.Vertices)
                    {
                        arr[v.Index]        = combine.Vertices.Add(new VertexTraits(v.Traits.Position));
                        arr[v.Index].Traits = v.Traits;
                    }
                    foreach (TriMesh.Face face in mesh.Faces)
                    {
                        TriMesh.Face faceNew = combine.Faces.Add(arr[face.GetVertex(0).Index],
                                                                 arr[face.GetVertex(1).Index],
                                                                 arr[face.GetVertex(2).Index]);
                        faceNew.Traits = face.Traits;
                    }
                }
            }
            return(combine);
        }
예제 #5
0
        public TriMesh AddSelectionFace(TriMesh mesh, int index)
        {
            TriMesh result = new TriMesh();

            List <TriMesh.Vertex> arr = new List <HalfEdgeMesh.Vertex>();
            int            vIndex     = 0;
            List <TriMesh> sel        = new List <TriMesh>();

            for (int i = 0; i < mesh.Faces.Count; i++)
            {
                if (mesh.Faces[i].Traits.SelectedFlag == index)
                {
                    foreach (TriMesh.Vertex v in mesh.Faces[i].Vertices)
                    {
                        arr.Add(result.Vertices.Add(new VertexTraits(v.Traits.Position)));
                        arr[arr.Count - 1].Traits = v.Traits;
                    }

                    TriMesh.Face faceNew = result.Faces.Add(arr[vIndex * 3 + 0],
                                                            arr[vIndex * 3 + 1],
                                                            arr[vIndex * 3 + 2]);
                    faceNew.Traits = mesh.Faces[i].Traits;
                    vIndex++;
                }
            }


            result.FileName = Path.GetFileNameWithoutExtension(mesh.FileName) + "-F-" + index.ToString();

            TriMeshUtil.SetUpVertexNormal(result, EnumNormal.AreaWeight);
            return(result);
        }
예제 #6
0
        public static List <TriMesh> SeperateComponent(TriMesh mesh)
        {
            List <TriMesh> meshes = new List <TriMesh>();
            Dictionary <int, TriMesh.Vertex> map = new Dictionary <int, HalfEdgeMesh.Vertex>();

            bool[] visited             = new bool[mesh.Faces.Count];
            Queue <TriMesh.Face> queue = new Queue <HalfEdgeMesh.Face>();

            TriMesh newMesh = new TriMesh();

            queue.Enqueue(mesh.Faces[0]);
            visited[0] = true;
            while (queue.Count != 0)
            {
                TriMesh.Face face = queue.Dequeue();
                foreach (var hf in face.Halfedges)
                {
                    if (!map.ContainsKey(hf.ToVertex.Index))
                    {
                        TriMesh.Vertex v =
                            new HalfEdgeMesh.Vertex(new VertexTraits(hf.ToVertex.Traits.Position));
                        newMesh.AppendToVertexList(v);
                        map[hf.ToVertex.Index] = v;
                    }
                    if (hf.Opposite.Face != null && !visited[hf.Opposite.Face.Index])
                    {
                        queue.Enqueue(hf.Opposite.Face);
                        visited[hf.Opposite.Face.Index] = true;
                    }
                }

                newMesh.Faces.AddTriangles(
                    map[face.HalfEdge.FromVertex.Index],
                    map[face.HalfEdge.ToVertex.Index],
                    map[face.HalfEdge.Next.ToVertex.Index]);

                if (queue.Count == 0)
                {
                    meshes.Add(newMesh);

                    for (int i = 0; i < visited.Length; i++)
                    {
                        if (!visited[i])
                        {
                            newMesh = new TriMesh();
                            queue.Enqueue(mesh.Faces[i]);
                            visited[i] = true;
                            break;
                        }
                    }
                }
            }


            foreach (TriMesh child in meshes)
            {
                TriMeshUtil.SetUpNormalVertex(child);
            }
            return(meshes);
        }
예제 #7
0
        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();
                }
            }
        }
예제 #8
0
        void UpdateAreaAndNormal(TriMesh.Face face)
        {
            Vector3D cross = this.Cross(face);

            this.FaceArea[face.Index]   = cross.Length() / 2d;
            this.FaceNormal[face.Index] = cross.Normalize();
        }
예제 #9
0
        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);
                        }
                    }
                }
            }
        }
예제 #10
0
        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());
        }
예제 #11
0
 public static void ShowOneRingFaceOfFace(TriMesh.Face face)
 {
     foreach (var item in face.Vertices)
     {
         ShowOneRingFaceOfVertex(item);
     }
     face.Traits.Color = Color4.Black;
 }
예제 #12
0
 public static void ShowNeighborFaceOfFace(TriMesh.Face face)
 {
     foreach (TriMesh.Face neighbors in face.Faces)
     {
         neighbors.Traits.SelectedFlag = 9;
         neighbors.Traits.Color        = RetrieveResult.Instance.FaceResult;
     }
     face.Traits.Color = Color4.Black;
 }
예제 #13
0
        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);
        }
예제 #14
0
        public static void RemoveFace(TriMesh.Face face)
        {
            TriMesh mesh = (TriMesh)face.Mesh;

            foreach (TriMesh.HalfEdge halfedge in face.Halfedges)
            {
                halfedge.Face = null;
            }
            mesh.RemoveFace(face);
        }
예제 #15
0
        Vector3D GetNormal(TriMesh.Face face)
        {
            List <Vector3D> list = new List <Vector3D>();

            foreach (var item in face.Vertices)
            {
                list.Add(item.Traits.Position);
            }
            return((list[2] - list[1]).Cross(list[2] - list[0]).Normalize());
        }
예제 #16
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)
     });
 }
예제 #17
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
     });
 }
예제 #18
0
        public static Vector3D GetMidPoint(TriMesh.Face face)
        {
            Vector3D sum = new Vector3D();

            foreach (var v in face.Vertices)
            {
                sum += v.Traits.Position;
            }
            return(sum / 3);
        }
예제 #19
0
        public static Vector3D ComputeFaceCenter(TriMesh.Face face)
        {
            Vector3D center = Vector3D.Zero;

            foreach (TriMesh.Vertex v in face.Vertices)
            {
                center += v.Traits.Position;
            }
            center = center / 3d;
            return(center);
        }
예제 #20
0
        public static T[]  GetFromVertices <T>(TriMesh.Face face, Func <T> func)
        {
            T[] arr = new T[3];
            int i   = 0;

            foreach (var hf in face.Halfedges)
            {
                arr[i++] = func(hf.FromVertex);
            }
            return(arr);
        }
예제 #21
0
        public static List <double> ComputeAngleDegree(TriMesh.Face face)
        {
            List <double> angles = ComputeAngle(face);

            for (int i = 0; i < angles.Count; i++)
            {
                angles[i] = angles[i] * 180 / 3.14;
            }

            return(angles);
        }
예제 #22
0
        public double ComputeFaceAngle(TriMesh.Face face1, TriMesh.Face face2)//计算两个面的cos角度值
        {
            double angel = 0;
            double a = 0, b = 0, c = 0;

            c     = face1.Traits.Normal.x * face2.Traits.Normal.x + face1.Traits.Normal.y * face2.Traits.Normal.y + face1.Traits.Normal.z * face2.Traits.Normal.z;
            a     = Math.Pow(Math.Pow(face1.Traits.Normal.x, 2) + Math.Pow(face1.Traits.Normal.y, 2) + Math.Pow(face1.Traits.Normal.z, 2), 0.5);
            b     = Math.Pow(Math.Pow(face2.Traits.Normal.x, 2) + Math.Pow(face2.Traits.Normal.y, 2) + Math.Pow(face2.Traits.Normal.z, 2), 0.5);
            angel = c / (a + b);
            //angel = Math.Acos(angel);
            return(angel);
        }
예제 #23
0
        Vector3D Cross(TriMesh.Face face)
        {
            Vector3D[] arr = new Vector3D[3];
            int        i   = 0;

            foreach (var v in face.Vertices)
            {
                arr[i++] = v.Traits.Position;
            }

            return((arr[1] - arr[0]).Cross(arr[2] - arr[0]));
        }
예제 #24
0
        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)));
        }
예제 #25
0
 public void RemoveFaces(TriMesh.Face Face)
 {
     for (int j = 0; j < BoundaryFaces.Count; j++)
     {
         if (BoundaryFaces[j].Equals(Face))
         {
             // Console.WriteLine("BF:" + BoundaryFaces.Count);
             Faces.Add(BoundaryFaces[j]);
             BoundaryFaces.Remove(Face);
             //Console.WriteLine("BA:" + BoundaryFaces.Count);
         }
     }
 }
예제 #26
0
        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);
        }
예제 #27
0
 public static bool IsBoundary(TriMesh.HalfEdge hf, bool[] faceFlags)
 {
     TriMesh.Face left  = hf.Face;
     TriMesh.Face right = hf.Opposite.Face;
     if (left == null)
     {
         return(false);
     }
     if (right == null)
     {
         return(faceFlags[left.Index]);
     }
     return(faceFlags[left.Index] && !faceFlags[right.Index]);
 }
예제 #28
0
 public static TriMesh.Vertex MergeTriangle(TriMesh.Face face, Vector3D pos)
 {
     TriMesh.Edge   edge1 = face.HalfEdge.Edge;
     TriMesh.Edge   edge2 = face.HalfEdge.Next.Edge;
     TriMesh.Vertex v     = MergeEdge(edge1, pos);
     if (IsMergeable(edge2))
     {
         v = MergeEdge(edge2, pos);
     }
     else
     {
         edge2.Traits.SelectedFlag = 1;
     }
     return(v);
 }
예제 #29
0
 public static bool IsMergeable(TriMesh.Face face)
 {
     if (face.OnBoundary)
     {
         //return false;
     }
     foreach (var hf in face.Halfedges)
     {
         if (!TriMeshModify.IsMergeable(hf.Edge))
         {
             return(false);
         }
     }
     return(true);
 }
예제 #30
0
        TriMesh.Vertex GetMinCvtVertex(TriMesh.Face face)
        {
            double minCvt = double.MaxValue;

            TriMesh.Vertex min = null;
            foreach (var v in face.Vertices)
            {
                double cvt = Math.Abs(this.traits.VertexDiscreteCurvature[v.Index]);
                if (cvt < minCvt)
                {
                    minCvt = cvt;
                    min    = v;
                }
            }
            return(min);
        }
예제 #31
0
        private static TriMesh.HalfEdge[] AddInnerTriangle(TriMesh mesh, params TriMesh.Vertex[] verteces)
        {
            TriMesh.Face face = new TriMesh.Face();
            mesh.AppendToFaceList(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];
            ConnectHalfEdge(hfs);
            return hfs;
        }
예제 #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;
        }
예제 #33
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;
        }
예제 #34
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;
        }
예제 #35
0
파일: Region.cs 프로젝트: meshdgp/MeshDGP
 public void SetSeedFaces(int n)
 {
     Seedface = this.mesh.Faces[n];
 }