Program Listing for File OctreeReduction.hpp

Return to documentation for file (include/lvr2/registration/OctreeReduction.hpp)

#ifndef __OCTREE_REDUCTION__
#define __OCTREE_REDUCTION__

#include "lvr2/types/MatrixTypes.hpp"
#include "lvr2/types/PointBuffer.hpp"
#include "lvr2/util/Timestamp.hpp"
#include "lvr2/registration/ReductionAlgorithm.hpp"
#include "lvr2/util/Logging.hpp"

#include <vector>

namespace lvr2
{

enum OctreeType {RANDOM_SAMPLE, NEAREST_CENTER, CENTER};

class OctreeReductionBase
{
public:
    OctreeReductionBase() = delete;

    OctreeReductionBase(PointBufferPtr pointBuffer, float voxelSize, size_t minPointsPerVoxel)
        : m_voxelSize(voxelSize),
          m_minPointsPerVoxel(minPointsPerVoxel),
          m_numPoints(pointBuffer->numPoints()),
          m_pointBuffer(pointBuffer) {}


    virtual PointBufferPtr getReducedPoints() = 0;

protected:

    OctreeReductionBase(size_t numPoints, float voxelSize, size_t minPointsPerVoxel)
        : m_voxelSize(voxelSize),
          m_minPointsPerVoxel(minPointsPerVoxel),
          m_numPoints(numPoints),
          m_pointBuffer(nullptr) {}

    std::vector<size_t> m_pointIndices;

    PointBufferPtr      m_pointBuffer;

    float               m_voxelSize;

    size_t              m_minPointsPerVoxel;

    size_t              m_numPoints;
};

class RandomSampleOctreeReduction : public OctreeReductionBase
{
public:
    RandomSampleOctreeReduction(PointBufferPtr pointBuffer, float voxelSize, size_t minPointsPerVoxel);
    RandomSampleOctreeReduction(Vector3f* points, size_t& n, float voxelSize, size_t minPointsPerVoxel);

    PointBufferPtr getReducedPoints() override;

private:
    void init();

    void createOctree(size_t start, size_t n, const Vector3f& min, const Vector3f& max, unsigned int level = 0);

    size_t splitPoints(size_t start, size_t n, unsigned int axis, float splitValue);

    bool*               m_flags;

    Vector3f*           m_points;
};

class NearestCenterOctreeReduction : public OctreeReductionBase
{
public:
    NearestCenterOctreeReduction(PointBufferPtr pointBuffer, float voxelSize, size_t minPointsPerVoxel);

    PointBufferPtr getReducedPoints() override;

private:
    void createOctree(size_t* start, size_t* end, const Vector3f& min, const Vector3f& max, unsigned int level = 0);

    size_t* splitPoints(size_t* start, size_t* end, unsigned int axis, float splitValue);

    floatArr                m_points;

    std::vector<size_t>     m_samplePointIndices;
};

class OctreeReductionAlgorithm : public ReductionAlgorithm
{
public:
    OctreeReductionAlgorithm(float voxelSize, size_t minPoints, OctreeType type = RANDOM_SAMPLE) :
            m_octree(nullptr), m_voxelSize(voxelSize), m_minPoints(minPoints), m_reductionType(type) {};

    void setPointBuffer(PointBufferPtr ptr) override
    {
        // Create octree
        switch(m_reductionType)
        {
            case RANDOM_SAMPLE:
                m_octree.reset(new RandomSampleOctreeReduction(ptr, m_voxelSize, m_minPoints));
                break;
            case NEAREST_CENTER:
                m_octree.reset(new NearestCenterOctreeReduction(ptr, m_voxelSize, m_minPoints));
                break;
            default:
                m_octree.reset(new RandomSampleOctreeReduction(ptr, m_voxelSize, m_minPoints));
        }
        m_octree.reset(new RandomSampleOctreeReduction(ptr, m_voxelSize, m_minPoints));
    }

    PointBufferPtr getReducedPoints() override
    {
        // Check if an octree instance exists
        // Otherwise return empty point buffer
        if(m_octree)
        {
            return m_octree->getReducedPoints();
        }
        lvr2::logout::get()
            << lvr2::warning << "[OctreeReduction] Cannot get reduced points without point buffer." << lvr2::endl;

        return PointBufferPtr(new PointBuffer());
    }

private:
    std::shared_ptr<OctreeReductionBase> m_octree;

    float m_voxelSize;

    size_t m_minPoints;

    OctreeType m_reductionType;
};

using OctreeReductionAlgorithmPtr = std::shared_ptr<OctreeReductionAlgorithm>;

} // namespace lvr2

#endif