Ponca  80e34c4ed3322bafe25349c3ea7523ca4a3aa60d
Point Cloud Analysis library
Loading...
Searching...
No Matches
basket.h
1/*
2 This Source Code Form is subject to the terms of the Mozilla Public
3 License, v. 2.0. If a copy of the MPL was not distributed with this
4 file, You can obtain one at http://mozilla.org/MPL/2.0/.
5*/
6
7#pragma once
8
9#include "defines.h"
10#include "enums.h"
11#include "primitive.h"
12#include "compute.h"
13
14namespace Ponca
15{
16
17#define BSKNF typename BasketType::NeighborFilter
18#define BSKP typename BasketType::DataPoint
19
20#ifndef PARSED_WITH_DOXYGEN
22namespace internal
23{
33 template <class P, class NF,
34 typename Aggregate,
35 template <class, class, typename> class Ext,
36 template <class, class, typename> class... Exts>
37 struct BasketAggregateImpl
38 {
39 using type = typename BasketAggregateImpl<P, NF, Ext<P, NF, Aggregate>, Exts...>::type;
40 };
41
50 template <class P, class NF,
51 typename Aggregate,
52 template <class, class, typename> class Ext>
53 struct BasketAggregateImpl<P, NF, Aggregate, Ext>
54 {
55 using type = Ext<P, NF, Aggregate>;
56 };
57
66 template <class P, class NF,
67 template <class, class, typename> class... Exts>
68 struct BasketAggregate : BasketAggregateImpl<P, NF, PrimitiveBase<P, NF>, Exts...>
69 {
70 };
71
81 template <int Type,
82 typename BasketType,
83 template <class, class, int, typename> class Ext,
84 template <class, class, int, typename> class... Exts>
85 struct BasketDiffAggregateImpl
86 {
87 using type = typename BasketDiffAggregateImpl<Type, Ext<BSKP, BSKNF, Type, BasketType>, Exts...>::type;
88 };
89
97 template <int Type,
98 typename BasketType,
99 template <class, class, int, typename> class Ext>
100 struct BasketDiffAggregateImpl<Type, BasketType, Ext>
101 {
102 using type = Ext<BSKP, BSKNF, Type, BasketType>;
103 };
104
113 template <typename BasketType, int Type,
114 template <class, class, int, typename> class... Exts>
115 struct BasketDiffAggregate : BasketDiffAggregateImpl<Type, BasketType, PrimitiveDer, Exts...>
116 {
117 };
118}
119#endif
120
142 template<typename _Derived, typename _Base>
143 struct BasketComputeObject : public ComputeObject<_Derived>, public virtual _Base {
144 using Base = _Base;
145 using Derived = _Derived;
146 using Scalar = typename Base::Scalar;
147 protected:
149 public:
150 using ComputeObject<Derived>::compute; // Makes the default compute(container) accessible when using a CPU architecture
151
158 template <typename IteratorBegin, typename IteratorEnd>
159 PONCA_MULTIARCH inline FIT_RESULT compute(const IteratorBegin& begin, const IteratorEnd& end){
160 Base::init();
161 FIT_RESULT res = UNDEFINED;
162
163 do {
164 derived().startNewPass();
165 for (auto it = begin; it != end; ++it){
166 derived().addNeighbor(*it);
167 }
168 res = Base::finalize();
169 } while ( res == NEED_OTHER_PASS );
170
171 return res;
172 }
173
181 template <typename IndexRange, typename PointContainer>
182 PONCA_MULTIARCH inline FIT_RESULT computeWithIds(IndexRange ids, const PointContainer& points){
183 Base::init();
184 FIT_RESULT res = UNDEFINED;
185
186 do {
187 derived().startNewPass();
188 for (const auto& i : ids){
189 derived().addNeighbor(points[i]);
190 }
191 res = Base::finalize();
192 } while ( res == NEED_OTHER_PASS );
193
194 return res;
195 }
196
197 protected:
205 template<typename Func>
206 FIT_RESULT computeMLSImpl(Func&& computeFunc, const int mlsIter, const Scalar epsilon) {
207 FIT_RESULT res = UNDEFINED;
208 auto lastPos = Base::getNeighborFilter().evalPos();
209
210 for (int mm = 0; mm < mlsIter; ++mm) {
211 Base::getNeighborFilter().changeNeighborhoodFrame(lastPos);
212 res = computeFunc();
213
214 if (Base::isStable()) {
215 auto newPos = Base::project(lastPos);
216 if (newPos.isApprox(lastPos, epsilon))
217 return res;
218 lastPos = newPos;
219 } else {
220 return res;
221 }
222 }
223 return res;
224 }
225
226 public:
231 template<typename PointContainer>
233 const PointContainer& points,
234 const int mlsIter = 5,
235 const Scalar epsilon = Eigen::NumTraits<Scalar>::dummy_precision()
236 ) {
237 return computeMLSImpl(
238 [&]() { return compute(points); },
239 mlsIter, epsilon
240 );
241 }
242
248 template<typename IndexRange, typename PointContainer>
250 const IndexRange& ids,
251 const PointContainer& points,
252 const int mlsIter = 5,
253 const Scalar epsilon = Eigen::NumTraits<Scalar>::dummy_precision()
254 ) {
255 return computeMLSImpl(
256 [&]() { return computeWithIds(ids, points); },
257 mlsIter, epsilon
258 );
259 }
260 };
261
262#define WRITE_COMPUTE_FUNCTIONS \
263 using BasketComputeObject<Self, Base>::compute; \
264 using BasketComputeObject<Self, Base>::computeWithIds; \
265 using BasketComputeObject<Self, Base>::computeMLS; \
266 using BasketComputeObject<Self, Base>::computeWithIdsMLS;
267
276 template <typename BasketType, int Type,
277 template <class, class, int, typename> class Ext0,
278 template <class, class, int, typename> class... Exts>
279 class BasketDiff : public BasketComputeObject<BasketDiff<BasketType, Type, Ext0, Exts...>,
280 typename internal::BasketDiffAggregate<BasketType, Type, Ext0, Exts...>::type>
281 {
282 private:
283 using Self = BasketDiff;
284 public:
285 using Base = typename internal::BasketDiffAggregate<BasketType,Type,Ext0,Exts...>::type;
287 using NeighborFilter = BSKNF;
289 using DataPoint = BSKP;
291 using Scalar = typename BasketType::Scalar;
292 WRITE_COMPUTE_FUNCTIONS
293
295 PONCA_MULTIARCH inline bool addNeighbor(const DataPoint &_nei) {
296 // compute weight
297 auto neiFilterOutput = Base::getNeighborFilter()(_nei);
298 typename Base::ScalarArray dw;
299
300 if (neiFilterOutput.first > Scalar(0.)) {
301 Base::addLocalNeighbor(neiFilterOutput.first, neiFilterOutput.second, _nei, dw);
302 return true;
303 }
304 return false;
305 }
306};
307
316 template <class P, class NF,
317 template <class, class, typename> class Ext0,
318 template <class, class, typename> class... Exts>
319 class Basket : public BasketComputeObject<Basket<P, NF, Ext0, Exts...>,
320 typename internal::BasketAggregate<P, NF, Ext0, Exts...>::type>
321 {
322 private:
323 using Self = Basket;
324 public:
326 using Base = typename internal::BasketAggregate<P, NF, Ext0, Exts...>::type;
328 using Scalar = typename P::Scalar;
329 using VectorType = typename P::VectorType;
331 using DataPoint = P;
333 using NeighborFilter = NF;
334
335 WRITE_COMPUTE_FUNCTIONS
336
343 PONCA_MULTIARCH inline bool addNeighbor(const DataPoint &_nei) {
344 // compute weight
345 auto neiFilterOutput = Base::getNeighborFilter()(_nei);
346
347 if (neiFilterOutput.first > Scalar(0.)) {
348 Base::addLocalNeighbor(neiFilterOutput.first, neiFilterOutput.second, _nei);
349 return true;
350 }
351 return false;
352 }
353
354
355
363 PONCA_MULTIARCH [[nodiscard]] inline VectorType projectDescent (const VectorType& _q, int nbIter = 16) const
364 {
365 PONCA_MULTIARCH_STD_MATH(min)
366
367 // turn to centered basis
368 const VectorType lq = Base::getNeighborFilter().convertToLocalBasis(_q);
369
370 VectorType grad;
371 VectorType dir = Base::primitiveGradientLocal(lq);
372 Scalar ilg = Scalar(1.)/dir.norm();
373 dir = dir*ilg;
374 Scalar ad = Base::potentialLocal(lq);
375 Scalar delta = -ad*min(ilg,Scalar(1.));
376 VectorType proj = lq + dir*delta;
377
378 for (int i=0; i<nbIter; ++i)
379 {
380 grad = Base::primitiveGradientLocal(proj);
381 ilg = Scalar(1.)/grad.norm();
382 delta = -Base::potentialLocal(proj)*min(ilg,Scalar(1.));
383 proj += dir*delta;
384 }
385 return Base::getNeighborFilter().convertToGlobalBasis( proj );
386 }
387 }; // class Basket
388
389#undef WRITE_COMPUTE_FUNCTIONS
390} //namespace Ponca
391
Aggregator class used to declare specialized structures with derivatives computations,...
Definition basket.h:281
typename BasketType::DataPoint DataPoint
Point type used for computation.
Definition basket.h:289
bool addNeighbor(const DataPoint &_nei)
Add a neighbor to perform the fit.
Definition basket.h:295
typename BasketType::NeighborFilter NeighborFilter
Neighbor Filter.
Definition basket.h:287
typename BasketType::Scalar Scalar
Scalar type used for computation, as defined from Basket.
Definition basket.h:291
Aggregator class used to declare specialized structures using CRTP.
Definition basket.h:321
typename internal::BasketAggregate< P, NF, Ext0, Exts... >::type Base
Base type, which aggregates all the computational objects using the CRTP.
Definition basket.h:326
P DataPoint
Point type used for computation.
Definition basket.h:331
VectorType projectDescent(const VectorType &_q, int nbIter=16) const
Project a point on the primitive using Gradient Descent This projection is realized by following the ...
Definition basket.h:363
typename P::Scalar Scalar
Scalar type used for computation, as defined from template parameter P
Definition basket.h:328
NF NeighborFilter
Weighting function.
Definition basket.h:333
bool addNeighbor(const DataPoint &_nei)
Add a neighbor to perform the fit.
Definition basket.h:343
This Source Code Form is subject to the terms of the Mozilla Public License, v.
FIT_RESULT
Enum corresponding to the state of a fitting method (and what the finalize function returns)
Definition enums.h:15
@ UNDEFINED
The fitting is undefined, you can't use it for valid results.
Definition enums.h:22
@ NEED_OTHER_PASS
The fitting procedure needs to analyse the neighborhood another time.
Definition enums.h:25
Base ComputeObject for the Basket classes.
Definition basket.h:143
FIT_RESULT computeWithIds(IndexRange ids, const PointContainer &points)
Convenience function to iterate over a subset of samples in a PointContainer Add neighbors stored in ...
Definition basket.h:182
FIT_RESULT computeMLS(const PointContainer &points, const int mlsIter=5, const Scalar epsilon=Eigen::NumTraits< Scalar >::dummy_precision())
Computes the fit using the MLS iteration process.
Definition basket.h:232
FIT_RESULT computeMLSImpl(Func &&computeFunc, const int mlsIter, const Scalar epsilon)
Computes the fit using the MLS iteration process.
Definition basket.h:206
FIT_RESULT compute(const IteratorBegin &begin, const IteratorEnd &end)
Convenience function for STL-like iterators Add neighbors stored in a container using STL-like iterat...
Definition basket.h:159
FIT_RESULT computeWithIdsMLS(const IndexRange &ids, const PointContainer &points, const int mlsIter=5, const Scalar epsilon=Eigen::NumTraits< Scalar >::dummy_precision())
Computes the fit using the MLS iteration process.
Definition basket.h:249
typename Base::Scalar Scalar
Alias to the Derived type.
Definition basket.h:146
ComputeObject is a virtual object that represents an algorithm which can be used with the compute fun...
Definition compute.h:21
_Derived & derived()
Retrieve the top layer object Returns a reference to the derived class so that we can use its overwri...
Definition compute.h:25