14 #include <mrpt/random/random_shuffle.h>
32 for (
const auto& glLayerKV : pcGlobal.
layers)
34 const auto& glLayerName = glLayerKV.first;
37 std::map<std::string, std::optional<double>> localLayers;
45 for (
const auto& kv : itGlob->second) localLayers[kv.first] = kv.second;
50 localLayers[glLayerName] = {};
53 for (
const auto& localWeight : localLayers)
55 const auto& localLayerName = localWeight.first;
56 const bool hasWeight = localWeight.second.has_value();
59 auto itLocal = pcLocal.
layers.find(localLayerName);
60 if (itLocal == pcLocal.
layers.end())
67 "Local pointcloud layer '%s' not found matching global "
69 localLayerName.c_str(), glLayerName.c_str());
72 const mrpt::maps::CMetricMap::Ptr& glLayer = glLayerKV.second;
75 const mrpt::maps::CMetricMap::Ptr& lcLayerMap = itLocal->second;
80 "Local layer map must be a point cloud, but found type "
82 lcLayerMap->GetRuntimeClass()->className);
84 const size_t nBefore =
out.paired_pt2pt.size();
94 glLayerPts->mark_as_modified();
101 const size_t nAfter =
out.paired_pt2pt.size();
103 if (hasWeight && nAfter != nBefore)
105 const double w = localWeight.second.value();
106 out.point_weights.emplace_back(nAfter - nBefore, w);
118 if (params.has(
"pointLayerMatches"))
120 auto& p = params[
"pointLayerMatches"];
123 ASSERT_(p.isSequence());
129 for (
const auto& entry : p.asSequence())
131 ASSERT_(entry.isMap());
132 const auto& em = entry.asMap();
134 ASSERT_(em.count(
"global"));
135 ASSERT_(em.count(
"local"));
139 const double w = em.count(
"weight") != 0 ? em.at(
"weight").as<
double>() : 1.0;
156 if (
auto val = params.getOrDefault(
"kdtree_leaf_max_points", 0); val > 0)
164 const mrpt::maps::CPointsMap& pcLocal,
const mrpt::poses::CPose3D& localPose,
165 const std::size_t maxLocalPoints,
const uint64_t localPointsSampleSeed)
170 const auto lambdaKeepBBox = [&](
float x,
float y,
float z)
172 mrpt::keep_max(r.localMax.x,
x);
173 mrpt::keep_max(r.localMax.y, y);
174 mrpt::keep_max(r.localMax.z, z);
176 mrpt::keep_min(r.localMin.x,
x);
177 mrpt::keep_min(r.localMin.y, y);
178 mrpt::keep_min(r.localMin.z, z);
181 const auto& lxs = pcLocal.getPointsBufferRef_x();
182 const auto& lys = pcLocal.getPointsBufferRef_y();
183 const auto& lzs = pcLocal.getPointsBufferRef_z();
185 const size_t nLocalPoints = pcLocal.size();
187 if (maxLocalPoints == 0 || nLocalPoints <= maxLocalPoints)
190 r.x_locals.resize(nLocalPoints);
191 r.y_locals.resize(nLocalPoints);
192 r.z_locals.resize(nLocalPoints);
194 for (
size_t i = 0; i < nLocalPoints; i++)
196 localPose.composePoint(
197 lxs[i], lys[i], lzs[i], r.x_locals[i], r.y_locals[i], r.z_locals[i]);
198 lambdaKeepBBox(r.x_locals[i], r.y_locals[i], r.z_locals[i]);
204 r.idxs.emplace(maxLocalPoints);
205 std::iota(r.idxs->begin(), r.idxs->end(), 0);
207 const unsigned int seed = localPointsSampleSeed != 0
208 ? localPointsSampleSeed
209 : std::chrono::system_clock::now().time_since_epoch().count();
211 mrpt::random::partial_shuffle(
212 r.idxs->begin(), r.idxs->end(), std::default_random_engine(seed), maxLocalPoints);
214 r.x_locals.resize(maxLocalPoints);
215 r.y_locals.resize(maxLocalPoints);
216 r.z_locals.resize(maxLocalPoints);
218 for (
size_t ri = 0; ri < maxLocalPoints; ri++)
220 const auto i = (*r.idxs)[ri];
221 localPose.composePoint(
222 lxs[i], lys[i], lzs[i], r.x_locals[ri], r.y_locals[ri], r.z_locals[ri]);
223 lambdaKeepBBox(r.x_locals[ri], r.y_locals[ri], r.z_locals[ri]);