cgv
cuberille.h
1 #pragma once
2 
3 #include <vector>
4 #include <deque>
5 #include <cgv/utils/progression.h>
6 #include <cgv/math/qem.h>
7 #include <cgv/math/mfunc.h>
8 #include <cgv/media/axis_aligned_box.h>
9 #include "streaming_mesh.h"
10 
11 namespace cgv {
12  namespace media {
13  namespace mesh {
14 
15  template <typename T>
16  struct greater_equal
17  {
18  T reference_value;
19  greater_equal(const T& _value) : reference_value(_value) {}
20  bool operator () (const T& _value) const { return _value >= reference_value; }
21  };
22 
23  template <typename T>
24  struct equal
25  {
26  T reference_value;
27  equal(const T& _value) : reference_value(_value) {}
28  bool operator () (const T& _value) const { return _value == reference_value; }
29  };
30 
31 
33 template <typename T, class P>
35 {
36  unsigned resx, resy;
37  unsigned nr_vertices;
38  std::vector<bool> flags;
39  std::vector<int> indices;
41  c_slice_info(unsigned int _resx, unsigned int _resy) : resx(_resx), resy(_resy) {
42  unsigned int n = resx*resy;
43  flags.resize(n, false);
44  indices.resize(n, -1);
45  nr_vertices = 0;
46  }
48  void init() {
49  std::fill(flags.begin(), flags.end(), false);
50  std::fill(indices.begin(), indices.end(), -1);
51  nr_vertices = 0;
52  }
53  int linear_index(int x, int y) const { return y*resx + x; }
55  bool flag(int x, int y) const { return (x>=0) && (y>=0) && flags[linear_index(x, y)]; }
57  void set_flag(int x, int y, bool flag) { flags[linear_index(x, y)] = flag; }
59  const int& index(int x, int y) const { return indices[linear_index(x, y)]; }
60  void set_index(int x, int y, int idx) {
61  indices[linear_index(x,y)] = idx;
62  ++nr_vertices;
63  }
64 };
65 
67 template <typename X, typename T, class P>
68 class cuberille : public streaming_mesh<X>
69 {
70 public:
76 private:
77  pnt_type p, minp;
78  unsigned int resx, resy, resz;
79  vec_type d;
80  const P& pred;
81 protected:
82  const cgv::math::v3_func<X,T>& func;
83 public:
87  const P& _pred) :
88  func(_func), pred(_pred)
89  {
91  }
93  void generate_edge_quad(int vi, int vj, int vk, int vl, bool reorient)
94  {
95  if (reorient)
96  base_type::new_quad(vi, vl, vk, vj);
97  else
98  base_type::new_quad(vi, vj, vk, vl);
99  }
102  {
103  // init slice info
104  I[0]->init();
105  // iterate voxels of slice to create slice vertices
106  unsigned i, j;
107  for (j = 0, p(1) = minp(1); j <= resy; ++j, p(1) += d(1)) {
108  for (i = 0, p(0) = minp(0); i <= resx; ++i, p(0) += d(0)) {
109  // set voxel flag
110  I[0]->set_flag(i, j, i < resx && j < resy && pred(func.evaluate(p.to_vec())));
111  // and check whether assigned vertex is needed
112  bool need_vertex = false;
113  need_vertex = need_vertex || (I[0]->flag(i, j) != I[1]->flag(i, j)); // z(x0,y0)
114  need_vertex = need_vertex || (I[0]->flag(i, j) != I[0]->flag(i, j - 1)); // y(x0,z0)
115  need_vertex = need_vertex || (I[1]->flag(i, j) != I[1]->flag(i, j - 1)); // y(x0,z1)
116  need_vertex = need_vertex || (I[0]->flag(i, j) != I[0]->flag(i - 1, j)); // x(y0,z0)
117  need_vertex = need_vertex || (I[1]->flag(i, j) != I[1]->flag(i - 1, j)); // x(y0,z1)
118  if (i > 0) {
119  need_vertex = need_vertex || (I[0]->flag(i - 1, j) != I[1]->flag(i - 1, j)); // z(x1,y0)
120  need_vertex = need_vertex || (I[0]->flag(i - 1, j) != I[0]->flag(i - 1, j - 1)); // y(x1,z0)
121  need_vertex = need_vertex || (I[1]->flag(i - 1, j) != I[1]->flag(i - 1, j - 1)); // y(x1,z1)
122  if (j > 0) {
123  need_vertex = need_vertex || (I[0]->flag(i - 1, j - 1) != I[1]->flag(i - 1, j - 1)); // z(x1,y1)
124  }
125  }
126  if (j > 0) {
127  need_vertex = need_vertex || (I[0]->flag(i, j - 1) != I[1]->flag(i - 1, j)); // z(x0,y1)
128  need_vertex = need_vertex || (I[0]->flag(i, j - 1) != I[0]->flag(i - 1, j - 1)); // x(y1,z0)
129  need_vertex = need_vertex || (I[1]->flag(i, j - 1) != I[1]->flag(i - 1, j - 1)); // x(y1,z1)
130  }
131  // create vertex if necessary
132  if (need_vertex)
133  I[0]->set_index(i, j, new_vertex(p - T(0.5)*d));
134  }
135  }
136  // iterate voxels again to create edge quads
137  for (j = 0, p(1) = minp(1); j <= resy; ++j, p(1) += d(1)) {
138  for (i = 0, p(0) = minp(0); i <= resx; ++i, p(0) += d(0)) {
139  if ((j < resy) && (I[1]->flag(i - 1, j) != I[1]->flag(i, j)))
140  generate_edge_quad(I[1]->index(i, j), I[1]->index(i, j + 1), I[0]->index(i, j + 1), I[0]->index(i, j), I[1]->flag(i, j));
141  if ((i < resx) && (I[1]->flag(i, j - 1) != I[1]->flag(i, j)))
142  generate_edge_quad(I[1]->index(i, j), I[0]->index(i, j), I[0]->index(i + 1, j), I[1]->index(i + 1, j), I[1]->flag(i, j));
143  if ((i < resx) && (j < resy) && (I[1]->flag(i, j) != I[0]->flag(i, j)))
144  generate_edge_quad(I[0]->index(i, j), I[0]->index(i + 1, j), I[0]->index(i + 1, j + 1), I[0]->index(i, j + 1), I[0]->flag(i, j));
145  }
146  }
147  }
150  unsigned int _resx, unsigned int _resy, unsigned int _resz,
151  bool show_progress = false)
152  {
153  // prepare private members
154  resx = _resx; resy = _resy; resz = _resz;
155  minp = p = box.get_min_pnt();
156  d = box.get_extent();
157  d(0) /= (resx-1); d(1) /= (resy-1); d(2) /= (resz-1);
158 
159  // prepare progression
161  if (show_progress)
162  prog.init("extraction", resz+1, 10);
163 
164  // construct three slice infos
165  c_slice_info<T, P> slice_info_1(resx+1,resy+1), slice_info_2(resx+1,resy+1);
166  c_slice_info<T, P> *I[2] = { &slice_info_1, &slice_info_2 };
167  for (unsigned k=0; k<=resz; ++k, p(2) += d(2)) {
168  process_slice(I);
169  base_type::drop_vertices(I[1]->nr_vertices);
170  // show progression
171  if (show_progress)
172  prog.step();
173  std::swap(I[0], I[1]);
174  }
175  }
176 };
177  }
178  }
179 }
cgv::media::mesh::streaming_mesh< X >::set_callback_handler
void set_callback_handler(streaming_mesh_callback_handler *_smcbh)
set a new callback handler
Definition: streaming_mesh.h:47
cgv::media::mesh::cuberille
class used to perform the marching cubes algorithm
Definition: cuberille.h:69
cgv::math::fvec< X, 3 >
cgv::math::v3_func
Definition: mfunc.h:63
cgv::media::mesh::streaming_mesh_callback_handler
Definition: streaming_mesh.h:13
cgv::media::mesh::cuberille::pnt_type
cgv::math::fvec< X, 3 > pnt_type
points must have three components
Definition: cuberille.h:73
cgv::media::mesh::streaming_mesh< X >::new_vertex
unsigned int new_vertex(const pnt_type &p)
add a new vertex with the given location and call the callback of the callback handler
Definition: streaming_mesh.h:80
cgv::media::axis_aligned_box::get_extent
fvec_type get_extent() const
return a vector with the extents in the different dimensions
Definition: axis_aligned_box.h:80
cgv::media::axis_aligned_box
Definition: axis_aligned_box.h:15
cgv::media::mesh::cuberille::vec_type
cgv::math::fvec< X, 3 > vec_type
vectors must have three components
Definition: cuberille.h:75
cgv::math::fvec::to_vec
vec< T > to_vec() const
conversion to vector type
Definition: fvec.h:411
cgv::media::mesh::cuberille::process_slice
void process_slice(c_slice_info< T, P > *I[2])
generate all vertices needed in the given slice I[0] with I[1] being the previous slice
Definition: cuberille.h:101
cgv::media::axis_aligned_box::get_min_pnt
const fpnt_type & get_min_pnt() const
return a const reference to corner 0
Definition: axis_aligned_box.h:60
cgv::media::mesh::cuberille::cuberille
cuberille(const cgv::math::v3_func< X, T > &_func, streaming_mesh_callback_handler *_smcbh, const P &_pred)
construct dual contouring object
Definition: cuberille.h:85
cgv::media::mesh::streaming_mesh
class used to perform the marching cubes algorithm
Definition: streaming_mesh.h:25
cgv::media::mesh::cuberille::generate_edge_quad
void generate_edge_quad(int vi, int vj, int vk, int vl, bool reorient)
construct a quadrilateral
Definition: cuberille.h:93
cgv::media::mesh::c_slice_info
Definition: cuberille.h:35
cgv::media::mesh::streaming_mesh< X >::new_quad
void new_quad(unsigned int vi, unsigned int vj, unsigned int vk, unsigned int vl)
construct a new quad by calling the new polygon method of the callback handler
Definition: streaming_mesh.h:99
cgv::utils::progression
Definition: progression.h:14
cgv::math::mfunc::evaluate
virtual T evaluate(const pnt_type &p) const =0
interface for evaluation of the multivariate function
cgv::media::mesh::streaming_mesh< X >::drop_vertices
void drop_vertices(unsigned int n)
drop n vertices from the front of the deque
Definition: streaming_mesh.h:67
cgv
the cgv namespace
Definition: vr_calib.cxx:9
cgv::media::mesh::cuberille::extract
void extract(const axis_aligned_box< X, 3 > &box, unsigned int _resx, unsigned int _resy, unsigned int _resz, bool show_progress=false)
extract iso surface and send quads to streaming mesh handler
Definition: cuberille.h:149