Skip to content

Commit

Permalink
Feature/first-in-voxel filter (#2699)
Browse files Browse the repository at this point in the history
* Added First Entry Voxel Filter

* Removed unused headers

* Adding rst and minor code changes

* Added tests

* Rename filter name

* doc update

* Added comments in voxelize() and done variable name corrections.

* test update

* test update

* Remove hash_combine and use array instead of BOX3D to store pivot voxel.

* minor formatting

* addressed comments and added improvements

* Added default value to cell.

* minor comment updates.

* Addressed comments.

* Added Pivot initialization flag as a member variable.

* fixed Indents
  • Loading branch information
Pravin Shinde authored and abellgithub committed Sep 5, 2019
1 parent 15d45d4 commit 969b0c9
Show file tree
Hide file tree
Showing 5 changed files with 402 additions and 0 deletions.
37 changes: 37 additions & 0 deletions doc/stages/filters.firstInVoxel.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
.. _filters.firstInVoxel:

filters.firstInVoxel
===============================================================================

The **firstInVoxel filter** is a voxel-based sampling filter.
The input point
cloud is divided into 3D voxels at the given cell size. For each populated
voxel, the first point entering in the voxel is accepted and voxel is marked as populated.
All other points entering in the same voxel are ignored/skipped.

Example
-------

.. code-block:: json
[
"input.las",
{
"type":"filters.firstInVoxel",
"cell":1.0
},
"output.las"
]
.. seealso::

:ref:`filters.voxelcenternearestneighbor` offers a similar solution,
using
the coordinates of the voxel center as the query point in a 3D nearest neighbor search.
The nearest neighbor is then added to the output point cloud, along with any existing dimensions.

Options
-------------------------------------------------------------------------------

cell
Cell size in the ``X``, ``Y``, and ``Z`` dimension. [Default: 0.001]
130 changes: 130 additions & 0 deletions filters/FirstInVoxelFilter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/******************************************************************************
* Copyright (c) 2019, Helix.re
* Contact Person : Pravin Shinde (pravin@helix.re, https://github.com/pravinshinde825)
*
* 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 Hobu, Inc. or Flaxen Geo Consulting 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.
****************************************************************************/

#include "FirstInVoxelFilter.hpp"

namespace pdal
{

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

CREATE_STATIC_STAGE(FirstInVoxelFilter, s_info)

std::string FirstInVoxelFilter::getName() const
{
return s_info.name;
}

void FirstInVoxelFilter::addArgs(ProgramArgs& args)
{
args.add("cell", "Cell size", m_cell, 0.001);
}

PointViewSet FirstInVoxelFilter::run(PointViewPtr view)
{
PointViewPtr output = view->makeNew();
for (PointId id = 0; id < view->size(); ++id)
{
if (voxelize(view->point(id)))
{
output->appendPoint(*view, id);
}
}

PointViewSet viewSet;
viewSet.insert(output);
return viewSet;
}

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;

if (!m_pivotVoxelInitialized)
{
/*
* Save global coordinates of first incoming point's voxel.
* This will act as a Pivot for calculation of local coordinates of the
* voxels.
*/
m_pivotVoxel[0] = gx; // X Coordinate of an Pivot voxel
m_pivotVoxel[1] = gy; // Y Coordinate of an Pivot voxel
m_pivotVoxel[2] = gz; // Z Coordinate of an Pivot voxel
m_pivotVoxelInitialized = true;
}

/*
* Calculate the local voxel coordinates for incoming point, Using the Pivot
* voxel.
*/
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;
}

bool FirstInVoxelFilter::processOne(PointRef& point)
{
return voxelize(point);
}

} // namespace pdal
69 changes: 69 additions & 0 deletions filters/FirstInVoxelFilter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/******************************************************************************
* Copyright (c) 2019, Helix.re
* Contact Person : Pravin Shinde (pravin@helix.re, https://github.com/pravinshinde825)
*
* 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 Hobu, Inc. or Flaxen Geo Consulting 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.
****************************************************************************/

#pragma once

#include <pdal/Filter.hpp>
#include <pdal/Streamable.hpp>

namespace pdal
{

class PointLayout;
class PointView;

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

private:
double m_cell;

virtual void addArgs(ProgramArgs& args) override;
virtual PointViewSet run(PointViewPtr view) override;
bool processOne(PointRef& point) override;
bool voxelize(const PointRef point);
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
1 change: 1 addition & 0 deletions test/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ PDAL_ADD_TEST(pdal_filters_transformation_test FILES
filters/TransformationFilterTest.cpp)
PDAL_ADD_TEST(pdal_filters_hexbin_test FILES filters/HexbinFilterTest.cpp)
PDAL_ADD_TEST(pdal_filters_voxel_test FILES filters/VoxelTest.cpp)
PDAL_ADD_TEST(pdal_filters_first_in_voxel_test FILES filters/FirstInVoxelFilterTest.cpp)

PDAL_ADD_TEST(pdal_app_test FILES apps/AppTest.cpp)
PDAL_ADD_TEST(pdal_app_plugin_test FILES apps/AppPluginTest.cpp)
Expand Down

0 comments on commit 969b0c9

Please sign in to comment.