00001 #include "megatree/tree_functions.h"
00002 #include <boost/bind.hpp>
00003 #include <megatree/common.h>
00004
00005
00006 namespace megatree
00007 {
00008
00009 void dumpTimers()
00010 {
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 }
00024
00025 void addPointRecursive(MegaTree& tree, NodeHandle& node,
00026 const double* pt, const double* color,
00027 double point_accuracy)
00028 {
00029
00030 double node_cell_size = node.getNodeGeometry().getSize();
00031
00032
00033 if (node.isEmpty() && point_accuracy >= node_cell_size / BITS_D)
00034 {
00035 node.setPoint(pt, color);
00036 return;
00037 }
00038
00039
00040 if (node_cell_size < tree.getMinCellSize())
00041 {
00042 node.addPoint(pt, color);
00043 return;
00044 }
00045
00046
00047
00048 if (!node.isEmpty() && node.isLeaf())
00049 {
00050
00051 uint8_t original_child = node.getChildForNodePoint();
00052
00053
00054 NodeHandle new_leaf;
00055 tree.createChildNode(node, original_child, new_leaf);
00056
00057
00058 node.getNode()->copyToChildNode(original_child, new_leaf.getNode());
00059 tree.releaseNode(new_leaf);
00060 }
00061
00062
00063 uint8_t new_child = node.getNodeGeometry().whichChild(pt);
00064 NodeHandle new_child_node;
00065 if (node.hasChild(new_child)) {
00066
00067 tree.getChildNode(node, new_child, new_child_node);
00068 new_child_node.waitUntilLoaded();
00069
00070 }
00071 else {
00072
00073 tree.createChildNode(node, new_child, new_child_node);
00074
00075 }
00076
00077
00078 addPointRecursive(tree, new_child_node, pt, color, point_accuracy);
00079
00080 tree.releaseNode(new_child_node);
00081
00082
00083 MegaTree::ChildIterator it(tree, node, new_child_node.getNodeFile());
00084 node.copyFromChildNodes(it.getAllChildren());
00085 }
00086
00087
00088
00089
00090
00091
00092 void addPoint(MegaTree& tree, const std::vector<double>& pt, const std::vector<double>& col)
00093 {
00094
00095 if (!tree.getRootGeometry().contains(pt))
00096 {
00097 fprintf(stderr, "Point (%lf, %lf, %lf) is out of tree bounds (%lf, %lf, %lf)--(%lf, %lf, %lf)\n",
00098 pt[0], pt[1], pt[2],
00099 tree.getRootGeometry().getLo(0), tree.getRootGeometry().getLo(1), tree.getRootGeometry().getLo(2),
00100 tree.getRootGeometry().getHi(0), tree.getRootGeometry().getHi(1), tree.getRootGeometry().getHi(2));
00101 return;
00102 }
00103
00104 NodeHandle root;
00105 tree.getRoot(root);
00106
00107 addPointRecursive(tree, root, &pt[0], &col[0], tree.getMinCellSize());
00108
00109
00110 tree.releaseNode(root);
00111 }
00112
00113
00114
00115
00116 void TreeFastCache::addPoint(std::vector<double> &pt, const std::vector<double>& col)
00117 {
00118
00119 while (!top().nh->getNodeGeometry().contains(pt))
00120 pop();
00121
00122
00123 this->addPointRecursive(&pt[0], &col[0], tree.getMinCellSize());
00124 }
00125
00126
00127 void TreeFastCache::addPointRecursive(const double pt[3], const double color[3], double point_accuracy)
00128 {
00129 NodeHandle* nh = top().nh;
00130 assert(nh);
00131 double node_cell_size = nh->getNodeGeometry().getSize();
00132
00133
00134 if (nh->isEmpty() && point_accuracy >= node_cell_size / BITS_D)
00135 {
00136 nh->setPoint(pt, color);
00137 return;
00138 }
00139
00140
00141 if (node_cell_size < tree.getMinCellSize())
00142 {
00143 nh->addPoint(pt, color);
00144 return;
00145 }
00146
00147
00148
00149 if (!nh->isEmpty() && nh->isLeaf())
00150 {
00151
00152 uint8_t original_child = nh->getChildForNodePoint();
00153 NodeHandle new_leaf;
00154 tree.createChildNode(*nh, original_child, new_leaf);
00155
00156 nh->getNode()->copyToChildNode(original_child, new_leaf.getNode());
00157 tree.releaseNode(new_leaf);
00158 }
00159
00160
00161 uint8_t new_child = nh->getNodeGeometry().whichChild(pt);
00162 NodeHandle* new_child_nh = NULL;
00163 if (nh->hasChild(new_child)) {
00164 new_child_nh = tree.getChildNode(*nh, new_child);
00165 new_child_nh->waitUntilLoaded();
00166 }
00167 else {
00168 new_child_nh = tree.createChildNode(*nh, new_child);
00169 }
00170
00171
00172 push(NodeCache(new_child_nh));
00173
00174 addPointRecursive(pt, color, point_accuracy);
00175 }
00176
00177
00178
00179 void queryRangeIntersecting(MegaTree &tree, NodeHandle& node,
00180 const double* range_mid, const double* range_size,
00181 std::vector<double> &results, std::vector<double> &colors)
00182 {
00183
00184
00185
00186
00187
00188
00189 assert(!node.isEmpty());
00190 double point[3];
00191 node.getPoint(point);
00192
00193 if (point[0] >= range_mid[0] - range_size[0]/2 &&
00194 point[0] < range_mid[0] + range_size[0]/2 &&
00195 point[1] >= range_mid[1] - range_size[1]/2 &&
00196 point[1] < range_mid[1] + range_size[1]/2 &&
00197 point[2] >= range_mid[2] - range_size[2]/2 &&
00198 point[2] < range_mid[2] + range_size[2]/2)
00199 {
00200 results.push_back(point[0]);
00201 results.push_back(point[1]);
00202 results.push_back(point[2]);
00203
00204 double color[3];
00205 node.getColor(color);
00206 colors.push_back(color[0]);
00207 colors.push_back(color[1]);
00208 colors.push_back(color[2]);
00209 }
00210 }
00211
00212
00213
00214 void getAllPointsRecursive(MegaTree &tree, NodeHandle& node, double resolution, std::vector<double> &results, std::vector<double> &colors)
00215 {
00216
00217
00218
00219 assert(!node.isEmpty());
00220
00221
00222 if (node.isLeaf() || node.getNodeGeometry().getSize() <= resolution)
00223 {
00224 double point[3];
00225 node.getPoint(point);
00226 results.push_back(point[0]);
00227 results.push_back(point[1]);
00228 results.push_back(point[2]);
00229
00230 double color[3];
00231 node.getColor(color);
00232 colors.push_back(color[0]);
00233 colors.push_back(color[1]);
00234 colors.push_back(color[2]);
00235 }
00236
00237
00238 else
00239 {
00240 for (MegaTree::ChildIterator it(tree, node); !it.finished(); it.next())
00241 {
00242 getAllPointsRecursive(tree, it.getChildNode(), resolution, results, colors);
00243 }
00244 }
00245 }
00246
00247
00248 bool nodeOutsideRange(const NodeGeometry& node_geom, const double* range_mid, const double* range_size)
00249 {
00250 return
00251 node_geom.getHi(0) <= (range_mid[0] - range_size[0]/2) || node_geom.getLo(0) >= (range_mid[0] + range_size[0]/2) ||
00252 node_geom.getHi(1) <= (range_mid[1] - range_size[1]/2) || node_geom.getLo(1) >= (range_mid[1] + range_size[1]/2) ||
00253 node_geom.getHi(2) <= (range_mid[2] - range_size[2]/2) || node_geom.getLo(2) >= (range_mid[2] + range_size[2]/2);
00254 }
00255
00256 bool nodeInsideRange(const NodeGeometry& node_geom, const double* range_mid, const double* range_size)
00257 {
00258 return
00259 (range_mid[0] - range_size[0]/2) <= node_geom.getLo(0) && node_geom.getHi(0) <= (range_mid[0] + range_size[0]/2) &&
00260 (range_mid[1] - range_size[1]/2) <= node_geom.getLo(1) && node_geom.getHi(1) <= (range_mid[1] + range_size[1]/2) &&
00261 (range_mid[2] - range_size[2]/2) <= node_geom.getLo(2) && node_geom.getHi(2) <= (range_mid[2] + range_size[2]/2);
00262 }
00263
00264
00265 void queryRangeRecursive(MegaTree &tree, NodeHandle& node,
00266 const double* range_mid, const double* range_size,
00267 double resolution, std::vector<double> &results, std::vector<double> &colors)
00268 {
00269
00270
00271
00272
00273
00274
00275
00276 if (nodeOutsideRange(node.getNodeGeometry(), range_mid, range_size))
00277 {
00278
00279 }
00280 else if (nodeInsideRange(node.getNodeGeometry(), range_mid, range_size))
00281 {
00282
00283 getAllPointsRecursive(tree, node, resolution, results, colors);
00284 }
00285
00286
00287 else
00288 {
00289
00290 if (node.isLeaf() || node.getNodeGeometry().getSize() <= resolution)
00291 {
00292 queryRangeIntersecting(tree, node, range_mid, range_size, results, colors);
00293 }
00294
00295 else
00296 {
00297 for (MegaTree::ChildIterator it(tree, node); !it.finished(); it.next())
00298 {
00299
00300 queryRangeRecursive(tree, it.getChildNode(), range_mid, range_size, resolution, results, colors);
00301 }
00302 }
00303 }
00304 }
00305
00306
00307
00308 void queryRange(MegaTree &tree, const std::vector<double>& lo, const std::vector<double>&hi,
00309 double resolution, std::vector<double> &results, std::vector<double> &colors)
00310 {
00311 if (results.size() > 0)
00312 fprintf(stderr, "Warning: called queryRange with non-empty results\n");
00313
00314 NodeHandle root;
00315 tree.getRoot(root);
00316 double range_mid[3];
00317 range_mid[0] = (hi[0] + lo[0])/2;
00318 range_mid[1] = (hi[1] + lo[1])/2;
00319 range_mid[2] = (hi[2] + lo[2])/2;
00320 double range_size[3];
00321 range_size[0] = hi[0] - lo[0];
00322 range_size[1] = hi[1] - lo[1];
00323 range_size[2] = hi[2] - lo[2];
00324
00325 queryRangeRecursive(tree, root, range_mid, range_size, resolution, results, colors);
00326 tree.releaseNode(root);
00327 }
00328
00329
00330
00331
00332
00333 void numChildren(MegaTree& tree, NodeHandle& node, unsigned count_cutoff, unsigned& num_children, unsigned& count)
00334 {
00335 printf("Node %s\n", node.toString().c_str());
00336 if (node.getCount() >= count_cutoff)
00337 {
00338 int this_count = 0;
00339 for (MegaTree::ChildIterator it(tree, node); !it.finished(); it.next())
00340 {
00341 numChildren(tree, it.getChildNode(), count_cutoff, num_children, count);
00342 this_count++;
00343 }
00344 count++;
00345
00346
00347 num_children += this_count;
00348 }
00349 }
00350
00351 static int process_queue_size = 0;
00352 void getAllPointsRecursiveAsync(MegaTree &tree, NodeHandle& node, double resolution,
00353 std::vector<double> &results, std::vector<double> &colors, megatree::List<NodeHandle*>& nodes_to_load)
00354 {
00355
00356
00357
00358 assert(!node.isEmpty());
00359
00360
00361 if (node.isLeaf() || node.getNodeGeometry().getSize() <= resolution)
00362 {
00363 double point[3];
00364 node.getPoint(point);
00365 results.push_back(point[0]);
00366 results.push_back(point[1]);
00367 results.push_back(point[2]);
00368
00369 double color[3];
00370 node.getColor(color);
00371 colors.push_back(color[0]);
00372 colors.push_back(color[1]);
00373 colors.push_back(color[2]);
00374 }
00375
00376
00377 else
00378 {
00379 for(int i = 0; i < 8; ++i)
00380 {
00381 if(node.hasChild(i))
00382 {
00383 megatree::NodeHandle* child = new megatree::NodeHandle;
00384 tree.getChildNode(node, i, *child);
00385
00386
00387 if(!child->isValid())
00388 {
00389 nodes_to_load.push_back(child);
00390 process_queue_size++;
00391 }
00392 else
00393 {
00394 getAllPointsRecursiveAsync(tree, *child, resolution, results, colors, nodes_to_load);
00395 tree.releaseNode(*child);
00396 delete child;
00397 }
00398 }
00399 }
00400 }
00401 }
00402
00403 void queryRangeRecursiveAsync(MegaTree &tree, NodeHandle& node,
00404 const double* range_mid, const double* range_size, double resolution,
00405 std::vector<double> &results, std::vector<double> &colors, megatree::List<NodeHandle*>& nodes_to_load)
00406 {
00407
00408
00409
00410
00411
00412
00413
00414 if (nodeOutsideRange(node.getNodeGeometry(), range_mid, range_size))
00415 {
00416
00417 }
00418 else if (nodeInsideRange(node.getNodeGeometry(), range_mid, range_size))
00419 {
00420
00421 getAllPointsRecursiveAsync(tree, node, resolution, results, colors, nodes_to_load);
00422 }
00423
00424
00425 else
00426 {
00427
00428 if (node.isLeaf() || node.getNodeGeometry().getSize() <= resolution)
00429 {
00430 queryRangeIntersecting(tree, node, range_mid, range_size, results, colors);
00431 }
00432
00433 else
00434 {
00435
00436 for(int i = 0; i < 8; ++i)
00437 {
00438 if(node.hasChild(i))
00439 {
00440 megatree::NodeHandle* child = new megatree::NodeHandle;
00441 tree.getChildNode(node, i, *child);
00442
00443
00444 if(!child->isValid())
00445 {
00446 nodes_to_load.push_back(child);
00447 process_queue_size++;
00448 }
00449 else
00450 {
00451 queryRangeRecursiveAsync(tree, *child, range_mid, range_size, resolution, results, colors, nodes_to_load);
00452 tree.releaseNode(*child);
00453 delete child;
00454 }
00455 }
00456 }
00457 }
00458 }
00459 }
00460
00461 void rangeQueryLoop(MegaTree& tree, std::vector<double> lo, std::vector<double> hi, double resolution, std::vector<double>& results, std::vector<double>& colors)
00462 {
00463 megatree::List<NodeHandle*> process_queue;
00464
00465 megatree::NodeHandle* root = new megatree::NodeHandle;
00466 tree.getRoot(*root);
00467 assert(root->isValid());
00468 process_queue.push_back(root);
00469 process_queue_size = 1;
00470
00471 double range_mid[3];
00472 range_mid[0] = (hi[0] + lo[0])/2;
00473 range_mid[1] = (hi[1] + lo[1])/2;
00474 range_mid[2] = (hi[2] + lo[2])/2;
00475 double range_size[3];
00476 range_size[0] = hi[0] - lo[0];
00477 range_size[1] = hi[1] - lo[1];
00478 range_size[2] = hi[2] - lo[2];
00479
00480 while(!process_queue.empty())
00481 {
00482 megatree::NodeHandle* node_to_process = process_queue.front();
00483
00484
00485 if(!node_to_process->isValid())
00486 {
00487 process_queue.moveToBack(process_queue.getFrontPointer());
00488 node_to_process = NULL;
00489
00490 }
00491 else
00492 {
00493 megatree::List<NodeHandle*> nodes_to_load;
00494 queryRangeRecursiveAsync(tree, *node_to_process, range_mid, range_size, resolution, results, colors, nodes_to_load);
00495 process_queue.pop_front();
00496 process_queue_size--;
00497 tree.releaseNode(*node_to_process);
00498 delete node_to_process;
00499 process_queue.spliceToBack(nodes_to_load);
00500
00501 }
00502 }
00503 }
00504
00505
00506 }