Esempio n. 1
0
        /// <summary>
        /// Find regions of the input meshes that are horizontal, returns binned by Z-value.
        /// Currently only finds upward-facing regions.
        /// </summary>
        protected Dictionary <double, List <PlanarRegion> > FindPlanarZRegions(double minDimension, double dotNormalTol = 0.999)
        {
            Dictionary <double, List <PlanarRegion> > Regions = new Dictionary <double, List <PlanarRegion> >();
            SpinLock region_lock = new SpinLock();

            gParallel.ForEach(Meshes, (sliceMesh) => {
                if (sliceMesh.options.IsCavity == false)
                {
                    return;
                }
                DMesh3 mesh = sliceMesh.mesh;

                HashSet <int> planar_tris = new HashSet <int>();
                foreach (int tid in mesh.TriangleIndices())
                {
                    Vector3d n = mesh.GetTriNormal(tid);
                    double dot = n.Dot(Vector3d.AxisZ);
                    if (dot > dotNormalTol)
                    {
                        planar_tris.Add(tid);
                    }
                }

                MeshConnectedComponents regions = new MeshConnectedComponents(mesh);
                regions.FilterF = planar_tris.Contains;
                regions.FindConnectedT();
                foreach (var c in regions)
                {
                    AxisAlignedBox3d bounds = MeshMeasurements.BoundsT(mesh, c.Indices);
                    if (bounds.Width > minDimension && bounds.Height > minDimension)
                    {
                        double z = Math.Round(bounds.Center.z, PrecisionDigits);

                        PlanarRegion planar = new PlanarRegion()
                        {
                            Mesh = mesh, Z = z, Triangles = c.Indices
                        };

                        bool taken = false;
                        region_lock.Enter(ref taken);
                        List <PlanarRegion> zregions;
                        if (Regions.TryGetValue(z, out zregions))
                        {
                            zregions.Add(planar);
                        }
                        else
                        {
                            zregions = new List <PlanarRegion>()
                            {
                                planar
                            };
                            Regions[z] = zregions;
                        }
                        region_lock.Exit();
                    }
                }
            });

            return(Regions);
        }
Esempio n. 2
0
        public void RemoveComponent(int tid, bool bInteractive)
        {
            if (PreviewMesh.IsTriangle(tid) == false)
            {
                DebugUtil.Log("MeshEditorTool.RemoveComponent: invalid tid!");
                return;
            }
            var tris = MeshConnectedComponents.FindConnectedT(PreviewMesh, tid);

            do_remove_triangles(tris, bInteractive);
        }
Esempio n. 3
0
        /// <summary>
        /// this runs inside SO.SafeMeshRead
        /// </summary>
        private object LockedComputeMeshBoundaryData(DMesh3 mesh)
        {
            ComponentData data = new ComponentData();

            data.timestamp = mesh.ShapeTimestamp;

            MeshConnectedComponents comp = new MeshConnectedComponents(mesh);

            comp.FindConnectedT();
            if (comp.Count == 1)
            {
                return(data);
            }

            // [TODO]
            //   - a very common case is a huge mesh with a few floaters. We
            //     should have a way to handle this w/o having to create all
            //     these spatial data structures for the huge mesh! We can
            //     do a quick sort based on bounding boxes, and for very
            //     small submeshes we could use non-fast WN, etc, etc...


            DSubmesh3Set subMeshes = new DSubmesh3Set(mesh, comp);

            MeshSpatialSort sort = new MeshSpatialSort();

            foreach (var submesh in subMeshes)
            {
                sort.AddMesh(submesh.SubMesh, submesh);
            }
            sort.Sort();

            foreach (var solid in sort.Solids)
            {
                foreach (var cavity in solid.Cavities)
                {
                    data.InteriorMeshes.Add(cavity.Mesh);
                }
                if (solid.Outer.InsideOf.Count > 0)
                {
                    data.InteriorMeshes.Add(solid.Outer.Mesh);
                }
            }

            // reverse orientation so that shading and culling works
            gParallel.ForEach(data.InteriorMeshes, (m) => {
                m.ReverseOrientation(true);
            });

            return(data);
        }
Esempio n. 4
0
        public static List <double> Volumes(MeshGeometry3D mesh)
        {
            DMesh3 m3 = MeshGeometryToDMesh(mesh);

            DMesh3[]      mC      = MeshConnectedComponents.Separate(m3);
            List <double> ListVol = new List <double>();

            foreach (DMesh3 m in mC)
            {
                var triangles = m.TriangleIndices();
                Func <int, Vector3d> getVertexF = (a) =>
                {
                    Vector3d V = m.GetVertex(a);
                    return(V);
                };
                Vector2d Vol = MeshMeasurements.VolumeArea(m, triangles, getVertexF);
                ListVol.Add(Vol.x / 1000);
            }
            return(ListVol);
        }
Esempio n. 5
0
    public static MeshConnectedComponents FindConnectedComponents(CuttingInfo info, List <int> painted)
    {
        var components = new MeshConnectedComponents(info.mesh);

        if (info.data.Multipiece)
        {
            components.FilterF = i => info.mesh.GetTriangleGroup(i) == info.data.ColorNum;
            components.FindConnectedT();
        }
        else
        {
            var newC = new MeshConnectedComponents.Component
            {
                Indices = painted.ToArray()
            };
            components.Components.Add(newC);
        }

        return(components);
    }
        public static void test_sort_mesh_components()
        {
            DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_nested_spheres.obj");

            MeshConnectedComponents components = new MeshConnectedComponents(mesh);

            components.FindConnectedT();
            DSubmesh3Set componentMeshes = new DSubmesh3Set(mesh, components);

            LocalProfiler p = new LocalProfiler();

            p.Start("sort");

            MeshSpatialSort sorter = new MeshSpatialSort();

            foreach (DSubmesh3 submesh in componentMeshes)
            {
                sorter.AddMesh(submesh.SubMesh, submesh);
            }
            sorter.Sort();

            p.Stop("sort");
            System.Console.WriteLine(p.AllTimes());

            DMesh3 resultMesh = new DMesh3();

            foreach (var solid in sorter.Solids)
            {
                if (solid.Outer.InsideOf.Count == 0)
                {
                    MeshEditor.Append(resultMesh, solid.Outer.Mesh);
                }
            }

            TestUtil.WriteTestOutputMesh(resultMesh, "mesh_components.obj");
        }
Esempio n. 7
0
        public virtual void Update()
        {
            base.begin_update();
            int start_timestamp = this.CurrentInputTimestamp;

            if (MeshSource == null)
            {
                throw new Exception("SeparateSolidsOp: must set valid MeshSource to compute!");
            }

            ResultMeshes = null;

            try {
                DMesh3 meshIn = new DMesh3(MeshSource.GetDMeshUnsafe());

                MeshConnectedComponents comp = new MeshConnectedComponents(meshIn);
                comp.FindConnectedT();
                DSubmesh3Set subMeshes = new DSubmesh3Set(meshIn, comp);

                List <DMesh3> curMeshes = new List <DMesh3>();
                foreach (var submesh in subMeshes)
                {
                    curMeshes.Add(submesh.SubMesh);
                }

                if (group_nested_shells)
                {
                    MeshSpatialSort sort = new MeshSpatialSort();
                    foreach (var mesh in curMeshes)
                    {
                        sort.AddMesh(mesh, mesh);
                    }
                    sort.Sort();

                    curMeshes.Clear();
                    foreach (var solid in sort.Solids)
                    {
                        DMesh3 outer = solid.Outer.Mesh;
                        if (orient_nested_shells && is_outward_oriented(outer) == false)
                        {
                            outer.ReverseOrientation();
                        }

                        foreach (var hole in solid.Cavities)
                        {
                            if (orient_nested_shells && hole.Mesh.CachedIsClosed && is_outward_oriented(hole.Mesh) == true)
                            {
                                hole.Mesh.ReverseOrientation();
                            }
                            MeshEditor.Append(outer, hole.Mesh);
                        }

                        curMeshes.Add(outer);
                    }
                }

                ResultMeshes = curMeshes;

                base.complete_update();
            } catch (Exception) {
                ResultMeshes = new List <DMesh3>();
                base.complete_update();
                throw;
            }
        }
Esempio n. 8
0
        void process()
        {
            DMesh3 useSourceMesh = SourceMesh;

            // try to do simple mesh repairs
            if (useSourceMesh.CachedIsClosed == false)
            {
                useSourceMesh = new DMesh3(SourceMesh);

                // [TODO] should remove duplicate triangles here?
                RemoveDuplicateTriangles dupes = new RemoveDuplicateTriangles(useSourceMesh);
                dupes.Apply();

                // close cracks
                MergeCoincidentEdges merge = new MergeCoincidentEdges(useSourceMesh);
                //merge.OnlyUniquePairs = true;
                merge.Apply();
            }

            //Util.WriteDebugMesh(useSourceMesh, "c:\\scratch\\__FIRST_MERGE.obj");


            DMesh3[] components = MeshConnectedComponents.Separate(useSourceMesh);

            List <DMesh3> solidComps = new List <DMesh3>();

            foreach (DMesh3 mesh in components)
            {
                // [TODO] check if this is a mesh w/ cracks, in which case we
                // can do other processing?

                bool closed = mesh.CachedIsClosed;
                if (closed == false)
                {
                    OpenMeshes.Add(mesh);
                    continue;
                }

                solidComps.Add(mesh);
            }


            if (solidComps.Count == 0)
            {
                return;
            }
            if (solidComps.Count == 1)
            {
                ClosedSolids = new List <DMesh3>()
                {
                    solidComps[0]
                };
            }


            if (HasNoVoids)
            {
                // each solid is a separate solid
                ClosedSolids = process_solids_novoid(solidComps);
            }
            else
            {
                ClosedSolids = process_solids(solidComps);
            }
        }
Esempio n. 9
0
    public override DMesh3 Cut(CuttingInfo info)
    {
        var painted = FindPaintedTriangles(info.mesh, info.data.ColorNum);

        if (painted.Count <= 0)
        {
            return(info.mesh);
        }

        var components = new MeshConnectedComponents(info.mesh);

        components.FilterF = i => info.mesh.GetTriangleGroup(i) == info.data.ColorNum;
        components.FindConnectedT();
        var subMeshes = new List <DMesh3>();

        foreach (var component in components)
        {
            DSubmesh3 subMesh = new DSubmesh3(info.mesh, component.Indices);
            var       newMesh = subMesh.SubMesh;
            newMesh.EnableTriangleGroups();

            var normals  = new List <Vector3d>();
            var vertices = new List <Vector3d>();

            foreach (var componentTriIndex in component.Indices)
            {
                var tri    = info.mesh.GetTriangle(componentTriIndex);
                var normal = info.mesh.GetTriNormal(componentTriIndex);
                normals.Add(normal);
                var orgA = info.mesh.GetVertex(tri.a);
                vertices.Add(orgA);
                var orgB = info.mesh.GetVertex(tri.b);
                vertices.Add(orgB);
                var orgC = info.mesh.GetVertex(tri.c);
                vertices.Add(orgC);
            }

            var avgNormal   = normals.Average();
            var avgVertices = vertices.Average();
            var newPoint    = avgVertices - avgNormal * info.data.depth;

            if (info.data.modifier == CutSettingData.Modifier.Compute)
            {
                newPoint = MovePointInsideAndAwayFromShell(info, newPoint);
            }
            if (info.data.modifier == CutSettingData.Modifier.DepthDependant)
            {
                newPoint = MovePointDepthDependant(info, avgVertices, avgNormal);
            }
            component.Indices.ToList().ForEach(index => info.mesh.RemoveTriangle(index));


            var newPointId          = newMesh.AppendVertex(newPoint);
            var newPointIdInOldMesh = info.mesh.AppendVertex(newPoint);
            info.PointToPoint.Add(newPointId, newPointIdInOldMesh);

            var eidsNewMesh = newMesh.BoundaryEdgeIndices().ToList();
            foreach (var openEdge in eidsNewMesh)
            {
                var edge = newMesh.GetOrientedBoundaryEdgeV(openEdge);
                newMesh.AppendTriangle(edge.b, edge.a, newPointId, info.data.ColorNum);
                info.mesh.AppendTriangle(subMesh.MapVertexToBaseMesh(edge.a), subMesh.MapVertexToBaseMesh(edge.b),
                                         newPointIdInOldMesh, ColorManager.Instance.MainColorId);
            }

            subMeshes.Add(newMesh);
        }

        InstantiateNewObjects(info, subMeshes);


        return(info.mesh);
    }
Esempio n. 10
0
        public virtual void Update()
        {
            base.begin_update();
            int start_timestamp = this.CurrentInputTimestamp;

            if (MeshSource == null)
            {
                throw new Exception("CombineMeshesOp: must set valid MeshSource to compute!");
            }

            ResultMesh = null;

            try {
                DMesh3 meshIn = new DMesh3(MeshSource.GetDMeshUnsafe());

                if (orient_nested_shells)
                {
                    MeshConnectedComponents comp = new MeshConnectedComponents(meshIn);
                    comp.FindConnectedT();
                    DSubmesh3Set subMeshes = new DSubmesh3Set(meshIn, comp);

                    List <DMesh3> curMeshes = new List <DMesh3>();
                    foreach (var submesh in subMeshes)
                    {
                        curMeshes.Add(submesh.SubMesh);
                    }

                    MeshSpatialSort sort = new MeshSpatialSort();
                    foreach (var mesh in curMeshes)
                    {
                        sort.AddMesh(mesh, mesh);
                    }
                    sort.Sort();

                    ResultMesh = new DMesh3();
                    MeshEditor editor = new MeshEditor(ResultMesh);
                    foreach (var solid in sort.Solids)
                    {
                        DMesh3 outer = solid.Outer.Mesh;
                        if (!is_outward_oriented(outer))
                        {
                            outer.ReverseOrientation();
                        }
                        editor.AppendMesh(outer, ResultMesh.AllocateTriangleGroup());

                        foreach (var hole in solid.Cavities)
                        {
                            if (hole.Mesh.CachedIsClosed && is_outward_oriented(hole.Mesh) == true)
                            {
                                hole.Mesh.ReverseOrientation();
                            }
                            editor.AppendMesh(hole.Mesh, ResultMesh.AllocateTriangleGroup());
                        }
                    }
                }
                else
                {
                    ResultMesh = meshIn;
                }

                base.complete_update();
            } catch (Exception e) {
                PostOnOperatorException(e);
                ResultMesh = base.make_failure_output(MeshSource.GetDMeshUnsafe());
                base.complete_update();
            }
        }
Esempio n. 11
0
        protected virtual DMesh3 compute_wrap()
        {
            DMesh3 meshIn = MeshSource.GetDMeshUnsafe();

            double unsigned_offset = Math.Abs(distance);

            if (cached_sdf == null ||
                unsigned_offset > cached_sdf_max_offset ||
                grid_cell_size != cached_sdf.CellSize)
            {
                DMeshAABBTree3 use_spatial = input_spatial;
                CachingMeshSDF sdf         = new CachingMeshSDF(meshIn, grid_cell_size, use_spatial);
                sdf.MaxOffsetDistance = 2 * (float)unsigned_offset;

                sdf.CancelF = is_invalidated;
                sdf.Initialize();
                if (is_invalidated())
                {
                    return(null);
                }

                cached_sdf            = sdf;
                cached_sdf_max_offset = unsigned_offset;
                cached_sdf_bounds     = meshIn.CachedBounds;
            }

            var grid_iso = new CachingMeshSDFImplicit(cached_sdf);
            // currently MCPro-Continuation does not work w/ non-zero
            //   isovalues, so we have to shift our target offset externally
            var iso = new ImplicitOffset3d()
            {
                A = grid_iso, Offset = distance
            };

            MarchingCubesPro c = new MarchingCubesPro();

            c.Implicit = iso;
            c.Bounds   = cached_sdf_bounds;
            c.CubeSize = mesh_cell_size;
            c.Bounds.Expand(distance + 3 * c.CubeSize);

            c.CancelF = is_invalidated;
            c.GenerateContinuation(offset_seeds(meshIn, distance));
            if (is_invalidated())
            {
                return(null);
            }

            Reducer r = new Reducer(c.Mesh);

            r.FastCollapsePass(c.CubeSize * 0.5, 3, true);
            if (is_invalidated())
            {
                return(null);
            }

            if (min_component_volume > 0)
            {
                MeshEditor.RemoveSmallComponents(c.Mesh, min_component_volume, min_component_volume);
            }
            if (is_invalidated())
            {
                return(null);
            }

            DMesh3 offsetMesh = c.Mesh;

            MeshConnectedComponents comp = new MeshConnectedComponents(offsetMesh);

            comp.FindConnectedT();
            if (is_invalidated())
            {
                return(null);
            }
            DSubmesh3Set subMeshes = new DSubmesh3Set(offsetMesh, comp);

            if (is_invalidated())
            {
                return(null);
            }

            MeshSpatialSort sort = new MeshSpatialSort();

            foreach (var subMesh in subMeshes)
            {
                sort.AddMesh(subMesh.SubMesh, subMesh);
            }
            sort.Sort();
            if (is_invalidated())
            {
                return(null);
            }

            DMesh3 outerMesh = new DMesh3();

            foreach (var solid in sort.Solids)
            {
                DMesh3 outer = solid.Outer.Mesh;
                //if (is_outward_oriented(outer) == false)
                //    outer.ReverseOrientation();
                MeshEditor.Append(outerMesh, outer);
            }
            if (is_invalidated())
            {
                return(null);
            }

            return(compute_inset(outerMesh));
        }
Esempio n. 12
0
        protected void do_flatten(DMesh3 mesh)
        {
            double   BAND_HEIGHT = flatten_band_height;
            Vector3d down_axis   = -Vector3d.AxisY;
            double   dot_thresh  = 0.2;

            AxisAlignedBox3d bounds  = mesh.CachedBounds;
            DMeshAABBTree3   spatial = new DMeshAABBTree3(mesh, true);

            Ray3d   ray     = new Ray3d(bounds.Center - 2 * bounds.Height * Vector3d.AxisY, Vector3d.AxisY);
            int     hit_tid = spatial.FindNearestHitTriangle(ray);
            Frame3f hitF;

            MeshQueries.RayHitPointFrame(mesh, spatial, ray, out hitF);
            Vector3d basePt = hitF.Origin;

            Frame3f basePlane = new Frame3f(basePt, Vector3f.AxisY);

            MeshConnectedComponents components = new MeshConnectedComponents(mesh)
            {
                FilterF = (tid) => {
                    if (mesh.GetTriangleGroup(tid) != LastExtrudeOuterGroupID)
                    {
                        return(false);
                    }
                    Vector3d n, c; double a;
                    mesh.GetTriInfo(tid, out n, out a, out c);
                    double h = Math.Abs(c.y - basePt.y);
                    if (h > BAND_HEIGHT)
                    {
                        return(false);
                    }
                    if (n.Dot(down_axis) < dot_thresh)
                    {
                        return(false);
                    }
                    return(true);
                },
                SeedFilterF = (tid) => {
                    return(tid == hit_tid);
                }
            };

            components.FindConnectedT();

            MeshFaceSelection all_faces = new MeshFaceSelection(mesh);

            foreach (var comp in components)
            {
                MeshVertexSelection vertices = new MeshVertexSelection(mesh);
                vertices.SelectTriangleVertices(comp.Indices);
                foreach (int vid in vertices)
                {
                    Vector3d v = mesh.GetVertex(vid);
                    v = basePlane.ProjectToPlane((Vector3f)v, 2);
                    mesh.SetVertex(vid, v);
                }
                all_faces.SelectVertexOneRings(vertices);
            }

            all_faces.ExpandToOneRingNeighbours(3, (tid) => {
                return(mesh.GetTriangleGroup(tid) == LastExtrudeOuterGroupID);
            });

            RegionRemesher r = new RegionRemesher(mesh, all_faces);

            r.SetProjectionTarget(MeshProjectionTarget.Auto(mesh));
            r.SetTargetEdgeLength(2.0f);
            r.SmoothSpeedT = 1.0f;
            for (int k = 0; k < 10; ++k)
            {
                r.BasicRemeshPass();
            }
            r.SetProjectionTarget(null);
            r.SmoothSpeedT = 1.0f;
            for (int k = 0; k < 10; ++k)
            {
                r.BasicRemeshPass();
            }
            r.BackPropropagate();
        }