DGtal 1.4.0
Loading...
Searching...
No Matches
ChordGenericStandardPlaneComputer.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 ChordGenericStandardPlaneComputer.ih
19 * @author Jacques-Olivier Lachaud (\c jacques-olivier.lachaud@univ-savoie.fr )
20 * Laboratory of Mathematics (CNRS, UMR 5127), University of Savoie, France
21 *
22 * @date 2012/09/20
23 *
24 * Implementation of inline methods defined in ChordGenericStandardPlaneComputer.h
25 *
26 * This file is part of the DGtal library.
27 */
28
29
30//////////////////////////////////////////////////////////////////////////////
31#include <cstdlib>
32//////////////////////////////////////////////////////////////////////////////
33
34///////////////////////////////////////////////////////////////////////////////
35// DEFINITION of static members
36///////////////////////////////////////////////////////////////////////////////
37template <typename TSpace, typename TInputPoint, typename TInternalScalar>
38typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Transform
39DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::myTransforms[4] = {
40 Transform( true, true ), Transform( true, false ), Transform( false, true ), Transform( false, false ) };
41
42///////////////////////////////////////////////////////////////////////////////
43// IMPLEMENTATION of inline methods.
44///////////////////////////////////////////////////////////////////////////////
45
46///////////////////////////////////////////////////////////////////////////////
47// ----------------------- Standard services ------------------------------
48
49//-----------------------------------------------------------------------------
50template <typename TSpace, typename TInputPoint, typename TInternalScalar>
51inline
52DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
53~ChordGenericStandardPlaneComputer()
54{ // Nothing to do.
55}
56//-----------------------------------------------------------------------------
57template <typename TSpace, typename TInputPoint, typename TInternalScalar>
58inline
59DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
60ChordGenericStandardPlaneComputer()
61{ // Object is invalid
62 _orthantsToErase.reserve( 4 );
63}
64//-----------------------------------------------------------------------------
65template <typename TSpace, typename TInputPoint, typename TInternalScalar>
66inline
67DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
68ChordGenericStandardPlaneComputer( const ChordGenericStandardPlaneComputer & other )
69 : myOrthants( other.myOrthants )
70{
71 for ( OrthantConstIterator it = myOrthants.begin(), itE = myOrthants.end();
72 it != itE; ++it )
73 myComputers[ *it ] = other.myComputers[ *it ];
74 _orthantsToErase.reserve( 4 );
75}
76//-----------------------------------------------------------------------------
77template <typename TSpace, typename TInputPoint, typename TInternalScalar>
78inline
79DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar> &
80DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
81operator=( const ChordGenericStandardPlaneComputer & other )
82{
83 if ( this != &other )
84 {
85 myOrthants = other.myOrthants;
86 for ( OrthantConstIterator it = myOrthants.begin(), itE = myOrthants.end();
87 it != itE; ++it )
88 myComputers[ *it ] = other.myComputers[ *it ];
89 }
90 return *this;
91}
92//-----------------------------------------------------------------------------
93template <typename TSpace, typename TInputPoint, typename TInternalScalar>
94inline
95DGtal::Dimension
96DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
97active() const
98{
99 ASSERT( myOrthants.size() > 0 );
100 return myOrthants[ 0 ];
101}
102//-----------------------------------------------------------------------------
103template <typename TSpace, typename TInputPoint, typename TInternalScalar>
104inline
105void
106DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
107clear()
108{
109 myOrthants.clear();
110 for ( unsigned int i = 0; i < 4; ++i )
111 {
112 myOrthants.push_back( i );
113 myComputers[ i ].clear();
114 }
115}
116//-----------------------------------------------------------------------------
117template <typename TSpace, typename TInputPoint, typename TInternalScalar>
118inline
119void
120DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
121init( InternalScalar widthNumerator,
122 InternalScalar widthDenominator )
123{
124 clear();
125 for ( unsigned int i = 0; i < 4; ++i )
126 {
127 // all Chord computers computes naive planes along z, but the 4
128 // transforms dilate the x,y coordinates in four different ways
129 // to get all the possible orientations of standard planes.
130 myComputers[ i ].init( 2, widthNumerator, widthDenominator );
131 }
132}
133//-----------------------------------------------------------------------------
134template <typename TSpace, typename TInputPoint, typename TInternalScalar>
135inline
136typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Size
137DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
138size() const
139{
140 return myComputers[ active() ].size();
141}
142//-----------------------------------------------------------------------------
143template <typename TSpace, typename TInputPoint, typename TInternalScalar>
144inline
145bool
146DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
147empty() const
148{
149 return myComputers[ active() ].empty();
150}
151//-----------------------------------------------------------------------------
152template <typename TSpace, typename TInputPoint, typename TInternalScalar>
153inline
154typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::ConstIterator
155DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
156begin() const
157{
158 return ConstIterator( myComputers[ active() ].begin(), invT( active() ) );
159}
160//-----------------------------------------------------------------------------
161template <typename TSpace, typename TInputPoint, typename TInternalScalar>
162inline
163typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::ConstIterator
164DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
165end() const
166{
167 return ConstIterator( myComputers[ active() ].end(), invT( active() ) );
168}
169
170//-----------------------------------------------------------------------------
171template <typename TSpace, typename TInputPoint, typename TInternalScalar>
172inline
173typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Size
174DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
175max_size() const
176{
177 return myComputers[ active() ].max_size();
178}
179//-----------------------------------------------------------------------------
180template <typename TSpace, typename TInputPoint, typename TInternalScalar>
181inline
182typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Size
183DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
184maxSize() const
185{
186 return max_size();
187}
188//-----------------------------------------------------------------------------
189template <typename TSpace, typename TInputPoint, typename TInternalScalar>
190inline
191bool
192DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
193operator()( const Point & p ) const
194{
195 return myComputers[ active() ].operator()( t( active() )( p ) );
196}
197
198//-----------------------------------------------------------------------------
199template <typename TSpace, typename TInputPoint, typename TInternalScalar>
200inline
201bool
202DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
203extendAsIs( const InputPoint & p )
204{
205 ASSERT( isValid() );
206 unsigned int nbok = 0;
207 for ( OrthantConstIterator it = myOrthants.begin(), itE = myOrthants.end();
208 it != itE; ++it )
209 {
210 nbok += myComputers[ *it ].operator()( t( *it )( p ) ) ? 1 : 0;
211 }
212 if ( nbok != 0 ) // at least one is ok.
213 {
214 for ( OrthantIterator it = myOrthants.begin(); it != myOrthants.end(); )
215 // cannot put end() in variable, since end() moves when
216 // modifiying a vector.
217 {
218 bool ok = myComputers[ *it ].extendAsIs( t( *it )( p ) );
219 if ( ! ok )
220 it = myOrthants.erase( it );
221 else
222 ++it;
223 }
224 ASSERT( ! myOrthants.empty() );
225 return true;
226 }
227 return false;
228}
229
230//-----------------------------------------------------------------------------
231template <typename TSpace, typename TInputPoint, typename TInternalScalar>
232bool
233DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
234extend( const InputPoint & p )
235{
236 ASSERT( isValid() );
237 unsigned int nbok = 0;
238 _orthantsToErase.clear();
239 for ( OrthantConstIterator orthIt = myOrthants.begin(), orthItE = myOrthants.end();
240 orthIt != orthItE; ++orthIt )
241 {
242 Point Tp = t( *orthIt )( p );
243 bool ok = myComputers[ *orthIt ].extend( Tp );
244 if ( ! ok ) _orthantsToErase.push_back( *orthIt );
245 else ++nbok;
246 }
247 if ( nbok != 0 ) // at least one is ok.
248 { // if one is ok, we must remove ko ones from the list of active
249 // axes.
250 OrthantIterator orthIt = myOrthants.begin();
251 for ( unsigned int i = 0; i < _orthantsToErase.size(); ++i )
252 {
253 while ( *orthIt != _orthantsToErase[ i ] ) ++orthIt;
254 orthIt = myOrthants.erase( orthIt );
255 }
256 return true;
257 }
258 return false;
259}
260//-----------------------------------------------------------------------------
261template <typename TSpace, typename TInputPoint, typename TInternalScalar>
262bool
263DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
264isExtendable( const InputPoint & p ) const
265{
266 ASSERT( isValid() );
267 unsigned int nbok = 0;
268 for ( OrthantConstIterator it = myOrthants.begin(), itE = myOrthants.end();
269 it != itE; ++it )
270 {
271 nbok += myComputers[ *it ].isExtendable( t( *it )( p ) ) ? 1 : 0;
272 }
273 return nbok != 0;
274}
275//-----------------------------------------------------------------------------
276template <typename TSpace, typename TInputPoint, typename TInternalScalar>
277template <typename TInputIterator>
278bool
279DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
280extend( TInputIterator it, TInputIterator itE )
281{
282 BOOST_CONCEPT_ASSERT(( boost::InputIterator<TInputIterator> ));
283 ASSERT( isValid() );
284 typedef boost::transform_iterator<Transform,TInputIterator,InputPoint,InputPoint>
285 TransformedInputIterator;
286 unsigned int nbok = 0;
287 _orthantsToErase.clear();
288 for ( OrthantConstIterator orthIt = myOrthants.begin(), orthItE = myOrthants.end();
289 orthIt != orthItE; ++orthIt )
290 {
291 Dimension orthant = *orthIt;
292 TransformedInputIterator transIt ( it, t( orthant ) );
293 TransformedInputIterator transItE( itE, t( orthant ) );
294 bool ok = myComputers[ orthant ].extend( transIt, transItE );
295 if ( ! ok ) _orthantsToErase.push_back( *orthIt );
296 else ++nbok;
297 }
298 if ( nbok != 0 ) // at least one is ok.
299 { // if one is ok, we must remove ko ones from the list of active
300 // axes.
301 OrthantIterator orthIt = myOrthants.begin();
302 for ( unsigned int i = 0; i < _orthantsToErase.size(); ++i )
303 {
304 while ( *orthIt != _orthantsToErase[ i ] ) ++orthIt;
305 orthIt = myOrthants.erase( orthIt );
306 }
307 return true;
308 }
309 return false;
310}
311//-----------------------------------------------------------------------------
312template <typename TSpace, typename TInputPoint, typename TInternalScalar>
313template <typename TInputIterator>
314bool
315DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
316isExtendable( TInputIterator it, TInputIterator itE ) const
317{
318 BOOST_CONCEPT_ASSERT(( boost::InputIterator<TInputIterator> ));
319 ASSERT( isValid() );
320 typedef boost::transform_iterator<Transform,TInputIterator,InputPoint,InputPoint>
321 TransformedInputIterator;
322 unsigned int nbok = 0;
323 for ( OrthantConstIterator orthIt = myOrthants.begin(), orthItE = myOrthants.end();
324 orthIt != orthItE; ++orthIt )
325 {
326 Dimension orthant = *orthIt;
327 TransformedInputIterator transIt ( it, t( orthant ) );
328 TransformedInputIterator transItE( itE, t( orthant ) );
329 nbok += myComputers[ orthant ].isExtendable( transIt, transItE ) ? 1 : 0;
330 }
331 return nbok != 0;
332}
333
334//-----------------------------------------------------------------------------
335template <typename TSpace, typename TInputPoint, typename TInternalScalar>
336inline
337typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Primitive
338DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
339primitive() const
340{
341 InternalVector n;
342 InternalScalar imin, imax;
343 InputPoint p_min, p_max;
344 getCharacteristics( n, imin, imax, p_min, p_max );
345 double ddenom = NumberTraits<InternalScalar>::castToDouble( n[ 2 ] );
346 double min = ( NumberTraits<InternalScalar>::castToDouble( imin ) - 0.5 ) / ddenom;
347 double max = ( NumberTraits<InternalScalar>::castToDouble( imax ) + 0.5 ) / ddenom;
348 typename Space::RealVector normal;
349 normal[ 0 ] = NumberTraits<InternalScalar>::castToDouble( n[ 0 ] ) / ddenom;
350 normal[ 1 ] = NumberTraits<InternalScalar>::castToDouble( n[ 1 ] ) / ddenom;
351 normal[ 2 ] = NumberTraits<InternalScalar>::castToDouble( n[ 2 ] ) / ddenom;
352 return Primitive( min, normal, max-min );
353}
354
355//-----------------------------------------------------------------------------
356template <typename TSpace, typename TInputPoint, typename TInternalScalar>
357template <typename Vector3D>
358inline
359void
360DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
361getNormal( Vector3D & normal ) const
362{
363 myComputers[ active() ].getNormal( normal );
364 invT( active() ).transform( normal );
365}
366//-----------------------------------------------------------------------------
367//-----------------------------------------------------------------------------
368template <typename TSpace, typename TInputPoint, typename TInternalScalar>
369template <typename Vector3D>
370inline
371void
372DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
373getUnitNormal( Vector3D & normal ) const
374{
375 myComputers[ active() ].getNormal( normal );
376 invT( active() ).transform( normal );
377 normal /= sqrt( normal[0]*normal[0]
378 +normal[1]*normal[1]
379 +normal[2]*normal[2] );
380}
381//-----------------------------------------------------------------------------
382template <typename TSpace, typename TInputPoint, typename TInternalScalar>
383inline
384void
385DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
386getBounds( double & min, double & max ) const
387{
388 InternalVector n;
389 InternalScalar imin, imax;
390 InputPoint p_min, p_max;
391 getCharacteristics( n, imin, imax, p_min, p_max );
392 double ddenom = NumberTraits<InternalScalar>::castToDouble( n[ 2 ] );
393 min = ( NumberTraits<InternalScalar>::castToDouble( imin ) - 0.5 ) / ddenom;
394 max = ( NumberTraits<InternalScalar>::castToDouble( imax ) + 0.5 ) / ddenom;
395}
396//-----------------------------------------------------------------------------
397template <typename TSpace, typename TInputPoint, typename TInternalScalar>
398inline
399typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::InputPoint
400DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
401minimalPoint() const
402{
403 InternalVector n;
404 InternalScalar imin, imax;
405 InputPoint p_min, p_max;
406 getCharacteristics( n, imin, imax, p_min, p_max );
407 return p_min;
408}
409//-----------------------------------------------------------------------------
410template <typename TSpace, typename TInputPoint, typename TInternalScalar>
411inline
412typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::InputPoint
413DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
414maximalPoint() const
415{
416 InternalVector n;
417 InternalScalar imin, imax;
418 InputPoint p_min, p_max;
419 getCharacteristics( n, imin, imax, p_min, p_max );
420 return p_max;
421}
422
423//-----------------------------------------------------------------------------
424template <typename TSpace, typename TInputPoint, typename TInternalScalar>
425inline
426void
427DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
428getCharacteristics( InternalVector & n,
429 InternalScalar & imin, InternalScalar & imax,
430 InputPoint & p_min, InputPoint & p_max ) const
431{
432 // This rather complex method is necessary to guarantee that there
433 // are no numeric error due to bad rounding when casting to double.
434 p_min = invT( active() )( myComputers[ active() ].minimalPoint() );
435 p_max = invT( active() )( myComputers[ active() ].maximalPoint() );
436 // min and max may be swapped because of the transform.
437 n = myComputers[ active() ].exactNormal();
438 invT( active() ).transform( n );
439 if ( n[ 2 ] < NumberTraits<InternalScalar>::ZERO )
440 { n = -n; }
441 imin =
442 ( ( n[ 0 ] * InternalScalar( p_min[ 0 ] ) )
443 + ( n[ 1 ] * InternalScalar( p_min[ 1 ] ) )
444 + ( n[ 2 ] * InternalScalar( p_min[ 2 ] ) ) );
445 imax =
446 ( ( n[ 0 ] * InternalScalar( p_max[ 0 ] ) )
447 + ( n[ 1 ] * InternalScalar( p_max[ 1 ] ) )
448 + ( n[ 2 ] * InternalScalar( p_max[ 2 ] ) ) );
449 if ( imax < imin )
450 {
451 std::swap( imin, imax );
452 std::swap( p_min, p_max );
453 }
454}
455
456
457///////////////////////////////////////////////////////////////////////////////
458// Interface - public :
459
460/**
461 * Writes/Displays the object on an output stream.
462 * @param out the output stream where the object is written.
463 */
464template <typename TSpace, typename TInputPoint, typename TInternalScalar>
465inline
466void
467DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::selfDisplay ( std::ostream & out ) const
468{
469 out << "[ChordGenericStandardPlaneComputer";
470 for ( OrthantConstIterator orthIt = myOrthants.begin(), orthItE = myOrthants.end();
471 orthIt != orthItE; ++orthIt )
472 out << " " << myComputers[ *orthIt ];
473 out << " ]";
474}
475
476/**
477 * Checks the validity/consistency of the object.
478 * @return 'true' if the object is valid, 'false' otherwise.
479 */
480template <typename TSpace, typename TInputPoint, typename TInternalScalar>
481inline
482bool
483DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::isValid() const
484{
485 return myComputers[ active() ].isValid();
486}
487
488
489///////////////////////////////////////////////////////////////////////////////
490// Internals
491///////////////////////////////////////////////////////////////////////////////
492
493//-----------------------------------------------------------------------------
494template <typename TSpace, typename TInputPoint, typename TInternalScalar>
495inline
496typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Transform
497DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
498t( Dimension orthant )
499{
500 ASSERT( orthant < 4 );
501 return myTransforms[ orthant ];
502}
503//-----------------------------------------------------------------------------
504template <typename TSpace, typename TInputPoint, typename TInternalScalar>
505inline
506typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Transform
507DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
508invT( Dimension orthant )
509{
510 ASSERT( orthant < 4 );
511 return myTransforms[ orthant ^ 0x3 ];
512}
513
514///////////////////////////////////////////////////////////////////////////////
515// Implementation of inline functions //
516
517template <typename TSpace, typename TInputPoint, typename TInternalScalar>
518inline
519std::ostream&
520DGtal::operator<< ( std::ostream & out,
521 const ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar> & object )
522{
523 object.selfDisplay( out );
524 return out;
525}
526
527// //
528///////////////////////////////////////////////////////////////////////////////
529