octree_disk_container.h
/*
* Software License Agreement (BSD License)
*
* Point Cloud Library (PCL) - www.pointclouds.org
* Copyright (c) 2010-2012, Willow Garage, Inc.
* Copyright (c) 2012, Urban Robotics, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Willow Garage, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* $Id: octree_disk_container.h 6927M 2012-08-24 13:26:40Z (local) $
*/
#pragma once
// C++
#include <mutex>
#include <vector>
#include <string>
// Boost
#include <boost/uuid/random_generator.hpp>
#include <pcl/outofcore/boost.h>
#include <pcl/outofcore/octree_abstract_node_container.h>
#include <pcl/io/pcd_io.h>
#include <pcl/PCLPointCloud2.h>
//allows operation on POSIX
#if !defined WIN32
#define _fseeki64 fseeko
#elif defined __MINGW32__
#define _fseeki64 fseeko64
#endif
namespace pcl
{
namespace outofcore
{
/** \class OutofcoreOctreeDiskContainer
* \note Code was adapted from the Urban Robotics out of core octree implementation.
* Contact Jacob Schloss <jacob.schloss@urbanrobotics.net> with any questions.
* http://www.urbanrobotics.net/
*
* \brief Class responsible for serialization and deserialization of out of core point data
* \ingroup outofcore
* \author Jacob Schloss (jacob.schloss@urbanrobotics.net)
*/
template<typename PointT = pcl::PointXYZ>
class OutofcoreOctreeDiskContainer : public OutofcoreAbstractNodeContainer<PointT>
{
public:
using AlignedPointTVector = typename OutofcoreAbstractNodeContainer<PointT>::AlignedPointTVector;
/** \brief Empty constructor creates disk container and sets filename from random uuid string*/
OutofcoreOctreeDiskContainer ();
/** \brief Creates uuid named file or loads existing file
*
* If \b dir is a directory, this constructor will create a new
* uuid named file; if \b dir is an existing file, it will load the
* file metadata for accessing the tree.
*
* \param[in] dir Path to the tree. If it is a directory, it
* will create the metadata. If it is a file, it will load the metadata into memory.
*/
OutofcoreOctreeDiskContainer (const boost::filesystem::path &dir);
/** \brief flushes write buffer, then frees memory */
~OutofcoreOctreeDiskContainer ();
/** \brief provides random access to points based on a linear index
*/
inline PointT
operator[] (std::uint64_t idx) const override;
/** \brief Adds a single point to the buffer to be written to disk when the buffer grows sufficiently large, the object is destroyed, or the write buffer is manually flushed */
inline void
push_back (const PointT& p);
/** \brief Inserts a vector of points into the disk data structure */
void
insertRange (const AlignedPointTVector& src);
/** \brief Inserts a PCLPointCloud2 object directly into the disk container */
void
insertRange (const pcl::PCLPointCloud2::Ptr &input_cloud);
void
insertRange (const PointT* const * start, const std::uint64_t count) override;
/** \brief This is the primary method for serialization of
* blocks of point data. This is called by the outofcore
* octree interface, opens the binary file for appending data,
* and writes it to disk.
*
* \param[in] start address of the first point to insert
* \param[in] count offset from start of the last point to insert
*/
void
insertRange (const PointT* start, const std::uint64_t count) override;
/** \brief Reads \b count points into memory from the disk container
*
* Reads \b count points into memory from the disk container, reading at most 2 million elements at a time
*
* \param[in] start index of first point to read from disk
* \param[in] count offset of last point to read from disk
* \param[out] dst std::vector as destination for points read from disk into memory
*/
void
readRange (const std::uint64_t start, const std::uint64_t count, AlignedPointTVector &dst) override;
void
readRange (const std::uint64_t, const std::uint64_t, pcl::PCLPointCloud2::Ptr &dst);
/** \brief Reads the entire point contents from disk into \c output_cloud
* \param[out] output_cloud
*/
int
read (pcl::PCLPointCloud2::Ptr &output_cloud);
/** \brief grab percent*count random points. points are \b not guaranteed to be
* unique (could have multiple identical points!)
*
* \param[in] start The starting index of points to select
* \param[in] count The length of the range of points from which to randomly sample
* (i.e. from start to start+count)
* \param[in] percent The percentage of count that is enough points to make up this random sample
* \param[out] dst std::vector as destination for randomly sampled points; size will
* be percentage*count
*/
void
readRangeSubSample (const std::uint64_t start, const std::uint64_t count, const double percent,
AlignedPointTVector &dst) override;
/** \brief Use bernoulli trials to select points. All points selected will be unique.
*
* \param[in] start The starting index of points to select
* \param[in] count The length of the range of points from which to randomly sample
* (i.e. from start to start+count)
* \param[in] percent The percentage of count that is enough points to make up this random sample
* \param[out] dst std::vector as destination for randomly sampled points; size will
* be percentage*count
*/
void
readRangeSubSample_bernoulli (const std::uint64_t start, const std::uint64_t count,
const double percent, AlignedPointTVector& dst);
/** \brief Returns the total number of points for which this container is responsible, \c filelen_ + points in \c writebuff_ that have not yet been flushed to the disk
*/
std::uint64_t
size () const override
{
return (filelen_ + writebuff_.size ());
}
/** \brief STL-like empty test
* \return true if container has no data on disk or waiting to be written in \c writebuff_ */
inline bool
empty () const override
{
return ((filelen_ == 0) && writebuff_.empty ());
}
/** \brief Exposed functionality for manually flushing the write buffer during tree creation */
void
flush (const bool force_cache_dealloc)
{
flushWritebuff (force_cache_dealloc);
}
/** \brief Returns this objects path name */
inline std::string&
path ()
{
return (disk_storage_filename_);
}
inline void
clear () override
{
//clear elements that have not yet been written to disk
writebuff_.clear ();
//remove the binary data in the directory
PCL_DEBUG ("[Octree Disk Container] Removing the point data from disk, in file %s\n", disk_storage_filename_.c_str ());
boost::filesystem::remove (boost::filesystem::path (disk_storage_filename_.c_str ()));
//reset the size-of-file counter
filelen_ = 0;
}
/** \brief write points to disk as ascii
*
* \param[in] path
*/
void
convertToXYZ (const boost::filesystem::path &path) override
{
if (boost::filesystem::exists (disk_storage_filename_))
{
FILE* fxyz = fopen (path.string ().c_str (), "we");
FILE* f = fopen (disk_storage_filename_.c_str (), "rbe");
assert (f != NULL);
std::uint64_t num = size ();
PointT p;
char* loc = reinterpret_cast<char*> ( &p );
for (std::uint64_t i = 0; i < num; i++)
{
int seekret = _fseeki64 (f, i * sizeof (PointT), SEEK_SET);
(void)seekret;
assert (seekret == 0);
std::size_t readlen = fread (loc, sizeof (PointT), 1, f);
(void)readlen;
assert (readlen == 1);
//of << p.x << "\t" << p.y << "\t" << p.z << "\n";
std::stringstream ss;
ss << std::fixed;
ss.precision (16);
ss << p.x << "\t" << p.y << "\t" << p.z << "\n";
fwrite (ss.str ().c_str (), 1, ss.str ().size (), fxyz);
}
int res = fclose (f);
(void)res;
assert (res == 0);
res = fclose (fxyz);
assert (res == 0);
}
}
/** \brief Generate a universally unique identifier (UUID)
*
* A mutex lock happens to ensure uniqueness
*
*/
static void
getRandomUUIDString (std::string &s);
/** \brief Returns the number of points in the PCD file by reading the PCD header. */
std::uint64_t
getDataSize () const;
private:
//no copy construction
OutofcoreOctreeDiskContainer (const OutofcoreOctreeDiskContainer& /*rval*/) { }
OutofcoreOctreeDiskContainer&
operator= (const OutofcoreOctreeDiskContainer& /*rval*/) { }
void
flushWritebuff (const bool force_cache_dealloc);
/** \brief Name of the storage file on disk (i.e., the PCD file) */
std::string disk_storage_filename_;
//--- possibly deprecated parameter variables --//
//number of elements in file
std::uint64_t filelen_;
/** \brief elements [0,...,size()-1] map to [filelen, ..., filelen + size()-1] */
AlignedPointTVector writebuff_;
const static std::uint64_t READ_BLOCK_SIZE_;
static const std::uint64_t WRITE_BUFF_MAX_;
static std::mutex rng_mutex_;
static boost::mt19937 rand_gen_;
static boost::uuids::basic_random_generator<boost::mt19937> uuid_gen_;
};
} //namespace outofcore
} //namespace pcl
pcl::outofcore::OutofcoreOctreeDiskContainer::read
int read(pcl::PCLPointCloud2::Ptr &output_cloud)
Reads the entire point contents from disk into output_cloud.
Definition: octree_disk_container.hpp:576
pcl
This file defines compatibility wrappers for low level I/O functions.
Definition: convolution.h:45
pcl::outofcore::OutofcoreOctreeDiskContainer::flush
void flush(const bool force_cache_dealloc)
Exposed functionality for manually flushing the write buffer during tree creation.
Definition: octree_disk_container.h:195
pcl::outofcore::OutofcoreOctreeDiskContainer::operator[]
PointT operator[](std::uint64_t idx) const override
provides random access to points based on a linear index
Definition: octree_disk_container.hpp:197
pcl::outofcore::OutofcoreOctreeDiskContainer::readRangeSubSample
void readRangeSubSample(const std::uint64_t start, const std::uint64_t count, const double percent, AlignedPointTVector &dst) override
grab percent*count random points.
Definition: octree_disk_container.hpp:358
pcl::PCLPointCloud2::Ptr
shared_ptr< ::pcl::PCLPointCloud2 > Ptr
Definition: PCLPointCloud2.h:38
pcl::outofcore::OutofcoreOctreeDiskContainer::size
std::uint64_t size() const override
Returns the total number of points for which this container is responsible, filelen_ + points in writ...
Definition: octree_disk_container.h:180
pcl::outofcore::OutofcoreOctreeDiskContainer::OutofcoreOctreeDiskContainer
OutofcoreOctreeDiskContainer()
Empty constructor creates disk container and sets filename from random uuid string.
Definition: octree_disk_container.hpp:103
pcl::outofcore::OutofcoreAbstractNodeContainer::AlignedPointTVector
std::vector< PointT, Eigen::aligned_allocator< PointT > > AlignedPointTVector
Definition: octree_abstract_node_container.h:56
pcl::outofcore::OutofcoreOctreeDiskContainer::readRangeSubSample_bernoulli
void readRangeSubSample_bernoulli(const std::uint64_t start, const std::uint64_t count, const double percent, AlignedPointTVector &dst)
Use bernoulli trials to select points.
Definition: octree_disk_container.hpp:265
pcl::PointXYZRGB
A point structure representing Euclidean xyz coordinates, and the RGB color.
Definition: point_types.hpp:623
pcl::outofcore::OutofcoreOctreeDiskContainer::readRange
void readRange(const std::uint64_t start, const std::uint64_t count, AlignedPointTVector &dst) override
Reads count points into memory from the disk container.
Definition: octree_disk_container.hpp:238
pcl::outofcore::OutofcoreOctreeDiskContainer::empty
bool empty() const override
STL-like empty test.
Definition: octree_disk_container.h:188
pcl::outofcore::OutofcoreOctreeDiskContainer::getRandomUUIDString
static void getRandomUUIDString(std::string &s)
Generate a universally unique identifier (UUID)
Definition: octree_disk_container.hpp:88
pcl::outofcore::OutofcoreOctreeDiskContainer::path
std::string & path()
Returns this objects path name.
Definition: octree_disk_container.h:202
pcl::outofcore::OutofcoreOctreeDiskContainer::~OutofcoreOctreeDiskContainer
~OutofcoreOctreeDiskContainer()
flushes write buffer, then frees memory
Definition: octree_disk_container.hpp:159
pcl::outofcore::OutofcoreOctreeDiskContainer
Class responsible for serialization and deserialization of out of core point data.
Definition: octree_disk_container.h:76
pcl::outofcore::OutofcoreOctreeDiskContainer::AlignedPointTVector
typename OutofcoreAbstractNodeContainer< PointT >::AlignedPointTVector AlignedPointTVector
Definition: octree_disk_container.h:80
pcl::outofcore::OutofcoreOctreeDiskContainer::push_back
void push_back(const PointT &p)
Adds a single point to the buffer to be written to disk when the buffer grows sufficiently large,...
Definition: octree_disk_container.hpp:455
pcl::outofcore::OutofcoreOctreeDiskContainer::convertToXYZ
void convertToXYZ(const boost::filesystem::path &path) override
write points to disk as ascii
Definition: octree_disk_container.h:224
pcl::outofcore::OutofcoreAbstractNodeContainer
Definition: octree_abstract_node_container.h:52
pcl::outofcore::OutofcoreOctreeDiskContainer::clear
void clear() override
Definition: octree_disk_container.h:208
pcl::outofcore::OutofcoreOctreeDiskContainer::getDataSize
std::uint64_t getDataSize() const
Returns the number of points in the PCD file by reading the PCD header.
Definition: octree_disk_container.hpp:672
pcl::outofcore::OutofcoreOctreeDiskContainer::insertRange
void insertRange(const AlignedPointTVector &src)
Inserts a vector of points into the disk data structure.
Definition: octree_disk_container.hpp:466
pcl::uint64_t
std::uint64_t uint64_t
Definition: pcl_macros.h:98