Skip to content

Commit

Permalink
Small voxel filter fixes (#2720)
Browse files Browse the repository at this point in the history
* Small fixes for firstInVoxel filter.

* Set origin in test to 0.

* Improve description as recommended (thanks Brad).
  • Loading branch information
abellgithub committed Sep 5, 2019
1 parent db0123a commit 4f8efe6
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 38 deletions.
File renamed without changes.
4 changes: 4 additions & 0 deletions doc/stages/filters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ the input. These filters will invalidate an existing KD-tree.

filters.crop
filters.decimation
filters.firstinvoxel
filters.head
filters.iqr
filters.locate
Expand All @@ -227,6 +228,9 @@ the input. These filters will invalidate an existing KD-tree.
Remove points that are in a raster cell but have a value far from the
value of the raster.

:ref:`filters.firstinvoxel`
Retain the first point detected in each voxel.

:ref:`filters.head`
Return N points from beginning of the point cloud.

Expand Down
47 changes: 21 additions & 26 deletions filters/FirstInVoxelFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,19 @@
namespace pdal
{

static StaticPluginInfo const s_info{"filters.firstInVoxel",
"First Entry Voxel Filter",
"http://pdal.io/stages/filters.firstInVoxel.html"};
static StaticPluginInfo const s_info
{
"filters.firstinvoxel",
"First Entry Voxel Filter",
"http://pdal.io/stages/filters.firstinvoxel.html"
};

CREATE_STATIC_STAGE(FirstInVoxelFilter, s_info)

FirstInVoxelFilter::FirstInVoxelFilter()
{}


std::string FirstInVoxelFilter::getName() const
{
return s_info.name;
Expand All @@ -54,6 +61,13 @@ void FirstInVoxelFilter::addArgs(ProgramArgs& args)
args.add("cell", "Cell size", m_cell, 0.001);
}


void FirstInVoxelFilter::ready(PointTableRef)
{
m_pivotVoxelInitialized = false;
}


PointViewSet FirstInVoxelFilter::run(PointViewPtr view)
{
PointViewPtr output = view->makeNew();
Expand All @@ -76,9 +90,9 @@ bool FirstInVoxelFilter::voxelize(const PointRef point)
* Calculate the voxel coordinates for the incoming point.
* gx, gy, gz will be the global coordinates from (0, 0, 0).
*/
int gx = point.getFieldAs<double>(Dimension::Id::X) / m_cell;
int gy = point.getFieldAs<double>(Dimension::Id::Y) / m_cell;
int gz = point.getFieldAs<double>(Dimension::Id::Z) / m_cell;
int gx = std::floor(point.getFieldAs<double>(Dimension::Id::X) / m_cell);
int gy = std::floor(point.getFieldAs<double>(Dimension::Id::Y) / m_cell);
int gz = std::floor(point.getFieldAs<double>(Dimension::Id::Z) / m_cell);

if (!m_pivotVoxelInitialized)
{
Expand All @@ -100,26 +114,7 @@ bool FirstInVoxelFilter::voxelize(const PointRef point)
auto t = std::make_tuple(gx - m_pivotVoxel[0], gy - m_pivotVoxel[1],
gz - m_pivotVoxel[2]);

/*
* Is already in populates voxels?
*/
auto pi = m_populatedVoxels.find(t);
if (pi == m_populatedVoxels.end())
{
/*
* No, Voxel is not there in populated voxels.
* Mark the voxel as populated by making entry in m_populatedVoxels.
* Accept this point.
*/
m_populatedVoxels.insert(t);
return true;
}
/*
* Yes, Voxel is already in populated voxels.
* That means the voxel is already contains a point.
* Ignore this point.
*/
return false;
return (m_populatedVoxels.insert(t).second);
}

bool FirstInVoxelFilter::processOne(PointRef& point)
Expand Down
20 changes: 11 additions & 9 deletions filters/FirstInVoxelFilter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,26 +44,28 @@ namespace pdal
class PointLayout;
class PointView;

class PDAL_DLL FirstInVoxelFilter : public Filter, Streamable
class PDAL_DLL FirstInVoxelFilter : public Filter, public Streamable
{
public:
FirstInVoxelFilter() : Filter(), Streamable(), m_pivotVoxelInitialized(false) {}
std::string getName() const;
FirstInVoxelFilter();
FirstInVoxelFilter& operator=(const FirstInVoxelFilter&) = delete;
FirstInVoxelFilter(const FirstInVoxelFilter&) = delete;

private:
double m_cell;
std::string getName() const override;

private:
virtual void addArgs(ProgramArgs& args) override;
virtual PointViewSet run(PointViewPtr view) override;
bool processOne(PointRef& point) override;
virtual void ready(PointTableRef) override;
virtual bool processOne(PointRef& point) override;

bool voxelize(const PointRef point);

double m_cell;
std::set<std::tuple<int,int,int>> m_populatedVoxels;
int m_pivotVoxel[3]; // [0]: X dimension, [1]: Y dimension, [2]: Z
// dimension.
bool m_pivotVoxelInitialized;

FirstInVoxelFilter& operator=(const FirstInVoxelFilter&); // not implemented
FirstInVoxelFilter(const FirstInVoxelFilter&); // not implemented
};

} // namespace pdal
67 changes: 64 additions & 3 deletions test/unit/filters/FirstInVoxelFilterTest.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/******************************************************************************
* Copyright (c) 2019, Helix.re
* Contact Person : Pravin Shinde (pravin@helix.re, https://github.com/pravinshinde825)
* Contact Person : Pravin Shinde (pravin@helix.re,
* https://github.com/pravinshinde825)
*
* All rights reserved.
*
Expand Down Expand Up @@ -36,8 +37,8 @@
#include <pdal/pdal_test_main.hpp>

#include <pdal/StageFactory.hpp>
#include <pdal/Reader.hpp>
#include <pdal/Streamable.hpp>
#include "io/BufferReader.hpp"
#include "filters/FirstInVoxelFilter.hpp"

#include "Support.hpp"
Expand All @@ -54,7 +55,7 @@ TEST(FirstInVoxelFilterTest, standard)
ro.add("filename", Support::datapath("las/autzen_trim.las"));
reader->setOptions(ro);

Stage *filter = fac.createStage("filters.firstInVoxel");
Stage *filter = fac.createStage("filters.firstinvoxel");
Options fo;
fo.add("cell", 10);
filter->setOptions(fo);
Expand All @@ -68,6 +69,66 @@ TEST(FirstInVoxelFilterTest, standard)
EXPECT_EQ(v->size(), 7788U);
}

TEST(FirstInVoxelFilterTest, origin)
{
using namespace Dimension;

PointTable t;
t.layout()->registerDims({Id::X, Id::Y, Id::Z});
PointViewPtr v(new PointView(t));

v->setField(Id::X, 0, 1);
v->setField(Id::Y, 0, 1);
v->setField(Id::Z, 0, 1);

v->setField(Id::X, 1, 1);
v->setField(Id::Y, 1, 1);
v->setField(Id::Z, 1, 1);

v->setField(Id::X, 2, 1);
v->setField(Id::Y, 2, 1);
v->setField(Id::Z, 2, -1);

v->setField(Id::X, 3, 1);
v->setField(Id::Y, 3, -1);
v->setField(Id::Z, 3, 1);

v->setField(Id::X, 4, 1);
v->setField(Id::Y, 4, -1);
v->setField(Id::Z, 4, -1);

v->setField(Id::X, 5, -1);
v->setField(Id::Y, 5, 1);
v->setField(Id::Z, 5, 1);

v->setField(Id::X, 6, -1);
v->setField(Id::Y, 6, 1);
v->setField(Id::Z, 6, -1);

v->setField(Id::X, 7, -1);
v->setField(Id::Y, 7, -1);
v->setField(Id::Z, 7, 1);

v->setField(Id::X, 8, -1);
v->setField(Id::Y, 8, -1);
v->setField(Id::Z, 8, -1);

BufferReader r;
r.addView(v);

FirstInVoxelFilter f;
Options o;
o.add("cell", 10);
f.setOptions(o);
f.setInput(r);

f.prepare(t);
PointViewSet s = f.execute(t);
EXPECT_EQ(s.size(), 1u);
v = *s.begin();
EXPECT_EQ(v->size(), 8u);
}

TEST(FirstInVoxelFilterTest, stream)
{
using namespace Dimension;
Expand Down

0 comments on commit 4f8efe6

Please sign in to comment.