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///////////////////////////////////////////////////////////////////////////////
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 ) };
42///////////////////////////////////////////////////////////////////////////////
43// IMPLEMENTATION of inline methods.
44///////////////////////////////////////////////////////////////////////////////
46///////////////////////////////////////////////////////////////////////////////
47// ----------------------- Standard services ------------------------------
49//-----------------------------------------------------------------------------
50template <typename TSpace, typename TInputPoint, typename TInternalScalar>
52DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
53~ChordGenericStandardPlaneComputer()
56//-----------------------------------------------------------------------------
57template <typename TSpace, typename TInputPoint, typename TInternalScalar>
59DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
60ChordGenericStandardPlaneComputer()
62 _orthantsToErase.reserve( 4 );
64//-----------------------------------------------------------------------------
65template <typename TSpace, typename TInputPoint, typename TInternalScalar>
67DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
68ChordGenericStandardPlaneComputer( 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//-----------------------------------------------------------------------------
77template <typename TSpace, typename TInputPoint, typename TInternalScalar>
79DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar> &
80DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
81operator=( const ChordGenericStandardPlaneComputer & other )
85 myOrthants = other.myOrthants;
86 for ( OrthantConstIterator it = myOrthants.begin(), itE = myOrthants.end();
88 myComputers[ *it ] = other.myComputers[ *it ];
92//-----------------------------------------------------------------------------
93template <typename TSpace, typename TInputPoint, typename TInternalScalar>
96DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
99 ASSERT( myOrthants.size() > 0 );
100 return myOrthants[ 0 ];
102//-----------------------------------------------------------------------------
103template <typename TSpace, typename TInputPoint, typename TInternalScalar>
106DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
110 for ( unsigned int i = 0; i < 4; ++i )
112 myOrthants.push_back( i );
113 myComputers[ i ].clear();
116//-----------------------------------------------------------------------------
117template <typename TSpace, typename TInputPoint, typename TInternalScalar>
120DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
121init( 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//-----------------------------------------------------------------------------
134template <typename TSpace, typename TInputPoint, typename TInternalScalar>
136typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Size
137DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
140 return myComputers[ active() ].size();
142//-----------------------------------------------------------------------------
143template <typename TSpace, typename TInputPoint, typename TInternalScalar>
146DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
149 return myComputers[ active() ].empty();
151//-----------------------------------------------------------------------------
152template <typename TSpace, typename TInputPoint, typename TInternalScalar>
154typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::ConstIterator
155DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
158 return ConstIterator( myComputers[ active() ].begin(), invT( active() ) );
160//-----------------------------------------------------------------------------
161template <typename TSpace, typename TInputPoint, typename TInternalScalar>
163typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::ConstIterator
164DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
167 return ConstIterator( myComputers[ active() ].end(), invT( active() ) );
170//-----------------------------------------------------------------------------
171template <typename TSpace, typename TInputPoint, typename TInternalScalar>
173typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Size
174DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
177 return myComputers[ active() ].max_size();
179//-----------------------------------------------------------------------------
180template <typename TSpace, typename TInputPoint, typename TInternalScalar>
182typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Size
183DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
188//-----------------------------------------------------------------------------
189template <typename TSpace, typename TInputPoint, typename TInternalScalar>
192DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
193operator()( const Point & p ) const
195 return myComputers[ active() ].operator()( t( active() )( p ) );
198//-----------------------------------------------------------------------------
199template <typename TSpace, typename TInputPoint, typename TInternalScalar>
202DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
203extendAsIs( 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//-----------------------------------------------------------------------------
231template <typename TSpace, typename TInputPoint, typename TInternalScalar>
233DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
234extend( 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//-----------------------------------------------------------------------------
261template <typename TSpace, typename TInputPoint, typename TInternalScalar>
263DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
264isExtendable( 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//-----------------------------------------------------------------------------
276template <typename TSpace, typename TInputPoint, typename TInternalScalar>
277template <typename TInputIterator>
279DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
280extend( 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//-----------------------------------------------------------------------------
312template <typename TSpace, typename TInputPoint, typename TInternalScalar>
313template <typename TInputIterator>
315DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
316isExtendable( 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//-----------------------------------------------------------------------------
335template <typename TSpace, typename TInputPoint, typename TInternalScalar>
337typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Primitive
338DGtal::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//-----------------------------------------------------------------------------
356template <typename TSpace, typename TInputPoint, typename TInternalScalar>
357template <typename Vector3D>
360DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
361getNormal( Vector3D & normal ) const
363 myComputers[ active() ].getNormal( normal );
364 invT( active() ).transform( normal );
366//-----------------------------------------------------------------------------
367//-----------------------------------------------------------------------------
368template <typename TSpace, typename TInputPoint, typename TInternalScalar>
369template <typename Vector3D>
372DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
373getUnitNormal( 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//-----------------------------------------------------------------------------
382template <typename TSpace, typename TInputPoint, typename TInternalScalar>
385DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
386getBounds( 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//-----------------------------------------------------------------------------
397template <typename TSpace, typename TInputPoint, typename TInternalScalar>
399typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::InputPoint
400DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
404 InternalScalar imin, imax;
405 InputPoint p_min, p_max;
406 getCharacteristics( n, imin, imax, p_min, p_max );
409//-----------------------------------------------------------------------------
410template <typename TSpace, typename TInputPoint, typename TInternalScalar>
412typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::InputPoint
413DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
417 InternalScalar imin, imax;
418 InputPoint p_min, p_max;
419 getCharacteristics( n, imin, imax, p_min, p_max );
423//-----------------------------------------------------------------------------
424template <typename TSpace, typename TInputPoint, typename TInternalScalar>
427DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
428getCharacteristics( 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.
464template <typename TSpace, typename TInputPoint, typename TInternalScalar>
467DGtal::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.
480template <typename TSpace, typename TInputPoint, typename TInternalScalar>
483DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::isValid() const
485 return myComputers[ active() ].isValid();
489///////////////////////////////////////////////////////////////////////////////
491///////////////////////////////////////////////////////////////////////////////
493//-----------------------------------------------------------------------------
494template <typename TSpace, typename TInputPoint, typename TInternalScalar>
496typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Transform
497DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
498t( Dimension orthant )
500 ASSERT( orthant < 4 );
501 return myTransforms[ orthant ];
503//-----------------------------------------------------------------------------
504template <typename TSpace, typename TInputPoint, typename TInternalScalar>
506typename DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::Transform
507DGtal::ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar>::
508invT( Dimension orthant )
510 ASSERT( orthant < 4 );
511 return myTransforms[ orthant ^ 0x3 ];
514///////////////////////////////////////////////////////////////////////////////
515// Implementation of inline functions //
517template <typename TSpace, typename TInputPoint, typename TInternalScalar>
520DGtal::operator<< ( std::ostream & out,
521 const ChordGenericStandardPlaneComputer<TSpace, TInputPoint, TInternalScalar> & object )
523 object.selfDisplay( out );
528///////////////////////////////////////////////////////////////////////////////