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>
46 MRPT_LOG_DEBUG_STREAM(
"Loading these params:\n" << c);
61 const auto& pc = *pcPtr;
70 pcPtr->GetRuntimeClass()->className);
71 if (outPcLarger) outPcLarger->reserve(outPcLarger->size() + pc.size() / 10);
78 pcPtr->GetRuntimeClass()->className);
79 if (outPcSmaller) outPcSmaller->reserve(outPcSmaller->size() + pc.size() / 10);
86 pcPtr->GetRuntimeClass()->className);
87 if (outPcOther) outPcOther->reserve(outPcOther->size() + pc.size() / 10);
90 outPcLarger || outPcSmaller,
91 "At least one 'output_layer_larger_curvature' or "
92 "'output_layer_smaller_curvature' output layers must be provided.");
94 const auto& xs = pc.getPointsBufferRef_x();
95 const auto& ys = pc.getPointsBufferRef_y();
96 const auto& zs = pc.getPointsBufferRef_z();
97 const auto* ptrRings = pc.getPointsBufferRef_ring();
98 if (!ptrRings || ptrRings->empty())
101 "Error: this filter needs the input layer '%s' to has a 'ring' "
106 const auto& ringPerPt = *ptrRings;
107 ASSERT_EQUAL_(ringPerPt.size(), xs.size());
109 const size_t N = xs.size();
111 const uint16_t nRings = 1 + *std::max_element(ringPerPt.begin(), ringPerPt.end());
113 const auto estimPtsPerRing = N / nRings;
115 MRPT_LOG_DEBUG_STREAM(
"nRings: " << nRings <<
" estimPtsPerRing: " << estimPtsPerRing);
116 ASSERT_(nRings > 0 && nRings < 5000 );
118 std::vector<std::vector<size_t>> idxPerRing;
119 idxPerRing.resize(nRings);
120 for (
auto& r : idxPerRing) r.reserve(estimPtsPerRing);
123 auto glPts = mrpt::opengl::CPointCloudColoured::Create();
124 glPts->setPointSize(4.0
f);
125 auto glRawPts = mrpt::opengl::CPointCloudColoured::Create();
126 glRawPts->setPointSize(1.0
f);
129 for (
size_t i = 0; i < N; i++)
131 auto& trg = idxPerRing.at(ringPerPt[i]);
134 auto ringId = ringPerPt[i];
135 auto col = mrpt::img::colormap(mrpt::img::cmJET,
static_cast<double>(ringId) / nRings);
136 glRawPts->insertPoint({xs[i], ys[i], zs[i], col.R, col.G, col.B});
142 auto li = trg.back();
143 const auto lastPt = mrpt::math::TPoint3Df(xs[li], ys[li], zs[li]);
144 const auto pt = mrpt::math::TPoint3Df(xs[i], ys[i], zs[i]);
145 const auto d =
pt - lastPt;
155 glPts->insertPoint({xs[i], ys[i], zs[i], col.R, col.G, col.B});
162 mrpt::opengl::Scene scene;
163 scene.insert(glRawPts);
165 scene.saveToFile(mrpt::format(
"debug_curvature_%04i.3Dscene", iter++));
171 size_t counterLarger = 0, counterLess = 0;
173 for (
size_t ri = 0; ri < nRings; ri++)
175 const auto& idxs = idxPerRing.at(ri);
177 if (idxs.size() <= 3)
181 for (
size_t idx = 0; idx < idxs.size(); idx++)
183 const size_t i = idxs[idx];
185 if (outPcLarger) outPcLarger->insertPointFrom(pc, i);
191 for (
size_t idx = 0; idx < idxs.size(); idx++)
193 const size_t im1 = idxs[idx > 0 ? idx - 1 : idxs.size() - 1];
194 const size_t i = idxs[idx];
195 const size_t ip1 = idxs[idx < idxs.size() - 1 ? idx + 1 : 0];
197 const auto pt = mrpt::math::TPoint3Df(xs[i], ys[i], zs[i]);
198 const auto ptm1 = mrpt::math::TPoint3Df(xs[im1], ys[im1], zs[im1]);
199 const auto ptp1 = mrpt::math::TPoint3Df(xs[ip1], ys[ip1], zs[ip1]);
201 if ((
pt - ptm1).sqrNorm() > maxGapSqr || (
pt - ptp1).sqrNorm() > maxGapSqr)
206 if (
pt.sqrNorm() < ptm1.sqrNorm())
209 if (outPcLarger) outPcLarger->insertPointFrom(pc, i);
213 if (outPcOther) outPcOther->insertPointFrom(pc, i);
218 const auto v1 = (
pt - ptm1);
219 const auto v2 = (ptp1 -
pt);
220 const auto v1n = v1.norm();
221 const auto v2n = v2.norm();
223 const float score = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
228 if (outPcLarger) outPcLarger->insertPointFrom(pc, i);
233 if (outPcSmaller) outPcSmaller->insertPointFrom(pc, i);
238 MRPT_LOG_DEBUG_STREAM(
239 "[FilterCurvature] Raw input points=" << N <<
" larger_curvature=" << counterLarger
240 <<
" smaller_curvature=" << counterLess);