Skip to content

Commit 8a42e7d

Browse files
chambbjhobu
andauthored
Add some logging and error handling for covariancefeature edge cases (PDAL#4707)
* Add some logging and error handling for covariancefeature edge cases * Log empty covariance in several filters * bump fixed builder, add geotiff package to current --------- Co-authored-by: Howard Butler <[email protected]>
1 parent 7d35f50 commit 8a42e7d

File tree

7 files changed

+73
-6
lines changed

7 files changed

+73
-6
lines changed

filters/ApproximateCoplanarFilter.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,17 @@ void ApproximateCoplanarFilter::filter(PointView& view)
8989
// compute covariance of the neighborhood
9090
Matrix3d B = math::computeCovariance(view, ids);
9191

92+
// Check if the covariance matrix is all zeros
93+
if (B.isZero())
94+
{
95+
log()->get(LogLevel::Info)
96+
<< "Skipping point " << p.pointId()
97+
<< ". Covariance matrix is all zeros. This suggests a large "
98+
"number of redundant points. Consider using filters.sample "
99+
"with a small radius to remove redundant points.\n";
100+
continue;
101+
}
102+
92103
// perform the eigen decomposition
93104
Eigen::SelfAdjointEigenSolver<Matrix3d> solver(B);
94105
if (solver.info() != Eigen::Success)

filters/CovarianceFeaturesFilter.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ void CovarianceFeaturesFilter::filter(PointView& view)
181181
if (npoints % m_threads) chunk_size++;
182182
std::vector<std::thread> threadList(m_threads);
183183

184+
log()->get(LogLevel::Debug) << "Processing " << npoints << " points in "
185+
<< m_threads << " threads.\n";
186+
184187
for(int t = 0; t < m_threads; t++)
185188
{
186189
threadList[t] = std::thread(
@@ -213,8 +216,12 @@ void CovarianceFeaturesFilter::setDimensionality(PointView &view, const PointId
213216
else if (m_radiusArg->set())
214217
{
215218
ids = kdi.radius(p, m_radius);
216-
if (ids.size() < (size_t)m_minK)
219+
if (ids.size() < (size_t)m_minK) {
220+
log()->get(LogLevel::Info)
221+
<< "Skipping point " << id << ". Found " << ids.size()
222+
<< " neighbors but required " << m_minK << ".\n";
217223
return;
224+
}
218225
}
219226
else
220227
{
@@ -224,6 +231,17 @@ void CovarianceFeaturesFilter::setDimensionality(PointView &view, const PointId
224231
// compute covariance of the neighborhood
225232
auto B = math::computeCovariance(view, ids);
226233

234+
// Check if the covariance matrix is all zeros
235+
if (B.isZero())
236+
{
237+
log()->get(LogLevel::Info)
238+
<< "Skipping point " << id
239+
<< ". Covariance matrix is all zeros. This suggests a large number "
240+
"of redundant points. Consider using filters.sample with a "
241+
"small radius to remove redundant points.\n";
242+
return;
243+
}
244+
227245
// perform the eigen decomposition
228246
SelfAdjointEigenSolver<Matrix3d> solver(B);
229247
if (solver.info() != Success)

filters/EigenvaluesFilter.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,12 @@ void EigenvaluesFilter::filter(PointView& view)
127127
// if insufficient number of neighbors, eigen solver will fail
128128
// anyway, it may be okay to silently return without setting any of
129129
// the computed features?
130-
if (ids.size() < (size_t)m_args->m_minK)
130+
if (ids.size() < (size_t)m_args->m_minK) {
131+
log()->get(LogLevel::Info)
132+
<< "Skipping point " << p.pointId() << ". Found " << ids.size()
133+
<< " neighbors but required " << m_args->m_minK << ".\n";
131134
continue;
135+
}
132136
}
133137
else
134138
{
@@ -138,6 +142,17 @@ void EigenvaluesFilter::filter(PointView& view)
138142
// compute covariance of the neighborhood
139143
Matrix3d B = math::computeCovariance(view, ids);
140144

145+
// Check if the covariance matrix is all zeros
146+
if (B.isZero())
147+
{
148+
log()->get(LogLevel::Info)
149+
<< "Skipping point " << p.pointId()
150+
<< ". Covariance matrix is all zeros. This suggests a large "
151+
"number of redundant points. Consider using filters.sample "
152+
"with a small radius to remove redundant points.\n";
153+
continue;
154+
}
155+
141156
// perform the eigen decomposition
142157
Eigen::SelfAdjointEigenSolver<Matrix3d> solver(B);
143158
if (solver.info() != Eigen::Success)

filters/NormalFilter.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,18 @@ void NormalFilter::compute(PointView& view, KD3Index& kdi)
133133
// neighborhood composed of k-nearest neighbors.
134134
PointIdList neighbors = kdi.neighbors(p.pointId(), m_args->m_knn);
135135
auto B = math::computeCovariance(view, neighbors);
136+
137+
// Check if the covariance matrix is all zeros
138+
if (B.isZero())
139+
{
140+
log()->get(LogLevel::Info)
141+
<< "Skipping point " << p.pointId()
142+
<< ". Covariance matrix is all zeros. This suggests a large "
143+
"number of redundant points. Consider using filters.sample "
144+
"with a small radius to remove redundant points.\n";
145+
continue;
146+
}
147+
136148
SelfAdjointEigenSolver<Matrix3d> solver(B);
137149
if (solver.info() != Success)
138150
throwError("Cannot perform eigen decomposition.");

filters/PlaneFitFilter.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,17 @@ void PlaneFitFilter::setPlaneFit(PointView& view, const PointId& i)
134134
// Compute covariance of the neighbors.
135135
Matrix3d B = math::computeCovariance(view, neighbors);
136136

137+
// Check if the covariance matrix is all zeros
138+
if (B.isZero())
139+
{
140+
log()->get(LogLevel::Info)
141+
<< "Skipping point " << i
142+
<< ". Covariance matrix is all zeros. This suggests a large "
143+
"number of redundant points. Consider using filters.sample "
144+
"with a small radius to remove redundant points.\n";
145+
return;
146+
}
147+
137148
// Perform the eigen decomposition, using the eigenvector of the smallest
138149
// eigenvalue as the normal.
139150
Eigen::SelfAdjointEigenSolver<Matrix3d> solver(B);

scripts/ci/current-environment.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ name: pdal-build
22
channels:
33
- conda-forge
44
dependencies:
5-
- libgdal
5+
- libgdal-core
6+
- geotiff
67
- libpq
78
- curl
89
- hdf5

scripts/ci/fixed-environment.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ name: pdal-build
22
channels:
33
- conda-forge
44
dependencies:
5-
- libgdal=3.8
6-
- boa
5+
- libgdal=3.9
76
- libpq
87
- curl
98
- hdf5
@@ -13,7 +12,7 @@ dependencies:
1312
- openssl
1413
- nitro
1514
- ceres-solver
16-
- python=3.10
15+
- python=3.12
1716
- conda
1817
- mamba
1918
- conda-build

0 commit comments

Comments
 (0)