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.
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.
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/>.
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
24 * Implementation of inline methods defined in ChordGenericStandardPlaneComputer.h
26 * This file is part of the DGtal library.
30 //////////////////////////////////////////////////////////////////////////////
32 //////////////////////////////////////////////////////////////////////////////
34 ///////////////////////////////////////////////////////////////////////////////
35 // DEFINITION of static members
36 ///////////////////////////////////////////////////////////////////////////////
37 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
38 typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Transform
39 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::myTransforms[4] = {
40 Transform( true, true ), Transform( true, false ), Transform( false, true ), Transform( false, false ) };
42 ///////////////////////////////////////////////////////////////////////////////
43 // IMPLEMENTATION of inline methods.
44 ///////////////////////////////////////////////////////////////////////////////
46 ///////////////////////////////////////////////////////////////////////////////
47 // ----------------------- Standard services ------------------------------
49 //-----------------------------------------------------------------------------
50 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
52 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
53 ~ChordGenericStandardPlaneComputer()
56 //-----------------------------------------------------------------------------
57 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
59 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
60 ChordGenericStandardPlaneComputer()
61 { // Object is invalid
62 _orthantsToErase.reserve( 4 );
64 //-----------------------------------------------------------------------------
65 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
67 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
68 ChordGenericStandardPlaneComputer( const ChordGenericStandardPlaneComputer & other )
69 : myOrthants( other.myOrthants )
71 for ( OrthantConstIterator it = myOrthants.begin(), itE = myOrthants.end();
73 myComputers[ *it ] = other.myComputers[ *it ];
74 _orthantsToErase.reserve( 4 );
76 //-----------------------------------------------------------------------------
77 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
79 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar> &
80 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
81 operator=( const ChordGenericStandardPlaneComputer & other )
85 myOrthants = other.myOrthants;
86 for ( OrthantConstIterator it = myOrthants.begin(), itE = myOrthants.end();
88 myComputers[ *it ] = other.myComputers[ *it ];
92 //-----------------------------------------------------------------------------
93 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
96 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
99 ASSERT( myOrthants.size() > 0 );
100 return myOrthants[ 0 ];
102 //-----------------------------------------------------------------------------
103 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
106 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
110 for ( unsigned int i = 0; i < 4; ++i )
112 myOrthants.push_back( i );
113 myComputers[ i ].clear();
116 //-----------------------------------------------------------------------------
117 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
120 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
121 init( InternalScalar widthNumerator,
122 InternalScalar widthDenominator )
125 for ( unsigned int i = 0; i < 4; ++i )
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 );
133 //-----------------------------------------------------------------------------
134 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
136 typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Size
137 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
140 return myComputers[ active() ].size();
142 //-----------------------------------------------------------------------------
143 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
146 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
149 return myComputers[ active() ].empty();
151 //-----------------------------------------------------------------------------
152 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
154 typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::ConstIterator
155 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
158 return ConstIterator( myComputers[ active() ].begin(), invT( active() ) );
160 //-----------------------------------------------------------------------------
161 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
163 typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::ConstIterator
164 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
167 return ConstIterator( myComputers[ active() ].end(), invT( active() ) );
170 //-----------------------------------------------------------------------------
171 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
173 typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Size
174 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
177 return myComputers[ active() ].max_size();
179 //-----------------------------------------------------------------------------
180 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
182 typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Size
183 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
188 //-----------------------------------------------------------------------------
189 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
192 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
193 operator()( const Point & p ) const
195 return myComputers[ active() ].operator()( t( active() )( p ) );
198 //-----------------------------------------------------------------------------
199 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
202 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
203 extendAsIs( const InputPoint & p )
206 unsigned int nbok = 0;
207 for ( OrthantConstIterator it = myOrthants.begin(), itE = myOrthants.end();
210 nbok += myComputers[ *it ].operator()( t( *it )( p ) ) ? 1 : 0;
212 if ( nbok != 0 ) // at least one is ok.
214 for ( OrthantIterator it = myOrthants.begin(); it != myOrthants.end(); )
215 // cannot put end() in variable, since end() moves when
216 // modifiying a vector.
218 bool ok = myComputers[ *it ].extendAsIs( t( *it )( p ) );
220 it = myOrthants.erase( it );
224 ASSERT( ! myOrthants.empty() );
230 //-----------------------------------------------------------------------------
231 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
233 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
234 extend( const InputPoint & p )
237 unsigned int nbok = 0;
238 _orthantsToErase.clear();
239 for ( OrthantConstIterator orthIt = myOrthants.begin(), orthItE = myOrthants.end();
240 orthIt != orthItE; ++orthIt )
242 Point Tp = t( *orthIt )( p );
243 bool ok = myComputers[ *orthIt ].extend( Tp );
244 if ( ! ok ) _orthantsToErase.push_back( *orthIt );
247 if ( nbok != 0 ) // at least one is ok.
248 { // if one is ok, we must remove ko ones from the list of active
250 OrthantIterator orthIt = myOrthants.begin();
251 for ( unsigned int i = 0; i < _orthantsToErase.size(); ++i )
253 while ( *orthIt != _orthantsToErase[ i ] ) ++orthIt;
254 orthIt = myOrthants.erase( orthIt );
260 //-----------------------------------------------------------------------------
261 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
263 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
264 isExtendable( const InputPoint & p ) const
267 unsigned int nbok = 0;
268 for ( OrthantConstIterator it = myOrthants.begin(), itE = myOrthants.end();
271 nbok += myComputers[ *it ].isExtendable( t( *it )( p ) ) ? 1 : 0;
275 //-----------------------------------------------------------------------------
276 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
277 template <typename TInputIterator>
279 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
280 extend( TInputIterator it, TInputIterator itE )
282 BOOST_CONCEPT_ASSERT(( boost::InputIterator<TInputIterator> ));
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 )
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 );
298 if ( nbok != 0 ) // at least one is ok.
299 { // if one is ok, we must remove ko ones from the list of active
301 OrthantIterator orthIt = myOrthants.begin();
302 for ( unsigned int i = 0; i < _orthantsToErase.size(); ++i )
304 while ( *orthIt != _orthantsToErase[ i ] ) ++orthIt;
305 orthIt = myOrthants.erase( orthIt );
311 //-----------------------------------------------------------------------------
312 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
313 template <typename TInputIterator>
315 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
316 isExtendable( TInputIterator it, TInputIterator itE ) const
318 BOOST_CONCEPT_ASSERT(( boost::InputIterator<TInputIterator> ));
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 )
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;
334 //-----------------------------------------------------------------------------
335 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
337 typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Primitive
338 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
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 );
355 //-----------------------------------------------------------------------------
356 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
357 template <typename Vector3D>
360 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
361 getNormal( Vector3D & normal ) const
363 myComputers[ active() ].getNormal( normal );
364 invT( active() ).transform( normal );
366 //-----------------------------------------------------------------------------
367 //-----------------------------------------------------------------------------
368 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
369 template <typename Vector3D>
372 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
373 getUnitNormal( Vector3D & normal ) const
375 myComputers[ active() ].getNormal( normal );
376 invT( active() ).transform( normal );
377 normal /= sqrt( normal[0]*normal[0]
379 +normal[2]*normal[2] );
381 //-----------------------------------------------------------------------------
382 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
385 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
386 getBounds( double & min, double & max ) const
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;
396 //-----------------------------------------------------------------------------
397 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
399 typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::InputPoint
400 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
404 InternalScalar imin, imax;
405 InputPoint p_min, p_max;
406 getCharacteristics( n, imin, imax, p_min, p_max );
409 //-----------------------------------------------------------------------------
410 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
412 typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::InputPoint
413 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
417 InternalScalar imin, imax;
418 InputPoint p_min, p_max;
419 getCharacteristics( n, imin, imax, p_min, p_max );
423 //-----------------------------------------------------------------------------
424 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
427 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
428 getCharacteristics( InternalVector & n,
429 InternalScalar & imin, InternalScalar & imax,
430 InputPoint & p_min, InputPoint & p_max ) const
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 )
442 ( ( n[ 0 ] * InternalScalar( p_min[ 0 ] ) )
443 + ( n[ 1 ] * InternalScalar( p_min[ 1 ] ) )
444 + ( n[ 2 ] * InternalScalar( p_min[ 2 ] ) ) );
446 ( ( n[ 0 ] * InternalScalar( p_max[ 0 ] ) )
447 + ( n[ 1 ] * InternalScalar( p_max[ 1 ] ) )
448 + ( n[ 2 ] * InternalScalar( p_max[ 2 ] ) ) );
451 std::swap( imin, imax );
452 std::swap( p_min, p_max );
457 ///////////////////////////////////////////////////////////////////////////////
458 // Interface - public :
461 * Writes/Displays the object on an output stream.
462 * @param out the output stream where the object is written.
464 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
467 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::selfDisplay ( std::ostream & out ) const
469 out << "[ChordGenericStandardPlaneComputer";
470 for ( OrthantConstIterator orthIt = myOrthants.begin(), orthItE = myOrthants.end();
471 orthIt != orthItE; ++orthIt )
472 out << " " << myComputers[ *orthIt ];
477 * Checks the validity/consistency of the object.
478 * @return 'true' if the object is valid, 'false' otherwise.
480 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
483 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::isValid() const
485 return myComputers[ active() ].isValid();
489 ///////////////////////////////////////////////////////////////////////////////
491 ///////////////////////////////////////////////////////////////////////////////
493 //-----------------------------------------------------------------------------
494 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
496 typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Transform
497 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
498 t( Dimension orthant )
500 ASSERT( orthant < 4 );
501 return myTransforms[ orthant ];
503 //-----------------------------------------------------------------------------
504 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
506 typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Transform
507 DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
508 invT( Dimension orthant )
510 ASSERT( orthant < 4 );
511 return myTransforms[ orthant ^ 0x3 ];
514 ///////////////////////////////////////////////////////////////////////////////
515 // Implementation of inline functions //
517 template <typename TSpace, typename TInputPoint, typename TInternalScalar>
520 DGtal::operator<< ( std::ostream & out,
521 const ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar> & object )
523 object.selfDisplay( out );
528 ///////////////////////////////////////////////////////////////////////////////