tree_functions.cpp
Go to the documentation of this file.
00001 #include "megatree/tree_functions.h"
00002 #include <boost/bind.hpp>
00003 #include <megatree/common.h>  // For the timers
00004 
00005 
00006 namespace megatree
00007 {
00008 //PausingTimer overall_add_timer, getnode_timer, create_leaf_timer, create_node_timer;
00009 void dumpTimers()
00010 {
00011   /*
00012     printf("Overall:      %8.3f\n", overall_add_timer.getElapsed());
00013     printf("getNode:      %8.3f\n", getnode_timer.getElapsed());
00014     printf("create leaf:  %8.3f\n", create_leaf_timer.getElapsed());
00015     printf("create node:  %8.3f\n", create_node_timer.getElapsed());
00016     printf("unknown:      %8.3f\n", overall_add_timer.getElapsed() -
00017     (create_node_timer.getElapsed() + getnode_timer.getElapsed() + create_leaf_timer.getElapsed()));
00018     overall_add_timer.reset();
00019     getnode_timer.reset();
00020     create_leaf_timer.reset();
00021     create_node_timer.reset();
00022   */
00023 }
00024 
00025 void addPointRecursive(MegaTree& tree, NodeHandle& node, 
00026                        const double* pt, const double* color,
00027                        double point_accuracy)
00028 {
00029   //printf("Adding point %f %f %f to node %s\n", pt[0], pt[1], pt[2], node.toString().c_str());
00030   double node_cell_size = node.getNodeGeometry().getSize();
00031 
00032   // adds point to empty node
00033   if (node.isEmpty() && point_accuracy >= node_cell_size / BITS_D)
00034   {
00035     node.setPoint(pt, color);
00036     return;
00037   }
00038     
00039   // reached maximum resultion of the tree
00040   if (node_cell_size < tree.getMinCellSize())
00041   {
00042     node.addPoint(pt, color);
00043     return;
00044   }
00045 
00046 
00047   // this node is a leaf, and we need to copy the original point one level down
00048   if (!node.isEmpty() && node.isLeaf())
00049   {
00050     // Determines which child the point should be added to.
00051     uint8_t original_child = node.getChildForNodePoint();
00052 
00053     //create_leaf_timer.start();
00054     NodeHandle new_leaf;
00055     tree.createChildNode(node, original_child, new_leaf);
00056     //create_leaf_timer.pause();
00057 
00058     node.getNode()->copyToChildNode(original_child, new_leaf.getNode());
00059     tree.releaseNode(new_leaf);
00060   }
00061 
00062   // Gets the child node to recurse on.
00063   uint8_t new_child = node.getNodeGeometry().whichChild(pt);
00064   NodeHandle new_child_node;
00065   if (node.hasChild(new_child)) {
00066     //getnode_timer.start();
00067     tree.getChildNode(node, new_child, new_child_node);
00068     new_child_node.waitUntilLoaded();
00069     //getnode_timer.pause();
00070   }
00071   else {
00072     //create_node_timer.start();
00073     tree.createChildNode(node, new_child, new_child_node);
00074     //create_node_timer.pause();
00075   }
00076 
00077   // recursion to add point to child
00078   addPointRecursive(tree, new_child_node, pt, color, point_accuracy);
00079 
00080   tree.releaseNode(new_child_node);
00081 
00082   // Re-computes the summary point.
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   // check tree bounds
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   //overall_add_timer.start();
00107   addPointRecursive(tree, root, &pt[0], &col[0], tree.getMinCellSize());
00108   //overall_add_timer.pause();
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   // go through nodes to find closest node
00119   while (!top().nh->getNodeGeometry().contains(pt))
00120     pop();
00121 
00122   // add point 
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   // adds point to empty node
00134   if (nh->isEmpty() && point_accuracy >= node_cell_size / BITS_D)
00135   {
00136     nh->setPoint(pt, color);
00137     return;
00138   }
00139     
00140   // reached maximum resultion of the tree
00141   if (node_cell_size < tree.getMinCellSize())
00142   {
00143     nh->addPoint(pt, color);
00144     return;
00145   }
00146 
00147 
00148   // this node is a leaf, and we need to copy the original point one level down
00149   if (!nh->isEmpty() && nh->isLeaf())
00150   {
00151     // Determines which child the point should be added to.
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   // Gets the child node to recurse on.
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   // recursion to add point to child
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     printf("Query range node for node %s with frame offset %f %f %f, range mid %f %f %f and size %f %f %f\n",
00185     node.getId().toString().c_str(), frame_offset[0], frame_offset[1], frame_offset[2],
00186     range_mid[0], range_mid[1], range_mid[2], range_size[0], range_size[1], range_size[2]);
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 // frame_offset
00214 void getAllPointsRecursive(MegaTree &tree, NodeHandle& node, double resolution, std::vector<double> &results, std::vector<double> &colors)
00215 {
00216   //printf("Get all points recursive for node %s with frame offset %f %f %f\n",
00217   //       node.getId().toString().c_str(), frame_offset[0], frame_offset[1], frame_offset[2]);
00218 
00219   assert(!node.isEmpty());
00220 
00221   // we hit a leaf
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   // need to descend further
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     printf("Query recursive for node %s with %f points frame offset %f %f %f, range mid %f %f %f and size %f %f %f\n",
00271     node.getId().toString().c_str(), node.getCount(), frame_offset[0], frame_offset[1], frame_offset[2],
00272     range_mid[0], range_mid[1], range_mid[2], range_size[0], range_size[1], range_size[2]); 
00273   */
00274 
00275   // If the query range is outside of the node.
00276   if (nodeOutsideRange(node.getNodeGeometry(), range_mid, range_size))
00277   {
00278     // Completely outside.  Stop
00279   }
00280   else if (nodeInsideRange(node.getNodeGeometry(), range_mid, range_size)) 
00281   {
00282     // Completely inside
00283     getAllPointsRecursive(tree, node, resolution, results, colors);
00284   }
00285 
00286   // Partially intersecting
00287   else 
00288   { 
00289     // node is leaf
00290     if (node.isLeaf() || node.getNodeGeometry().getSize() <= resolution)
00291     {  
00292       queryRangeIntersecting(tree, node, range_mid, range_size, results, colors);
00293     }
00294     // node is not a leaf
00295     else   
00296     {
00297       for (MegaTree::ChildIterator it(tree, node); !it.finished(); it.next())
00298       {
00299         // recurse to child
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     //printf("Call numchildren on node %s\n", node.toString().c_str());
00346     //printf("This count %d\n", this_count);
00347     num_children += this_count;
00348   }
00349 }
00350 
00351 static int process_queue_size = 0;  // TODO: For debugging, remove eventually
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   //printf("Get all points recursive for node %s with frame offset %f %f %f\n",
00356   //       node.getId().toString().c_str(), frame_offset[0], frame_offset[1], frame_offset[2]);
00357 
00358   assert(!node.isEmpty());
00359 
00360   // we hit a leaf
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   // need to descend further
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         //if the child isn't valid, we'll push it onto our nodes to load list
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      printf("Query recursive for node %s with %f points frame offset %f %f %f, range mid %f %f %f and size %f %f %f\n",
00409      node.getId().toString().c_str(), node.getCount(), frame_offset[0], frame_offset[1], frame_offset[2],
00410      range_mid[0], range_mid[1], range_mid[2], range_size[0], range_size[1], range_size[2]); 
00411      */
00412 
00413   // If the query range is outside of the node.
00414   if (nodeOutsideRange(node.getNodeGeometry(), range_mid, range_size))
00415   {
00416     // Completely outside.  Stop
00417   }
00418   else if (nodeInsideRange(node.getNodeGeometry(), range_mid, range_size)) 
00419   {
00420     // Completely inside
00421     getAllPointsRecursiveAsync(tree, node, resolution, results, colors, nodes_to_load);
00422   }
00423 
00424   // Partially intersecting
00425   else 
00426   { 
00427     // node is leaf
00428     if (node.isLeaf() || node.getNodeGeometry().getSize() <= resolution)
00429     {  
00430       queryRangeIntersecting(tree, node, range_mid, range_size, results, colors);
00431     }
00432     // node is not a leaf
00433     else   
00434     {
00435       // recurse to child if we can
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           //if the child isn't valid, we'll push it onto our nodes to load list
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     //if the node isn't valid yet, we'll just move it to the back of the queue.
00485     if(!node_to_process->isValid())
00486     {
00487       process_queue.moveToBack(process_queue.getFrontPointer());
00488       node_to_process = NULL;
00489       //printf("%d\n", process_queue_size);
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       //printf("#%d\n", process_queue_size);
00501     }
00502   }
00503 }
00504 
00505 
00506 }


megatree_cpp
Author(s): Stuart Glaser
autogenerated on Thu Nov 28 2013 11:30:34