DGtal  0.9.2
COBAGenericStandardPlaneComputer.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 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
21  *
22  * @date 2012/09/20
23  *
24  * Implementation of inline methods defined in COBAGenericStandardPlaneComputer.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 ///////////////////////////////////////////////////////////////////////////////
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 ) };
41 
42 ///////////////////////////////////////////////////////////////////////////////
43 // IMPLEMENTATION of inline methods.
44 ///////////////////////////////////////////////////////////////////////////////
45 
46 ///////////////////////////////////////////////////////////////////////////////
47 // ----------------------- Standard services ------------------------------
48 
49 //-----------------------------------------------------------------------------
50 template <typename TSpace, typename TInternalInteger>
51 inline
52 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
53 ~COBAGenericStandardPlaneComputer()
54 { // Nothing to do.
55 }
56 //-----------------------------------------------------------------------------
57 template <typename TSpace, typename TInternalInteger>
58 inline
59 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
60 COBAGenericStandardPlaneComputer()
61 { // Object is invalid
62  _orthantsToErase.reserve( 4 );
63 }
64 //-----------------------------------------------------------------------------
65 template <typename TSpace, typename TInternalInteger>
66 inline
67 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
68 COBAGenericStandardPlaneComputer( const COBAGenericStandardPlaneComputer & 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 //-----------------------------------------------------------------------------
77 template <typename TSpace, typename TInternalInteger>
78 inline
79 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger> &
80 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
81 operator=( const COBAGenericStandardPlaneComputer & 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 //-----------------------------------------------------------------------------
93 template <typename TSpace, typename TInternalInteger>
94 inline
95 DGtal::Dimension
96 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
97 active() const
98 {
99  ASSERT( myOrthants.size() > 0 );
100  return myOrthants[ 0 ];
101 }
102 //-----------------------------------------------------------------------------
103 template <typename TSpace, typename TInternalInteger>
104 inline
105 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::MyIntegerComputer &
106 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
107 ic() const
108 {
109  return myComputers[ active() ].ic();
110 }
111 //-----------------------------------------------------------------------------
112 template <typename TSpace, typename TInternalInteger>
113 inline
114 void
115 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
116 clear()
117 {
118  myOrthants.clear();
119  for ( unsigned int i = 0; i < 4; ++i )
120  {
121  myOrthants.push_back( i );
122  myComputers[ i ].clear();
123  }
124 }
125 //-----------------------------------------------------------------------------
126 template <typename TSpace, typename TInternalInteger>
127 inline
128 void
129 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
130 init( InternalInteger diameter,
131  InternalInteger widthNumerator,
132  InternalInteger widthDenominator )
133 {
134  clear();
135  for ( unsigned int i = 0; i < 4; ++i )
136  {
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 );
141  }
142 }
143 //-----------------------------------------------------------------------------
144 template <typename TSpace, typename TInternalInteger>
145 inline
146 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::ConstIterator
147 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
148 begin() const
149 {
150  return ConstIterator( myComputers[ active() ].begin(), invT( active() ) );
151 }
152 //-----------------------------------------------------------------------------
153 template <typename TSpace, typename TInternalInteger>
154 inline
155 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::ConstIterator
156 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
157 end() const
158 {
159  return ConstIterator( myComputers[ active() ].end(), invT( active() ) );
160 }
161 //-----------------------------------------------------------------------------
162 template <typename TSpace, typename TInternalInteger>
163 inline
164 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Size
165 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
166 size() const
167 {
168  return myComputers[ active() ].size();
169 }
170 //-----------------------------------------------------------------------------
171 template <typename TSpace, typename TInternalInteger>
172 inline
173 bool
174 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
175 empty() const
176 {
177  return myComputers[ active() ].empty();
178 }
179 //-----------------------------------------------------------------------------
180 template <typename TSpace, typename TInternalInteger>
181 inline
182 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Size
183 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
184 max_size() const
185 {
186  return myComputers[ active() ].max_size();
187 }
188 //-----------------------------------------------------------------------------
189 template <typename TSpace, typename TInternalInteger>
190 inline
191 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Size
192 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
193 maxSize() const
194 {
195  return max_size();
196 }
197 //-----------------------------------------------------------------------------
198 template <typename TSpace, typename TInternalInteger>
199 inline
200 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Size
201 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
202 complexity() const
203 {
204  return myComputers[ active() ].complexity();
205 }
206 //-----------------------------------------------------------------------------
207 template <typename TSpace, typename TInternalInteger>
208 inline
209 bool
210 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
211 operator()( const Point & p ) const
212 {
213  return myComputers[ active() ].operator()( t( active() )( p ) );
214 }
215 
216 //-----------------------------------------------------------------------------
217 template <typename TSpace, typename TInternalInteger>
218 inline
219 bool
220 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
221 extendAsIs( const Point & p )
222 {
223  ASSERT( isValid() );
224  unsigned int nbok = 0;
225  for ( OrthantConstIterator it = myOrthants.begin(), itE = myOrthants.end();
226  it != itE; ++it )
227  {
228  nbok += myComputers[ *it ].operator()( t( *it )( p ) ) ? 1 : 0;
229  }
230  if ( nbok != 0 ) // at least one is ok.
231  {
232  for ( OrthantIterator it = myOrthants.begin(); it != myOrthants.end(); )
233  // cannot put end() in variable, since end() moves when
234  // modifiying a vector.
235  {
236  bool ok = myComputers[ *it ].extendAsIs( t( *it )( p ) );
237  if ( ! ok )
238  it = myOrthants.erase( it );
239  else
240  ++it;
241  }
242  ASSERT( ! myOrthants.empty() );
243  return true;
244  }
245  return false;
246 }
247 
248 //-----------------------------------------------------------------------------
249 template <typename TSpace, typename TInternalInteger>
250 bool
251 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
252 extend( const Point & p )
253 {
254  ASSERT( isValid() );
255  unsigned int nbok = 0;
256  _orthantsToErase.clear();
257  for ( OrthantConstIterator orthIt = myOrthants.begin(), orthItE = myOrthants.end();
258  orthIt != orthItE; ++orthIt )
259  {
260  Point Tp = t( *orthIt )( p );
261  bool ok = myComputers[ *orthIt ].extend( Tp );
262  if ( ! ok ) _orthantsToErase.push_back( *orthIt );
263  else ++nbok;
264  }
265  if ( nbok != 0 ) // at least one is ok.
266  { // if one is ok, we must remove ko ones from the list of active
267  // orthants.
268  OrthantIterator orthIt = myOrthants.begin();
269  for ( unsigned int i = 0; i < _orthantsToErase.size(); ++i )
270  {
271  while ( *orthIt != _orthantsToErase[ i ] ) ++orthIt;
272  orthIt = myOrthants.erase( orthIt );
273  }
274  return true;
275  }
276  return false;
277 }
278 //-----------------------------------------------------------------------------
279 template <typename TSpace, typename TInternalInteger>
280 bool
281 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
282 isExtendable( const Point & p ) const
283 {
284  ASSERT( isValid() );
285  unsigned int nbok = 0;
286  for ( OrthantConstIterator it = myOrthants.begin(), itE = myOrthants.end();
287  it != itE; ++it )
288  {
289  nbok += myComputers[ *it ].isExtendable( t( *it )( p ) ) ? 1 : 0;
290  }
291  return nbok != 0;
292 }
293 //-----------------------------------------------------------------------------
294 template <typename TSpace, typename TInternalInteger>
295 template <typename TInputIterator>
296 bool
297 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
298 extend( TInputIterator it, TInputIterator itE )
299 {
300  BOOST_CONCEPT_ASSERT(( boost::InputIterator<TInputIterator> ));
301  ASSERT( isValid() );
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 )
307  {
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 );
313  else ++nbok;
314  }
315  if ( nbok != 0 ) // at least one is ok.
316  { // if one is ok, we must remove ko ones from the list of active
317  // orthants.
318  OrthantIterator orthIt = myOrthants.begin();
319  for ( unsigned int i = 0; i < _orthantsToErase.size(); ++i )
320  {
321  while ( *orthIt != _orthantsToErase[ i ] ) ++orthIt;
322  orthIt = myOrthants.erase( orthIt );
323  }
324  return true;
325  }
326  return false;
327 }
328 //-----------------------------------------------------------------------------
329 template <typename TSpace, typename TInternalInteger>
330 template <typename TInputIterator>
331 bool
332 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
333 isExtendable( TInputIterator it, TInputIterator itE ) const
334 {
335  BOOST_CONCEPT_ASSERT(( boost::InputIterator<TInputIterator> ));
336  ASSERT( isValid() );
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 )
342  {
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;
347  }
348  return nbok != 0;
349 }
350 //-----------------------------------------------------------------------------
351 template <typename TSpace, typename TInternalInteger>
352 inline
353 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Primitive
354 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
355 primitive() const
356 {
357  IntegerVector3 n;
358  InternalInteger imin, imax;
359  Point p_min, p_max;
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 );
369 }
370 //-----------------------------------------------------------------------------
371 template <typename TSpace, typename TInternalInteger>
372 template <typename Vector3D>
373 inline
374 void
375 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
376 getNormal( Vector3D & normal ) const
377 {
378  myComputers[ active() ].getNormal( normal );
379  invT( active() ).transform( normal );
380 }
381 //-----------------------------------------------------------------------------
382 //-----------------------------------------------------------------------------
383 template <typename TSpace, typename TInternalInteger>
384 template <typename Vector3D>
385 inline
386 void
387 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
388 getUnitNormal( Vector3D & normal ) const
389 {
390  myComputers[ active() ].getNormal( normal );
391  invT( active() ).transform( normal );
392  normal /= sqrt( normal[0]*normal[0]
393  +normal[1]*normal[1]
394  +normal[2]*normal[2] );
395 }
396 //-----------------------------------------------------------------------------
397 template <typename TSpace, typename TInternalInteger>
398 inline
399 void
400 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
401 getBounds( double & min, double & max ) const
402 {
403  IntegerVector3 n;
404  InternalInteger imin, imax;
405  Point p_min, p_max;
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;
410 }
411 //-----------------------------------------------------------------------------
412 template <typename TSpace, typename TInternalInteger>
413 inline
414 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Point
415 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
416 minimalPoint() const
417 {
418  IntegerVector3 n;
419  InternalInteger imin, imax;
420  Point p_min, p_max;
421  getCharacteristics( n, imin, imax, p_min, p_max );
422  return p_min;
423 }
424 //-----------------------------------------------------------------------------
425 template <typename TSpace, typename TInternalInteger>
426 inline
427 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Point
428 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
429 maximalPoint() const
430 {
431  IntegerVector3 n;
432  InternalInteger imin, imax;
433  Point p_min, p_max;
434  getCharacteristics( n, imin, imax, p_min, p_max );
435  return p_max;
436 }
437 
438 //-----------------------------------------------------------------------------
439 template <typename TSpace, typename TInternalInteger>
440 inline
441 void
442 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
443 getCharacteristics( IntegerVector3 & n,
444  InternalInteger & imin, InternalInteger & imax,
445  Point & p_min, Point & p_max ) const
446 {
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 )
455  { n = -n; }
456  imin =
457  ( ( n[ 0 ] * InternalInteger( p_min[ 0 ] ) )
458  + ( n[ 1 ] * InternalInteger( p_min[ 1 ] ) )
459  + ( n[ 2 ] * InternalInteger( p_min[ 2 ] ) ) );
460  imax =
461  ( ( n[ 0 ] * InternalInteger( p_max[ 0 ] ) )
462  + ( n[ 1 ] * InternalInteger( p_max[ 1 ] ) )
463  + ( n[ 2 ] * InternalInteger( p_max[ 2 ] ) ) );
464  if ( imax < imin )
465  {
466  std::swap( imin, imax );
467  std::swap( p_min, p_max );
468  }
469 }
470 
471 ///////////////////////////////////////////////////////////////////////////////
472 // Interface - public :
473 
474 /**
475  * Writes/Displays the object on an output stream.
476  * @param out the output stream where the object is written.
477  */
478 template <typename TSpace, typename TInternalInteger>
479 inline
480 void
481 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::selfDisplay ( std::ostream & out ) const
482 {
483  out << "[COBAGenericStandardPlaneComputer";
484  for ( OrthantConstIterator orthIt = myOrthants.begin(), orthItE = myOrthants.end();
485  orthIt != orthItE; ++orthIt )
486  out << " " << myComputers[ *orthIt ];
487  out << " ]";
488 }
489 
490 /**
491  * Checks the validity/consistency of the object.
492  * @return 'true' if the object is valid, 'false' otherwise.
493  */
494 template <typename TSpace, typename TInternalInteger>
495 inline
496 bool
497 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::isValid() const
498 {
499  return myComputers[ active() ].isValid();
500 }
501 
502 
503 ///////////////////////////////////////////////////////////////////////////////
504 // Internals
505 ///////////////////////////////////////////////////////////////////////////////
506 
507 //-----------------------------------------------------------------------------
508 template <typename TSpace, typename TInternalInteger>
509 inline
510 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Transform
511 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
512 t( Dimension orthant )
513 {
514  ASSERT( orthant < 4 );
515  return myTransforms[ orthant ];
516 }
517 //-----------------------------------------------------------------------------
518 template <typename TSpace, typename TInternalInteger>
519 inline
520 typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Transform
521 DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
522 invT( Dimension orthant )
523 {
524  ASSERT( orthant < 4 );
525  return myTransforms[ orthant ^ 0x3 ];
526 }
527 
528 ///////////////////////////////////////////////////////////////////////////////
529 // Implementation of inline functions //
530 
531 template <typename TSpace, typename TInternalInteger>
532 inline
533 std::ostream&
534 DGtal::operator<< ( std::ostream & out,
535  const COBAGenericStandardPlaneComputer<TSpace, TInternalInteger> & object )
536 {
537  object.selfDisplay( out );
538  return out;
539 }
540 
541 // //
542 ///////////////////////////////////////////////////////////////////////////////
543 
544