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 ///////////////////////////////////////////////////////////////////////////////
37 template <typename TSpace, typename TInternalInteger>
38 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Transform
39 DGtal::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 //-----------------------------------------------------------------------------
50 template <typename TSpace, typename TInternalInteger>
52 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
53 ~COBAGenericStandardPlaneComputer()
56 //-----------------------------------------------------------------------------
57 template <typename TSpace, typename TInternalInteger>
59 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
60 COBAGenericStandardPlaneComputer()
61 { // Object is invalid
62 _orthantsToErase.reserve( 4 );
64 //-----------------------------------------------------------------------------
65 template <typename TSpace, typename TInternalInteger>
67 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
68 COBAGenericStandardPlaneComputer( 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 //-----------------------------------------------------------------------------
77 template <typename TSpace, typename TInternalInteger>
79 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger> &
80 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
81 operator=( const COBAGenericStandardPlaneComputer & 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 TInternalInteger>
96 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
99 ASSERT( myOrthants.size() > 0 );
100 return myOrthants[ 0 ];
102 //-----------------------------------------------------------------------------
103 template <typename TSpace, typename TInternalInteger>
105 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::MyIntegerComputer &
106 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
109 return myComputers[ active() ].ic();
111 //-----------------------------------------------------------------------------
112 template <typename TSpace, typename TInternalInteger>
115 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
119 for ( unsigned int i = 0; i < 4; ++i )
121 myOrthants.push_back( i );
122 myComputers[ i ].clear();
125 //-----------------------------------------------------------------------------
126 template <typename TSpace, typename TInternalInteger>
129 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
130 init( 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 //-----------------------------------------------------------------------------
144 template <typename TSpace, typename TInternalInteger>
146 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::ConstIterator
147 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
150 return ConstIterator( myComputers[ active() ].begin(), invT( active() ) );
152 //-----------------------------------------------------------------------------
153 template <typename TSpace, typename TInternalInteger>
155 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::ConstIterator
156 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
159 return ConstIterator( myComputers[ active() ].end(), invT( active() ) );
161 //-----------------------------------------------------------------------------
162 template <typename TSpace, typename TInternalInteger>
164 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Size
165 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
168 return myComputers[ active() ].size();
170 //-----------------------------------------------------------------------------
171 template <typename TSpace, typename TInternalInteger>
174 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
177 return myComputers[ active() ].empty();
179 //-----------------------------------------------------------------------------
180 template <typename TSpace, typename TInternalInteger>
182 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Size
183 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
186 return myComputers[ active() ].max_size();
188 //-----------------------------------------------------------------------------
189 template <typename TSpace, typename TInternalInteger>
191 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Size
192 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
197 //-----------------------------------------------------------------------------
198 template <typename TSpace, typename TInternalInteger>
200 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Size
201 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
204 return myComputers[ active() ].complexity();
206 //-----------------------------------------------------------------------------
207 template <typename TSpace, typename TInternalInteger>
210 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
211 operator()( const Point & p ) const
213 return myComputers[ active() ].operator()( t( active() )( p ) );
216 //-----------------------------------------------------------------------------
217 template <typename TSpace, typename TInternalInteger>
220 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
221 extendAsIs( 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 //-----------------------------------------------------------------------------
249 template <typename TSpace, typename TInternalInteger>
251 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
252 extend( 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 //-----------------------------------------------------------------------------
279 template <typename TSpace, typename TInternalInteger>
281 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
282 isExtendable( 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 //-----------------------------------------------------------------------------
294 template <typename TSpace, typename TInternalInteger>
295 template <typename TInputIterator>
297 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
298 extend( 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 //-----------------------------------------------------------------------------
329 template <typename TSpace, typename TInternalInteger>
330 template <typename TInputIterator>
332 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
333 isExtendable( 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 //-----------------------------------------------------------------------------
351 template <typename TSpace, typename TInternalInteger>
353 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Primitive
354 DGtal::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 //-----------------------------------------------------------------------------
371 template <typename TSpace, typename TInternalInteger>
372 template <typename Vector3D>
375 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
376 getNormal( Vector3D & normal ) const
378 myComputers[ active() ].getNormal( normal );
379 invT( active() ).transform( normal );
381 //-----------------------------------------------------------------------------
382 //-----------------------------------------------------------------------------
383 template <typename TSpace, typename TInternalInteger>
384 template <typename Vector3D>
387 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
388 getUnitNormal( 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 //-----------------------------------------------------------------------------
397 template <typename TSpace, typename TInternalInteger>
400 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
401 getBounds( 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 //-----------------------------------------------------------------------------
412 template <typename TSpace, typename TInternalInteger>
414 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Point
415 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
419 InternalInteger imin, imax;
421 getCharacteristics( n, imin, imax, p_min, p_max );
424 //-----------------------------------------------------------------------------
425 template <typename TSpace, typename TInternalInteger>
427 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Point
428 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
432 InternalInteger imin, imax;
434 getCharacteristics( n, imin, imax, p_min, p_max );
438 //-----------------------------------------------------------------------------
439 template <typename TSpace, typename TInternalInteger>
442 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
443 getCharacteristics( 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.
478 template <typename TSpace, typename TInternalInteger>
481 DGtal::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.
494 template <typename TSpace, typename TInternalInteger>
497 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::isValid() const
499 return myComputers[ active() ].isValid();
503 ///////////////////////////////////////////////////////////////////////////////
505 ///////////////////////////////////////////////////////////////////////////////
507 //-----------------------------------------------------------------------------
508 template <typename TSpace, typename TInternalInteger>
510 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Transform
511 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
512 t( Dimension orthant )
514 ASSERT( orthant < 4 );
515 return myTransforms[ orthant ];
517 //-----------------------------------------------------------------------------
518 template <typename TSpace, typename TInternalInteger>
520 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Transform
521 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
522 invT( Dimension orthant )
524 ASSERT( orthant < 4 );
525 return myTransforms[ orthant ^ 0x3 ];
528 ///////////////////////////////////////////////////////////////////////////////
529 // Implementation of inline functions //
531 template <typename TSpace, typename TInternalInteger>
534 DGtal::operator<< ( std::ostream & out,
535 const COBAGenericStandardPlaneComputer<TSpace, TInternalInteger> & object )
537 object.selfDisplay( out );
542 ///////////////////////////////////////////////////////////////////////////////