src/examples/distance.c

    Distance field computation from a 3D model

    The goal is to build a distance field representation of a 3D CAD model.

    #include "grid/octree.h"
    #include "utils.h"
    #include "distance.h"
    #include "fractions.h"
    #include "view.h"
    
    int main()
    {

    We get the 3D model from the Large Geometric Models Archive. This is in PLY format which we need to convert to STL using meshlab.

      system ("test -f distance.stl || "
    	  "(wget http://www.cc.gatech.edu/data_files/large_models/horse.ply.gz && "
    	  "gunzip -f horse.ply.gz && "
    	  "meshlabserver -i horse.ply -o distance.stl)");

    We read the STL file, compute the bounding box of the model and set the domain center and size using this bounding box.

      coord * p = input_stl (fopen ("distance.stl", "r"));
      coord min, max;
      bounding_box (p, &min, &max);  
      double maxl = -HUGE;
      foreach_dimension()
        if (max.x - min.x > maxl)
          maxl = max.x - min.x;
      
      init_grid (8);
      size (1.2*maxl);
      origin ((max.x + min.x)/2. - L0/2,
    	  (max.y + min.y)/2. - L0/2,
    	  (max.z + min.z)/2. - L0/2);

    We initialize the distance field on the coarse initial mesh and refine it adaptively until the threshold error (on distance) is reached.

      scalar d[];
      distance (d, p);
      while (adapt_wavelet ({d}, (double[]){5e-4*L0}, 10).nf);

    We display an isosurface of the distance function coloured with the level of refinement.

      view (fov = 15.65, quat = {-0.52,0.31,0.38,-0.7},
    	tx = -0.045, ty = 0.015, width = 640, height = 480, bg = {1,1,1});
      isosurface ("d", 0, color = "level", min = 5, max = 10);
      save ("horse.png");

    We also compute the volume and surface fractions from the distance field.

      scalar f[];
      face vector s[];
      solid (f, s, (d[] + d[-1] + d[0,-1] + d[-1,-1] +
    		d[0,0,-1] + d[-1,0,-1] + d[0,-1,-1] + d[-1,-1,-1])/8.);

    Finally we display the surface reconstructed from volume fractions.

      clear();
      draw_vof ("f", "s");
      draw_vof ("f", "s", edges = true, lw = 0.5);
      save ("vof.png");
    }

    Note that the “tail” of the horse is an artefact due to an inconsistency in the surface mesh, which is self-intersecting near this point.

    Isosurface of the distance function coloured with level of refinement.

    Isosurface of the distance function coloured with level of refinement.

    Reconstructed VOF surface.

    Reconstructed VOF surface.

    See also