Beispiel #1
0
        /// <summary>
        /// Apply LaplacianMeshSmoother to subset of mesh triangles.
        /// border of subset always has soft constraint with borderWeight,
        /// but is then snapped back to original vtx pos after solve.
        /// nConstrainLoops inner loops are also soft-constrained, with weight falloff via square roots.
        /// interiorWeight is soft constraint added to all vertices
        /// </summary>
        public static void RegionSmooth(DMesh3 mesh, IEnumerable <int> triangles, int nConstrainLoops,
                                        double borderWeight = 10.0, double interiorWeight = 0.0)
        {
            RegionOperator        region     = new RegionOperator(mesh, triangles);
            DSubmesh3             submesh    = region.Region;
            DMesh3                smoothMesh = submesh.SubMesh;
            LaplacianMeshSmoother smoother   = new LaplacianMeshSmoother(smoothMesh);

            // soft constraint on all interior vertices, if requested
            if (interiorWeight > 0)
            {
                foreach (int vid in smoothMesh.VertexIndices())
                {
                    smoother.SetConstraint(vid, smoothMesh.GetVertex(vid), interiorWeight, false);
                }
            }

            // now constrain borders
            double w = borderWeight;

            HashSet <int> constrained = (region.Region.BaseBorderV.Count > 0) ? new HashSet <int>() : null;

            foreach (int base_vid in region.Region.BaseBorderV)
            {
                int sub_vid = submesh.BaseToSubV[base_vid];
                smoother.SetConstraint(sub_vid, smoothMesh.GetVertex(sub_vid), w, true);
                if (constrained != null)
                {
                    constrained.Add(sub_vid);
                }
            }

            if (constrained.Count > 0)
            {
                w = Math.Sqrt(w);
                for (int k = 0; k < nConstrainLoops; ++k)
                {
                    HashSet <int> next_layer = new HashSet <int>();

                    foreach (int sub_vid in constrained)
                    {
                        foreach (int nbr_vid in smoothMesh.VtxVerticesItr(sub_vid))
                        {
                            if (constrained.Contains(nbr_vid) == false)
                            {
                                smoother.SetConstraint(nbr_vid, smoothMesh.GetVertex(nbr_vid), w, false);
                                next_layer.Add(nbr_vid);
                            }
                        }
                    }

                    constrained.UnionWith(next_layer);
                    w = Math.Sqrt(w);
                }
            }


            smoother.SolveAndUpdateMesh();
            region.BackPropropagateVertices(true);
        }
Beispiel #2
0
        void add_regionop_subfaces(int parent, RegionOperator op)
        {
            HashSet <int> subfaces = get_subfaces(parent);

            foreach (int tid in op.CurrentBaseTriangles)
            {
                if (tid != parent)
                {
                    add_subface(subfaces, parent, tid);
                }
            }
        }
Beispiel #3
0
        void insert_segment(IntersectSegment seg)
        {
            List <int> subfaces = get_all_baseface_tris(seg.base_tid);

            var op = new RegionOperator(Target, subfaces);

            Vector3d n = BaseFaceNormals[seg.base_tid];
            Vector3d c = BaseFaceCentroids[seg.base_tid];
            Vector3d e0, e1;

            Vector3d.MakePerpVectors(ref n, out e0, out e1);

            DMesh3 mesh = op.Region.SubMesh;

            MeshTransforms.PerVertexTransform(mesh, (v) =>
            {
                v -= c;
                return(new Vector3d(v.Dot(e0), v.Dot(e1), 0));
            });

            Vector3d end0 = seg.v0.v, end1 = seg.v1.v;

            end0 -= c; end1 -= c;
            var p0   = new Vector2d(end0.Dot(e0), end0.Dot(e1));
            var p1   = new Vector2d(end1.Dot(e0), end1.Dot(e1));
            var path = new PolyLine2d();

            path.AppendVertex(p0); path.AppendVertex(p1);

            var insert = new MeshInsertUVPolyCurve(mesh, path);

            insert.Apply();

            var cutVerts = new MeshVertexSelection(mesh);

            cutVerts.SelectEdgeVertices(insert.OnCutEdges);

            MeshTransforms.PerVertexTransform(mesh, (v) =>
            {
                return(c + v.x * e0 + v.y * e1);
            });

            op.BackPropropagate();

            // add new cut vertices to cut list
            foreach (int vid in cutVerts)
            {
                SegmentInsertVertices.Add(op.ReinsertSubToBaseMapV[vid]);
            }

            add_regionop_subfaces(seg.base_tid, op);
        }
        /// <summary>
        /// Apply LaplacianMeshSmoother to subset of mesh triangles.
        /// border of subset always has soft constraint with borderWeight,
        /// but is then snapped back to original vtx pos after solve.
        /// nConstrainLoops inner loops are also soft-constrained, with weight falloff via square roots (defines continuity)
        /// interiorWeight is soft constraint added to all vertices
        /// </summary>
        public static void RegionSmooth(DMesh3 mesh, IEnumerable <int> triangles,
                                        int nConstrainLoops,
                                        int nIncludeExteriorRings,
                                        bool bPreserveExteriorRings,
                                        double borderWeight = 10.0, double interiorWeight = 0.0)
        {
            HashSet <int> fixedVerts = new HashSet <int>();

            if (nIncludeExteriorRings > 0)
            {
                MeshFaceSelection expandTris = new MeshFaceSelection(mesh);
                expandTris.Select(triangles);
                if (bPreserveExteriorRings)
                {
                    MeshEdgeSelection bdryEdges = new MeshEdgeSelection(mesh);
                    bdryEdges.SelectBoundaryTriEdges(expandTris);
                    expandTris.ExpandToOneRingNeighbours(nIncludeExteriorRings);
                    MeshVertexSelection startVerts = new MeshVertexSelection(mesh);
                    startVerts.SelectTriangleVertices(triangles);
                    startVerts.DeselectEdges(bdryEdges);
                    MeshVertexSelection expandVerts = new MeshVertexSelection(mesh, expandTris);
                    foreach (int vid in expandVerts)
                    {
                        if (startVerts.IsSelected(vid) == false)
                        {
                            fixedVerts.Add(vid);
                        }
                    }
                }
                else
                {
                    expandTris.ExpandToOneRingNeighbours(nIncludeExteriorRings);
                }
                triangles = expandTris;
            }

            RegionOperator        region     = new RegionOperator(mesh, triangles);
            DSubmesh3             submesh    = region.Region;
            DMesh3                smoothMesh = submesh.SubMesh;
            LaplacianMeshSmoother smoother   = new LaplacianMeshSmoother(smoothMesh);

            // map fixed verts to submesh
            HashSet <int> subFixedVerts = new HashSet <int>();

            foreach (int base_vid in fixedVerts)
            {
                subFixedVerts.Add(submesh.MapVertexToSubmesh(base_vid));
            }

            // constrain borders
            double w = borderWeight;

            HashSet <int> constrained = (submesh.BaseBorderV.Count > 0) ? new HashSet <int>() : null;

            foreach (int base_vid in submesh.BaseBorderV)
            {
                int sub_vid = submesh.BaseToSubV[base_vid];
                smoother.SetConstraint(sub_vid, smoothMesh.GetVertex(sub_vid), w, true);
                if (constrained != null)
                {
                    constrained.Add(sub_vid);
                }
            }

            if (constrained.Count > 0)
            {
                w = Math.Sqrt(w);
                for (int k = 0; k < nConstrainLoops; ++k)
                {
                    HashSet <int> next_layer = new HashSet <int>();

                    foreach (int sub_vid in constrained)
                    {
                        foreach (int nbr_vid in smoothMesh.VtxVerticesItr(sub_vid))
                        {
                            if (constrained.Contains(nbr_vid) == false)
                            {
                                if (smoother.IsConstrained(nbr_vid) == false)
                                {
                                    smoother.SetConstraint(nbr_vid, smoothMesh.GetVertex(nbr_vid), w, subFixedVerts.Contains(nbr_vid));
                                }
                                next_layer.Add(nbr_vid);
                            }
                        }
                    }

                    constrained.UnionWith(next_layer);
                    w = Math.Sqrt(w);
                }
            }

            // soft constraint on all interior vertices, if requested
            if (interiorWeight > 0)
            {
                foreach (int vid in smoothMesh.VertexIndices())
                {
                    if (smoother.IsConstrained(vid) == false)
                    {
                        smoother.SetConstraint(vid, smoothMesh.GetVertex(vid), interiorWeight, subFixedVerts.Contains(vid));
                    }
                }
            }
            else if (subFixedVerts.Count > 0)
            {
                foreach (int vid in subFixedVerts)
                {
                    if (smoother.IsConstrained(vid) == false)
                    {
                        smoother.SetConstraint(vid, smoothMesh.GetVertex(vid), 0, true);
                    }
                }
            }

            smoother.SolveAndUpdateMesh();
            region.BackPropropagateVertices(true);
        }