public double Value(ref Vector3d pt)
            {
                double winding = Spatial.FastWindingNumber(pt);

                // shift zero-isocontour to winding isovalue, and then flip sign
                return(-(winding - IsoValue));
            }
        public static void test_fast_winding_implicit()
        {
            //Sphere3Generator_NormalizedCube gen = new Sphere3Generator_NormalizedCube() { EdgeVertices = 15, Radius = 5 };
            //CappedCylinderGenerator gen = new CappedCylinderGenerator() { };
            //TrivialBox3Generator gen = new TrivialBox3Generator() { Box = new Box3d(Vector3d.Zero, 5 * Vector3d.One) };
            //DMesh3 mesh = gen.Generate().MakeDMesh();
            //MeshTransforms.Translate(mesh, 5 * Vector3d.One);
            DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj");
            //DMesh3 mesh = TestUtil.LoadTestInputMesh("holey_bunny.obj");
            //DMesh3 mesh = TestUtil.LoadTestInputMesh("holey_bunny_2.obj");
            //DMesh3 mesh = TestUtil.LoadTestMesh("C:\\git\\gsOrthoVRApp\\sample_files\\scan_1_raw.obj");   // use iso 0.25
            //DMesh3 mesh = TestUtil.LoadTestMesh("C:\\scratch\\irongiant.stl");
            //DMesh3 mesh = TestUtil.LoadTestMesh("C:\\Users\\rms\\Dropbox\\meshes\\cars\\beetle.obj");
            //DMesh3 mesh = TestUtil.LoadTestMesh("c:\\scratch\\PigHead_rot90.obj");
            //DMesh3 mesh = TestUtil.LoadTestMesh("C:\\Projects\\nia_files\\testscan2.obj");

            //TestUtil.WriteTestOutputMesh(mesh, "xxx.obj");

            int mesh_cells = 128;

            AxisAlignedBox3d meshBounds  = mesh.CachedBounds;
            float            winding_iso = 0.5f;

            DMeshAABBTreePro spatialPro = new DMeshAABBTreePro(mesh, true);

            spatialPro.FastWindingNumber(Vector3d.Zero);
            //spatialPro.FWNBeta = 1.0;

            FastWindingImplicit fwnImplicit = new FastWindingImplicit(spatialPro, winding_iso);

            MarchingCubes c = new MarchingCubes();

            c.Implicit = fwnImplicit;
            c.Bounds   = mesh.CachedBounds;
            c.CubeSize = c.Bounds.MaxDim / mesh_cells;
            c.Bounds.Expand(c.CubeSize * 3);
            c.RootMode      = MarchingCubes.RootfindingModes.Bisection;
            c.RootModeSteps = 10;

            c.Generate();

            // reproject
            //foreach (int vid in c.Mesh.VertexIndices()) {
            //    Vector3d v = c.Mesh.GetVertex(vid);

            //    int tid = spatial.FindNearestTriangle(v, cell_size * MathUtil.SqrtTwo);
            //    if (tid != DMesh3.InvalidID) {
            //        var query = MeshQueries.TriangleDistance(mesh, tid, v);
            //        if (v.Distance(query.TriangleClosest) < cell_size * 1.5)
            //            c.Mesh.SetVertex(vid, query.TriangleClosest);
            //    }
            //}

            //MeshNormals.QuickCompute(c.Mesh);
            TestUtil.WriteTestOutputMesh(c.Mesh, "mwn_implicit.obj");
        }
 public FastWindingImplicit(DMeshAABBTreePro spatial, double isoValue = 0.5)
 {
     Spatial = spatial;
     spatial.FastWindingNumber(Vector3d.Zero);
     IsoValue = isoValue;
 }
        public static void test_fast_winding_grid()
        {
            //Sphere3Generator_NormalizedCube gen = new Sphere3Generator_NormalizedCube() { EdgeVertices = 15, Radius = 5 };
            //CappedCylinderGenerator gen = new CappedCylinderGenerator() { };
            //TrivialBox3Generator gen = new TrivialBox3Generator() { Box = new Box3d(Vector3d.Zero, 5 * Vector3d.One) };
            //DMesh3 mesh = gen.Generate().MakeDMesh();
            //MeshTransforms.Translate(mesh, 5 * Vector3d.One);
            DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj");
            //DMesh3 mesh = TestUtil.LoadTestInputMesh("holey_bunny.obj");
            //DMesh3 mesh = TestUtil.LoadTestInputMesh("holey_bunny_2.obj");
            //DMesh3 mesh = TestUtil.LoadTestMesh("C:\\git\\gsOrthoVRApp\\sample_files\\scan_1_raw.obj");   // use iso 0.25
            //DMesh3 mesh = TestUtil.LoadTestMesh("C:\\scratch\\irongiant.stl");
            //DMesh3 mesh = TestUtil.LoadTestMesh("C:\\Users\\rms\\Dropbox\\meshes\\cars\\beetle.obj");
            //DMesh3 mesh = TestUtil.LoadTestMesh("c:\\scratch\\PigHead_rot90.obj");
            //DMesh3 mesh = TestUtil.LoadTestMesh("C:\\Projects\\nia_files\\testscan2.obj");

            //TestUtil.WriteTestOutputMesh(mesh, "xxx.obj");

            AxisAlignedBox3d meshBounds = mesh.CachedBounds;
            int    num_cells            = 256;
            double cell_size            = meshBounds.MaxDim / num_cells;

            float winding_iso = 0.35f;

            DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true);

            spatial.WindingNumber(Vector3d.Zero);

            DMeshAABBTreePro spatialPro = new DMeshAABBTreePro(mesh, true);

            spatialPro.FastWindingNumber(Vector3d.Zero);

            Func <Vector3d, double> exactWN     = (q) => { return(spatial.WindingNumber(q)); };
            Func <Vector3d, double> PerFacePtWN = (q) => { return(eval_point_wn(mesh, q)); };
            Func <Vector3d, double> fastWN      = (q) => { return(spatialPro.FastWindingNumber(q)); };

            //MeshScalarSamplingGrid mwnGrid = new MeshScalarSamplingGrid(mesh, cell_size, exactWN);
            //MeshScalarSamplingGrid mwnGrid = new MeshScalarSamplingGrid(mesh, cell_size, PerFacePtWN );
            MeshScalarSamplingGrid mwnGrid = new MeshScalarSamplingGrid(mesh, cell_size, fastWN);

            mwnGrid.IsoValue   = winding_iso;
            mwnGrid.DebugPrint = true;

            LocalProfiler p = new LocalProfiler();

            p.Start("grid");
            mwnGrid.Compute();
            p.Stop("grid");
            System.Console.WriteLine(p.AllTimes());


            MarchingCubes c = new MarchingCubes();

            c.Implicit = new SampledGridImplicit(mwnGrid);

            c.Bounds   = mesh.CachedBounds;
            c.CubeSize = c.Bounds.MaxDim / 128;

            //c.Bounds = mesh.CachedBounds;
            c.Bounds.Expand(c.CubeSize * 3);
            //c.CubeSize = cell_size * 0.5;
            //c.IsoValue = mwnGrid.WindingIsoValue;

            c.Generate();

            // reproject
            foreach (int vid in c.Mesh.VertexIndices())
            {
                Vector3d v = c.Mesh.GetVertex(vid);

                int tid = spatial.FindNearestTriangle(v, cell_size * MathUtil.SqrtTwo);
                if (tid != DMesh3.InvalidID)
                {
                    var query = MeshQueries.TriangleDistance(mesh, tid, v);
                    if (v.Distance(query.TriangleClosest) < cell_size * 1.5)
                    {
                        c.Mesh.SetVertex(vid, query.TriangleClosest);
                    }
                }
            }

            //MeshNormals.QuickCompute(c.Mesh);
            TestUtil.WriteTestOutputMesh(c.Mesh, "mwn_implicit.obj");
        }