DGtal 1.4.0
Loading...
Searching...
No Matches
PlaneProbingTetrahedronEstimator.ih
1/**
2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *
15 **/
16
17/**
18 * @file
19 * @author Jocelyn Meyron (\c jocelyn.meyron@liris.cnrs.fr )
20 * Laboratoire d'InfoRmatique en Image et Systemes d'information - LIRIS (CNRS, UMR 5205), CNRS, France
21 *
22 * @date 2020/12/04
23 *
24 * Implementation of inline methods defined in PlaneProbingTetrahedronEstimator.h
25 *
26 * This file is part of the DGtal library.
27 */
28
29
30//////////////////////////////////////////////////////////////////////////////
31#include <cassert>
32#include <cstdlib>
33#include <array>
34#include <vector>
35#include "DGtal/geometry/helpers/PlaneProbingEstimatorHelper.h"
36#include "DGtal/geometry/surfaces/estimation/PlaneProbingHNeighborhood.h"
37#include "DGtal/geometry/surfaces/estimation/PlaneProbingRNeighborhood.h"
38#include "DGtal/geometry/surfaces/estimation/PlaneProbingR1Neighborhood.h"
39//////////////////////////////////////////////////////////////////////////////
40
41///////////////////////////////////////////////////////////////////////////////
42// IMPLEMENTATION of inline methods.
43///////////////////////////////////////////////////////////////////////////////
44
45namespace DGtal
46{
47 namespace detail
48 {
49 // Helper class to choose the PlaneProbingNeighborhood class at compile-time
50 // (used in the constructor of PlaneProbingTetrahedronEstimator)
51 template < typename TPredicate, DGtal::ProbingMode mode >
52 struct PlaneProbingNeighborhoodSelector
53 {
54 static DGtal::PlaneProbingNeighborhood<TPredicate>*
55 select(TPredicate const&,
56 typename DGtal::PlaneProbingNeighborhood<TPredicate>::Point const&,
57 typename DGtal::PlaneProbingNeighborhood<TPredicate>::Triangle const&);
58 };
59
60 template < typename TPredicate >
61 struct PlaneProbingNeighborhoodSelector<TPredicate, DGtal::ProbingMode::H>
62 {
63 static DGtal::PlaneProbingNeighborhood<TPredicate>*
64 select(TPredicate const& aPredicate,
65 typename DGtal::PlaneProbingNeighborhood<TPredicate>::Point const& aQ,
66 typename DGtal::PlaneProbingNeighborhood<TPredicate>::Triangle const& aM)
67 {
68 return new DGtal::PlaneProbingHNeighborhood<TPredicate>(aPredicate, aQ, aM);
69 }
70 };
71
72 template < typename TPredicate >
73 struct PlaneProbingNeighborhoodSelector<TPredicate, DGtal::ProbingMode::R>
74 {
75 static DGtal::PlaneProbingNeighborhood<TPredicate>*
76 select(TPredicate const& aPredicate,
77 typename DGtal::PlaneProbingNeighborhood<TPredicate>::Point const& aQ,
78 typename DGtal::PlaneProbingNeighborhood<TPredicate>::Triangle const& aM)
79 {
80 return new DGtal::PlaneProbingRNeighborhood<TPredicate>(aPredicate, aQ, aM);
81 }
82 };
83
84 template < typename TPredicate >
85 struct PlaneProbingNeighborhoodSelector<TPredicate, DGtal::ProbingMode::R1>
86 {
87 static DGtal::PlaneProbingNeighborhood<TPredicate>*
88 select(TPredicate const& aPredicate,
89 typename DGtal::PlaneProbingNeighborhood<TPredicate>::Point const& aQ,
90 typename DGtal::PlaneProbingNeighborhood<TPredicate>::Triangle const& aM)
91 {
92 return new DGtal::PlaneProbingR1Neighborhood<TPredicate>(aPredicate, aQ, aM);
93 }
94 };
95
96 } // namespace detail
97} // namespace DGtal
98
99///////////////////////////////////////////////////////////////////////////////
100// ----------------------- Standard services ------------------------------
101
102// ------------------------------------------------------------------------
103template < typename TPredicate, DGtal::ProbingMode mode >
104inline
105DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::
106PlaneProbingTetrahedronEstimator (Point const& aPoint, Triangle const& aM, Predicate const& aPredicate)
107 : myM(aM), myPredicate(aPredicate), myS(aM[0] + aM[1] + aM[2]), myQ(aPoint + myS)
108{
109 myNeighborhood = DGtal::detail::PlaneProbingNeighborhoodSelector<TPredicate, mode>::select(myPredicate, myQ, myM);
110}
111
112// ------------------------------------------------------------------------
113template < typename TPredicate, DGtal::ProbingMode mode >
114inline
115DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::
116~PlaneProbingTetrahedronEstimator ()
117{
118 delete myNeighborhood;
119 myNeighborhood = nullptr;
120}
121
122///////////////////////////////////////////////////////////////////////////////
123// ----------------------- Plane probing services ------------------------------
124
125// ------------------------------------------------------------------------
126template < typename TPredicate, DGtal::ProbingMode mode >
127inline
128typename DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::Vector const&
129DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::m (int aIndex) const
130{
131 assert(aIndex == 0 || aIndex == 1 || aIndex == 2);
132 return myM[aIndex];
133}
134
135// ------------------------------------------------------------------------
136template < typename TPredicate, DGtal::ProbingMode mode >
137inline
138typename DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::Point const&
139DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::q () const
140{
141 return myQ;
142}
143
144// ------------------------------------------------------------------------
145template < typename TPredicate, DGtal::ProbingMode mode >
146inline
147typename DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::Point
148DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::getOrigin () const
149{
150 return myQ - (myM[0] + myM[1] + myM[2]);
151}
152
153// ------------------------------------------------------------------------
154template < typename TPredicate, DGtal::ProbingMode mode >
155inline
156typename DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::Triangle
157DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::vertices () const
158{
159 return { myQ - myM[0], myQ - myM[1], myQ - myM[2] };
160}
161
162// ------------------------------------------------------------------------
163template < typename TPredicate, DGtal::ProbingMode mode >
164inline
165std::pair<typename DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::Vector,
166 typename DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::Vector>
167DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::getBasis () const
168{
169 using DGtal::detail::squaredNorm;
170
171 Vector u = myM[1] - myM[0],
172 v = myM[2] - myM[1],
173 w = myM[0] - myM[2];
174 ASSERT(w == -u - v);
175
176 if (squaredNorm(u) < squaredNorm(v)) {
177 if (squaredNorm(u) < squaredNorm(w)) {
178 if (squaredNorm(-w) < squaredNorm(v)) {
179 return std::make_pair(u, -w);
180 } else {
181 return std::make_pair(u, v);
182 }
183 } else {
184 if (squaredNorm(-v) < squaredNorm(u)) {
185 return std::make_pair(w, -v);
186 } else {
187 return std::make_pair(w, u);
188 }
189 }
190 } else {
191 if (squaredNorm(v) < squaredNorm(w)) {
192 if (squaredNorm(-u) < squaredNorm(w)) {
193 return std::make_pair(v, -u);
194 } else {
195 return std::make_pair(v, w);
196 }
197 } else {
198 if (squaredNorm(-v) < squaredNorm(u)) {
199 return std::make_pair(w, -v);
200 } else {
201 return std::make_pair(w, u);
202 }
203 }
204 }
205}
206
207// ------------------------------------------------------------------------
208template < typename TPredicate, DGtal::ProbingMode mode >
209inline
210bool
211DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::isReduced () const
212{
213 auto basis = getBasis();
214 return DGtal::detail::isBasisReduced(basis.first, basis.second);
215}
216
217// ------------------------------------------------------------------------
218template < typename TPredicate, DGtal::ProbingMode mode >
219inline
220typename DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::Vector
221DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::getNormal () const
222{
223 auto basis = getBasis();
224 return basis.first.crossProduct(basis.second);
225}
226
227// ------------------------------------------------------------------------
228template < typename TPredicate, DGtal::ProbingMode mode >
229inline
230std::pair<bool, typename DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::UpdateOperation>
231DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::advance (std::vector<PointOnProbingRay> const& aNeighbors)
232{
233 myNeighborhood->setNeighbors(aNeighbors);
234 HexagonState state = hexagonState();
235
236 if (state == HexagonState::Planar)
237 {
238 UpdateOperation op = myNeighborhood->closestCandidate();
239 update(op);
240 ASSERT(isValid());
241 return { true, op };
242 }
243
244 return { false, {} };
245}
246
247// ------------------------------------------------------------------------
248template < typename TPredicate, DGtal::ProbingMode mode >
249inline
250std::pair<bool, typename DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::UpdateOperation>
251DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::advance ()
252{
253 return advance({});
254}
255
256// ------------------------------------------------------------------------
257template < typename TPredicate, DGtal::ProbingMode mode >
258inline
259typename DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::Quantity
260DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::compute (std::vector<PointOnProbingRay> const& aNeighbors)
261{
262 while (advance(aNeighbors).first) {}
263
264 return getNormal();
265}
266
267// ------------------------------------------------------------------------
268template < typename TPredicate, DGtal::ProbingMode mode >
269inline
270typename DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::Quantity
271DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::compute ()
272{
273 return compute({});
274}
275
276// ------------------------------------------------------------------------
277template < typename TPredicate, DGtal::ProbingMode mode >
278inline
279typename DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::Neighborhood::HexagonState
280DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::hexagonState () const
281{
282 return myNeighborhood->hexagonState();
283}
284
285// ------------------------------------------------------------------------
286template < typename TPredicate, DGtal::ProbingMode mode >
287inline
288void
289DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::translateQ (Vector const& aTranslation)
290{
291 myQ += aTranslation;
292}
293
294// ------------------------------------------------------------------------
295template < typename TPredicate, DGtal::ProbingMode mode >
296inline
297void
298DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::translateQ ()
299{
300 UpdateOperation const& lastOp = myOperations[myOperations.size() - 1];
301 Point translation = lastOp.coeffs[1] * myM[lastOp.sigma[1]] + lastOp.coeffs[2] * myM[lastOp.sigma[2]];
302
303 translateQ(translation);
304}
305
306///////////////////////////////////////////////////////////////////////////////
307// ------------------------- Internals ------------------------------------
308
309// ------------------------------------------------------------------------
310template < typename TPredicate, DGtal::ProbingMode mode >
311inline
312void
313DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::applyOperation (UpdateOperation const& aOp)
314{
315 myM[aOp.sigma[0]] = aOp.coeffs[0] * myM[aOp.sigma[0]] + aOp.coeffs[1] * myM[aOp.sigma[1]] + aOp.coeffs[2] * myM[aOp.sigma[2]];
316}
317
318// ------------------------------------------------------------------------
319template < typename TPredicate, DGtal::ProbingMode mode >
320inline
321void
322DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::update (UpdateOperation const& aOp)
323{
324 applyOperation(aOp);
325 myOperations.push_back(aOp);
326}
327
328///////////////////////////////////////////////////////////////////////////////
329// Interface - public :
330
331// ------------------------------------------------------------------------
332template <typename TPredicate, DGtal::ProbingMode mode>
333inline
334void
335DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::selfDisplay ( std::ostream & out ) const
336{
337 out << "[PlaneProbingTetrahedronEstimator]";
338}
339
340// ------------------------------------------------------------------------
341template <typename TPredicate, DGtal::ProbingMode mode>
342inline
343bool
344DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::isValid() const
345{
346 return ( isUnimodular() && isProjectedInside() );
347}
348
349// ------------------------------------------------------------------------
350template <typename TPredicate, DGtal::ProbingMode mode>
351inline
352bool
353DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::isInside() const
354{
355 Triangle v = vertices();
356 for (int i = 0; i < 3; ++i) {
357 if (! myPredicate(v[i])) {
358 return false;
359 }
360 }
361 return true;
362}
363
364// ------------------------------------------------------------------------
365template <typename TPredicate, DGtal::ProbingMode mode>
366inline
367bool
368DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::isUnimodular() const
369{
370 Point nest = getNormal();
371 for (int i = 0; i < 3; ++i) {
372 if (myM[i].dot(nest) != 1) {
373 return false;
374 }
375 }
376 return true;
377}
378
379// ------------------------------------------------------------------------
380template < typename TPredicate, DGtal::ProbingMode mode >
381inline
382bool
383DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::isProjectedInside (Triangle const& aTriangle) const
384{
385 Triangle vec = { myQ - aTriangle[0], myQ - aTriangle[1], myQ - aTriangle[2] };
386
387 Point s = myM[0] + myM[1] + myM[2];
388 std::array<bool, 3> res, res_not;
389 for (int i = 0; i < 3; ++i)
390 {
391 int im1 = (i - 1 + 3) % 3;
392 Point nk = vec[im1].crossProduct(vec[i]);
393
394 res[i] = (nk.dot(-s) <= 0);
395 res_not[i] = !res[i];
396 }
397
398 return (res[0] && res[1] && res[2]) || (res_not[0] && res_not[1] && res_not[2]);
399}
400
401// ------------------------------------------------------------------------
402template < typename TPredicate, DGtal::ProbingMode mode >
403inline
404bool
405DGtal::PlaneProbingTetrahedronEstimator<TPredicate, mode>::isProjectedInside () const
406{
407 return isProjectedInside(vertices());
408}
409
410
411///////////////////////////////////////////////////////////////////////////////
412// Implementation of inline functions //
413
414template <typename TPredicate, DGtal::ProbingMode mode>
415inline
416std::ostream&
417DGtal::operator<< ( std::ostream & out,
418 const PlaneProbingTetrahedronEstimator<TPredicate, mode> & object )
419{
420 object.selfDisplay( out );
421 return out;
422}
423
424// //
425///////////////////////////////////////////////////////////////////////////////
426
427