13template<
typename Scalar,
typename Index,
int NumDimensions>
19template<
typename Scalar,
typename Index,
int NumDimensions>
20V_COREEXPORT void Celltree<Scalar, Index, NumDimensions>::refreshImpl()
const
23template<
typename Scalar,
typename Index,
int NumDimensions>
27 assert(nodes().size() == 1);
28 for (
int i = 0; i < NumDimensions; ++i)
29 this->
min()[i] = gmin[i];
30 for (
int i = 0; i < NumDimensions; ++i)
31 this->max()[i] = gmax[i];
34 const Vector *m_min, *m_max;
40 auto vmin = m_min[elem], vmax = m_max[elem];
47 MinMaxBoundsFunctor boundFunc(
min, max);
48 this->validateTree(boundFunc);
50 refine(
min, max, 0, gmin, gmax);
52 std::cerr <<
"created celltree: " << nodes().size() <<
" nodes, " << cells().size() <<
" cells" << std::endl;
53 validateTree(boundFunc);
57template<
typename Scalar,
typename Index,
int NumDimensions>
61 const Scalar smax = std::numeric_limits<Scalar>::max();
63 const int NumBuckets = 5;
65 Node *node = &(nodes()[curNode]);
72 Index *cells = d()->m_cells->data();
77 Index bucket[NumDimensions][NumBuckets];
78 Vector bmin[NumBuckets], bmax[NumBuckets];
79 for (
int i = 0; i < NumBuckets; ++i) {
80 for (
int d = 0; d < NumDimensions; ++d)
94 for (
Index i = node->start; i < node->start + node->size; ++i) {
95 const Index cell = cells[i];
96 Vector cent = center(cell);
97 for (
int d = 0; d < NumDimensions; ++d) {
98 if (cmin[d] > cent[d])
100 if (cmax[d] < cent[d])
106 const Vector crange = cmax - cmin;
108 auto getBucket = [cmin, cmax, crange, NumBuckets](
Vector center,
int d) ->
int {
109 return crange[d] == 0 ? 0 :
std::min(
int((center[d] - cmin[d]) / crange[d] * NumBuckets), NumBuckets - 1);
112 for (
Index i = node->start; i < node->start + node->size; ++i) {
113 const Index cell = cells[i];
114 const Vector cent = center(cell);
115 for (
int d = 0; d < NumDimensions; ++d) {
116 const int b = getBucket(cent, d);
118 assert(b < NumBuckets);
121 bmax[b][d] = std::max(bmax[b][d], max[cell][d]);
126 for (
int d = 0; d < NumDimensions; ++d) {
127 for (
int b = NumBuckets - 2; b >= 0; --b) {
128 if (bmin[b][d] > bmin[b + 1][d])
129 bmin[b][d] = bmin[b + 1][d];
131 for (
int b = 1; b < NumBuckets; ++b) {
132 if (bmax[b][d] < bmax[b - 1][d])
133 bmax[b][d] = bmax[b - 1][d];
139 int best_dim = -1, best_bucket = -1;
140 for (
int d = 0; d < NumDimensions; ++d) {
142 for (
int split_b = 0; split_b < NumBuckets - 1; ++split_b) {
143 nleft += bucket[d][split_b];
144 assert(node->size >= nleft);
145 const Index nright = node->size - nleft;
147 nleft * (bmax[split_b][d] - bmin[0][d]) + nright * (bmax[NumBuckets - 1][d] - bmin[split_b + 1][d]);
149 weight /= node->size * crange[d];
153 if (nleft > 0 && nright > 0 && weight < min_weight) {
156 best_bucket = split_b;
159 assert(nleft + bucket[d][NumBuckets - 1] == node->size);
161 if (best_dim == -1) {
162 std::cerr <<
"abandoning split with " << node->size <<
" children" << std::endl;
167 const Index size = node->size;
168 const Index start = node->start;
171 const Scalar Lmax = bmax[best_bucket][best_dim];
172 const Scalar Rmin = bmin[best_bucket + 1][best_dim];
173 *node =
Node(best_dim, Lmax, Rmin, nodes().size());
174 const Index D = best_dim;
177 return Scalar(0.5) * (
min[c][D] + max[c][D]);
179 auto getBucketD = [cmin, cmax, crange, D, NumBuckets](
Scalar center) ->
int {
180 return crange[D] == 0 ? 0 :
std::min(
int((center - cmin[D]) / crange[D] * NumBuckets), NumBuckets - 1);
184 const Scalar split = cmin[D] + crange[D] / NumBuckets * (best_bucket + 1);
185#ifdef CT_DEBUG_VERBOSE
186 std::cerr <<
"split: dim=" << best_dim <<
", bucket=" << best_bucket;
188 for (
int i = 0; i < NumBuckets; ++i) {
189 std::cerr << bucket[best_dim][i];
190 if (i == best_bucket)
192 else if (i < NumBuckets - 1)
196 std::cerr <<
" split: " << split;
197 std::cerr <<
" (" << cmin[D] <<
" - " << cmax[D] <<
")";
198 std::cerr << std::endl;
203 Index *top = &cells[start + size];
204 for (
Index *c = &cells[start]; c < top; ++c) {
205 const Scalar cent = centerD(*c);
206 const int b = getBucketD(cent);
207 if (b > best_bucket) {
210 other = centerD(*top);
211 const int bo = getBucketD(other);
212 if (bo < best_bucket + 1) {
226 for (
Index i = nleft; i < size; ++i) {
227 Index c = cells[start + i];
229 assert(cent[D] >= split);
230 assert(
min[c][D] >= Rmin);
231 for (
int i = 0; i < 3; ++i) {
232 assert(
min[c][i] >= gmin[i]);
233 assert(max[c][i] <= gmax[i]);
236 for (
Index i = 0; i < nleft; ++i) {
237 Index c = cells[start + i];
239 assert(cent[D] <= split);
240 assert(max[c][D] <= Lmax);
241 for (
int i = 0; i < 3; ++i) {
242 assert(
min[c][i] >= gmin[i]);
243 assert(max[c][i] <= gmax[i]);
248 Index l = nodes().size();
249 nodes().push_back(
Node(start, nleft));
251 Index r = nodes().size();
252 nodes().push_back(
Node(start + nleft, size - nleft));
254 assert(nodes()[l].size < size);
255 assert(nodes()[r].size < size);
256 assert(nodes()[l].size + nodes()[r].size == size);
262 nmin[best_dim] = bmin[0][best_dim];
263 nmax[best_dim] = bmax[best_bucket][best_dim];
264 refine(
min, max, l, nmin, nmax);
267 nmin[best_dim] = bmin[best_bucket + 1][best_dim];
268 nmax[best_dim] = bmax[NumBuckets - 1][best_dim];
269 refine(
min, max, r, nmin, nmax);
272template<
typename Scalar,
typename Index,
int NumDimensions>
273template<
class BoundsFunctor>
277 for (
int c = 0; c < NumDimensions; ++c) {
282 std::cerr <<
"validateCelltree: min=" << mmin <<
", max=" << mmax << std::endl;
284 return validateNode(boundFunc, 0, mmin, mmax);
287template<
typename Scalar,
typename Index,
int NumDimensions>
288template<
class BoundsFunctor>
293 const Index *cells = d()->m_cells->data();
294 const Node *node = &(nodes()[nodenum]);
295 if (node->isLeaf()) {
296 for (
Index i = node->start; i < node->start + node->size; ++i) {
297 const Index elem = cells[i];
299 boundFunc(elem, &emin, &emax);
300 for (
int d = 0; d < NumDimensions; ++d) {
301 if (emin[d] <
min[d]) {
302 std::cerr <<
"celltree node " << nodenum <<
" @" << i - node->start <<
" of " << node->size
303 <<
": min[" << d <<
"] violation on elem " << elem <<
": is " << emin <<
", should "
307 if (emax[d] > max[d]) {
308 std::cerr <<
"celltree node " << nodenum <<
" @" << i - node->start <<
" of " << node->size
309 <<
": max[" << d <<
"] violation on elem " << elem <<
": is " << emax <<
", should "
318 if (node->Lmax <
min[node->dim]) {
319 std::cerr <<
"celltree: Lmax=" << node->Lmax <<
" too small for dim=" << node->dim
320 <<
", should >= " <<
min[node->dim] << std::endl;
323 if (node->Rmin <
min[node->dim]) {
324 std::cerr <<
"celltree: Rmin=" << node->Rmin <<
" too small for dim=" << node->dim
325 <<
", should >= " <<
min[node->dim] << std::endl;
328 if (node->Lmax > max[node->dim]) {
329 std::cerr <<
"celltree: Lmax=" << node->Lmax <<
" too large for dim=" << node->dim
330 <<
", should <= " << max[node->dim] << std::endl;
333 if (node->Rmin > max[node->dim]) {
334 std::cerr <<
"celltree: Rmin=" << node->Rmin <<
" too large for dim=" << node->dim
335 <<
", should <= " << max[node->dim] << std::endl;
340 lmax[node->dim] = node->Lmax;
341 rmin[node->dim] = node->Rmin;
343 if (!validateNode(boundFunc, node->left(),
min, lmax))
345 if (!validateNode(boundFunc, node->right(), rmin, max))
350template<
class Scalar,
class Index,
int NumDimensions>
351template<
class Archive>
354 assert(
"serialization of Celltree::Node not implemented" == 0);
357template<
typename Scalar,
typename Index,
int NumDimensions>
364template<
typename Scalar,
typename Index,
int NumDimensions>
370template<
typename Scalar,
typename Index,
int NumDimensions>
376template<
typename Scalar,
typename Index,
int NumDimensions>
379 return d()->m_nodes->empty() || d()->m_cells->empty();
382template<
typename Scalar,
typename Index,
int NumDimensions>
385 return d()->m_nodes->empty() || d()->m_cells->empty();
388template<
typename Scalar,
typename Index,
int NumDimensions>
389bool Celltree<Scalar, Index, NumDimensions>::checkImpl()
const
391 V_CHECK(d()->m_nodes->size() >= 1);
392 V_CHECK(d()->m_nodes->size() <= d()->m_cells->size());
393 if ((*d()->m_nodes)[0].isLeaf()) {
394 V_CHECK((*d()->m_nodes)[0].size <= d()->m_cells->size());
396 V_CHECK((*d()->m_nodes)[0].Lmax >= (*d()->m_nodes)[0].Rmin);
401template<
typename Scalar,
typename Index,
int NumDimensions>
402void Celltree<Scalar, Index, NumDimensions>::Data::initData()
404 const Scalar smax = std::numeric_limits<Scalar>::max();
405 for (
int d = 0; d < NumDimensions; ++d) {
407 m_bounds[NumDimensions + d] = -smax;
410 m_nodes.construct(1);
411 (*m_nodes)[0] = Node(0, 0);
414template<
typename Scalar,
typename Index,
int NumDimensions>
415Celltree<Scalar, Index, NumDimensions>::Data::Data(
const Data &o,
const std::string &n)
416: Celltree::Base::Data(o, n), m_cells(o.m_cells), m_nodes(o.m_nodes)
418 memcpy(m_bounds, o.m_bounds,
sizeof(m_bounds));
421template<
typename Scalar,
typename Index,
int NumDimensions>
422Celltree<Scalar, Index, NumDimensions>::Data::Data(
const std::string &name,
const Index numCells,
const Meta &meta)
423: Base::Data(Object::Type(Object::CELLTREE1 - 1 + NumDimensions), name, meta)
427 m_cells.construct(numCells);
430 for (
Index i = 0; i < numCells; ++i) {
434 (*m_nodes)[0] =
Node(0, numCells);
437template<
typename Scalar,
typename Index,
int NumDimensions>
451template<
typename Scalar,
typename Index,
int NumDimensions>
452Celltree<Scalar, Index, NumDimensions>::Data::Data(
Object::Type id,
const std::string &name,
const Meta &meta)
453: Base::Data(id, name, meta)
458template<
typename Scalar,
typename Index,
int NumDimensions>
460Celltree<Scalar, Index, NumDimensions>::Data::createNamed(
Object::Type id,
const std::string &name)
compute bounding box of a cell
Definition: celltree.h:78
Definition: celltree.h:31
void refine(const Vector *min, const Vector *max, Index nodeIdx, const Vector &gmin, const Vector &gmax)
Definition: celltree_impl.h:58
shm< Index >::array & cells()
Definition: celltree.h:99
VistleScalarVector< NumDimensions >::type Vector
Definition: celltree.h:37
CelltreeNode< sizeof(Index), NumDimensions > Node
Definition: celltree.h:38
bool validateTree(BoundsFunctor &func) const
Definition: celltree_impl.h:274
void init(const Vector *min, const Vector *max, const Vector &gmin, const Vector &gmax)
Definition: celltree_impl.h:24
Celltree(const Index numCells, const Meta &meta=Meta())
Definition: celltree_impl.h:358
virtual bool isEmpty() const
Definition: object.cpp:349
ObjectData Data
Definition: object.h:69
Type
Definition: object.h:84
@ CELLTREE1
Definition: object.h:109
std::string createObjectId(const std::string &name="")
Definition: shm.cpp:435
static Shm & the()
Definition: shm.cpp:315
#define V_COREEXPORT
Definition: export.h:9
void serialize(Archive &ar, vistle::Vector1 &v, const unsigned int version)
Definition: vector.h:105
static T min(T a, T b)
Definition: messages.cpp:28
Definition: allobjects.cpp:30
const unsigned MaxLeafSize
Definition: celltree_impl.h:11
Vector3 Vector
Definition: vector.h:36
float Scalar
Definition: scalar.h:14
uint32_t Index
Definition: index.h:13
Definition: celltree.h:20
#define V_OBJECT_CREATE_NAMED(ObjType)
Definition: object.h:542
#define V_CHECK(true_expr)
use in checkImpl
Definition: object.h:368
Meta meta
Definition: object.h:238
static ObjectData * create(Object::Type id, const std::string &name, const Meta &m)
Definition: object.cpp:244
const shm_name_t name
Definition: shmdata.h:41
static managed_shm::segment_manager::template construct_proxy< T >::type construct(const std::string &name)
Definition: shm_impl.h:87