15 #include <mrpt/containers/yaml.h>
20 #include <mrpt/img/color_maps.h>
21 #include <mrpt/opengl/CPointCloudColoured.h>
22 #include <mrpt/opengl/Scene.h>
31 const mrpt::containers::yaml& c)
48 MRPT_LOG_DEBUG_STREAM(
"Loading these params:\n" << c);
60 "Input point cloud layer '%s' was not found.",
63 const auto& pc = *pcPtr;
72 pcPtr->GetRuntimeClass()->className);
73 if (outPcLarger) outPcLarger->reserve(outPcLarger->size() + pc.size() / 10);
80 pcPtr->GetRuntimeClass()->className);
82 outPcSmaller->reserve(outPcSmaller->size() + pc.size() / 10);
89 pcPtr->GetRuntimeClass()->className);
90 if (outPcOther) outPcOther->reserve(outPcOther->size() + pc.size() / 10);
93 outPcLarger || outPcSmaller,
94 "At least one 'output_layer_larger_curvature' or "
95 "'output_layer_smaller_curvature' output layers must be provided.");
97 const auto& xs = pc.getPointsBufferRef_x();
98 const auto& ys = pc.getPointsBufferRef_y();
99 const auto& zs = pc.getPointsBufferRef_z();
100 const auto* ptrRings = pc.getPointsBufferRef_ring();
101 if (!ptrRings || ptrRings->empty())
104 "Error: this filter needs the input layer '%s' to has a 'ring' "
109 const auto& ringPerPt = *ptrRings;
110 ASSERT_EQUAL_(ringPerPt.size(), xs.size());
112 const size_t N = xs.size();
114 const uint16_t nRings =
115 1 + *std::max_element(ringPerPt.begin(), ringPerPt.end());
117 const auto estimPtsPerRing = N / nRings;
119 MRPT_LOG_DEBUG_STREAM(
120 "nRings: " << nRings <<
" estimPtsPerRing: " << estimPtsPerRing);
121 ASSERT_(nRings > 0 && nRings < 5000 );
123 std::vector<std::vector<size_t>> idxPerRing;
124 idxPerRing.resize(nRings);
125 for (
auto& r : idxPerRing) r.reserve(estimPtsPerRing);
128 auto glPts = mrpt::opengl::CPointCloudColoured::Create();
129 glPts->setPointSize(4.0
f);
130 auto glRawPts = mrpt::opengl::CPointCloudColoured::Create();
131 glRawPts->setPointSize(1.0
f);
134 for (
size_t i = 0; i < N; i++)
136 auto& trg = idxPerRing.at(ringPerPt[i]);
139 auto ringId = ringPerPt[i];
140 auto col = mrpt::img::colormap(
141 mrpt::img::cmJET,
static_cast<double>(ringId) / nRings);
142 glRawPts->insertPoint({xs[i], ys[i], zs[i], col.R, col.G, col.B});
148 auto li = trg.back();
149 const auto lastPt = mrpt::math::TPoint3Df(xs[li], ys[li], zs[li]);
150 const auto pt = mrpt::math::TPoint3Df(xs[i], ys[i], zs[i]);
151 const auto d =
pt - lastPt;
153 if (mrpt::max3(std::abs(
d.x), std::abs(
d.y), std::abs(
d.z)) <
162 glPts->insertPoint({xs[i], ys[i], zs[i], col.R, col.G, col.B});
169 mrpt::opengl::Scene scene;
170 scene.insert(glRawPts);
172 scene.saveToFile(mrpt::format(
"debug_curvature_%04i.3Dscene", iter++));
178 size_t counterLarger = 0, counterLess = 0;
180 for (
size_t ri = 0; ri < nRings; ri++)
182 const auto& idxs = idxPerRing.at(ri);
184 if (idxs.size() <= 3)
188 for (
size_t idx = 0; idx < idxs.size(); idx++)
190 const size_t i = idxs[idx];
192 if (outPcLarger) outPcLarger->insertPointFrom(pc, i);
198 for (
size_t idx = 0; idx < idxs.size(); idx++)
200 const size_t im1 = idxs[idx > 0 ? idx - 1 : idxs.size() - 1];
201 const size_t i = idxs[idx];
202 const size_t ip1 = idxs[idx < idxs.size() - 1 ? idx + 1 : 0];
204 const auto pt = mrpt::math::TPoint3Df(xs[i], ys[i], zs[i]);
205 const auto ptm1 = mrpt::math::TPoint3Df(xs[im1], ys[im1], zs[im1]);
206 const auto ptp1 = mrpt::math::TPoint3Df(xs[ip1], ys[ip1], zs[ip1]);
208 if ((
pt - ptm1).sqrNorm() > maxGapSqr ||
209 (
pt - ptp1).sqrNorm() > maxGapSqr)
214 if (
pt.sqrNorm() < ptm1.sqrNorm())
217 if (outPcLarger) outPcLarger->insertPointFrom(pc, i);
221 if (outPcOther) outPcOther->insertPointFrom(pc, i);
226 const auto v1 = (
pt - ptm1);
227 const auto v2 = (ptp1 -
pt);
228 const auto v1n = v1.norm();
229 const auto v2n = v2.norm();
231 const float score = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
236 if (outPcLarger) outPcLarger->insertPointFrom(pc, i);
241 if (outPcSmaller) outPcSmaller->insertPointFrom(pc, i);
246 MRPT_LOG_DEBUG_STREAM(
247 "[FilterCurvature] Raw input points="
248 << N <<
" larger_curvature=" << counterLarger
249 <<
" smaller_curvature=" << counterLess);