예제 #1
0
        /// <summary>
        /// Remove any connected components with volume &lt; min_volume area lt; min_area
        /// </summary>
        public int RemoveSmallComponents(double min_volume, double min_area)
        {
            MeshConnectedComponents C = new MeshConnectedComponents(Mesh);

            C.FindConnectedT();
            if (C.Count == 1)
            {
                return(0);
            }
            int nRemoved = 0;

            foreach (var comp in C.Components)
            {
                Vector2d vol_area = MeshMeasurements.VolumeArea(Mesh, comp.Indices, Mesh.GetVertex);
                if (vol_area.x < min_volume || vol_area.y < min_area)
                {
                    MeshEditor.RemoveTriangles(Mesh, comp.Indices);
                    nRemoved++;
                }
            }
            return(nRemoved);
        }
예제 #2
0
        // Remove the original submesh region and merge in the remeshed version.
        // You can call this multiple times as the base-triangle-set is updated.
        //
        // By default, we allow the submesh to be modified to prevent creation of
        // non-manifold edges. You can disable this, however then some of the submesh
        // triangles may be discarded.
        //
        // Returns false if there were errors in insertion, ie if some triangles
        // failed to insert. Does not revert changes that were successful.
        public bool BackPropropagate(bool bAllowSubmeshRepairs = true)
        {
            if (bAllowSubmeshRepairs)
            {
                RepairPossibleNonManifoldEdges();
            }

            // remove existing submesh triangles
            MeshEditor editor = new MeshEditor(BaseMesh);

            editor.RemoveTriangles(cur_base_tris, true);

            // insert new submesh
            int[] new_tris = new int[Region.SubMesh.TriangleCount];
            ReinsertSubToBaseMapV = null;
            bool bOK = editor.ReinsertSubmesh(Region, ref new_tris, out ReinsertSubToBaseMapV, ReinsertDuplicateTriBehavior);

            // reconstruct this...hacky?
            int NT = Region.SubMesh.MaxTriangleID;

            ReinsertSubToBaseMapT = new IndexMap(false, NT);
            int nti = 0;

            for (int ti = 0; ti < NT; ++ti)
            {
                if (Region.SubMesh.IsTriangle(ti) == false)
                {
                    continue;
                }
                ReinsertSubToBaseMapT[ti] = new_tris[nti++];
            }

            // assert that new triangles are all valid (goes wrong sometimes??)
            Debug.Assert(IndexUtil.IndicesCheck(new_tris, BaseMesh.IsTriangle));

            cur_base_tris = new_tris;
            return(bOK);
        }
예제 #3
0
        // Remove the original submesh region and merge in the remeshed version.
        // You can call this multiple times as the base-triangle-set is updated.
        //
        // By default, we allow the submesh to be modified to prevent creation of
        // non-manifold edges. You can disable this, however then some of the submesh
        // triangles may be discarded.
        //
        // Returns false if there were errors in insertion, ie if some triangles
        // failed to insert. Does not revert changes that were successful.
        public bool BackPropropagate(bool bAllowSubmeshRepairs = true)
        {
            if (bAllowSubmeshRepairs)
            {
                RepairPossibleNonManifoldEdges();
            }

            // remove existing submesh triangles
            MeshEditor editor = new MeshEditor(BaseMesh);

            editor.RemoveTriangles(cur_base_tris, true);

            // insert new submesh
            int[] new_tris = new int[Region.SubMesh.TriangleCount];
            ReinsertSubToBaseMapV = null;
            bool bOK = editor.ReinsertSubmesh(Region, ref new_tris, out ReinsertSubToBaseMapV, ReinsertDuplicateTriBehavior);

            // assert that new triangles are all valid (goes wrong sometimes??)
            Debug.Assert(IndexUtil.IndicesCheck(new_tris, BaseMesh.IsTriangle));

            cur_base_tris = new_tris;
            return(bOK);
        }
예제 #4
0
        public virtual bool Trim()
        {
            if (Spatial == null)
            {
                Spatial = new DMeshAABBTree3(new DMesh3(Mesh, false, MeshComponents.None));
                Spatial.Build();
            }

            if (seed_tri == -1)
            {
                seed_tri = Spatial.FindNearestTriangle(seed_pt);
            }

            var loop = new MeshFacesFromLoop(Mesh, TrimLine, Spatial, seed_tri);

            MeshFaceSelection selection = loop.ToSelection();

            selection.LocalOptimize(true, true);
            var editor = new MeshEditor(Mesh);

            editor.RemoveTriangles(selection, true);

            var components = new MeshConnectedComponents(Mesh);

            components.FindConnectedT();
            if (components.Count > 1)
            {
                int keep = components.LargestByCount;
                for (int i = 0; i < components.Count; ++i)
                {
                    if (i != keep)
                    {
                        editor.RemoveTriangles(components[i].Indices, true);
                    }
                }
            }
            editor.RemoveAllBowtieVertices(true);

            var  loops   = new MeshBoundaryLoops(Mesh);
            bool loopsOK = false;

            try
            {
                loopsOK = loops.Compute();
            }
            catch (Exception)
            {
                return(false);
            }
            if (!loopsOK)
            {
                return(false);
            }


            // [TODO] to support trimming mesh w/ existing holes, we need to figure out which
            // loop we created in RemoveTriangles above!
            if (loops.Count > 1)
            {
                return(false);
            }

            int[] loopVerts = loops[0].Vertices;

            var borderTris = new MeshFaceSelection(Mesh);

            borderTris.SelectVertexOneRings(loopVerts);
            borderTris.ExpandToOneRingNeighbours(RemeshBorderRings);

            var remesh = new RegionRemesher(Mesh, borderTris.ToArray());

            remesh.Region.MapVerticesToSubmesh(loopVerts);

            double target_len = TargetEdgeLength;

            if (target_len <= 0)
            {
                double mine, maxe, avge;
                MeshQueries.EdgeLengthStatsFromEdges(Mesh, loops[0].Edges, out mine, out maxe, out avge);
                target_len = avge;
            }

            var meshTarget = new MeshProjectionTarget(Spatial.Mesh, Spatial);

            remesh.SetProjectionTarget(meshTarget);
            remesh.SetTargetEdgeLength(target_len);
            remesh.SmoothSpeedT = SmoothingAlpha;

            var curveTarget = new DCurveProjectionTarget(TrimLine);
            var multiTarget = new SequentialProjectionTarget(curveTarget, meshTarget);

            int set_id = 3;

            MeshConstraintUtil.ConstrainVtxLoopTo(remesh, loopVerts, multiTarget, set_id);

            for (int i = 0; i < RemeshRounds; ++i)
            {
                remesh.BasicRemeshPass();
            }

            remesh.BackPropropagate();

            // [TODO] output loop somehow...use MeshConstraints.FindConstrainedEdgesBySetID(set_id)...

            return(true);
        }         // Trim()
예제 #5
0
        public static bool RemoveTriangles(DMesh3 Mesh, IEnumerable <int> triangles, bool bRemoveIsolatedVerts = true)
        {
            MeshEditor editor = new MeshEditor(Mesh);

            return(editor.RemoveTriangles(triangles, bRemoveIsolatedVerts));
        }
예제 #6
0
        private void Remove(TriangleRemoval rem = TriangleRemoval.contained)
        {
#if ACAD
            var lastColor = 0;
#endif

            DMeshAABBTree3 spatial = new DMeshAABBTree3(CutMesh, true);
            spatial.WindingNumber(Vector3d.Zero);
            SafeListBuilder <int> containedT    = new SafeListBuilder <int>();
            SafeListBuilder <int> removeAnywayT = new SafeListBuilder <int>();

            // if the windinging number for the centroid point candidate triangles
            // is one or more (or close for safety), then it's inside the volume of cutMesh
            //
            gParallel.ForEach(Target.TriangleIndices(), (tid) =>
            {
                if (Target.GetTriArea(tid) < VertexSnapTol)
                {
                    removeAnywayT.SafeAdd(tid);
                    return; // parallel: equivalent to continue.
                }
                Vector3d v = Target.GetTriCentroid(tid);
                if (AttemptPlanarRemoval)
                {
                    // slightly offset the point to be evaluated.
                    //
                    var nrm = Target.GetTriNormal(tid);
                    v      -= nrm * 5 * VertexSnapTol;
                }

                var winding     = spatial.WindingNumber(v);
                bool IsInternal = winding > 0.9;
#if ACAD
                // temporarily here for debug purposes
                var wantColor = IsInternal ? 1 : 2;
                if (lastColor != wantColor)
                {
                    Debug.WriteLine($"-LAYER set L{wantColor}");
                    Debug.WriteLine($"");
                    lastColor = wantColor;
                }
                Triangle3d tri = new Triangle3d();
                Target.GetTriVertices(tid, ref tri.V0, ref tri.V1, ref tri.V2);
                Debug.WriteLine($"3DPOLY {tri.V0.CommaDelimited} {tri.V1.CommaDelimited} {tri.V2.CommaDelimited} {tri.V0.CommaDelimited} {v.CommaDelimited} ");
#endif
                if (IsInternal)
                {
                    containedT.SafeAdd(tid);
                }
            });
            if (rem == TriangleRemoval.contained)
            {
                MeshEditor.RemoveTriangles(Target, containedT.Result);
            }
            else if (rem == TriangleRemoval.external)
            {
                var ext = Target.TriangleIndices().Except(containedT.Result);
                MeshEditor.RemoveTriangles(Target, ext);
            }

            MeshEditor.RemoveTriangles(Target, removeAnywayT.Result);

            // [RMS] construct set of on-cut vertices? This is not
            // necessarily all boundary vertices...
            CutVertices = new List <int>();
            foreach (int vid in SegmentInsertVertices)
            {
                if (Target.IsVertex(vid))
                {
                    CutVertices.Add(vid);
                }
            }
        }