sandbox/Antoonvh/bwatch-iterators.h

    Iterators bwatch

    Concept

    Iterate over

    • All camera rays
    • Each cell that the ray passes
    • Each cell where a ray intersects a facet
    // A helper function
    bool interfacial2 (scalar f, Point point) {
      if (f[] > 1e-6 && f[] < 1 - 1e-6)
        return true;
      return false;
    }
    
    void set_cr (coord * cr, coord * proj, coord * vert) {
      foreach_dimension() 
        cr->x = cam.poi.x - cam.O.x;
      normalize (cr);
      foreach_dimension() {
        proj->x = cam.up.x*cr->x;
        vert->x = cam.up.x - proj->x;
      }
    }
    
    void set_apoint (coord * apoint, coord hori, coord vert, int ii, int jj) {
      foreach_dimension() {
        apoint->x = (cam.poi.x
    		 + cam.fov*((ii + 0.5)/cam.nx - 0.5)*hori.x
    		 + ((float)cam.ny/cam.nx)*cam.fov*((jj + 0.5)/cam.ny - 0.5)*vert.x);  
      }
    }
    
    @def foreach_ray() 
    coord cr, proj, vert, hori;
    set_cr (&cr, &proj, &vert);
    hori = cross (cr, vert);
    normalize (&vert);
    normalize (&hori);
    for (int jj = cam.ny; jj > 0; jj--) {    
      for (int ii = 0; ii < cam.nx; ii++) {
        coord apoint;
        set_apoint (&apoint, hori, vert, ii, jj);
        ray _r;
        _r.depth = 0;
        _r.O = cam.O;
        _r.dir.x = apoint.x - cam.O.x;
        _r.dir.y = apoint.y - cam.O.y;
        _r.dir.z = apoint.z - cam.O.z;
        
        normalize (&_r.dir); 
        @
          @def end_foreach_ray()
          }
     }
    @
    
    @def foreach_ray_cell_intersection(r) 
      foreach_cell() { //MG acceleration
      coord _a[2] = {0};
        double _dist = ray_cell_intersect (r, point, _a);
        if (_dist < HUGE) {
          if (is_leaf(cell)) {
    	@
    	  @def end_foreach_ray_cell_intersection()
    	  }
        } else // Ray missed, skip children
      continue;
      } end_foreach_cell();
    @
    
    @def foreach_ray_facet_intersection(r, f)
    double _distg = HUGE;
    foreach_cell() { //MG acceleration
      coord _a[2] = {{0,0,0}, {0,0,0}}; //Pedantic...
      double _dist = ray_cell_intersect (r, point, _a);
      if (_dist < 0 || _dist < _distg) {
        if (interfacial2 (f, point)) {
          if (is_leaf(cell)) {
    	coord _n;
    	if (segment_facet_intersect (_a, f, point, &_n)) {
    	  normalize (&_n);
    	  _distg = _dist;
    	  @
    	    @def end_foreach_ray_facet_intersection()
    	    }
          }
        } else  // No fragment, skip children
          continue;
      } else   // Ray missed or blocked, skip children
        continue; 
    }end_foreach_cell();
    @

    Workhorses

    sketch should use optimized iterators,

    #include "PointTriangle.h"
    
    void find_nearby_distances (scalar s) {
      assert (s.vofd.i);
      boundary ({s});
      scalar d = s.vofd;
      foreach() {
        coord cc = {x, y, z};
        double dist = 3*Delta*sign (s[] - 0.5);
        foreach_neighbor (1) {
          if (s[] > 1e-6 && s[] < 1. - 1e-6) {
    	coord n = mycs (point, s);
    	double alpha = plane_alpha (s[], n);
    	coord v[12];
    	int m = facets (n, alpha, v, 1.);
    	// Using Alexis Berny's triangulation
    	for (int j = 0; j < m - 2; j++) {
    	  coord t1 = {x + v[0].x*Delta  , y + v[0].y*Delta  , z + v[0].z*Delta}; 
    	  coord t2 = {x + v[j+1].x*Delta, y + v[j+1].y*Delta, z + v[j+1].z*Delta};
    	  coord t3 = {x + v[j+2].x*Delta, y + v[j+2].y*Delta, z + v[j+2].z*Delta};
    	  double s, t, dtr = PointTriangleDistance (&cc, &t1, &t2, &t3, &s, &t);
    	  if (dtr > 0)
    	    if (fabs(sqrt(dtr)) < fabs(dist))
    	      dist = sqrt(dtr)*PointTriangleOrientation (&cc, &t1, &t2, &t3);
    	}
          }
        }
        d[] = dist;
      }
      boundary ({d});
    }
    
    long int find_possible (scalar s, double val) {
      scalar posi = s.possible;
      int n = 0;
      foreach(reduction (+:n)) {//leaf
        posi[] = 0;
        bool pos = false, neg = false; 
        foreach_neighbor(1) {
          if (s[] < val)
    	neg = true;
          if (s[] > val)
    	pos = true;
        }
        if (pos && neg) {
          n++;
          posi[] = 1;
        }
      }
      for (int l = depth() - 1; l >=0 ; l--) {
        foreach_coarse_level(l) {
          double p = 0;
          foreach_child()
    	if (posi[])
    	  p = 1;
          posi[] = p;
        }
      }
      return n;
    }
    
    bool maybe (scalar posi, Point point) {
      if (posi[])
        return true;
      return false;
    }
    
    @def foreach_possible_ray_equi_intersection(r, s, posi, DG)
    foreach_cell() { //MG acceleration
      if (maybe(posi, point)) {
        coord _a[2] = {0};
        double _dist = ray_cell_intersect (r, point, _a);
        if (_dist < DG) {
          if (is_leaf(cell)) {
    	@
    	  @def end_foreach_possible_ray_equi_intersection()
    	  }
        } else // Ray missed or blocked, skip children
          continue;
      } else // Does not contain the isosurface
        continue;
    } end_foreach_cell();
    @
    
    static inline bool precomp_segment_facet_intersect (coord a[2], double alpha, Point point, coord n) {
      coord cc = {x, y, z};
      double ALP = 0, ALP2 = 0;
      foreach_dimension() {
        ALP  += n.x*(a[0].x - cc.x)/Delta;
        ALP2 += n.x*(a[1].x - cc.x)/Delta;
      }
      if ((ALP2 - alpha)/(ALP - alpha) > 0.05) //~/wiki/sandbox/Antoonvh 5% gap filling
        return false;
      double w = fabs((ALP2 - alpha)) / (fabs(ALP - alpha) + fabs(ALP2 - alpha));
      foreach_dimension() {
        a[1].x = w*a[0].x + (1 - w)*a[1].x;
      }
      {;}
      return true;
    }
    
    static inline coord get_normal (scalar f, Point point) {
      coord n1 = {0};
      vector v = f.normals;
      foreach_dimension()
        n1.x = v.x[];
      return n1;
    }
    
    static inline double get_alpha (scalar f, Point point) {
      scalar s = f.possible;
      return s[];
    }
      
    @def foreach_precomp_ray_facet_intersection(r, f, DG)
    double _distg = HUGE;
    foreach_cell() { //MG acceleration
      if (interfacial2 (f, point)) {
        coord _a[2] = {{0,0,0}, {0,0,0}}; //Pedantic...
        double _dist = ray_cell_intersect (r, point, _a);
        if (_dist >= 0 && _dist < _distg && _dist < DG) {
          if (is_leaf(cell)) {
    	coord _n = get_normal (f, point);
    	double alpha = get_alpha (f, point);
    	if (precomp_segment_facet_intersect (_a, alpha, point, _n)) {
    	  normalize (&_n);
    	  _distg = _dist;
    	  @
    	    @def end_foreach_precomp_ray_facet_intersection()
    	    }
          }
        } else  // Ray missed or blocked, skip children
          continue;
      } else   // No fragment, skip children
        continue; 
    }end_foreach_cell();
    @

    Iterator for volumetric rendering

    long int find_possible_vol (scalar s, double mval) {
      scalar posi = s.possible;
      int n = 0;
      foreach(reduction(+:n)) {//leaf
        posi[] = 0;
        bool nv = false;
        foreach_neighbor(1)
          if (s[] > mval)
    	nv = true;
        if (nv)  {
          posi[] = 1;
          n++;
        } 
      }
      // restriction
      for (int l = depth() - 1; l >= 0; l--) {
        foreach_coarse_level(l) {
          double p = 0;
          foreach_child()
    	if (posi[])
    	  p = 1;
          posi[] = p;
        }
      }
      return n;
    }
    
    @def foreach_ray_cell_intersection_volume(r, dm, posi) 
    foreach_cell() { //MG acceleration
      if (maybe(posi, point)) {
        coord _a[2] = {0};
        double _dist = ray_cell_intersect (r, point, _a);
        if (_dist < dm) {
          if (is_leaf(cell)) { //do something
    	@
    	  @def end_foreach_ray_cell_intersection_volume()
    	  }
        } else // Ray missed or blocked, skip children
          continue;
    	} else // Nothing to see, skip children 
        continue;
    } end_foreach_cell();
    @