Esempio n. 1
0
    public int SanityCheck()
    {
        if (isImported)
        {
            return(0);
        }
        var tree   = new DMeshAABBTree3(cuttingInfo.oldMesh, true); //todo build tree earlier??
        var errors = 0;

        foreach (var keyValuePair in cuttingInfo.PointToPoint)
        {
            if (!mesh.IsVertex(keyValuePair.Key))
            {
                Debug.Log($"NonVertex from {cuttingInfo.data.algo.ToString()}");
            }
            var coords  = mesh.GetVertex(keyValuePair.Key);
            var oldMesh = cuttingInfo.oldMesh;

            if (!tree.IsInside(coords))
            {
                errors++;
            }
        }

        return(errors);
    }
Esempio n. 2
0
        /// <summary>
        /// Checks if a point is inside of a mesh. This function is slow due to the need to build a spatial data structure using geometry3Sharp.
        /// </summary>
        /// <param name="mesh">The mesh to be checked.</param>
        /// <param name="point">The point in question.</param>
        /// <returns>Whether the point is inside the mesh.</returns>
        public static bool IsPointInside(this Mesh mesh, Vector3 point)
        {
            var mesh3   = GenerateDynamicMesh(mesh.vertices, mesh.triangles, mesh.normals);
            var spatial = new DMeshAABBTree3(mesh3);

            spatial.Build();
            return(spatial.IsInside(new Vector3d(point.x, point.y, point.z)));
        }
 public Vector3d Project(Vector3d vPoint, int identifier)
 {
     if (Spatial.IsInside(vPoint))
     {
         return(MeshQueries.NearestPointFrame(Spatial.Mesh, Spatial, vPoint).Origin);
     }
     else
     {
         return(vPoint);
     }
 }
Esempio n. 4
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            int        num_cells = 128;
            DMesh3_goo dMsh_goo  = null;

            DA.GetData(0, ref dMsh_goo);
            DA.GetData(1, ref num_cells);

            DMesh3 dMsh_copy = new DMesh3(dMsh_goo.Value);
            double cell_size = dMsh_copy.CachedBounds.MaxDim / num_cells;

            DMeshAABBTree3 spatial = new DMeshAABBTree3(dMsh_copy, autoBuild: true);

            AxisAlignedBox3d  bounds   = dMsh_copy.CachedBounds;
            double            cellsize = bounds.MaxDim / num_cells;
            ShiftGridIndexer3 indexer  = new ShiftGridIndexer3(bounds.Min, cellsize);

            Bitmap3 bmp = new Bitmap3(new Vector3i(num_cells, num_cells, num_cells));

            foreach (Vector3i idx in bmp.Indices())
            {
                g3.Vector3d v = indexer.FromGrid(idx);
                bmp.Set(idx, spatial.IsInside(v));
            }

            VoxelSurfaceGenerator voxGen = new VoxelSurfaceGenerator();

            voxGen.Voxels = bmp;
            voxGen.Generate();
            DMesh3 voxMesh = voxGen.Meshes[0];

            var vecSize = dMsh_copy.CachedBounds.Extents;
            var box     = dMsh_copy.GetBounds();

            // Scale voxel mesh
            //MeshTransforms.Scale(voxMesh,)

            DA.SetData(0, voxMesh);
        }
Esempio n. 5
0
    internal Vector3d MovePointInsideAndAwayFromShell(CuttingInfo info, Vector3d position, int maxCount = 5)
    {
        var tree = new DMeshAABBTree3(info.mesh, true);

        if (!tree.IsInside(position))
        {
            Debug.Log("Point outside of mesh");
            var getInside = GetInsideShell(tree, position, info.data.ColorNum);
            if (getInside != null)
            {
                position += getInside.Value;
                Debug.Log($"GetInside. New Pos: {position} ");
            }
            else
            {
                Debug.Log("Point too far away from shell");
            }
        }
        var getAway = this.GetAwayFromShellDirection(info, tree, position);
        int count   = 0;

        while (getAway != null)
        {
            position += getAway.Value.Normalized * info.data.minDepth;
            Debug.Log($"Getaway. New Pos: {position} ");

            count++;

            if (count >= maxCount)
            {
                Debug.Log("MoveAway could not find a suitable position, count exceeded");
                StaticFunctions.ErrorMessage("The object is too thin to find a suitable position. Might cause intersections.");
                break;
            }
            getAway = GetAwayFromShellDirection(info, tree, position);
        }
        return(position);
    }
Esempio n. 6
0
        public static DMesh3 MineCraft(DMesh3 mesh, int num_cells, out double scalefactor)
        {
            DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, autoBuild: true);


            AxisAlignedBox3d bounds   = mesh.CachedBounds;
            double           cellsize = bounds.MaxDim / num_cells;

            scalefactor = cellsize;

            ShiftGridIndexer3 indexer = new ShiftGridIndexer3(bounds.Min, cellsize);

            Bitmap3 bmp = new Bitmap3(new Vector3i(num_cells, num_cells, num_cells));

            foreach (Vector3i idx in bmp.Indices())
            {
                g3.Vector3d v = indexer.FromGrid(idx);
                if (spatial.IsInside(v))
                {
                    bmp.Set(idx, true);
                }
                else
                {
                    bmp.Set(idx, false);
                }
            }

            VoxelSurfaceGenerator voxGen = new VoxelSurfaceGenerator();

            voxGen.Voxels = bmp;
            voxGen.Generate();

            DMesh3 voxMesh = voxGen.Meshes[0];

            return(voxMesh);
        }
        void constrained_smooth(DGraph3 graph, double surfDist, double dotThresh, double alpha, int rounds)
        {
            int NV = graph.MaxVertexID;

            Vector3d[] pos = new Vector3d[NV];

            for (int ri = 0; ri < rounds; ++ri)
            {
                gParallel.ForEach(graph.VertexIndices(), (vid) => {
                    Vector3d v = graph.GetVertex(vid);

                    if (GroundVertices.Contains(vid) || TipVertices.Contains(vid))
                    {
                        pos[vid] = v;
                        return;
                    }

                    // for tip base vertices, we could allow them to move down and away within angle cone...
                    if (TipBaseVertices.Contains(vid))
                    {
                        pos[vid] = v;
                        return;
                    }


                    // compute smoothed position of vtx
                    Vector3d centroid = Vector3d.Zero; int nbr_count = 0;
                    foreach (int nbr_vid in graph.VtxVerticesItr(vid))
                    {
                        centroid += graph.GetVertex(nbr_vid);
                        nbr_count++;
                    }
                    if (nbr_count == 1)
                    {
                        pos[vid] = v;
                        return;
                    }
                    centroid     /= nbr_count;
                    Vector3d vnew = (1 - alpha) * v + (alpha) * centroid;

                    // make sure we don't violate angle constraint to any nbrs
                    int attempt = 0;
                    try_again:
                    foreach (int nbr_vid in graph.VtxVerticesItr(vid))
                    {
                        Vector3d dv = graph.GetVertex(nbr_vid) - vnew;
                        dv.Normalize();
                        double dot = dv.Dot(Vector3d.AxisY);
                        if (Math.Abs(dot) < dotThresh)
                        {
                            if (attempt++ < 3)
                            {
                                vnew = Vector3d.Lerp(v, vnew, 0.66);
                                goto try_again;
                            }
                            else
                            {
                                pos[vid] = v;
                                return;
                            }
                        }
                    }

                    // offset from nearest point on surface
                    Frame3f fNearest  = MeshQueries.NearestPointFrame(Mesh, MeshSpatial, vnew, true);
                    Vector3d vNearest = fNearest.Origin;
                    double dist       = vnew.Distance(vNearest);
                    bool inside       = MeshSpatial.IsInside(vnew);

                    if (inside || dist < surfDist)
                    {
                        Vector3d normal = fNearest.Z;
                        // don't push down?
                        if (normal.Dot(Vector3d.AxisY) < 0)
                        {
                            normal.y = 0; normal.Normalize();
                        }
                        vnew = fNearest.Origin + surfDist * normal;
                    }


                    pos[vid] = vnew;
                });

                foreach (int vid in graph.VertexIndices())
                {
                    graph.SetVertex(vid, pos[vid]);
                }
            }
        }
        public virtual bool Apply()
        {
            DMesh3 testAgainstMesh = Mesh;

            if (InsideMode == CalculationMode.RayParity)
            {
                MeshBoundaryLoops loops = new MeshBoundaryLoops(testAgainstMesh);
                if (loops.Count > 0)
                {
                    testAgainstMesh = new DMesh3(Mesh);
                    foreach (var loop in loops)
                    {
                        if (Cancelled())
                        {
                            return(false);
                        }
                        SimpleHoleFiller filler = new SimpleHoleFiller(testAgainstMesh, loop);
                        filler.Fill();
                    }
                }
            }

            DMeshAABBTree3 spatial = (Spatial != null && testAgainstMesh == Mesh) ?
                                     Spatial : new DMeshAABBTree3(testAgainstMesh, true);

            if (InsideMode == CalculationMode.AnalyticWindingNumber)
            {
                spatial.WindingNumber(Vector3d.Zero);
            }
            else if (InsideMode == CalculationMode.FastWindingNumber)
            {
                spatial.FastWindingNumber(Vector3d.Zero);
            }

            if (Cancelled())
            {
                return(false);
            }

            // ray directions
            List <Vector3d> ray_dirs = null; int NR = 0;

            if (InsideMode == CalculationMode.SimpleOcclusionTest)
            {
                ray_dirs = new List <Vector3d>();
                ray_dirs.Add(Vector3d.AxisX); ray_dirs.Add(-Vector3d.AxisX);
                ray_dirs.Add(Vector3d.AxisY); ray_dirs.Add(-Vector3d.AxisY);
                ray_dirs.Add(Vector3d.AxisZ); ray_dirs.Add(-Vector3d.AxisZ);
                NR = ray_dirs.Count;
            }

            Func <Vector3d, bool> isOccludedF = (pt) => {
                if (InsideMode == CalculationMode.RayParity)
                {
                    return(spatial.IsInside(pt));
                }
                else if (InsideMode == CalculationMode.AnalyticWindingNumber)
                {
                    return(spatial.WindingNumber(pt) > WindingIsoValue);
                }
                else if (InsideMode == CalculationMode.FastWindingNumber)
                {
                    return(spatial.FastWindingNumber(pt) > WindingIsoValue);
                }
                else
                {
                    for (int k = 0; k < NR; ++k)
                    {
                        int hit_tid = spatial.FindNearestHitTriangle(new Ray3d(pt, ray_dirs[k]));
                        if (hit_tid == DMesh3.InvalidID)
                        {
                            return(false);
                        }
                    }
                    return(true);
                }
            };

            bool cancel = false;

            BitArray vertices = null;

            if (PerVertex)
            {
                vertices = new BitArray(Mesh.MaxVertexID);

                MeshNormals normals = null;
                if (Mesh.HasVertexNormals == false)
                {
                    normals = new MeshNormals(Mesh);
                    normals.Compute();
                }

                gParallel.ForEach(Mesh.VertexIndices(), (vid) => {
                    if (cancel)
                    {
                        return;
                    }
                    if (vid % 10 == 0)
                    {
                        cancel = Cancelled();
                    }

                    Vector3d c    = Mesh.GetVertex(vid);
                    Vector3d n    = (normals == null) ? Mesh.GetVertexNormal(vid) : normals[vid];
                    c            += n * NormalOffset;
                    vertices[vid] = isOccludedF(c);
                });
            }
            if (Cancelled())
            {
                return(false);
            }

            RemovedT = new List <int>();
            SpinLock removeLock = new SpinLock();

            gParallel.ForEach(Mesh.TriangleIndices(), (tid) => {
                if (cancel)
                {
                    return;
                }
                if (tid % 10 == 0)
                {
                    cancel = Cancelled();
                }

                bool inside = false;
                if (PerVertex)
                {
                    Index3i tri = Mesh.GetTriangle(tid);
                    inside      = vertices[tri.a] || vertices[tri.b] || vertices[tri.c];
                }
                else
                {
                    Vector3d c = Mesh.GetTriCentroid(tid);
                    Vector3d n = Mesh.GetTriNormal(tid);
                    c         += n * NormalOffset;
                    inside     = isOccludedF(c);
                }

                if (inside)
                {
                    bool taken = false;
                    removeLock.Enter(ref taken);
                    RemovedT.Add(tid);
                    removeLock.Exit();
                }
            });

            if (Cancelled())
            {
                return(false);
            }

            if (RemovedT.Count > 0)
            {
                MeshEditor editor = new MeshEditor(Mesh);
                bool       bOK    = editor.RemoveTriangles(RemovedT, true);
                RemoveFailed = (bOK == false);
            }

            return(true);
        }
Esempio n. 9
0
        public static void test_Winding()
        {
            Sphere3Generator_NormalizedCube gen = new Sphere3Generator_NormalizedCube()
            {
                EdgeVertices = 200
            };
            DMesh3 mesh = gen.Generate().MakeDMesh();
            //DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj");
            DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true);

            GC.Collect();

            double   maxdim = mesh.CachedBounds.MaxDim;
            Vector3d center = mesh.CachedBounds.Center;

            var pts        = TestUtil.RandomPoints3(100, new Random(31337), center, maxdim * 0.5);
            int num_inside = 0;

            foreach (Vector3d pt in pts)
            {
                bool   inside    = spatial.IsInside(pt);
                double distSqr   = MeshQueries.TriDistanceSqr(mesh, spatial.FindNearestTriangle(pt), pt);
                double ptDist    = pt.Length;
                double winding   = mesh.WindingNumber(pt);
                double winding_2 = spatial.WindingNumber(pt);
                if (Math.Abs(winding - winding_2) > 0.00001)
                {
                    System.Diagnostics.Debugger.Break();
                }
                bool winding_inside = Math.Abs(winding) > 0.5;
                if (inside != winding_inside)
                {
                    System.Diagnostics.Debugger.Break();
                }
                if (inside)
                {
                    num_inside++;
                }
            }
            System.Console.WriteLine("inside {0} / {1}", num_inside, pts.Length);

            // force rebuild for profiling code
            GC.Collect();

            LocalProfiler p = new LocalProfiler();

            pts = TestUtil.RandomPoints3(1000, new Random(31337), center, maxdim * 0.5);

            p.Start("full eval");
            double sum = 0;

            foreach (Vector3d pt in pts)
            {
                double winding = mesh.WindingNumber(pt);
                sum += winding;
            }
            p.StopAll();

            p.Start("tree build");
            spatial = new DMeshAABBTree3(mesh, true);
            spatial.WindingNumber(Vector3d.Zero);
            p.StopAll();

            GC.Collect();
            GC.Collect();

            p.Start("tree eval");
            sum = 0;
            foreach (Vector3d pt in pts)
            {
                double winding = spatial.WindingNumber(pt);
                sum += winding;
            }

            p.StopAll();

            System.Console.WriteLine(p.AllTimes());
        }