595 |
jab |
1 |
/* ----------------------------------------------------------------------- *
|
|
|
2 |
* This file is part of GEL, http://www.imm.dtu.dk/GEL
|
|
|
3 |
* Copyright (C) the authors and DTU Informatics
|
|
|
4 |
* For license and list of authors, see ../../doc/intro.pdf
|
|
|
5 |
* ----------------------------------------------------------------------- */
|
|
|
6 |
|
|
|
7 |
/**
|
|
|
8 |
* @file Cell.h
|
|
|
9 |
* @brief Cell class for a voxel grid in a 2 level grid.
|
|
|
10 |
*/
|
|
|
11 |
|
443 |
jab |
12 |
#ifndef __GEOMETRY_CELL_H
|
|
|
13 |
#define __GEOMETRY_CELL_H
|
61 |
jab |
14 |
|
|
|
15 |
#include <vector>
|
601 |
jab |
16 |
#include "../CGLA/Vec3i.h"
|
|
|
17 |
#include "../CGLA/BitMask.h"
|
61 |
jab |
18 |
#include "RGrid.h"
|
|
|
19 |
|
|
|
20 |
namespace Geometry
|
|
|
21 |
{
|
89 |
jab |
22 |
/** \brief Class template for a cell in a hierarchical grid.
|
|
|
23 |
|
61 |
jab |
24 |
The template arguments are the type and the cell dimension.
|
|
|
25 |
A Cell is much like an RGrid - except that a Cell may
|
|
|
26 |
be coalesced into a single value and then split again
|
|
|
27 |
when a new value is inserted. Also cells are constrained to
|
|
|
28 |
be of size NxNxN where N=2^m for some m. This makes some things
|
|
|
29 |
faster.
|
|
|
30 |
|
|
|
31 |
The reason for making CELL_DIM a template argument rather
|
|
|
32 |
than a constructor argument is that we generally have many
|
|
|
33 |
cells and do not wish that each cell contains its dimension.
|
|
|
34 |
*/
|
|
|
35 |
template<class T, int CELL_DIM, class ChildT>
|
|
|
36 |
class Cell
|
|
|
37 |
{
|
|
|
38 |
public:
|
|
|
39 |
typedef T DataType;
|
|
|
40 |
|
|
|
41 |
private:
|
|
|
42 |
bool touched;
|
|
|
43 |
|
|
|
44 |
/// Linear array containing data of this Cell.
|
|
|
45 |
std::vector<T> data;
|
|
|
46 |
|
|
|
47 |
/** Return a bit mask used to mask indices.
|
|
|
48 |
Some functions in this class are passed a Vec3i
|
|
|
49 |
whose lower bits index into the cell. The mask is
|
|
|
50 |
used to select these lower bits before the 3D
|
|
|
51 |
index is converted to a linear index.
|
|
|
52 |
|
|
|
53 |
If you are wondering about why the static variable
|
|
|
54 |
inside the function is not simply a static member of
|
|
|
55 |
the class, check out item 47 og "Effective C++" by
|
|
|
56 |
Scott Meyers.
|
|
|
57 |
*/
|
|
|
58 |
static const CGLA::BitMask& get_bit_mask()
|
|
|
59 |
{
|
|
|
60 |
static const CGLA::BitMask bit_mask(CELL_DIM);
|
|
|
61 |
return bit_mask;
|
|
|
62 |
}
|
|
|
63 |
|
|
|
64 |
public:
|
|
|
65 |
|
|
|
66 |
/** Get dimensions of Cell. Returns only one value since
|
|
|
67 |
x, y, and z dimensions are the same. */
|
|
|
68 |
static int get_dim()
|
|
|
69 |
{
|
|
|
70 |
return CELL_DIM;
|
|
|
71 |
}
|
|
|
72 |
|
|
|
73 |
private:
|
|
|
74 |
|
|
|
75 |
/** Get index. Computes an index into the linear array representation
|
|
|
76 |
of the voxels in the cell from a 3D grid index. The top bits (which
|
|
|
77 |
have been used to find this Cell) are masked out. */
|
|
|
78 |
int get_idx(const CGLA::Vec3i& idx) const
|
|
|
79 |
{
|
|
|
80 |
CGLA::Vec3i bot_idx = get_bit_mask().mask(idx);
|
|
|
81 |
return (bot_idx[2]*get_dim()+bot_idx[1])*get_dim()+bot_idx[0];
|
|
|
82 |
}
|
|
|
83 |
|
|
|
84 |
protected:
|
|
|
85 |
|
|
|
86 |
/** Store a value in the Cell. If the Cell is
|
|
|
87 |
coalesced, it is first resized to contain CELL_DIMS
|
|
|
88 |
cubed voxels, and then the voxel is inserted. */
|
|
|
89 |
void store_priv(const CGLA::Vec3i& p, const T& new_val)
|
|
|
90 |
{
|
|
|
91 |
if(is_coalesced()) split();
|
|
|
92 |
touched = true;
|
|
|
93 |
data[get_idx(p)] = new_val;
|
|
|
94 |
}
|
|
|
95 |
|
|
|
96 |
|
|
|
97 |
public:
|
|
|
98 |
|
|
|
99 |
/** Create empty grid cell. A Cell contains initially a single value.
|
|
|
100 |
Reading (using operator[]) any voxel will yield this value. */
|
|
|
101 |
Cell(const T& val): data(1,val), touched(false)
|
|
|
102 |
{
|
|
|
103 |
assert(CELL_DIM==get_dim());
|
|
|
104 |
}
|
|
|
105 |
|
|
|
106 |
/** Clear cell. Removes Cell contents replacing it with a single
|
|
|
107 |
specified value. */
|
|
|
108 |
void coalesce(const T& val)
|
|
|
109 |
{
|
|
|
110 |
data=std::vector<T>(1,val);
|
|
|
111 |
touched = true;
|
|
|
112 |
}
|
|
|
113 |
|
|
|
114 |
/// Split cell - causes memory to be reserved for CELL_DIM^3 voxels.
|
|
|
115 |
void split()
|
|
|
116 |
{
|
|
|
117 |
T val = data[0];
|
|
|
118 |
data.resize(CGLA::qbe(CELL_DIM), val);
|
|
|
119 |
touched = true;
|
|
|
120 |
}
|
|
|
121 |
|
|
|
122 |
/// Check if the cell is coalesced
|
|
|
123 |
bool is_coalesced() const
|
|
|
124 |
{
|
|
|
125 |
// We rely on size() being constant time below.
|
|
|
126 |
// Probably this function should be changed.... it would be bad
|
|
|
127 |
// if it was slow ... very bad....
|
|
|
128 |
return data.size()==1;
|
|
|
129 |
}
|
|
|
130 |
|
|
|
131 |
|
|
|
132 |
/** Read access to voxel grid. This function is passed
|
|
|
133 |
a Vec3i and returns the corresponding voxel. If the
|
|
|
134 |
cell is coalesced, the single value stored is returned. */
|
|
|
135 |
const T& operator[](const CGLA::Vec3i& p) const
|
|
|
136 |
{
|
|
|
137 |
if(is_coalesced()) return data[0];
|
|
|
138 |
return *(&data[get_idx(p)]);
|
|
|
139 |
}
|
|
|
140 |
|
|
|
141 |
void store(const CGLA::Vec3i& p, const T& new_val)
|
|
|
142 |
{
|
|
|
143 |
return static_cast<ChildT&>(*this).store(p,new_val);
|
|
|
144 |
}
|
|
|
145 |
|
|
|
146 |
|
|
|
147 |
/** Const get a pointer to the first element in the linear
|
|
|
148 |
array representation of the grid. */
|
|
|
149 |
const T* get() const {return &data[0];}
|
|
|
150 |
|
|
|
151 |
/** Non-const get a pointer to the first element in the linear
|
|
|
152 |
array representation of the grid. */
|
|
|
153 |
T* get()
|
|
|
154 |
{
|
|
|
155 |
touched = true;
|
|
|
156 |
return &data[0];
|
|
|
157 |
}
|
|
|
158 |
|
|
|
159 |
void untouch() {touched=false;}
|
|
|
160 |
void touch() {touched=true;}
|
|
|
161 |
bool is_touched() const {return touched;}
|
|
|
162 |
|
|
|
163 |
};
|
|
|
164 |
|
|
|
165 |
|
|
|
166 |
template<class T, int CELL_DIM>
|
|
|
167 |
class DefaultCell: public Cell<T,CELL_DIM,DefaultCell<T, CELL_DIM> >
|
|
|
168 |
{
|
|
|
169 |
public:
|
|
|
170 |
DefaultCell(const T& val): Cell<T,CELL_DIM,DefaultCell>(val){}
|
|
|
171 |
void store(const CGLA::Vec3i& p, const T& new_val)
|
|
|
172 |
{
|
|
|
173 |
store_priv(p, new_val);
|
|
|
174 |
}
|
|
|
175 |
|
|
|
176 |
};
|
|
|
177 |
|
|
|
178 |
|
|
|
179 |
}
|
|
|
180 |
#endif
|