Skip to content

Commit

Permalink
Use signed int for clustering/grouping
Browse files Browse the repository at this point in the history
Modify DBSCAN to use the standard ClusterID dimension, which is now
defined as int64. The Groupby filter is similarly instructed to evaluate
int64. This allows clustering algorithms like DBSCAN to use -1 to
indicate noise.
  • Loading branch information
chambbj committed May 21, 2020
1 parent 026ccff commit f0acbe5
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 15 deletions.
25 changes: 13 additions & 12 deletions filters/DBSCANFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
namespace pdal
{

using namespace Dimension;

static StaticPluginInfo const s_info{
"filters.dbscan", "DBSCAN Clustering.",
"http://pdal.io/stages/filters.dbscan.html"};
Expand All @@ -71,8 +73,7 @@ void DBSCANFilter::addArgs(ProgramArgs& args)

void DBSCANFilter::addDimensions(PointLayoutPtr layout)
{
m_cluster =
layout->registerOrAssignDim("ClusterID", Dimension::Type::Signed64);
layout->registerDim(Id::ClusterID);
}

void DBSCANFilter::prepared(PointTableRef table)
Expand All @@ -83,8 +84,8 @@ void DBSCANFilter::prepared(PointTableRef table)
{
for (std::string& s : m_dimStringList)
{
Dimension::Id id = layout->findDim(s);
if (id == Dimension::Id::Unknown)
Id id = layout->findDim(s);
if (id == Id::Unknown)
throwError("Invalid dimension '" + s +
"' specified for "
"'dimensions' option.");
Expand All @@ -105,22 +106,22 @@ void DBSCANFilter::filter(PointView& view)
for (PointId idx = 0; idx < view.size(); ++idx)
{
neighbors[idx] = kdfi.radius(idx, m_eps);
view.setField(m_cluster, idx, -2);
view.setField(Id::ClusterID, idx, -2);
}

// Second pass through point cloud performs DBSCAN clustering.
int64_t cluster_label = 0;
for (PointId idx = 0; idx < view.size(); ++idx)
{
// Point has already been labeled, so move on to next.
if (view.getFieldAs<int64_t>(m_cluster, idx) != -2)
if (view.getFieldAs<int64_t>(Id::ClusterID, idx) != -2)
continue;

// Density of the neighborhood does not meet minimum number of points
// constraint, label as noise.
if (neighbors[idx].size() < m_minPoints)
{
view.setField(m_cluster, idx, -1);
view.setField(Id::ClusterID, idx, -1);
continue;
}

Expand All @@ -132,7 +133,7 @@ void DBSCANFilter::filter(PointView& view)
neighbors_visited.insert(idx);

// Unlabeled point encountered; assign cluster label.
view.setField(m_cluster, idx, cluster_label);
view.setField(Id::ClusterID, idx, cluster_label);

// Consider all neighbors.
while (!neighbors_next.empty())
Expand All @@ -143,15 +144,15 @@ void DBSCANFilter::filter(PointView& view)
neighbors_visited.insert(p);

// Reassign cluster label to neighbor previously marked as noise.
if (view.getFieldAs<int64_t>(m_cluster, p) == -1)
view.setField(m_cluster, p, cluster_label);
if (view.getFieldAs<int64_t>(Id::ClusterID, p) == -1)
view.setField(Id::ClusterID, p, cluster_label);

// Neighbor has already been labeled, so move on to next.
if (view.getFieldAs<int64_t>(m_cluster, p) != -2)
if (view.getFieldAs<int64_t>(Id::ClusterID, p) != -2)
continue;

// Assign cluster label to neighbor.
view.setField(m_cluster, p, cluster_label);
view.setField(Id::ClusterID, p, cluster_label);

// If density of neighbor's neighborhood is sufficient, add it's
// neighbors to the set of neighbors to consider if they are not
Expand Down
1 change: 0 additions & 1 deletion filters/DBSCANFilter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ class PDAL_DLL DBSCANFilter : public Filter
private:
uint64_t m_minPoints;
double m_eps;
Dimension::Id m_cluster;
StringList m_dimStringList;
Dimension::IdList m_dimIdList;

Expand Down
2 changes: 1 addition & 1 deletion filters/GroupByFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ PointViewSet GroupByFilter::run(PointViewPtr inView)

for (PointId idx = 0; idx < inView->size(); idx++)
{
uint64_t val = inView->getFieldAs<uint64_t>(m_dimId, idx);
int64_t val = inView->getFieldAs<int64_t>(m_dimId, idx);
PointViewPtr& outView = m_viewMap[val];
if (!outView)
outView = inView->makeNew();
Expand Down
2 changes: 1 addition & 1 deletion pdal/Dimension.json
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@
},
{
"name": "ClusterID",
"type": "uint64_t",
"type": "int64_t",
"description": "ID assigned to a point by a point-clustering algorithm."
},
{
Expand Down

0 comments on commit f0acbe5

Please sign in to comment.