cgv
Loading...
Searching...
No Matches
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
11namespace cgv {
12 namespace media {
13 namespace mesh {
14
15 template <typename T>
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
33template <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
67template <typename X, typename T, class P>
68class cuberille : public streaming_mesh<X>
69{
70public:
76private:
77 pnt_type p, minp;
78 unsigned int resx, resy, resz;
79 vec_type d;
80 const P& pred;
81protected:
82 const cgv::math::v3_func<X,T>& func;
83public:
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}
A vector with zero based index.
Definition fvec.h:26
vec< T > to_vec() const
conversion to vector type
Definition fvec.h:730
virtual T evaluate(const pnt_type &p) const =0
interface for evaluation of the multivariate function
specialization of a multivariate function to three independent variables, which only reimplements the...
Definition mfunc.h:63
An axis aligned box, defined by to points: min and max.
fvec_type get_extent() const
return a vector with the extents in the different dimensions
const fpnt_type & get_min_pnt() const
return a const reference to corner 0
class used to perform the marching cubes algorithm
Definition cuberille.h:69
cgv::math::fvec< X, 3 > pnt_type
points must have three components
Definition cuberille.h:73
cgv::math::fvec< X, 3 > vec_type
vectors must have three components
Definition cuberille.h:75
void generate_edge_quad(int vi, int vj, int vk, int vl, bool reorient)
construct a quadrilateral
Definition cuberille.h:93
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
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
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
class used to perform the marching cubes algorithm
void set_callback_handler(streaming_mesh_callback_handler *_smcbh)
set a new callback handler
unsigned int new_vertex(const pnt_type &p)
add a new vertex with the given location and call the callback of the callback handler
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
void drop_vertices(unsigned int n)
drop n vertices from the front of the deque
the cgv namespace
Definition print.h:11
data structure for the information that is cached per volume slice by the cuberille algorithm
Definition cuberille.h:35
pure abstract interface to handle callbacks of a streaming mesh
progression provides a simple possibility to show progression of process in console.
Definition progression.h:14
void step()
next iteration
void init(const std::string &process, size_t total, int count)
reinitialize