예제 #1
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();
                }
            }
        }
예제 #2
0
        private TriMesh ChangeTopologyLoop(TriMesh sourceMesh)
        {
            TriMesh newMesh = new TriMesh();

            newMesh.Clear();
            vMap = new HalfEdgeMesh.Vertex[sourceMesh.Vertices.Count];
            eMap = new HalfEdgeMesh.Vertex[sourceMesh.Edges.Count];

            foreach (var v in sourceMesh.Vertices)
            {
                vMap[v.Index] = newMesh.Vertices.Add(new VertexTraits(v.Traits.Position));
            }

            foreach (var edge in sourceMesh.Edges)
            {
                eMap[edge.Index] = newMesh.Vertices.Add(
                    new VertexTraits(TriMeshUtil.GetMidPoint(edge)));
            }

            foreach (TriMesh.Face face in sourceMesh.Faces)
            {
                foreach (var hf in face.Halfedges)
                {
                    newMesh.Faces.AddTriangles(eMap[hf.Edge.Index],
                                               vMap[hf.ToVertex.Index], eMap[hf.Next.Edge.Index]);
                }
                newMesh.Faces.AddTriangles(
                    eMap[face.HalfEdge.Previous.Edge.Index],
                    eMap[face.HalfEdge.Edge.Index],
                    eMap[face.HalfEdge.Next.Edge.Index]);
            }
            return(newMesh);
        }
예제 #3
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);
                    }
                }
            }
        }
예제 #4
0
        private TriMesh ChangeTopologyInit(TriMesh sourceMesh)
        {
            TriMesh mesh = new TriMesh();

            vMap    = new HalfEdgeMesh.Vertex[sourceMesh.Vertices.Count];
            faceMap = new HalfEdgeMesh.Vertex[sourceMesh.Faces.Count];
            foreach (var face in sourceMesh.Faces)
            {
                faceMap[face.Index] = mesh.Vertices.Add(
                    new VertexTraits(TriMeshUtil.GetMidPoint(face)));
            }

            foreach (var v in sourceMesh.Vertices)
            {
                vMap[v.Index] = mesh.Vertices.Add(new VertexTraits(v.Traits.Position));
                foreach (var hf in v.HalfEdges)
                {
                    if (hf.Face != null && hf.Opposite.Face != null)
                    {
                        mesh.Faces.AddTriangles(faceMap[hf.Face.Index],
                                                vMap[v.Index], faceMap[hf.Opposite.Face.Index]);
                    }
                }
            }

            foreach (var hf in sourceMesh.HalfEdges)
            {
                if (hf.Face == null)
                {
                    mesh.Faces.AddTriangles(vMap[hf.ToVertex.Index],
                                            vMap[hf.FromVertex.Index], faceMap[hf.Opposite.Face.Index]);
                }
            }
            return(mesh);
        }
예제 #5
0
        public static PolygonMesh BuildDual(TriMesh mesh, EnumDual type)
        {
            TriMeshModify.RepaireAllHole(mesh);

            PolygonMesh.Vertex[] faceMap = new HalfEdgeMesh.Vertex[mesh.Faces.Count];
            PolygonMesh.Vertex[] edgeMap = new HalfEdgeMesh.Vertex[mesh.Edges.Count];
            PolygonMesh          pm      = new PolygonMesh();

            foreach (var face in mesh.Faces)
            {
                Vector3D center = Vector3D.Zero;
                switch (type)
                {
                case EnumDual.DualA:
                    center = TriMeshUtil.GetMidPoint(face);
                    break;

                case EnumDual.DualB:
                    TriMesh.Vertex vertex0  = face.GetVertex(0);
                    TriMesh.Vertex vertex1  = face.GetVertex(1);
                    TriMesh.Vertex vertex2  = face.GetVertex(2);
                    Triangle       triangle = new Triangle(vertex0.Traits.Position,
                                                           vertex1.Traits.Position,
                                                           vertex2.Traits.Position);
                    center = triangle.ComputeCircumCenter();
                    break;

                default:
                    break;
                }
                PolygonMesh.Vertex v = new HalfEdgeMesh.Vertex(new VertexTraits(center));
                faceMap[face.Index] = v;
                pm.AppendToVertexList(v);
            }

            foreach (var edge in mesh.Edges)
            {
                VertexTraits       trait = new VertexTraits(TriMeshUtil.GetMidPoint(edge));
                PolygonMesh.Vertex v     = new HalfEdgeMesh.Vertex(trait);
                edgeMap[edge.Index] = v;
                pm.AppendToVertexList(v);
            }

            foreach (var v in mesh.Vertices)
            {
                List <PolygonMesh.Vertex> list = new List <HalfEdgeMesh.Vertex>();
                foreach (var hf in v.HalfEdges)
                {
                    list.Add(faceMap[hf.Face.Index]);
                    list.Add(edgeMap[hf.Edge.Index]);
                }
                list.Reverse();
                pm.Faces.Add(list.ToArray());
            }
            return(pm);
        }
예제 #6
0
        public void Subdivision()
        {
            /*        /\                  /\
             *       /  \                /__\
             *      /    \              /\  /\
             *     /      \            /__\/__\
             *    /        \          /\  /\  /\
             *   /__________\        /__\/__\/__\
             *
             *   为了让每个顶点周围都有它专属的一圈价为6的点,把每个三角形拆成9个
             */
            TriMesh copy = TriMeshIO.Clone(this.mesh);

            this.mesh.Clear();

            TriMesh.Vertex[] faceMap = new HalfEdgeMesh.Vertex[copy.Faces.Count];
            TriMesh.Vertex[] hfMap   = new HalfEdgeMesh.Vertex[copy.HalfEdges.Count];

            foreach (var v in copy.Vertices)
            {
                this.mesh.Vertices.Add(new VertexTraits(v.Traits.Position));
            }

            foreach (var face in copy.Faces)
            {
                faceMap[face.Index] = this.mesh.Vertices.Add(new VertexTraits(TriMeshUtil.GetMidPoint(face)));
            }

            foreach (var hf in copy.HalfEdges)
            {
                Vector3D pos = hf.FromVertex.Traits.Position * 2 / 3 + hf.ToVertex.Traits.Position * 1 / 3;
                hfMap[hf.Index] = this.mesh.Vertices.Add(new VertexTraits(pos));
            }

            foreach (var face in copy.Faces)
            {
                foreach (var hf in face.Halfedges)
                {
                    this.mesh.Faces.AddTriangles(faceMap[face.Index], hfMap[hf.Index], hfMap[hf.Opposite.Index]);
                    this.mesh.Faces.AddTriangles(faceMap[face.Index], hfMap[hf.Opposite.Index], hfMap[hf.Next.Index]);
                }
            }

            foreach (var v in copy.Vertices)
            {
                foreach (var hf in v.HalfEdges)
                {
                    if (hf.Face != null)
                    {
                        this.mesh.Faces.AddTriangles(this.mesh.Vertices[v.Index], hfMap[hf.Index], hfMap[hf.Previous.Opposite.Index]);
                    }
                }
            }
        }
예제 #7
0
        static int GetNearest(TriMesh.Face face, Dictionary <int, Cluster> dict)
        {
            Vector3D center       = TriMeshUtil.GetMidPoint(face);
            int      nearestIndex = -1;
            double   nearest      = double.MaxValue;

            foreach (var item in dict)
            {
                double dist = Vector3D.Distance(center, item.Value.Center);
                if (dist < nearest)
                {
                    nearestIndex = item.Key;
                    nearest      = dist;
                }
            }
            return(nearestIndex);
        }
예제 #8
0
        public List <TriMesh.Edge> BuildCoTree(DynamicTree <TriMesh.Face> cotree)
        {
            if (cotree == null)
            {
                return(null);
            }

            List <TriMesh.Edge> cotreeMarks = new List <HalfEdgeMesh.Edge>();



            Vector3D[] bycenters = new Vector3D[mesh.Faces.Count];
            cotreeMarks = new List <HalfEdgeMesh.Edge>();
            TreeNode <TriMesh.Face>          currentCoNode = cotree.Root;
            Queue <TreeNode <TriMesh.Face> > coQueue       = new Queue <TreeNode <TriMesh.Face> >();

            coQueue.Enqueue(currentCoNode);
            do
            {
                currentCoNode = coQueue.Dequeue();
                bycenters[currentCoNode.Attribute.Index] = TriMeshUtil.GetMidPoint(currentCoNode.Attribute);

                TreeNode <TriMesh.Face> currentChild = currentCoNode.LeftMostChild;
                while (currentChild != null)
                {
                    //Mark edge
                    TriMesh.Face f1 = currentCoNode.Attribute;
                    TriMesh.Face f2 = currentChild.Attribute;

                    foreach (TriMesh.HalfEdge hf in f1.Halfedges)
                    {
                        if (hf.Opposite.Face == f2)
                        {
                            cotreeMarks.Add(hf.Edge);
                            break;
                        }
                    }

                    coQueue.Enqueue(currentChild);
                    currentChild = currentChild.RightSibling;
                }
            } while (coQueue.Count > 0);

            return(cotreeMarks);
        }
예제 #9
0
        protected Vector3D GetPos1(TriMesh.HalfEdge hf)
        {
            Vector3D from = hf.FromVertex.Traits.Position;
            Vector3D to   = hf.ToVertex.Traits.Position;
            Vector3D l    = to - from;

            Vector3D[] vi = this.GetV(hf);
            Vector3D[] vj = this.GetV(hf.Opposite);
            Vector3D   c1 = Vector3D.Zero;
            Vector3D   c2 = Vector3D.Zero;

            for (int i = 0; i < vi.Length - 1; i++)
            {
                c1 += (vi[i] - from).Cross(vi[i + 1] - from);
            }
            for (int i = 0; i < vj.Length - 1; i++)
            {
                c2 += (vj[i + 1] - to).Cross(vj[i] - to);
            }
            Matrix4D m = Matrix4D.ZeroMatrix;

            m.Row1 = new Vector4D(c1 - c2, to.Dot(c2) - from.Dot(c1));
            m.Row2 = new Vector4D(l.y, -l.x, 0d, to.y * l.x - to.x * l.y);
            m.Row3 = new Vector4D(l.z, 0d, -l.x, to.z * l.x - to.x * l.z);
            m.Row4 = new Vector4D(0d, 0d, 0d, 1d);

            Vector3D pos = Vector3D.Zero;
            double   det = Util.Solve(ref m, ref pos);

            if (det == 0)
            {
                pos = TriMeshUtil.GetMidPoint(hf.Edge);
            }
            else
            {
                double vo1 = c1.Dot(pos - from);
                double vo2 = c2.Dot(pos - to);
            }
            return(pos);
        }
예제 #10
0
        public void DrawTreeCotree(List <TriMesh.Edge> treeMarks, List <TriMesh.Edge> cotreeMarks)
        {
            OpenGLManager.Instance.SetColor(System.Drawing.Color.Green);
            //Draw Tree
            foreach (TriMesh.Edge item in treeMarks)
            {
                GL.Begin(BeginMode.Lines);
                Vector3D a = item.Vertex0.Traits.Position;
                Vector3D b = item.Vertex1.Traits.Position;


                GL.Vertex3(a.x, a.y, a.z);
                GL.Vertex3(b.x, b.y, b.z);
                GL.End();
            }

            OpenGLManager.Instance.SetColor(System.Drawing.Color.Red);
            //Draw CoTree
            foreach (TriMesh.Edge item in cotreeMarks)
            {
                Vector3D a            = TriMeshUtil.GetMidPoint(item.Face0);
                Vector3D b            = TriMeshUtil.GetMidPoint(item.Face1);
                Vector3D centerOfEdge = (item.Vertex0.Traits.Position + item.Vertex1.Traits.Position) / 2;


                GL.Begin(BeginMode.Lines);
                GL.Vertex3(a.x, a.y, a.z);
                GL.Vertex3(centerOfEdge.x, centerOfEdge.y, centerOfEdge.z);
                GL.End();

                GL.Begin(BeginMode.Lines);
                GL.Vertex3(centerOfEdge.x, centerOfEdge.y, centerOfEdge.z);
                GL.Vertex3(b.x, b.y, b.z);
                GL.End();
            }
        }
예제 #11
0
        private ErrorPair GetErrorPair(TriMesh.Face face)
        {
            Matrix4D m1 = this.GetVolumeMatrix(face);

            if (m1[1] != m1[4] || m1[2] != m1[8] || m1[6] != m1[9] ||
                m1[3] != m1[12] || m1[7] != m1[13] || m1[11] != m1[14]
                )
            {
                throw new Exception("Matrix m1 is not symmetric");
            }
            Matrix4D m2 = Matrix4D.ZeroMatrix;

            for (int i = 0; i <= 11; i++)
            {
                m2[i] = m1[i];
            }
            m2[12] = 0;
            m2[13] = 0;
            m2[14] = 0;
            m2[15] = 1;

            Vector3D newPos = Vector3D.Zero;

            double det = Util.Solve(ref m2, ref newPos);

            if (det == 0)
            {
                newPos = TriMeshUtil.GetMidPoint(face);
            }
            double error = this.GetError(m1, newPos);

            return(new ErrorPair()
            {
                Pos = newPos, Error = error
            });
        }
예제 #12
0
        public static EdgeContext Merge(TriMesh.Edge edge)
        {
            Vector3D position = TriMeshUtil.GetMidPoint(edge);

            return(Merge(edge, position));
        }
예제 #13
0
 protected virtual Vector3D GetPos(TriMesh.Face target)
 {
     return(TriMeshUtil.GetMidPoint(target));
 }
예제 #14
0
 protected override Vector3D GetPos(TriMesh.Face target)
 {
     return(TriMeshUtil.GetMidPoint(target));
     //return this.faceError[target.Index].Pos;
 }
예제 #15
0
 protected Vector3D GetPos(TriMesh.HalfEdge hf)
 {
     return(TriMeshUtil.GetMidPoint(hf.Edge));
 }
예제 #16
0
        public void DrawGenerators(TriMesh mesh, List <List <TriMesh.HalfEdge> > Generators)
        {
            if (Generators == null)
            {
                return;
            }


            Vector3D[] bycenters = new Vector3D[mesh.Faces.Count];
            foreach (TriMesh.Face face in mesh.Faces)
            {
                bycenters[face.Index] = TriMeshUtil.GetMidPoint(face);
            }


            bool[] edgeFlags = new bool[mesh.Edges.Count];

            int i = 0;

            System.Drawing.Color color = System.Drawing.Color.Orange;

            foreach (List <TriMesh.HalfEdge> loop in Generators)
            {
                switch (i)
                {
                case 1:
                    color = System.Drawing.Color.Green;
                    break;

                case 2:
                    color = System.Drawing.Color.Red;
                    break;

                case 3:
                    color = System.Drawing.Color.Purple;
                    break;

                default:
                    color = System.Drawing.Color.Orange;
                    break;
                }


                OpenGLManager.Instance.SetColor(color);
                foreach (TriMesh.HalfEdge loopItem in loop)
                {
                    TriMesh.Edge edge = loopItem.Edge;

                    if (edgeFlags[edge.Index] == false)
                    {
                        Vector3D a            = bycenters[edge.Face0.Index];
                        Vector3D b            = bycenters[edge.Face1.Index];
                        Vector3D centerOfEdge = (edge.Vertex0.Traits.Position + edge.Vertex1.Traits.Position) / 2;

                        GL.Begin(BeginMode.Lines);
                        GL.Vertex3(a.x, a.y, a.z);
                        GL.Vertex3(centerOfEdge.x, centerOfEdge.y, centerOfEdge.z);
                        GL.End();

                        GL.Begin(BeginMode.Lines);
                        GL.Vertex3(centerOfEdge.x, centerOfEdge.y, centerOfEdge.z);
                        GL.Vertex3(b.x, b.y, b.z);
                        GL.End();
                    }

                    edgeFlags[edge.Index] = true;
                }
                i++;
            }
        }
예제 #17
0
        private TriMesh ChangeTopologyLoopSelected(TriMesh sourceMesh)
        {
            TriMesh newMesh = new TriMesh();

            newMesh.Clear();

            vMap = new HalfEdgeMesh.Vertex[sourceMesh.Vertices.Count];
            eMap = new HalfEdgeMesh.Vertex[Mesh.Edges.Count];

            foreach (var v in sourceMesh.Vertices)
            {
                vMap[v.Index] = newMesh.Vertices.Add(new VertexTraits(v.Traits.Position));
            }

            foreach (var edge in sourceMesh.Edges)
            {
                if (edge.Vertex0.Traits.SelectedFlag != 0 && edge.Vertex1.Traits.SelectedFlag != 0)
                {
                    eMap[edge.Index] = newMesh.Vertices.Add(new VertexTraits(TriMeshUtil.GetMidPoint(edge)));
                }
            }

            foreach (TriMesh.Face face in sourceMesh.Faces)
            {
                List <TriMesh.HalfEdge> list = new List <HalfEdgeMesh.HalfEdge>();
                foreach (var hf in face.Halfedges)
                {
                    if (hf.ToVertex.Traits.SelectedFlag != 0 && hf.FromVertex.Traits.SelectedFlag != 0)
                    {
                        list.Add(hf);
                    }
                }

                switch (list.Count)
                {
                case 0:
                    newMesh.Faces.AddTriangles(
                        vMap[face.GetVertex(0).Index],
                        vMap[face.GetVertex(1).Index],
                        vMap[face.GetVertex(2).Index]);
                    break;

                case 1:
                    TriMesh.HalfEdge h = list[0];
                    newMesh.Faces.AddTriangles(
                        eMap[h.Edge.Index],
                        vMap[h.ToVertex.Index],
                        vMap[h.Next.ToVertex.Index]);
                    newMesh.Faces.AddTriangles(
                        eMap[h.Edge.Index],
                        vMap[h.Next.ToVertex.Index],
                        vMap[h.FromVertex.Index]);
                    break;

                case 3:
                    foreach (var hf in face.Halfedges)
                    {
                        newMesh.Faces.AddTriangles(eMap[hf.Edge.Index], vMap[hf.ToVertex.Index], eMap[hf.Next.Edge.Index]);
                    }
                    newMesh.Faces.AddTriangles(
                        eMap[face.HalfEdge.Previous.Edge.Index],
                        eMap[face.HalfEdge.Edge.Index],
                        eMap[face.HalfEdge.Next.Edge.Index]);
                    break;

                default:
                    break;
                }
            }
            return(newMesh);
        }
예제 #18
0
        public static TriMesh.Vertex MergeTriangle(TriMesh.Face face)
        {
            Vector3D pos = TriMeshUtil.GetMidPoint(face);

            return(MergeTriangle(face, pos));
        }