DGtal 1.4.0
Loading...
Searching...
No Matches
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///////////////////////////////////////////////////////////////////////////////
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 ) };
41
42///////////////////////////////////////////////////////////////////////////////
43// IMPLEMENTATION of inline methods.
44///////////////////////////////////////////////////////////////////////////////
45
46///////////////////////////////////////////////////////////////////////////////
47// ----------------------- Standard services ------------------------------
48
49//-----------------------------------------------------------------------------
50template <typename TSpace, typename TInternalInteger>
51inline
52DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
53~COBAGenericStandardPlaneComputer()
54{ // Nothing to do.
55}
56//-----------------------------------------------------------------------------
57template <typename TSpace, typename TInternalInteger>
58inline
59DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
60COBAGenericStandardPlaneComputer()
61{ // Object is invalid
62 _orthantsToErase.reserve( 4 );
63}
64//-----------------------------------------------------------------------------
65template <typename TSpace, typename TInternalInteger>
66inline
67DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
68COBAGenericStandardPlaneComputer( 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//-----------------------------------------------------------------------------
77template <typename TSpace, typename TInternalInteger>
78inline
79DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger> &
80DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
81operator=( 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//-----------------------------------------------------------------------------
93template <typename TSpace, typename TInternalInteger>
94inline
95DGtal::Dimension
96DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
97active() const
98{
99 ASSERT( myOrthants.size() > 0 );
100 return myOrthants[ 0 ];
101}
102//-----------------------------------------------------------------------------
103template <typename TSpace, typename TInternalInteger>
104inline
105typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::MyIntegerComputer &
106DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
107ic() const
108{
109 return myComputers[ active() ].ic();
110}
111//-----------------------------------------------------------------------------
112template <typename TSpace, typename TInternalInteger>
113inline
114void
115DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
116clear()
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//-----------------------------------------------------------------------------
126template <typename TSpace, typename TInternalInteger>
127inline
128void
129DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
130init( 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//-----------------------------------------------------------------------------
144template <typename TSpace, typename TInternalInteger>
145inline
146typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::ConstIterator
147DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
148begin() const
149{
150 return ConstIterator( myComputers[ active() ].begin(), invT( active() ) );
151}
152//-----------------------------------------------------------------------------
153template <typename TSpace, typename TInternalInteger>
154inline
155typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::ConstIterator
156DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
157end() const
158{
159 return ConstIterator( myComputers[ active() ].end(), invT( active() ) );
160}
161//-----------------------------------------------------------------------------
162template <typename TSpace, typename TInternalInteger>
163inline
164typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Size
165DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
166size() const
167{
168 return myComputers[ active() ].size();
169}
170//-----------------------------------------------------------------------------
171template <typename TSpace, typename TInternalInteger>
172inline
173bool
174DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
175empty() const
176{
177 return myComputers[ active() ].empty();
178}
179//-----------------------------------------------------------------------------
180template <typename TSpace, typename TInternalInteger>
181inline
182typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Size
183DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
184max_size() const
185{
186 return myComputers[ active() ].max_size();
187}
188//-----------------------------------------------------------------------------
189template <typename TSpace, typename TInternalInteger>
190inline
191typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Size
192DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
193maxSize() const
194{
195 return max_size();
196}
197//-----------------------------------------------------------------------------
198template <typename TSpace, typename TInternalInteger>
199inline
200typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Size
201DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
202complexity() const
203{
204 return myComputers[ active() ].complexity();
205}
206//-----------------------------------------------------------------------------
207template <typename TSpace, typename TInternalInteger>
208inline
209bool
210DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
211operator()( const Point & p ) const
212{
213 return myComputers[ active() ].operator()( t( active() )( p ) );
214}
215
216//-----------------------------------------------------------------------------
217template <typename TSpace, typename TInternalInteger>
218inline
219bool
220DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
221extendAsIs( 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//-----------------------------------------------------------------------------
249template <typename TSpace, typename TInternalInteger>
250bool
251DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
252extend( 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//-----------------------------------------------------------------------------
279template <typename TSpace, typename TInternalInteger>
280bool
281DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
282isExtendable( 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//-----------------------------------------------------------------------------
294template <typename TSpace, typename TInternalInteger>
295template <typename TInputIterator>
296bool
297DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
298extend( 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//-----------------------------------------------------------------------------
329template <typename TSpace, typename TInternalInteger>
330template <typename TInputIterator>
331bool
332DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
333isExtendable( 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//-----------------------------------------------------------------------------
351template <typename TSpace, typename TInternalInteger>
352inline
353typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Primitive
354DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
355primitive() 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//-----------------------------------------------------------------------------
371template <typename TSpace, typename TInternalInteger>
372template <typename Vector3D>
373inline
374void
375DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
376getNormal( Vector3D & normal ) const
377{
378 myComputers[ active() ].getNormal( normal );
379 invT( active() ).transform( normal );
380}
381//-----------------------------------------------------------------------------
382//-----------------------------------------------------------------------------
383template <typename TSpace, typename TInternalInteger>
384template <typename Vector3D>
385inline
386void
387DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
388getUnitNormal( 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//-----------------------------------------------------------------------------
397template <typename TSpace, typename TInternalInteger>
398inline
399void
400DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
401getBounds( 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//-----------------------------------------------------------------------------
412template <typename TSpace, typename TInternalInteger>
413inline
414typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Point
415DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
416minimalPoint() 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//-----------------------------------------------------------------------------
425template <typename TSpace, typename TInternalInteger>
426inline
427typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Point
428DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
429maximalPoint() 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//-----------------------------------------------------------------------------
439template <typename TSpace, typename TInternalInteger>
440inline
441void
442DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
443getCharacteristics( 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 */
478template <typename TSpace, typename TInternalInteger>
479inline
480void
481DGtal::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 */
494template <typename TSpace, typename TInternalInteger>
495inline
496bool
497DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::isValid() const
498{
499 return myComputers[ active() ].isValid();
500}
501
502
503///////////////////////////////////////////////////////////////////////////////
504// Internals
505///////////////////////////////////////////////////////////////////////////////
506
507//-----------------------------------------------------------------------------
508template <typename TSpace, typename TInternalInteger>
509inline
510typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Transform
511DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
512t( Dimension orthant )
513{
514 ASSERT( orthant < 4 );
515 return myTransforms[ orthant ];
516}
517//-----------------------------------------------------------------------------
518template <typename TSpace, typename TInternalInteger>
519inline
520typename DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::Transform
521DGtal::COBAGenericStandardPlaneComputer<TSpace, TInternalInteger>::
522invT( Dimension orthant )
523{
524 ASSERT( orthant < 4 );
525 return myTransforms[ orthant ^ 0x3 ];
526}
527
528///////////////////////////////////////////////////////////////////////////////
529// Implementation of inline functions //
530
531template <typename TSpace, typename TInternalInteger>
532inline
533std::ostream&
534DGtal::operator<< ( std::ostream & out,
535 const COBAGenericStandardPlaneComputer<TSpace, TInternalInteger> & object )
536{
537 object.selfDisplay( out );
538 return out;
539}
540
541// //
542///////////////////////////////////////////////////////////////////////////////
543
544