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 COBAGenericStandardPlaneComputer.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 COBAGenericStandardPlaneComputer.h
26 * This file is part of the DGtal library.
30//////////////////////////////////////////////////////////////////////////////
32//////////////////////////////////////////////////////////////////////////////
34///////////////////////////////////////////////////////////////////////////////
35// DEFINITION of static members
36///////////////////////////////////////////////////////////////////////////////
37template <typename TSpace, typename TInternalInteger>
38typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Transform
39DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::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 TInternalInteger>
52DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
53~COBAGenericStandardPlaneComputer()
56//-----------------------------------------------------------------------------
57template <typename TSpace, typename TInternalInteger>
59DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
60COBAGenericStandardPlaneComputer()
62 _orthantsToErase.reserve( 4 );
64//-----------------------------------------------------------------------------
65template <typename TSpace, typename TInternalInteger>
67DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
68COBAGenericStandardPlaneComputer( const COBAGenericStandardPlaneComputer & 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 TInternalInteger>
79DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger> &
80DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
81operator=( const COBAGenericStandardPlaneComputer & 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 TInternalInteger>
96DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
99 ASSERT( myOrthants.size() > 0 );
100 return myOrthants[ 0 ];
102//-----------------------------------------------------------------------------
103template <typename TSpace, typename TInternalInteger>
105typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::MyIntegerComputer &
106DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
109 return myComputers[ active() ].ic();
111//-----------------------------------------------------------------------------
112template <typename TSpace, typename TInternalInteger>
115DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
119 for ( unsigned int i = 0; i < 4; ++i )
121 myOrthants.push_back( i );
122 myComputers[ i ].clear();
125//-----------------------------------------------------------------------------
126template <typename TSpace, typename TInternalInteger>
129DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
130init( InternalInteger diameter,
131 InternalInteger widthNumerator,
132 InternalInteger widthDenominator )
135 for ( unsigned int i = 0; i < 4; ++i )
137 // all COBA computers computes naive planes along z, but the 4
138 // transforms dilate the x,y coordinates in four different ways
139 // to get all the possible orientations of standard planes.
140 myComputers[ i ].init( 2, diameter, widthNumerator, widthDenominator );
143//-----------------------------------------------------------------------------
144template <typename TSpace, typename TInternalInteger>
146typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::ConstIterator
147DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
150 return ConstIterator( myComputers[ active() ].begin(), invT( active() ) );
152//-----------------------------------------------------------------------------
153template <typename TSpace, typename TInternalInteger>
155typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::ConstIterator
156DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
159 return ConstIterator( myComputers[ active() ].end(), invT( active() ) );
161//-----------------------------------------------------------------------------
162template <typename TSpace, typename TInternalInteger>
164typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Size
165DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
168 return myComputers[ active() ].size();
170//-----------------------------------------------------------------------------
171template <typename TSpace, typename TInternalInteger>
174DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
177 return myComputers[ active() ].empty();
179//-----------------------------------------------------------------------------
180template <typename TSpace, typename TInternalInteger>
182typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Size
183DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
186 return myComputers[ active() ].max_size();
188//-----------------------------------------------------------------------------
189template <typename TSpace, typename TInternalInteger>
191typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Size
192DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
197//-----------------------------------------------------------------------------
198template <typename TSpace, typename TInternalInteger>
200typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Size
201DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
204 return myComputers[ active() ].complexity();
206//-----------------------------------------------------------------------------
207template <typename TSpace, typename TInternalInteger>
210DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
211operator()( const Point & p ) const
213 return myComputers[ active() ].operator()( t( active() )( p ) );
216//-----------------------------------------------------------------------------
217template <typename TSpace, typename TInternalInteger>
220DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
221extendAsIs( const Point & p )
224 unsigned int nbok = 0;
225 for ( OrthantConstIterator it = myOrthants.begin(), itE = myOrthants.end();
228 nbok += myComputers[ *it ].operator()( t( *it )( p ) ) ? 1 : 0;
230 if ( nbok != 0 ) // at least one is ok.
232 for ( OrthantIterator it = myOrthants.begin(); it != myOrthants.end(); )
233 // cannot put end() in variable, since end() moves when
234 // modifiying a vector.
236 bool ok = myComputers[ *it ].extendAsIs( t( *it )( p ) );
238 it = myOrthants.erase( it );
242 ASSERT( ! myOrthants.empty() );
248//-----------------------------------------------------------------------------
249template <typename TSpace, typename TInternalInteger>
251DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
252extend( const Point & p )
255 unsigned int nbok = 0;
256 _orthantsToErase.clear();
257 for ( OrthantConstIterator orthIt = myOrthants.begin(), orthItE = myOrthants.end();
258 orthIt != orthItE; ++orthIt )
260 Point Tp = t( *orthIt )( p );
261 bool ok = myComputers[ *orthIt ].extend( Tp );
262 if ( ! ok ) _orthantsToErase.push_back( *orthIt );
265 if ( nbok != 0 ) // at least one is ok.
266 { // if one is ok, we must remove ko ones from the list of active
268 OrthantIterator orthIt = myOrthants.begin();
269 for ( unsigned int i = 0; i < _orthantsToErase.size(); ++i )
271 while ( *orthIt != _orthantsToErase[ i ] ) ++orthIt;
272 orthIt = myOrthants.erase( orthIt );
278//-----------------------------------------------------------------------------
279template <typename TSpace, typename TInternalInteger>
281DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
282isExtendable( const Point & p ) const
285 unsigned int nbok = 0;
286 for ( OrthantConstIterator it = myOrthants.begin(), itE = myOrthants.end();
289 nbok += myComputers[ *it ].isExtendable( t( *it )( p ) ) ? 1 : 0;
293//-----------------------------------------------------------------------------
294template <typename TSpace, typename TInternalInteger>
295template <typename TInputIterator>
297DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
298extend( TInputIterator it, TInputIterator itE )
300 BOOST_CONCEPT_ASSERT(( boost::InputIterator<TInputIterator> ));
302 typedef boost::transform_iterator<Transform,TInputIterator,Point,Point> TransformedInputIterator;
303 unsigned int nbok = 0;
304 _orthantsToErase.clear();
305 for ( OrthantConstIterator orthIt = myOrthants.begin(), orthItE = myOrthants.end();
306 orthIt != orthItE; ++orthIt )
308 Dimension orthant = *orthIt;
309 TransformedInputIterator transIt ( it, t( orthant ) );
310 TransformedInputIterator transItE( itE, t( orthant ) );
311 bool ok = myComputers[ orthant ].extend( transIt, transItE );
312 if ( ! ok ) _orthantsToErase.push_back( orthant );
315 if ( nbok != 0 ) // at least one is ok.
316 { // if one is ok, we must remove ko ones from the list of active
318 OrthantIterator orthIt = myOrthants.begin();
319 for ( unsigned int i = 0; i < _orthantsToErase.size(); ++i )
321 while ( *orthIt != _orthantsToErase[ i ] ) ++orthIt;
322 orthIt = myOrthants.erase( orthIt );
328//-----------------------------------------------------------------------------
329template <typename TSpace, typename TInternalInteger>
330template <typename TInputIterator>
332DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
333isExtendable( TInputIterator it, TInputIterator itE ) const
335 BOOST_CONCEPT_ASSERT(( boost::InputIterator<TInputIterator> ));
337 typedef boost::transform_iterator<Transform,TInputIterator,Point,Point>
338 TransformedInputIterator;
339 unsigned int nbok = 0;
340 for ( OrthantConstIterator orthIt = myOrthants.begin(), orthItE = myOrthants.end();
341 orthIt != orthItE; ++orthIt )
343 Dimension orthant = *orthIt;
344 TransformedInputIterator transIt ( it, t( orthant ) );
345 TransformedInputIterator transItE( itE, t( orthant ) );
346 nbok += myComputers[ orthant ].isExtendable( transIt, transItE ) ? 1 : 0;
350//-----------------------------------------------------------------------------
351template <typename TSpace, typename TInternalInteger>
353typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Primitive
354DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
358 InternalInteger imin, imax;
360 getCharacteristics( n, imin, imax, p_min, p_max );
361 double ddenom = NumberTraits<InternalInteger>::castToDouble( n[ 2 ] );
362 double min = ( NumberTraits<InternalInteger>::castToDouble( imin ) - 0.5 ) / ddenom;
363 double max = ( NumberTraits<InternalInteger>::castToDouble( imax ) + 0.5 ) / ddenom;
364 typename Space::RealVector normal;
365 normal[ 0 ] = NumberTraits<InternalInteger>::castToDouble( n[ 0 ] ) / ddenom;
366 normal[ 1 ] = NumberTraits<InternalInteger>::castToDouble( n[ 1 ] ) / ddenom;
367 normal[ 2 ] = NumberTraits<InternalInteger>::castToDouble( n[ 2 ] ) / ddenom;
368 return Primitive( min, normal, max-min );
370//-----------------------------------------------------------------------------
371template <typename TSpace, typename TInternalInteger>
372template <typename Vector3D>
375DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
376getNormal( Vector3D & normal ) const
378 myComputers[ active() ].getNormal( normal );
379 invT( active() ).transform( normal );
381//-----------------------------------------------------------------------------
382//-----------------------------------------------------------------------------
383template <typename TSpace, typename TInternalInteger>
384template <typename Vector3D>
387DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
388getUnitNormal( Vector3D & normal ) const
390 myComputers[ active() ].getNormal( normal );
391 invT( active() ).transform( normal );
392 normal /= sqrt( normal[0]*normal[0]
394 +normal[2]*normal[2] );
396//-----------------------------------------------------------------------------
397template <typename TSpace, typename TInternalInteger>
400DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
401getBounds( double & min, double & max ) const
404 InternalInteger imin, imax;
406 getCharacteristics( n, imin, imax, p_min, p_max );
407 double ddenom = NumberTraits<InternalInteger>::castToDouble( n[ 2 ] );
408 min = ( NumberTraits<InternalInteger>::castToDouble( imin ) - 0.5 ) / ddenom;
409 max = ( NumberTraits<InternalInteger>::castToDouble( imax ) + 0.5 ) / ddenom;
411//-----------------------------------------------------------------------------
412template <typename TSpace, typename TInternalInteger>
414typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Point
415DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
419 InternalInteger imin, imax;
421 getCharacteristics( n, imin, imax, p_min, p_max );
424//-----------------------------------------------------------------------------
425template <typename TSpace, typename TInternalInteger>
427typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Point
428DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
432 InternalInteger imin, imax;
434 getCharacteristics( n, imin, imax, p_min, p_max );
438//-----------------------------------------------------------------------------
439template <typename TSpace, typename TInternalInteger>
442DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
443getCharacteristics( IntegerVector3 & n,
444 InternalInteger & imin, InternalInteger & imax,
445 Point & p_min, Point & p_max ) const
447 // This rather complex method is necessary to guarantee that there
448 // are no numeric error due to bad rounding when casting to double.
449 p_min = invT( active() )( myComputers[ active() ].minimalPoint() );
450 p_max = invT( active() )( myComputers[ active() ].maximalPoint() );
451 // min and max may be swapped because of the transform.
452 n = myComputers[ active() ].exactNormal();
453 invT( active() ).transform( n );
454 if ( n[ 2 ] < NumberTraits<InternalInteger>::ZERO )
457 ( ( n[ 0 ] * InternalInteger( p_min[ 0 ] ) )
458 + ( n[ 1 ] * InternalInteger( p_min[ 1 ] ) )
459 + ( n[ 2 ] * InternalInteger( p_min[ 2 ] ) ) );
461 ( ( n[ 0 ] * InternalInteger( p_max[ 0 ] ) )
462 + ( n[ 1 ] * InternalInteger( p_max[ 1 ] ) )
463 + ( n[ 2 ] * InternalInteger( p_max[ 2 ] ) ) );
466 std::swap( imin, imax );
467 std::swap( p_min, p_max );
471///////////////////////////////////////////////////////////////////////////////
472// Interface - public :
475 * Writes/Displays the object on an output stream.
476 * @param out the output stream where the object is written.
478template <typename TSpace, typename TInternalInteger>
481DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::selfDisplay ( std::ostream & out ) const
483 out << "[COBAGenericStandardPlaneComputer";
484 for ( OrthantConstIterator orthIt = myOrthants.begin(), orthItE = myOrthants.end();
485 orthIt != orthItE; ++orthIt )
486 out << " " << myComputers[ *orthIt ];
491 * Checks the validity/consistency of the object.
492 * @return 'true' if the object is valid, 'false' otherwise.
494template <typename TSpace, typename TInternalInteger>
497DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::isValid() const
499 return myComputers[ active() ].isValid();
503///////////////////////////////////////////////////////////////////////////////
505///////////////////////////////////////////////////////////////////////////////
507//-----------------------------------------------------------------------------
508template <typename TSpace, typename TInternalInteger>
510typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Transform
511DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
512t( Dimension orthant )
514 ASSERT( orthant < 4 );
515 return myTransforms[ orthant ];
517//-----------------------------------------------------------------------------
518template <typename TSpace, typename TInternalInteger>
520typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Transform
521DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
522invT( Dimension orthant )
524 ASSERT( orthant < 4 );
525 return myTransforms[ orthant ^ 0x3 ];
528///////////////////////////////////////////////////////////////////////////////
529// Implementation of inline functions //
531template <typename TSpace, typename TInternalInteger>
534DGtal::operator<< ( std::ostream & out,
535 const COBAGenericStandardPlaneComputer<TSpace, TInternalInteger> & object )
537 object.selfDisplay( out );
542///////////////////////////////////////////////////////////////////////////////