Skip to content

Commit 71acaf2

Browse files
committed
Fix tests for RadiusAssignFilter
1 parent e5482d3 commit 71acaf2

File tree

4 files changed

+2195
-49
lines changed

4 files changed

+2195
-49
lines changed

filters/RadiusAssignFilter.cpp

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ void RadiusAssignFilter::addArgs(ProgramArgs& args)
3737
args.add("update_expression", "Value to assign to dimension of points of src_domain "
3838
"that have at least one neighbor in reference domain based on expression.",
3939
m_updateExpr);
40+
args.add("is3d", "Search in 3d", m_search3d, false );
41+
args.add("max2d_above", "if search in 2d : upward maximum distance in Z for potential neighbors "
42+
"(corresponds to a search in a cylinder with a height = max2d_above above the source point). "
43+
"Values < 0 mean infinite height", m_max2dAbove, -1.);
44+
args.add("max2d_below", "if search in 2d : downward maximum distance in Z for potential neighbors ("
45+
"corresponds to a search in a cylinder with a height = max2d_below below the source point). "
46+
"Values < 0 mean infinite height", m_max2dBelow, -1.);
47+
4048
}
4149

4250

@@ -104,27 +112,49 @@ void RadiusAssignFilter::ready(PointTableRef)
104112
}
105113

106114

107-
void RadiusAssignFilter::doOneNoDomain(PointRef &point, KD2Index &kdi)
115+
void RadiusAssignFilter::doOneNoDomain(PointRef &pointSrc)
108116
{
109-
PointIdList iNeighbors = kdi.radius(point, m_radius);
117+
PointIdList iNeighbors;
118+
if (m_search3d) iNeighbors = refView->build3dIndex().radius(pointSrc, m_radius);
119+
else iNeighbors = refView->build2dIndex().radius(pointSrc, m_radius);
120+
121+
110122
if (iNeighbors.size() == 0)
111123
return;
112124

113-
m_ptsToUpdate.push_back(point.pointId());
125+
if (!m_search3d && (m_max2dBelow>=0 || m_max2dAbove>=0))
126+
{
127+
double Zsrc = pointSrc.getFieldAs<double>(Dimension::Id::Z);
128+
129+
bool take (false);
130+
for (PointId ptId : iNeighbors)
131+
{
132+
double Zref = refView->point(ptId).getFieldAs<double>(Dimension::Id::Z);
133+
if (m_max2dAbove>=0 && Zref>Zsrc && (Zref-Zsrc)>m_max2dAbove) continue;
134+
if (m_max2dBelow>=0 && Zsrc>Zref && (Zsrc-Zref)>m_max2dBelow) continue;
135+
take = true;
136+
break;
137+
}
138+
139+
if (!take) return;
140+
}
141+
142+
143+
m_ptsToUpdate.push_back(pointSrc.pointId());
114144

115145
}
116146

117147
// update point. kdi and temp both reference the NN point cloud
118-
bool RadiusAssignFilter::doOne(PointRef& point, KD2Index &kdi)
148+
bool RadiusAssignFilter::doOne(PointRef& pointSrc)
119149
{
120150
if (m_srcDomain.empty()) // No domain, process all points
121-
doOneNoDomain(point, kdi);
151+
doOneNoDomain(pointSrc);
122152

123153
for (DimRange& r : m_srcDomain)
124154
{ // process only points that satisfy a domain condition
125-
if (r.valuePasses(point.getFieldAs<double>(r.m_id)))
155+
if (r.valuePasses(pointSrc.getFieldAs<double>(r.m_id)))
126156
{
127-
doOneNoDomain(point, kdi);
157+
doOneNoDomain(pointSrc);
128158
break;
129159
}
130160
}
@@ -133,22 +163,21 @@ bool RadiusAssignFilter::doOne(PointRef& point, KD2Index &kdi)
133163

134164
void RadiusAssignFilter::filter(PointView& view)
135165
{
136-
PointRef point_src(view, 0);
137-
// Create a kd tree only with the points in the reference domain (to make the search faster)
138-
PointViewPtr refView;
139-
PointRef temp(view, 0);
166+
PointRef pointTemp(view, 0);
167+
168+
// Create reference domain view
169+
refView = view.makeNew();
140170
if (m_referenceDomain.empty())
141171
for (PointId id = 0; id < view.size(); ++id)
142172
refView->appendPoint(view, id);
143173
else
144174
{
145-
refView = view.makeNew();
146175
for (PointId id = 0; id < view.size(); ++id)
147176
{
148177
for (DimRange& r : m_referenceDomain)
149-
{ // process only points that satisfy a domain condition
150-
temp.setPointId(id);
151-
if (r.valuePasses(temp.getFieldAs<double>(r.m_id)))
178+
{
179+
pointTemp.setPointId(id);
180+
if (r.valuePasses(pointTemp.getFieldAs<double>(r.m_id)))
152181
{
153182
refView->appendPoint(view, id);
154183
break;
@@ -157,20 +186,23 @@ void RadiusAssignFilter::filter(PointView& view)
157186
}
158187
}
159188

160-
KD2Index& kdiRef = refView->build2dIndex();
189+
// Process all points (mark them if they need to be updated)
161190
for (PointId id = 0; id < view.size(); ++id)
162191
{
163-
point_src.setPointId(id);
164-
doOne(point_src, kdiRef);
192+
pointTemp.setPointId(id);
193+
doOne(pointTemp);
165194
}
195+
196+
166197
for (auto id: m_ptsToUpdate)
167198
{
168-
temp.setPointId(id);
199+
pointTemp.setPointId(id);
169200
for (expr::AssignStatement& expr : m_updateExpr)
170-
// if (expr.conditionalExpr().eval(temp))
171-
temp.setField(expr.identExpr().eval(), expr.valueExpr().eval(temp));
201+
if (expr.conditionalExpr().eval(pointTemp))
202+
pointTemp.setField(expr.identExpr().eval(), expr.valueExpr().eval(pointTemp));
172203
}
173204
}
174205

206+
175207
} // namespace pdal
176208

filters/RadiusAssignFilter.hpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ class PDAL_DLL RadiusAssignFilter : public Filter
2828
virtual void addArgs(ProgramArgs& args);
2929
virtual void preparedDomain(std::vector<DimRange> &domain, PointLayoutPtr layout);
3030
virtual void prepared(PointTableRef table);
31-
bool doOne(PointRef& point, KD2Index &kdi);
32-
void doOneNoDomain(PointRef &point, KD2Index &kdi);
31+
bool doOne(PointRef& point);
32+
void doOneNoDomain(PointRef &point);
3333
virtual void filter(PointView& view);
3434
virtual void initializeDomain(StringList domainSpec, std::vector<DimRange> &domain);
3535
virtual void initialize();
@@ -43,6 +43,11 @@ class PDAL_DLL RadiusAssignFilter : public Filter
4343
std::vector<DimRange> m_srcDomain;
4444
double m_radius;
4545
std::vector<expr::AssignStatement> m_updateExpr;
46+
bool m_search3d;
47+
double m_max2dAbove;
48+
double m_max2dBelow;
49+
50+
PointViewPtr refView;
4651
PointIdList m_ptsToUpdate;
4752
};
4853

0 commit comments

Comments
 (0)