41#ifndef PCL_OUTOFCORE_OCTREE_BASE_NODE_IMPL_H_
42#define PCL_OUTOFCORE_OCTREE_BASE_NODE_IMPL_H_
53#include <pcl/common/utils.h>
54#include <pcl/visualization/common/common.h>
55#include <pcl/outofcore/octree_base_node.h>
56#include <pcl/filters/random_sample.h>
57#include <pcl/filters/extract_indices.h>
60#include <pcl/pcl_config.h>
61#if defined(HAVE_CJSON)
62#include <cjson/cJSON.h>
64#include <pcl/outofcore/cJSON.h>
72 template<
typename ContainerT,
typename Po
intT>
75 template<
typename ContainerT,
typename Po
intT>
78 template<
typename ContainerT,
typename Po
intT>
81 template<
typename ContainerT,
typename Po
intT>
84 template<
typename ContainerT,
typename Po
intT>
87 template<
typename ContainerT,
typename Po
intT>
90 template<
typename ContainerT,
typename Po
intT>
93 template<
typename ContainerT,
typename Po
intT>
96 template<
typename ContainerT,
typename Po
intT>
113 template<
typename ContainerT,
typename Po
intT>
128 if (super ==
nullptr)
130 node_metadata_->setDirectoryPathname (directory_path.parent_path ());
136 if (!boost::filesystem::exists (
node_metadata_->getDirectoryPathname ()))
138 PCL_ERROR (
"[pcl::outofcore::OutofcoreOctreeBaseNode] Could not find dir %s\n",
node_metadata_->getDirectoryPathname ().c_str ());
139 PCL_THROW_EXCEPTION (
PCLException,
"[pcl::outofcore::OutofcoreOctreeBaseNode] Outofcore Exception: missing directory");
148 boost::filesystem::directory_iterator directory_it_end;
151 bool b_loaded =
false;
153 for (boost::filesystem::directory_iterator directory_it (
node_metadata_->getDirectoryPathname ()); directory_it != directory_it_end; ++directory_it)
155 const boost::filesystem::path& file = *directory_it;
157 if (!boost::filesystem::is_directory (file))
169 PCL_ERROR (
"[pcl::outofcore::OutofcoreOctreeBaseNode] Could not find index\n");
170 PCL_THROW_EXCEPTION (
PCLException,
"[pcl::outofcore::OutofcoreOctreeBaseNode] Outofcore: Could not find node index");
187 template<
typename ContainerT,
typename Po
intT>
199 assert (tree !=
nullptr);
206 template<
typename ContainerT,
typename Po
intT>
void
209 assert (tree !=
nullptr);
219 Eigen::Vector3d tmp_max = bb_max;
222 double epsilon = 1e-8;
223 tmp_max += epsilon*Eigen::Vector3d (1.0, 1.0, 1.0);
230 if (!boost::filesystem::exists (
node_metadata_->getDirectoryPathname ()))
232 boost::filesystem::create_directory (
node_metadata_->getDirectoryPathname ());
235 else if (!boost::filesystem::is_directory (
node_metadata_->getDirectoryPathname ()))
237 PCL_ERROR (
"[pcl::outofcore::OutofcoreOctreeBaseNode] Need empty directory structure. Dir %s exists and is a file.\n",
node_metadata_->getDirectoryPathname ().c_str ());
238 PCL_THROW_EXCEPTION (
PCLException,
"[pcl::outofcore::OutofcoreOctreeBaseNode] Bad Path: Directory Already Exists");
246 std::string node_container_name;
253 boost::filesystem::create_directory (
node_metadata_->getDirectoryPathname ());
262 template<
typename ContainerT,
typename Po
intT>
271 template<
typename ContainerT,
typename Po
intT> std::size_t
274 std::size_t child_count = 0;
276 for(std::size_t i=0; i<8; i++)
278 boost::filesystem::path child_path = this->
node_metadata_->getDirectoryPathname () / boost::filesystem::path (std::to_string(i));
279 if (boost::filesystem::exists (child_path))
282 return (child_count);
287 template<
typename ContainerT,
typename Po
intT>
void
294 for (std::size_t i = 0; i < 8; i++)
304 template<
typename ContainerT,
typename Po
intT>
bool
311 template<
typename ContainerT,
typename Po
intT>
void
318 for (
int i = 0; i < 8; i++)
320 boost::filesystem::path child_dir =
node_metadata_->getDirectoryPathname () / boost::filesystem::path (std::to_string(i));
322 if (boost::filesystem::exists (child_dir) && this->
children_[i] ==
nullptr)
335 template<
typename ContainerT,
typename Po
intT>
void
343 for (std::size_t i = 0; i < 8; i++)
352 template<
typename ContainerT,
typename Po
intT> std::uint64_t
368 std::vector < std::vector<const PointT*> > c;
370 for (std::size_t i = 0; i < 8; i++)
372 c[i].reserve (p.size () / 8);
375 const std::size_t len = p.size ();
376 for (std::size_t i = 0; i < len; i++)
378 const PointT& pt = p[i];
384 PCL_ERROR (
"[pcl::outofcore::OutofcoreOctreeBaseNode::%s] Failed to place point within bounding box\n", __FUNCTION__ );
389 std::uint8_t box = 0;
392 box =
static_cast<std::uint8_t
>(((pt.z >= mid_xyz[2]) << 2) | ((pt.y >= mid_xyz[1]) << 1) | ((pt.x >= mid_xyz[0]) << 0));
393 c[
static_cast<std::size_t
>(box)].push_back (&pt);
396 std::uint64_t points_added = 0;
397 for (std::size_t i = 0; i < 8; i++)
403 points_added +=
children_[i]->addDataToLeaf (c[i],
true);
406 return (points_added);
411 template<
typename ContainerT,
typename Po
intT> std::uint64_t
426 payload_->insertRange (p.data (), p.size ());
431 std::vector<const PointT*> buff;
432 for (
const PointT* pt : p)
443 payload_->insertRange (buff.data (), buff.size ());
447 return (buff.size ());
455 std::vector < std::vector<const PointT*> > c;
457 for (std::size_t i = 0; i < 8; i++)
459 c[i].reserve (p.size () / 8);
462 const std::size_t len = p.size ();
463 for (std::size_t i = 0; i < len; i++)
475 std::uint8_t box = 00;
478 box =
static_cast<std::uint8_t
> (((p[i]->z >= mid_xyz[2]) << 2) | ((p[i]->y >= mid_xyz[1]) << 1) | ((p[i]->x >= mid_xyz[0] )));
480 c[box].push_back (p[i]);
483 std::uint64_t points_added = 0;
484 for (std::size_t i = 0; i < 8; i++)
490 points_added +=
children_[i]->addDataToLeaf (c[i],
true);
493 return (points_added);
498 template<
typename ContainerT,
typename Po
intT> std::uint64_t
501 assert (this->
root_node_->m_tree_ !=
nullptr);
503 if (input_cloud->height*input_cloud->width == 0)
518 std::vector < pcl::Indices > indices;
523 for(std::size_t k=0; k<indices.size (); k++)
525 PCL_DEBUG (
"[pcl::outofcore::OutofcoreOctreeBaseNode::%s] Computed %d indices in octact %d\n", __FUNCTION__, indices[k].
size (), k);
528 std::uint64_t points_added = 0;
530 for(std::size_t i=0; i<8; i++)
532 if ( indices[i].empty () )
542 PCL_DEBUG (
"[pcl::outofcore::OutofcoreOctreeBaseNode::%s] Extracting indices to bins\n", __FUNCTION__);
548 points_added +=
children_[i]->addPointCloud (dst_cloud,
false);
552 return (points_added);
555 PCL_ERROR (
"[pcl::outofcore::OutofcoreOctreeBaseNode] Skipped bounding box check. Points not inserted\n");
562 template<
typename ContainerT,
typename Po
intT>
void
565 assert (this->
root_node_->m_tree_ !=
nullptr);
570 for (
const PointT& pt: p)
574 sampleBuff.push_back(pt);
585 const auto samplesize =
static_cast<std::uint64_t
>(percent *
static_cast<double>(sampleBuff.size()));
586 const std::uint64_t inputsize = sampleBuff.size();
591 insertBuff.resize(samplesize);
595 std::uniform_int_distribution<std::uint64_t> buffdist(0, inputsize-1);
598 for(std::uint64_t i = 0; i < samplesize; ++i)
600 std::uint64_t buffstart = buffdist(
rng_);
601 insertBuff[i] = ( sampleBuff[buffstart] );
608 std::bernoulli_distribution buffdist(percent);
610 for(std::uint64_t i = 0; i < inputsize; ++i)
612 insertBuff.push_back( p[i] );
617 template<
typename ContainerT,
typename Po
intT> std::uint64_t
620 assert (this->
root_node_->m_tree_ !=
nullptr);
636 const std::size_t len = p.size ();
638 for (std::size_t i = 0; i < len; i++)
642 buff.push_back (p[i]);
651 return (buff.size ());
654 template<
typename ContainerT,
typename Po
intT> std::uint64_t
660 PCL_DEBUG (
"[pcl::outofcore::OutofcoreOctreeBaseNode::%s] Adding %u points at max depth, %u\n",__FUNCTION__, input_cloud->width*input_cloud->height, this->depth_);
662 this->
root_node_->m_tree_->incrementPointsInLOD (this->
depth_, input_cloud->width*input_cloud->height );
663 payload_->insertRange (input_cloud);
665 return (input_cloud->width*input_cloud->height);
667 PCL_ERROR (
"[pcl::outofcore::OutofcoreOctreeBaseNode] Not implemented\n");
673 template<
typename ContainerT,
typename Po
intT>
void
678 for(std::size_t i = 0; i < 8; i++)
679 c[i].reserve(p.size() / 8);
681 const std::size_t len = p.size();
682 for(std::size_t i = 0; i < len; i++)
684 const PointT& pt = p[i];
695 template<
typename ContainerT,
typename Po
intT>
void
699 std::size_t octant = 0;
700 octant = ((point.z >= mid_xyz[2]) << 2) | ((point.y >= mid_xyz[1]) << 1) | ((point.x >= mid_xyz[0]) << 0);
701 c[octant].push_back (point);
705 template<
typename ContainerT,
typename Po
intT> std::uint64_t
708 std::uint64_t points_added = 0;
710 if ( input_cloud->width * input_cloud->height == 0 )
715 if ( this->
depth_ == this->
root_node_->m_tree_->getDepth () || input_cloud->width*input_cloud->height < 8 )
718 assert (points_added > 0);
719 return (points_added);
739 std::uint64_t sample_size = input_cloud->width*input_cloud->height / 8;
740 random_sampler.
setSample (
static_cast<unsigned int> (sample_size));
747 random_sampler.
filter (*downsampled_cloud_indices);
752 extractor.
setIndices (downsampled_cloud_indices);
753 extractor.
filter (*downsampled_cloud);
758 extractor.
filter (*remaining_points);
760 PCL_DEBUG (
"[pcl::outofcore::OutofcoreOctreeBaseNode::%s] Random sampled: %lu of %lu\n", __FUNCTION__, downsampled_cloud->width * downsampled_cloud->height, input_cloud->width * input_cloud->height );
763 if ( downsampled_cloud->width * downsampled_cloud->height != 0 )
765 root_node_->m_tree_->incrementPointsInLOD ( this->
depth_, downsampled_cloud->width * downsampled_cloud->height );
766 payload_->insertRange (downsampled_cloud);
767 points_added += downsampled_cloud->width*downsampled_cloud->height ;
770 PCL_DEBUG (
"[pcl::outofcore::OutofcoreOctreeBaseNode::%s] Remaining points are %u\n",__FUNCTION__, remaining_points->width*remaining_points->height);
773 std::vector<pcl::Indices> indices;
779 for(std::size_t i=0; i<8; i++)
782 if(indices[i].empty ())
796 points_added +=
children_[i]->addPointCloud_and_genLOD (tmp_local_point_cloud);
797 PCL_DEBUG (
"[pcl::outofcore::OutofcoreOctreeBaseNode::%s] points_added: %lu, indices[i].size: %lu, tmp_local_point_cloud size: %lu\n", __FUNCTION__, points_added, indices[i].
size (), tmp_local_point_cloud->width*tmp_local_point_cloud->height);
800 assert (points_added == input_cloud->width*input_cloud->height);
801 return (points_added);
805 template<
typename ContainerT,
typename Po
intT> std::uint64_t
814 assert (this->
root_node_->m_tree_ !=
nullptr );
818 PCL_DEBUG (
"[pcl::outofcore::OutofcoreOctreeBaseNode::addDataToLeaf_and_genLOD] Adding data to the leaves\n");
830 if(!insertBuff.empty())
833 root_node_->m_tree_->incrementPointsInLOD (this->
depth_, insertBuff.size());
840 std::vector<AlignedPointTVector> c;
843 std::uint64_t points_added = 0;
844 for(std::size_t i = 0; i < 8; i++)
855 points_added +=
children_[i]->addDataToLeaf_and_genLOD(c[i],
true);
859 return (points_added);
863 template<
typename ContainerT,
typename Po
intT>
void
871 PCL_ERROR (
"[pcl::outofcore::OutofcoreOctreeBaseNode::createChild] Not allowed to create a 9th child of %s\n",this->
node_metadata_->getMetadataFilename ().c_str ());
876 Eigen::Vector3d step = (
node_metadata_->getBoundingBoxMax () - start)/
static_cast<double>(2.0);
878 Eigen::Vector3d childbb_min;
879 Eigen::Vector3d childbb_max;
884 x = ((idx == 5) || (idx == 7)) ? 1 : 0;
885 y = ((idx == 6) || (idx == 7)) ? 1 : 0;
890 x = ((idx == 1) || (idx == 3)) ? 1 : 0;
891 y = ((idx == 2) || (idx == 3)) ? 1 : 0;
895 childbb_min[2] = start[2] +
static_cast<double> (z) * step[2];
896 childbb_max[2] = start[2] +
static_cast<double> (z + 1) * step[2];
898 childbb_min[1] = start[1] +
static_cast<double> (y) * step[1];
899 childbb_max[1] = start[1] +
static_cast<double> (y + 1) * step[1];
901 childbb_min[0] = start[0] +
static_cast<double> (x) * step[0];
902 childbb_max[0] = start[0] +
static_cast<double> (x + 1) * step[0];
904 boost::filesystem::path childdir =
node_metadata_->getDirectoryPathname () / boost::filesystem::path (std::to_string(idx));
911 template<
typename ContainerT,
typename Po
intT>
bool
912 pointInBoundingBox (
const Eigen::Vector3d& min_bb,
const Eigen::Vector3d& max_bb,
const Eigen::Vector3d& point)
914 if (((min_bb[0] <= point[0]) && (point[0] < max_bb[0])) &&
915 ((min_bb[1] <= point[1]) && (point[1] < max_bb[1])) &&
916 ((min_bb[2] <= point[2]) && (point[2] < max_bb[2])))
926 template<
typename ContainerT,
typename Po
intT>
bool
929 const Eigen::Vector3d& min =
node_metadata_->getBoundingBoxMin ();
930 const Eigen::Vector3d& max =
node_metadata_->getBoundingBoxMax ();
932 if (((min[0] <= p.x) && (p.x < max[0])) &&
933 ((min[1] <= p.y) && (p.y < max[1])) &&
934 ((min[2] <= p.z) && (p.z < max[2])))
943 template<
typename ContainerT,
typename Po
intT>
void
950 if (this->
depth_ < query_depth){
951 for (std::size_t i = 0; i < this->
depth_; i++)
954 std::cout <<
"[" << min[0] <<
", " << min[1] <<
", " << min[2] <<
"] - ";
955 std::cout <<
"[" << max[0] <<
", " << max[1] <<
", " << max[2] <<
"] - ";
956 std::cout <<
"[" << max[0] - min[0] <<
", " << max[1] - min[1];
957 std::cout <<
", " << max[2] - min[2] <<
"]" << std::endl;
961 for (std::size_t i = 0; i < 8; i++)
964 children_[i]->printBoundingBox (query_depth);
971 template<
typename ContainerT,
typename Po
intT>
void
974 if (this->
depth_ < query_depth){
977 for (std::size_t i = 0; i < 8; i++)
980 children_[i]->getOccupiedVoxelCentersRecursive (voxel_centers, query_depth);
988 voxel_center.x =
static_cast<float>(mid_xyz[0]);
989 voxel_center.y =
static_cast<float>(mid_xyz[1]);
990 voxel_center.z =
static_cast<float>(mid_xyz[2]);
992 voxel_centers.push_back(voxel_center);
1048 template<
typename Container,
typename Po
intT>
void
1054 template<
typename Container,
typename Po
intT>
void
1058 enum {INSIDE, INTERSECT, OUTSIDE};
1060 int result = INSIDE;
1062 if (this->
depth_ > query_depth)
1070 if (!skip_vfc_check)
1072 for(
int i =0; i < 6; i++){
1073 double a = planes[(i*4)];
1074 double b = planes[(i*4)+1];
1075 double c = planes[(i*4)+2];
1076 double d = planes[(i*4)+3];
1080 Eigen::Vector3d normal(a, b, c);
1082 Eigen::Vector3d min_bb;
1083 Eigen::Vector3d max_bb;
1088 Eigen::Vector3d radius (std::abs (
static_cast<double> (max_bb.x () - center.x ())),
1089 std::abs (
static_cast<double> (max_bb.y () - center.y ())),
1090 std::abs (
static_cast<double> (max_bb.z () - center.z ())));
1092 double m = (center.x () * a) + (center.y () * b) + (center.z () * c) + d;
1093 double n = (radius.x () * std::abs(a)) + (radius.y () * std::abs(b)) + (radius.z () * std::abs(c));
1100 if (m - n < 0) result = INTERSECT;
1151 if (result == OUTSIDE)
1172 file_names.push_back (this->
node_metadata_->getMetadataFilename ().string ());
1182 for (std::size_t i = 0; i < 8; i++)
1185 children_[i]->queryFrustum (planes, file_names, query_depth, (result == INSIDE) );
1203 template<
typename Container,
typename Po
intT>
void
1208 if (this->
depth_ > query_depth)
1214 Eigen::Vector3d min_bb;
1215 Eigen::Vector3d max_bb;
1219 enum {INSIDE, INTERSECT, OUTSIDE};
1221 int result = INSIDE;
1223 if (!skip_vfc_check)
1225 for(
int i =0; i < 6; i++){
1226 double a = planes[(i*4)];
1227 double b = planes[(i*4)+1];
1228 double c = planes[(i*4)+2];
1229 double d = planes[(i*4)+3];
1233 Eigen::Vector3d normal(a, b, c);
1237 Eigen::Vector3d radius (std::abs (
static_cast<double> (max_bb.x () - center.x ())),
1238 std::abs (
static_cast<double> (max_bb.y () - center.y ())),
1239 std::abs (
static_cast<double> (max_bb.z () - center.z ())));
1241 double m = (center.x () * a) + (center.y () * b) + (center.z () * c) + d;
1242 double n = (radius.x () * std::abs(a)) + (radius.y () * std::abs(b)) + (radius.z () * std::abs(c));
1249 if (m - n < 0) result = INTERSECT;
1254 if (result == OUTSIDE)
1289 if (this->depth_ <= query_depth && payload_->
getDataSize () > 0)
1292 file_names.push_back (this->
node_metadata_->getMetadataFilename ().string ());
1296 if (coverage <= 10000)
1306 for (std::size_t i = 0; i < 8; i++)
1309 children_[i]->queryFrustum (planes, eye, view_projection_matrix, file_names, query_depth, (result == INSIDE) );
1315 template<
typename ContainerT,
typename Po
intT>
void
1318 if (this->
depth_ < query_depth){
1321 for (std::size_t i = 0; i < 8; i++)
1324 children_[i]->getOccupiedVoxelCentersRecursive (voxel_centers, query_depth);
1330 Eigen::Vector3d voxel_center =
node_metadata_->getVoxelCenter ();
1331 voxel_centers.push_back(voxel_center);
1338 template<
typename ContainerT,
typename Po
intT>
void
1343 if (this->
depth_ < query_depth)
1347 for (std::size_t i = 0; i < 8; i++)
1350 children_[i]->queryBBIntersects (min_bb, max_bb, query_depth, file_names);
1357 for (std::size_t i = 0; i < 8; i++)
1360 children_[i]->queryBBIntersects (min_bb, max_bb, query_depth, file_names);
1368 file_names.push_back (this->
node_metadata_->getMetadataFilename ().string ());
1374 template<
typename ContainerT,
typename Po
intT>
void
1377 std::uint64_t startingSize = dst_blob->width*dst_blob->height;
1378 PCL_DEBUG (
"[pcl::outofcore::OutofcoreOctreeBaseNode::%s] Starting points in destination blob: %ul\n", __FUNCTION__, startingSize );
1384 if (this->
depth_ < query_depth)
1394 for (std::size_t i = 0; i < 8; i++)
1397 children_[i]->queryBBIncludes (min_bb, max_bb, query_depth, dst_blob);
1399 PCL_DEBUG (
"[pcl::outofcore::OutofcoreOctreeBaseNode::%s] Points in dst_blob: %ul\n", __FUNCTION__, dst_blob->width*dst_blob->height );
1411 if( tmp_blob->width*tmp_blob->height == 0 )
1421 if( dst_blob->width*dst_blob->height != 0 )
1423 PCL_DEBUG (
"[pcl::outofocre::OutofcoreOctreeBaseNode::%s] Size of cloud before: %lu\n", __FUNCTION__, dst_blob->width*dst_blob->height );
1424 PCL_DEBUG (
"[pcl::outofcore::OutofcoreOctreeBaseNode::%s] Concatenating point cloud\n", __FUNCTION__);
1429 PCL_DEBUG (
"[pcl::outofocre::OutofcoreOctreeBaseNode::%s] Size of cloud after: %lu\n", __FUNCTION__, dst_blob->width*dst_blob->height );
1434 PCL_DEBUG (
"[pcl::outofcore::OutofcoreOctreeBaseNode] Copying point cloud into the destination blob\n");
1436 assert (tmp_blob->width*tmp_blob->height == dst_blob->width*dst_blob->height);
1438 PCL_DEBUG (
"[pcl::outofcore::OutofcoreOctreeBaseNode::%s] Points in dst_blob: %ul\n", __FUNCTION__, dst_blob->width*dst_blob->height );
1449 assert (tmp_blob->width*tmp_blob->height == tmp_cloud->
width*tmp_cloud->
height );
1451 Eigen::Vector4f min_pt (
static_cast<float> ( min_bb[0] ),
static_cast<float> ( min_bb[1] ),
static_cast<float> ( min_bb[2] ), 1.0f);
1452 Eigen::Vector4f max_pt (
static_cast<float> ( max_bb[0] ),
static_cast<float> ( max_bb[1] ) ,
static_cast<float>( max_bb[2] ), 1.0f );
1457 PCL_DEBUG (
"[pcl::outofcore::OutofcoreOctreeBaseNode::%s] Points in box: %d\n", __FUNCTION__, indices.size () );
1458 PCL_DEBUG (
"[pcl::outofcore::OutofcoreOctreeBaseNode::%s] Points remaining: %d\n", __FUNCTION__, tmp_cloud->
width*tmp_cloud->
height - indices.size () );
1460 if ( !indices.empty () )
1462 if( dst_blob->width*dst_blob->height > 0 )
1469 assert ( tmp_blob_within_bb->width*tmp_blob_within_bb->height == indices.size () );
1470 assert ( tmp_blob->fields.size () == tmp_blob_within_bb->fields.size () );
1472 PCL_DEBUG (
"[pcl::outofcore::OutofcoreOctreeBaseNode::%s] Concatenating point cloud in place\n", __FUNCTION__);
1473 std::uint64_t orig_points_in_destination = dst_blob->width*dst_blob->height;
1477 assert (dst_blob->width*dst_blob->height == indices.size () + orig_points_in_destination);
1483 assert ( dst_blob->width*dst_blob->height == indices.size () );
1489 PCL_DEBUG (
"[pcl::outofcore::OutofcoreOctreeBaseNode::%s] Points added by function call: %ul\n", __FUNCTION__, dst_blob->width*dst_blob->height - startingSize );
1492 template<
typename ContainerT,
typename Po
intT>
void
1500 if (this->
depth_ < query_depth)
1515 for (std::size_t i = 0; i < 8; i++)
1518 children_[i]->queryBBIncludes (min_bb, max_bb, query_depth, v);
1532 v.insert (v.end (), payload_cache.begin (), payload_cache.end ());
1542 std::uint64_t len =
payload_->size ();
1544 for (std::uint64_t i = 0; i < len; i++)
1546 const PointT& p = payload_cache[i];
1555 PCL_DEBUG (
"[pcl::outofcore::queryBBIncludes] Point %.2lf %.2lf %.2lf not in bounding box %.2lf %.2lf %.2lf", p.x, p.y, p.z, min_bb[0], min_bb[1], min_bb[2], max_bb[0], max_bb[1], max_bb[2]);
1563 template<
typename ContainerT,
typename Po
intT>
void
1568 if (this->
depth_ < query_depth)
1575 for (std::size_t i=0; i<8; i++)
1579 children_[i]->queryBBIncludes_subsample (min_bb, max_bb, query_depth, dst_blob, percent);
1592 std::uint64_t num_pts = tmp_blob->width*tmp_blob->height;
1594 double sample_points =
static_cast<double>(num_pts) * percent;
1598 sample_points = sample_points > 1 ? sample_points : 1;
1612 random_sampler.
setSample (
static_cast<unsigned int> (sample_points));
1618 random_sampler.
filter (*downsampled_cloud_indices);
1619 extractor.
setIndices (downsampled_cloud_indices);
1620 extractor.
filter (*downsampled_points);
1631 template<
typename ContainerT,
typename Po
intT>
void
1638 if (this->
depth_ < query_depth)
1649 for (std::size_t i = 0; i < 8; i++)
1652 children_[i]->queryBBIncludes_subsample (min_bb, max_bb, query_depth, percent, dst);
1665 payload_->readRangeSubSample (0,
payload_->size (), percent, payload_cache);
1666 dst.insert (dst.end (), payload_cache.begin (), payload_cache.end ());
1675 for (std::size_t i = 0; i <
payload_->size (); i++)
1677 const PointT& p = payload_cache[i];
1680 payload_cache_within_region.push_back (p);
1686 std::shuffle (payload_cache_within_region.begin (), payload_cache_within_region.end (), std::mt19937(std::random_device()()));
1687 auto numpick =
static_cast<std::size_t
> (percent *
static_cast<double> (payload_cache_within_region.size ()));;
1689 for (std::size_t i = 0; i < numpick; i++)
1691 dst.push_back (payload_cache_within_region[i]);
1699 template<
typename ContainerT,
typename Po
intT>
1713 if (super ==
nullptr)
1715 PCL_ERROR (
"[pc::outofcore::OutofcoreOctreeBaseNode] Super is null - don't make a root node this way!\n" );
1716 PCL_THROW_EXCEPTION (
PCLException,
"[pcl::outofcore::OutofcoreOctreeBaseNode] Outofcore Exception: Bad parent");
1729 std::string uuid_idx;
1730 std::string uuid_cont;
1736 std::string node_container_name;
1739 node_metadata_->setDirectoryPathname (boost::filesystem::path (dir));
1743 boost::filesystem::create_directory (
node_metadata_->getDirectoryPathname ());
1751 template<
typename ContainerT,
typename Po
intT>
void
1761 children_[i]->copyAllCurrentAndChildPointsRec (v);
1768 v.insert (v.end (), payload_cache.begin (), payload_cache.end ());
1774 template<
typename ContainerT,
typename Po
intT>
void
1782 for (std::size_t i = 0; i < 8; i++)
1785 children_[i]->copyAllCurrentAndChildPointsRec_sub (v, percent);
1788 std::vector<PointT> payload_cache;
1789 payload_->readRangeSubSample (0,
payload_->size (), percent, payload_cache);
1791 for (std::size_t i = 0; i < payload_cache.size (); i++)
1793 v.push_back (payload_cache[i]);
1799 template<
typename ContainerT,
typename Po
intT>
inline bool
1802 Eigen::Vector3d min, max;
1806 if (((min[0] <= min_bb[0]) && (min_bb[0] <= max[0])) || ((min_bb[0] <= min[0]) && (min[0] <= max_bb[0])))
1808 if (((min[1] <= min_bb[1]) && (min_bb[1] <= max[1])) || ((min_bb[1] <= min[1]) && (min[1] <= max_bb[1])))
1810 if (((min[2] <= min_bb[2]) && (min_bb[2] <= max[2])) || ((min_bb[2] <= min[2]) && (min[2] <= max_bb[2])))
1821 template<
typename ContainerT,
typename Po
intT>
inline bool
1824 Eigen::Vector3d min, max;
1828 if ((min_bb[0] <= min[0]) && (max[0] <= max_bb[0]))
1830 if ((min_bb[1] <= min[1]) && (max[1] <= max_bb[1]))
1832 if ((min_bb[2] <= min[2]) && (max[2] <= max_bb[2]))
1843 template<
typename ContainerT,
typename Po
intT>
inline bool
1848 if ((min_bb[0] <= p.x) && (p.x < max_bb[0]))
1850 if ((min_bb[1] <= p.y) && (p.y < max_bb[1]))
1852 if ((min_bb[2] <= p.z) && (p.z < max_bb[2]))
1863 template<
typename ContainerT,
typename Po
intT>
void
1866 Eigen::Vector3d min;
1867 Eigen::Vector3d max;
1870 double l = max[0] - min[0];
1871 double h = max[1] - min[1];
1872 double w = max[2] - min[2];
1873 file <<
"box( pos=(" << min[0] <<
", " << min[1] <<
", " << min[2] <<
"), length=" << l <<
", height=" << h
1874 <<
", width=" << w <<
" )\n";
1878 children_[i]->writeVPythonVisual (file);
1884 template<
typename ContainerT,
typename Po
intT>
int
1887 return (this->
payload_->read (output_cloud));
1895 PCL_DEBUG (
"[pcl::outofcore::OutofcoreOctreeBaseNode::%s] %d", __FUNCTION__, index_arg);
1900 template<
typename ContainerT,
typename Po
intT> std::uint64_t
1903 return (this->
payload_->getDataSize ());
1908 template<
typename ContainerT,
typename Po
intT> std::size_t
1911 std::size_t loaded_children_count = 0;
1913 for (std::size_t i=0; i<8; i++)
1916 loaded_children_count++;
1919 return (loaded_children_count);
1924 template<
typename ContainerT,
typename Po
intT>
void
1927 PCL_DEBUG (
"[pcl:outofcore::OutofcoreOctreeBaseNode] Loading metadata from %s\n", path.filename ().c_str ());
1942 template<
typename ContainerT,
typename Po
intT>
void
1945 std::string fname =
node_metadata_->getPCDFilename ().stem ().string () +
".dat.xyz";
1946 boost::filesystem::path xyzfile =
node_metadata_->getDirectoryPathname () / fname;
1954 for (std::size_t i = 0; i < 8; i++)
1963 template<
typename ContainerT,
typename Po
intT>
void
1966 for (std::size_t i = 0; i < 8; i++)
1975 template<
typename ContainerT,
typename Po
intT>
void
1978 if (indices.size () < 8)
1985 int x_offset = input_cloud->fields[x_idx].offset;
1986 int y_offset = input_cloud->fields[y_idx].offset;
1987 int z_offset = input_cloud->fields[z_idx].offset;
1989 for ( std::size_t point_idx =0; point_idx < input_cloud->data.size (); point_idx +=input_cloud->point_step )
1993 local_pt.x = * (
reinterpret_cast<float*
>(&input_cloud->data[point_idx + x_offset]));
1994 local_pt.y = * (
reinterpret_cast<float*
>(&input_cloud->data[point_idx + y_offset]));
1995 local_pt.z = * (
reinterpret_cast<float*
>(&input_cloud->data[point_idx + z_offset]));
1997 if (!std::isfinite (local_pt.x) || !std::isfinite (local_pt.y) || !std::isfinite (local_pt.z))
2002 PCL_ERROR (
"pcl::outofcore::OutofcoreOctreeBaseNode::%s] Point %2.lf %.2lf %.2lf not in bounding box\n", __FUNCTION__, local_pt.x, local_pt.y, local_pt.z);
2008 std::size_t box = 0;
2009 box = ((local_pt.z >= mid_xyz[2]) << 2) | ((local_pt.y >= mid_xyz[1]) << 1) | ((local_pt.x >= mid_xyz[0]) << 0);
2013 indices[box].push_back (
static_cast<int> (point_idx/input_cloud->point_step));
2027 thisnode->thisdir_ = path.parent_path ();
2029 if (!boost::filesystem::exists (thisnode->thisdir_))
2031 PCL_ERROR (
"[pcl::outofcore::OutofcoreOctreeBaseNode] could not find dir %s\n",thisnode->thisdir_.c_str () );
2032 PCL_THROW_EXCEPTION (
PCLException,
"[pcl::outofcore::OutofcoreOctreeBaseNode] Outofcore Octree Exception: Could not find directory");
2035 thisnode->thisnodeindex_ = path;
2042 thisnode->thisdir_ = path;
2046 if (thisnode->
depth_ > thisnode->root->max_depth_)
2048 thisnode->root->max_depth_ = thisnode->
depth_;
2051 boost::filesystem::directory_iterator diterend;
2052 bool loaded =
false;
2053 for (boost::filesystem::directory_iterator diter (thisnode->thisdir_); diter != diterend; ++diter)
2055 const boost::filesystem::path& file = *diter;
2056 if (!boost::filesystem::is_directory (file))
2060 thisnode->thisnodeindex_ = file;
2069 PCL_ERROR (
"[pcl::outofcore::OutofcoreOctreeBaseNode] Could not find index!\n");
2070 PCL_THROW_EXCEPTION (PCLException,
"[pcl::outofcore::OutofcoreOctreeBaseNode] Could not find node metadata index file");
2074 thisnode->max_depth_ = 0;
2077 std::ifstream f (thisnode->thisnodeindex_.string ().c_str (), std::ios::in);
2079 f >> thisnode->min_[0];
2080 f >> thisnode->min_[1];
2081 f >> thisnode->min_[2];
2082 f >> thisnode->max_[0];
2083 f >> thisnode->max_[1];
2084 f >> thisnode->max_[2];
2086 std::string filename;
2088 thisnode->thisnodestorage_ = thisnode->thisdir_ / filename;
2092 thisnode->
payload_.reset (
new ContainerT (thisnode->thisnodestorage_));
2106 template<
typename ContainerT,
typename Po
intT>
void
2107 queryBBIntersects_noload (
const boost::filesystem::path& root_node,
const Eigen::Vector3d& min,
const Eigen::Vector3d& max,
const std::uint32_t query_depth, std::list<std::string>& bin_name)
2112 std::cout <<
"test";
2114 if (root->intersectsWithBoundingBox (min, max))
2116 if (query_depth == root->max_depth_)
2118 if (!root->payload_->empty ())
2120 bin_name.push_back (root->thisnodestorage_.string ());
2125 for (
int i = 0; i < 8; i++)
2127 boost::filesystem::path child_dir = root->thisdir_
2128 / boost::filesystem::path (boost::lexical_cast<std::string> (i));
2129 if (boost::filesystem::exists (child_dir))
2132 root->num_children_++;
2142 template<
typename ContainerT,
typename Po
intT>
void
2145 if (current->intersectsWithBoundingBox (min, max))
2147 if (current->depth_ == query_depth)
2149 if (!current->payload_->empty ())
2151 bin_name.push_back (current->thisnodestorage_.string ());
2156 for (
int i = 0; i < 8; i++)
2158 boost::filesystem::path child_dir = current->thisdir_ / boost::filesystem::path (boost::lexical_cast<std::string> (i));
2159 if (boost::filesystem::exists (child_dir))
2162 current->num_children_++;
void filter(Indices &indices)
Calls the filtering method and returns the filtered point cloud indices.
void setNegative(bool negative)
Set whether the regular conditions for points filtering should apply, or the inverted conditions.
virtual void setInputCloud(const PointCloudConstPtr &cloud)
Provide a pointer to the input dataset.
virtual void setIndices(const IndicesPtr &indices)
Provide a pointer to the vector of indices that represents the input data.
A base class for all pcl exceptions which inherits from std::runtime_error.
PointCloud represents the base class in PCL for storing collections of 3D points.
std::uint32_t width
The point cloud width (if organized as an image-structure).
std::uint32_t height
The point cloud height (if organized as an image-structure).
shared_ptr< PointCloud< PointT > > Ptr
RandomSample applies a random sampling with uniform probability.
void setSample(unsigned int sample)
Set number of indices to be sampled.
This code defines the octree used for point storage at Urban Robotics.
OutofcoreOctreeBaseNode Class internally representing nodes of an outofcore octree,...
std::size_t depth_
Depth in the tree, root is 0, root's children are 1, ...
bool intersectsWithBoundingBox(const Eigen::Vector3d &min_bb, const Eigen::Vector3d &max_bb) const
Tests whether the input bounding box intersects with the current node's bounding box.
static const std::string node_index_basename
virtual std::uint64_t addPointCloud_and_genLOD(const pcl::PCLPointCloud2::Ptr input_cloud)
Add a single PCLPointCloud2 into the octree and build the subsampled LOD during construction; this me...
static const std::string node_index_extension
virtual std::uint64_t getDataSize() const
Gets the number of points available in the PCD file.
~OutofcoreOctreeBaseNode() override
Will recursively delete all children calling recFreeChildrein.
void copyAllCurrentAndChildPointsRec_sub(std::list< PointT > &v, const double percent)
void loadFromFile(const boost::filesystem::path &path, OutofcoreOctreeBaseNode *super)
Loads the nodes metadata from the JSON file.
bool hasUnloadedChildren() const
Returns whether or not a node has unloaded children data.
void randomSample(const AlignedPointTVector &p, AlignedPointTVector &insertBuff, const bool skip_bb_check)
Randomly sample point data.
virtual std::uint64_t addDataToLeaf_and_genLOD(const AlignedPointTVector &p, const bool skip_bb_check)
Recursively add points to the leaf and children subsampling LODs on the way down.
OutofcoreOctreeBase< ContainerT, PointT > * m_tree_
The tree we belong to.
static std::mutex rng_mutex_
Random number generator mutex.
virtual void queryBBIncludes_subsample(const Eigen::Vector3d &min_bb, const Eigen::Vector3d &max_bb, std::uint64_t query_depth, const double percent, AlignedPointTVector &v)
Recursively add points that fall into the queried bounding box up to the query_depth.
virtual std::size_t getNumChildren() const
Returns the total number of children on disk.
static const double sample_percent_
std::uint64_t num_children_
Number of children on disk.
virtual void queryBBIntersects(const Eigen::Vector3d &min_bb, const Eigen::Vector3d &max_bb, const std::uint32_t query_depth, std::list< std::string > &file_names)
Recursive acquires PCD paths to any node with which the queried bounding box intersects (at query_dep...
void writeVPythonVisual(std::ofstream &file)
Write a python visual script to file.
OutofcoreOctreeBaseNode()
Empty constructor; sets pointers for children and for bounding boxes to 0.
virtual std::size_t countNumChildren() const
Counts the number of child directories on disk; used to update num_children_.
void convertToXYZRecursive()
Recursively converts data files to ascii XZY files.
OutofcoreOctreeBaseNode * parent_
super-node
void init_root_node(const Eigen::Vector3d &bb_min, const Eigen::Vector3d &bb_max, OutofcoreOctreeBase< ContainerT, PointT > *const tree, const boost::filesystem::path &rootname)
Create root node and directory.
std::shared_ptr< ContainerT > payload_
what holds the points.
virtual int read(pcl::PCLPointCloud2::Ptr &output_cloud)
OutofcoreOctreeBaseNode * root_node_
The root node of the tree we belong to.
std::uint64_t num_loaded_children_
Number of loaded children this node has.
bool pointInBoundingBox(const Eigen::Vector3d &min_bb, const Eigen::Vector3d &max_bb, const Eigen::Vector3d &point)
Tests whether point falls within the input bounding box.
void saveIdx(bool recursive)
Save node's metadata to file.
void queryFrustum(const double planes[24], std::list< std::string > &file_names)
OutofcoreOctreeNodeMetadata::Ptr node_metadata_
std::vector< PointT, Eigen::aligned_allocator< PointT > > AlignedPointTVector
void sortOctantIndices(const pcl::PCLPointCloud2::Ptr &input_cloud, std::vector< pcl::Indices > &indices, const Eigen::Vector3d &mid_xyz)
Sorts the indices based on x,y,z fields and pushes the index into the proper octant's vector; This co...
void getOccupiedVoxelCentersRecursive(AlignedPointTVector &voxel_centers, const std::size_t query_depth)
Gets a vector of occupied voxel centers.
std::vector< OutofcoreOctreeBaseNode * > children_
The children of this node.
static const std::string node_container_basename
std::uint64_t size() const
Number of points in the payload.
static const std::string pcd_extension
Extension for this class to find the pcd files on disk.
virtual std::size_t getNumLoadedChildren() const
Count loaded children.
void subdividePoints(const AlignedPointTVector &p, std::vector< AlignedPointTVector > &c, const bool skip_bb_check)
Subdivide points to pass to child nodes.
void copyAllCurrentAndChildPointsRec(std::list< PointT > &v)
Copies points from this and all children into a single point container (std::list)
static std::mt19937 rng_
Mersenne Twister: A 623-dimensionally equidistributed uniform pseudo-random number generator.
void subdividePoint(const PointT &point, std::vector< AlignedPointTVector > &c)
Subdivide a single point into a specific child node.
virtual std::size_t getDepth() const
virtual void loadChildren(bool recursive)
Load nodes child data creating new nodes for each.
virtual std::size_t countNumLoadedChildren() const
Counts the number of loaded children by testing the children_ array; used to update num_loaded_childr...
void flushToDiskRecursive()
std::uint64_t addDataAtMaxDepth(const AlignedPointTVector &p, const bool skip_bb_check=true)
Add data to the leaf when at max depth of tree.
bool inBoundingBox(const Eigen::Vector3d &min_bb, const Eigen::Vector3d &max_bb) const
Tests whether the input bounding box falls inclusively within this node's bounding box.
virtual OutofcoreOctreeBaseNode * getChildPtr(std::size_t index_arg) const
Returns a pointer to the child in octant index_arg.
virtual std::uint64_t addDataToLeaf(const AlignedPointTVector &p, const bool skip_bb_check=true)
add point to this node if we are a leaf, or find the leaf below us that is supposed to take the point
static const std::string node_container_extension
void recFreeChildren()
Method which recursively free children of this node.
virtual void queryBBIncludes(const Eigen::Vector3d &min_bb, const Eigen::Vector3d &max_bb, std::size_t query_depth, AlignedPointTVector &dst)
Recursively add points that fall into the queried bounding box up to the query_depth.
void createChild(const std::size_t idx)
Creates child node idx.
virtual std::uint64_t addPointCloud(const pcl::PCLPointCloud2::Ptr &input_cloud, const bool skip_bb_check=false)
Add a single PCLPointCloud2 object into the octree.
virtual void printBoundingBox(const std::size_t query_depth) const
Write the voxel size to stdout at query_depth.
static void getRandomUUIDString(std::string &s)
Generate a universally unique identifier (UUID)
Define standard C methods and C++ classes that are common to all methods.
bool concatenate(const pcl::PointCloud< PointT > &cloud1, const pcl::PointCloud< PointT > &cloud2, pcl::PointCloud< PointT > &cloud_out)
Concatenate two pcl::PointCloud<PointT>
void getPointsInBox(const pcl::PointCloud< PointT > &cloud, Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt, Indices &indices)
Get a set of points residing in a box given its bounds.
void copyPointCloud(const pcl::PointCloud< PointInT > &cloud_in, pcl::PointCloud< PointOutT > &cloud_out)
Copy all the fields from a given point cloud into a new point cloud.
OutofcoreOctreeBaseNode< ContainerT, PointT > * makenode_norec(const boost::filesystem::path &path, OutofcoreOctreeBaseNode< ContainerT, PointT > *super)
Non-class function which creates a single child leaf; used with queryBBIntersects_noload to avoid loa...
bool pointInBoundingBox(const Eigen::Vector3d &min_bb, const Eigen::Vector3d &max_bb, const Eigen::Vector3d &point)
void queryBBIntersects_noload(const boost::filesystem::path &root_node, const Eigen::Vector3d &min, const Eigen::Vector3d &max, const std::uint32_t query_depth, std::list< std::string > &bin_name)
Non-class method which performs a bounding box query without loading any of the point cloud data from...
void ignore(const T &...)
Utility function to eliminate unused variable warnings.
PCL_EXPORTS float viewScreenArea(const Eigen::Vector3d &eye, const Eigen::Vector3d &min_bb, const Eigen::Vector3d &max_bb, const Eigen::Matrix4d &view_projection_matrix, int width, int height)
int getFieldIndex(const pcl::PointCloud< PointT > &, const std::string &field_name, std::vector< pcl::PCLPointField > &fields)
shared_ptr< Indices > IndicesPtr
IndicesAllocator<> Indices
Type used for indices in PCL.
void fromPCLPointCloud2(const pcl::PCLPointCloud2 &msg, pcl::PointCloud< PointT > &cloud, const MsgFieldMap &field_map, const std::uint8_t *msg_data)
Convert a PCLPointCloud2 binary data blob into a pcl::PointCloud<T> object using a field_map.
shared_ptr< ::pcl::PCLPointCloud2 > Ptr