void InitQuadrics()
        {
            Matrix <double>[] faceQuadrics = new Matrix <double> [heMesh.Faces.Length];

            // Compute quadrics for each face
            for (int i = 0; i < faceQuadrics.Length; i++)
            {
                Face f = heMesh.Faces[i];

                if (f.IsBoundary)
                {
                    continue;
                }

                Vector3 normal = f.Normal;
                Vector3 point  = f.anyHalfEdge.tailVertex.position;

                float d = -Vector3.Dot(normal, point);

                DenseVector v = DenseVector.OfArray(new double[] { normal.x, normal.y, normal.z, d });

                faceQuadrics[i] = v.OuterProduct(v);
            }

            // Compute quadrics for each vertex by adding face quadrics
            vertQuadrics = new ErrorQuadric[heMesh.Vertices.Length];

            for (int i = 0; i < vertQuadrics.Length; i++)
            {
                vertQuadrics[i] = new ErrorQuadric();
                Vertex v = heMesh.Vertices[i];

                HalfEdge he    = v.anyHalfEdge;
                HalfEdge start = he;

                do
                {
                    Face f = he.face;
                    if (!f.IsBoundary)
                    {
                        vertQuadrics[i].AddQuadric(faceQuadrics[f.Index]);
                    }
                    he = he.flip.next;
                }while (he != start);
            }

            edgeCosts = new float[heMesh.Edges.Length];
            // Compute initial error values for each edge
            for (int i = 0; i < heMesh.Edges.Length; i++)
            {
                ErrorQuadric Qsum = new ErrorQuadric();
                int          v1   = heMesh.Edges[i].anyHalfEdge.tailVertex.Index;
                int          v2   = heMesh.Edges[i].anyHalfEdge.headVertex.Index;
                Qsum.AddQuadric(vertQuadrics[v1]);
                Qsum.AddQuadric(vertQuadrics[v2]);

                Vector3 opt = Qsum.OptimalPoint(heMesh.Vertices[v1].position, heMesh.Vertices[v2].position);
                edgeCosts[i] = Qsum.ErrorAtPoint(opt);
            }
        }
        float QuadricCostOfEdge(Edge e)
        {
            int v1 = e.anyHalfEdge.tailVertex.Index;
            int v2 = e.anyHalfEdge.headVertex.Index;

            ErrorQuadric Qsum = new ErrorQuadric();

            Qsum.AddQuadric(uf.Find(v1).Quadric);
            Qsum.AddQuadric(uf.Find(v2).Quadric);

            Vector3 optPoint = Qsum.OptimalPoint(heMesh.Vertices[v1].position,
                                                 heMesh.Vertices[v2].position);

            return(Qsum.ErrorAtPoint(optPoint));
        }
Example #3
0
        public static UnionFind <VertexNode> MakeUnionFind(HalfEdgeMesh mesh)
        {
            UnionFind <VertexNode> uf = new UnionFind <VertexNode>(mesh.Vertices.Length);

            Matrix <double>[] faceQuadrics = new Matrix <double> [mesh.Faces.Length];
            for (int i = 0; i < faceQuadrics.Length; i++)
            {
                Face f = mesh.Faces[i];
                if (f.IsBoundary)
                {
                    continue;
                }
                Vector3 normal = f.Normal;
                Vector3 v1     = f.anyHalfEdge.tailVertex.position;

                float d = -Vector3.Dot(v1, normal);

                Vector <double> v = DenseVector.OfArray(new double[] { normal.x, normal.y, normal.z, d });

                faceQuadrics[i] = v.OuterProduct(v);
            }

            for (int i = 0; i < uf.NumNodes; i++)
            {
                VertexNode current = uf[i];
                current.position     = mesh.Vertices[i].position;
                current.containingUF = uf;

                ErrorQuadric vertQuadric = new ErrorQuadric();

                // Iterate over all faces surrounding this vertex and sum up the face quadrics
                HalfEdge start = mesh.Vertices[i].anyHalfEdge;
                HalfEdge he    = start;
                do
                {
                    Face f = he.face;
                    if (!f.IsBoundary)
                    {
                        Matrix <double> faceQuadric = faceQuadrics[he.face.Index];
                        vertQuadric.AddQuadric(faceQuadric);
                    }
                    he = he.flip.next;
                }while (he != start);

                current.quadric      = vertQuadric;
                current.mergedPoints = new HashSet <int>();
                current.mergedPoints.Add(i);
                current.Index = i;
            }

            return(uf);
        }
Example #4
0
        public override void Merge(UnionFindNode child)
        {
            VertexNode childNode = child as VertexNode;

            if (child.Parent != child)
            {
                throw new System.Exception("Merge wasn't given parent node");
            }

            quadric.AddQuadric(childNode.quadric);

            //position = (position + childNode.position) / 2;
            //position = quadric.OptimalPoint(position, childNode.position);

            int n1 = mergedPoints.Count;
            int n2 = childNode.mergedPoints.Count;

            position = ((n1 * position) + (n2 * childNode.position)) / (n1 + n2);

            currentCost = Cost(position);

            mergedPoints.UnionWith(childNode.mergedPoints);
        }