DGtal  1.2.0
PointVector.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 PointVector.ih
19  * @author David Coeurjolly (\c david.coeurjolly@liris.cnrs.fr )
20  * @author Guillaume Damiand
21  * Laboratoire d'InfoRmatique en Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), CNRS, France
22  *
23  * @date 2010/05/14
24  *
25  * Implementation of inline methods defined in PointVector.h
26  *
27  * This file is part of the DGtal library.
28  */
29 
30 ///////////////////////////////////////////////////////////////////////////////
31 // IMPLEMENTATION of inline methods.
32 ///////////////////////////////////////////////////////////////////////////////
33 
34 //////////////////////////////////////////////////////////////////////////////
35 #include <cstdlib>
36 #include <cmath>
37 #include <DGtal/base/BasicFunctors.h>
38 #include "DGtal/io/Color.h"
39 //////////////////////////////////////////////////////////////////////////////
40 
41 
42 template<DGtal::Dimension dim, typename Container>
43 inline
44 std::bitset<dim> DGtal::setDimensionsIn( const Container &dimensions )
45 {
46  std::bitset<dim> t1;
47  for ( typename Container::const_iterator it=dimensions.begin();
48  it!=dimensions.end(); ++it )
49  {
50  ASSERT( *it<dim );
51  t1.set(*it);
52  }
53  return t1;
54 }
55 //------------------------------------------------------------------------------
56 template<DGtal::Dimension dim, typename Container>
57 inline
58 std::bitset<dim> DGtal::setDimensionsNotIn( const Container &dimensions )
59 {
60  std::bitset<dim> t1; t1.set();
61  for ( typename Container::const_iterator it=dimensions.begin();
62  it!=dimensions.end(); ++it )
63  {
64  ASSERT( *it<dim );
65  t1.reset(*it);
66  }
67  return t1;
68 }
69 //------------------------------------------------------------------------------
70 
71 
72 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
73 inline
74 DGtal::PointVector<dim, TComponent, TContainer>::PointVector()
75 {
76  for ( Dimension i = 0; i < dim; ++i )
77  myArray[ i ] = NumberTraits<TComponent>::ZERO;
78 }
79 //------------------------------------------------------------------------------
80 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
81 template <
82  typename LeftComponent, typename LeftStorage,
83  typename RightComponent, typename RightStorage,
84  typename BinaryFunctor >
85 inline
86 DGtal::PointVector<dim, TComponent, TContainer>::PointVector(
87  const PointVector<dim, LeftComponent, LeftStorage> & apoint1,
88  const PointVector<dim, RightComponent, RightStorage> & apoint2,
89  const BinaryFunctor & f)
90 {
91  for ( Dimension i = 0; i < dim; ++i )
92  myArray[ i ] = static_cast<TComponent>( f(apoint1[i], apoint2[i]) );
93 }
94 //------------------------------------------------------------------------------
95 template <DGtal::Dimension dim, typename TComponent, typename TContainer>
96 template <typename OtherComponent, typename OtherStorage, typename UnaryFunctor>
97 inline
98 DGtal::PointVector<dim, TComponent,TContainer>::
99 PointVector(const PointVector<dim, OtherComponent, OtherStorage> & apoint1,
100  const UnaryFunctor& f)
101 {
102  for ( Dimension i = 0; i < dim; ++i )
103  myArray[ i ] = static_cast<TComponent>( f( apoint1[i] ) );
104 }
105 //------------------------------------------------------------------------------
106 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
107 inline
108 DGtal::PointVector<dim, TComponent, TContainer>::~PointVector()
109 {}
110 //------------------------------------------------------------------------------
111 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
112 inline
113 DGtal::PointVector<dim, TComponent, TContainer>::PointVector( const Component * ptrValues )
114 {
115  // The problem here is that we have no guaranty on the size of init !!
116  for ( Dimension i = 0; i < dim; ++i )
117  myArray[ i ] = ptrValues[ i ];
118 }
119 //------------------------------------------------------------------------------
120 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
121 inline
122 DGtal::PointVector<dim, TComponent, TContainer>::PointVector( const Component & x, const Component & y )
123 {
124  ASSERT( dim >= 2 );
125  myArray[ 0 ] = x;
126  myArray[ 1 ] = y;
127  for ( Dimension i = 2; i < dim; ++i )
128  myArray[ i ] = NumberTraits<TComponent>::ZERO;
129 }
130 //------------------------------------------------------------------------------
131 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
132 inline
133 DGtal::PointVector<dim, TComponent, TContainer>::PointVector( const Component & x,
134  const Component & y,
135  const Component & z )
136 {
137  ASSERT( dim >= 3 );
138  myArray[ 0 ] = x;
139  myArray[ 1 ] = y;
140  myArray[ 2 ] = z;
141  for ( Dimension i = 3; i < dim; ++i )
142  myArray[ i ] = NumberTraits<TComponent>::ZERO;
143 }
144 //------------------------------------------------------------------------------
145 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
146 inline
147 DGtal::PointVector<dim, TComponent, TContainer>::PointVector( const Component & x,
148  const Component & y,
149  const Component & z,
150  const Component & t )
151 {
152  ASSERT( dim >= 4 );
153  myArray[ 0 ] = x;
154  myArray[ 1 ] = y;
155  myArray[ 2 ] = z;
156  myArray[ 3 ] = t;
157  for ( Dimension i = 4; i < dim; ++i )
158  myArray[ i ] = NumberTraits<TComponent>::ZERO;
159 }
160 //------------------------------------------------------------------------------
161 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
162 inline
163 DGtal::PointVector<dim, TComponent, TContainer>::PointVector(std::initializer_list<Component> init)
164 {
165  unsigned int i = 0;
166  for (const Component *p = init.begin (); p != init.end () && i < dim; ++p, ++i)
167  myArray[ i ] = *p;
168  for ( ; i < dim; ++i)
169  myArray[i] = NumberTraits<TComponent>::ZERO;
170 }
171 //------------------------------------------------------------------------------
172 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
173 inline
174 DGtal::PointVector<dim, TComponent, TContainer>::PointVector ( const Self & other )
175  : myArray( other.myArray )
176 {}
177 //------------------------------------------------------------------------------
178 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
179 template <
180  typename OtherComponent, typename OtherCont,
181  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type >
182 inline
183 DGtal::PointVector<dim, TComponent, TContainer>::PointVector (const PointVector<dim,OtherComponent,OtherCont> & other )
184 {
185  for ( DGtal::Dimension i = 0; i < dimension; ++i )
186  this->myArray[ i ] = static_cast<TComponent>(other[ i ]);
187 }
188 //------------------------------------------------------------------------------
189 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
190 template <
191  typename OtherComponent, typename OtherCont,
192  typename std::enable_if< ! std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type >
193 inline
194 DGtal::PointVector<dim, TComponent, TContainer>::PointVector (const PointVector<dim,OtherComponent,OtherCont> & other )
195 {
196  for ( DGtal::Dimension i = 0; i < dimension; ++i )
197  this->myArray[ i ] = static_cast<TComponent>(other[ i ]);
198 }
199 //------------------------------------------------------------------------------
200 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
201 inline
202 typename DGtal::PointVector<dim, TComponent, TContainer>::Iterator
203 DGtal::PointVector<dim, TComponent, TContainer>::begin()
204 {
205  return myArray.begin();
206 }
207 //------------------------------------------------------------------------------
208 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
209 inline
210 typename DGtal::PointVector<dim, TComponent, TContainer>::Iterator
211 DGtal::PointVector<dim, TComponent, TContainer>::end()
212 {
213  return myArray.end();
214 }
215 //------------------------------------------------------------------------------
216 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
217 inline
218 typename DGtal::PointVector<dim, TComponent, TContainer>::ConstIterator
219 DGtal::PointVector<dim, TComponent, TContainer>::begin() const
220 {
221  return myArray.begin();
222 }
223 //------------------------------------------------------------------------------
224 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
225 inline
226 typename DGtal::PointVector<dim, TComponent, TContainer>::ConstIterator
227 DGtal::PointVector<dim, TComponent, TContainer>::end() const
228 {
229  return myArray.end();
230 }
231 //------------------------------------------------------------------------------
232 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
233 inline
234 typename DGtal::PointVector<dim, TComponent, TContainer>::ReverseIterator
235 DGtal::PointVector<dim, TComponent, TContainer>::rbegin()
236 {
237  return myArray.rbegin();
238 }
239 //------------------------------------------------------------------------------
240 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
241 inline
242 typename DGtal::PointVector<dim, TComponent, TContainer>::ReverseIterator
243 DGtal::PointVector<dim, TComponent, TContainer>::rend()
244 {
245  return myArray.rend();
246 }
247 //------------------------------------------------------------------------------
248 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
249 inline
250 typename DGtal::PointVector<dim, TComponent, TContainer>::ConstReverseIterator
251 DGtal::PointVector<dim, TComponent, TContainer>::rbegin() const
252 {
253  return myArray.rbegin();
254 }
255 //------------------------------------------------------------------------------
256 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
257 inline
258 typename DGtal::PointVector<dim, TComponent, TContainer>::ConstReverseIterator
259 DGtal::PointVector<dim, TComponent, TContainer>::rend() const
260 {
261  return myArray.rend();
262 }
263 //------------------------------------------------------------------------------
264 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
265 inline
266 typename DGtal::Dimension
267 DGtal::PointVector<dim, TComponent, TContainer>::size()
268 {
269  return dim;
270 }
271 //------------------------------------------------------------------------------
272 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
273 inline
274 const typename DGtal::PointVector<dim, TComponent, TContainer>::Component *
275 DGtal::PointVector<dim, TComponent, TContainer>::data() const noexcept
276 {
277  return myArray.data();
278 }
279 //------------------------------------------------------------------------------
280 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
281 inline
282 typename DGtal::PointVector<dim, TComponent, TContainer>::Component *
283 DGtal::PointVector<dim, TComponent, TContainer>::data() noexcept
284 {
285  return myArray.data();
286 }
287 //------------------------------------------------------------------------------
288 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
289 inline
290 const typename DGtal::PointVector<dim, TComponent, TContainer>::Component &
291 DGtal::PointVector<dim, TComponent, TContainer>::operator[]( Dimension i ) const
292 {
293  ASSERT ( i < dim );
294  return myArray[i];
295 }
296 //------------------------------------------------------------------------------
297 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
298 inline
299 typename DGtal::PointVector<dim, TComponent, TContainer>::Component &
300 DGtal::PointVector<dim, TComponent, TContainer>::operator[]( Dimension i )
301 {
302  ASSERT ( i < dim );
303  return myArray[i];
304 }
305 //------------------------------------------------------------------------------
306 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
307 inline
308 DGtal::PointVector<dim, TComponent, TContainer>&
309 DGtal::PointVector<dim, TComponent, TContainer>::operator= ( const Self & pv )
310 {
311  myArray = pv.myArray;
312  return *this;
313 }
314 //------------------------------------------------------------------------------
315 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
316 template <
317  typename OtherComponent,
318  typename OtherContainer,
319  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type>
320 inline
321 DGtal::PointVector<dim, TComponent, TContainer> &
322 DGtal::PointVector<dim, TComponent, TContainer>::operator= ( const DGtal::PointVector<dim, OtherComponent, OtherContainer> & v )
323 {
324  for ( DGtal::Dimension i = 0; i < dimension; ++i )
325  {
326  this->myArray[ i ] = static_cast<Component>( v[ i ] );
327  }
328  return *this;
329 }
330 //------------------------------------------------------------------------------
331 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
332 template <
333  typename OtherComponent,
334  typename OtherContainer,
335  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type>
336 inline
337 DGtal::PointVector<dim, TComponent, TContainer>&
338 DGtal::PointVector<dim, TComponent, TContainer>::partialCopy
339 ( const DGtal::PointVector<dim, OtherComponent, OtherContainer> & pv,
340  const std::vector<DGtal::Dimension> &dimensions)
341 {
342  std::bitset<dim> dims = setDimensionsIn<dim>(dimensions);
343  for ( DGtal::Dimension i = 0; i < dim; ++i )
344  {
345  if ( dims.test(i) ) myArray[i] = static_cast<TComponent>(pv.myArray[i]);
346  }
347  return *this;
348 }
349 //------------------------------------------------------------------------------
350 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
351 template <
352  typename OtherComponent,
353  typename OtherContainer,
354  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type>
355 inline
356 DGtal::PointVector<dim, TComponent, TContainer>&
357 DGtal::PointVector<dim, TComponent, TContainer>::partialCopyInv
358 ( const DGtal::PointVector<dim, OtherComponent, OtherContainer> & pv,
359  const std::vector<DGtal::Dimension> &dimensions)
360 {
361  std::bitset<dim> dims = setDimensionsIn<dim>(dimensions);
362  for ( DGtal::Dimension i = 0; i < dim; ++i )
363  {
364  if ( !dims.test(i) ) myArray[i] = static_cast<TComponent>(pv.myArray[i]);
365  }
366  return *this;
367 }
368 //------------------------------------------------------------------------------
369 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
370 template <
371  typename OtherComponent,
372  typename OtherContainer,
373  typename UnaryFunctor >
374 inline
375 DGtal::PointVector<dim, TComponent, TContainer>&
376 DGtal::PointVector<dim, TComponent, TContainer>::partialCopy
377 ( const DGtal::PointVector<dim, OtherComponent, OtherContainer> & pv,
378  const std::vector<DGtal::Dimension> &dimensions,
379  const UnaryFunctor &f)
380 {
381  std::bitset<dim> dims = setDimensionsIn<dim>(dimensions);
382  for ( DGtal::Dimension i = 0; i < dim; ++i )
383  {
384  if ( dims.test(i) ) myArray[i] = static_cast<TComponent>(f(pv.myArray[i]));
385  }
386  return *this;
387 }
388 //------------------------------------------------------------------------------
389 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
390 template <
391  typename OtherComponent,
392  typename OtherContainer,
393  typename UnaryFunctor >
394 inline
395 DGtal::PointVector<dim, TComponent, TContainer>&
396 DGtal::PointVector<dim, TComponent, TContainer>::partialCopyInv
397 ( const DGtal::PointVector<dim, OtherComponent, OtherContainer> & pv,
398  const std::vector<DGtal::Dimension> &dimensions,
399  const UnaryFunctor &f)
400 {
401  std::bitset<dim> dims = setDimensionsIn<dim>(dimensions);
402  for ( DGtal::Dimension i = 0; i < dim; ++i )
403  {
404  if ( !dims.test(i) ) myArray[i] = static_cast<TComponent>(f(pv.myArray[i]));
405  }
406  return *this;
407 }
408 //------------------------------------------------------------------------------
409 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
410 template <typename TOtherComponent, typename TOtherContainer>
411 inline
412 bool
413 DGtal::PointVector<dim, TComponent, TContainer>::partialEqual
414 ( const DGtal::PointVector<dim, TOtherComponent, TOtherContainer> & pv,
415  const std::vector<DGtal::Dimension> &dimensions ) const
416 {
417  std::bitset<dim> dims = setDimensionsIn<dim>(dimensions);
418  for ( DGtal::Dimension i = 0; i < dim; ++i )
419  {
420  if ( dims.test(i) && myArray[i] != pv.myArray[i]) return false;
421  }
422  return true;
423 }
424 //------------------------------------------------------------------------------
425 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
426 template <typename TOtherComponent, typename TOtherContainer>
427 inline
428 bool
429 DGtal::PointVector<dim, TComponent, TContainer>::partialEqualInv
430 ( const DGtal::PointVector<dim, TOtherComponent, TOtherContainer> & pv,
431  const std::vector<DGtal::Dimension> &dimensions ) const
432 {
433  std::bitset<dim> dims = setDimensionsIn<dim>(dimensions);
434  for ( DGtal::Dimension i = 0; i < dim; ++i )
435  {
436  if ( !dims.test(i) && myArray[i] != pv.myArray[i]) return false;
437  }
438  return true;
439 }
440 //------------------------------------------------------------------------------
441 template < DGtal::Dimension ptDim,
442  typename LeftEuclideanRing, typename LeftContainer,
443  typename RightEuclideanRing, typename RightContainer >
444 inline bool
445 DGtal::operator== ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
446  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
447  {
448  return std::equal( lhs.begin(), lhs.end(), rhs.begin() );
449  }
450 //------------------------------------------------------------------------------
451 template < DGtal::Dimension ptDim,
452  typename LeftEuclideanRing, typename LeftContainer,
453  typename RightEuclideanRing, typename RightContainer >
454 inline bool
455 DGtal::operator!= ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
456  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
457  {
458  return ! (lhs == rhs);
459  }
460 //------------------------------------------------------------------------------
461 template < DGtal::Dimension ptDim,
462  typename LeftEuclideanRing, typename LeftContainer,
463  typename RightEuclideanRing, typename RightContainer >
464 inline bool
465 DGtal::operator< ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
466  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
467  {
468  return std::lexicographical_compare( lhs.begin(), lhs.end(), rhs.begin(), rhs.end() );
469  }
470 //------------------------------------------------------------------------------
471 template < DGtal::Dimension ptDim,
472  typename LeftEuclideanRing, typename LeftContainer,
473  typename RightEuclideanRing, typename RightContainer >
474 inline bool
475 DGtal::operator> ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
476  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
477  {
478  return rhs < lhs;
479  }
480 //------------------------------------------------------------------------------
481 template < DGtal::Dimension ptDim,
482  typename LeftEuclideanRing, typename LeftContainer,
483  typename RightEuclideanRing, typename RightContainer >
484 inline bool
485 DGtal::operator<= ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
486  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
487  {
488  return ! ( lhs > rhs );
489  }
490 //------------------------------------------------------------------------------
491 template < DGtal::Dimension ptDim,
492  typename LeftEuclideanRing, typename LeftContainer,
493  typename RightEuclideanRing, typename RightContainer >
494 inline bool
495 DGtal::operator>= ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
496  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
497  {
498  return ! ( lhs < rhs );
499  }
500 //------------------------------------------------------------------------------
501 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
502 template <
503  typename OtherComponent, typename OtherStorage,
504  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type >
505 inline
506 DGtal::PointVector<dim, TComponent, TContainer>&
507 DGtal::PointVector<dim, TComponent, TContainer>::operator+= ( PointVector<dim, OtherComponent, OtherStorage> const& v )
508 {
509  for ( DGtal::Dimension i = 0; i < dim; ++i )
510  this->myArray[ i ] += v[ i ];
511  return *this;
512 }
513 //------------------------------------------------------------------------------
514 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
515 template <
516  typename OtherComponent,
517  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type >
518 inline
519 DGtal::PointVector<dim, TComponent, TContainer>&
520 DGtal::PointVector<dim, TComponent, TContainer>::operator+= ( OtherComponent coeff )
521 {
522  for ( DGtal::Dimension i = 0; i < dim; ++i )
523  this->myArray[ i ] += coeff;
524  return *this;
525 }
526 //------------------------------------------------------------------------------
527 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
528 template <
529  typename OtherComponent, typename OtherStorage,
530  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type >
531 inline
532 DGtal::PointVector<dim, TComponent, TContainer>&
533 DGtal::PointVector<dim, TComponent, TContainer>::operator-= ( PointVector<dim, OtherComponent, OtherStorage> const& v )
534 {
535  for ( DGtal::Dimension i = 0; i < dim; ++i )
536  this->myArray[ i ] -= v[ i ];
537  return *this;
538 }
539 //------------------------------------------------------------------------------
540 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
541 template <
542  typename OtherComponent,
543  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type >
544 inline
545 DGtal::PointVector<dim, TComponent, TContainer>&
546 DGtal::PointVector<dim, TComponent, TContainer>::operator-= ( OtherComponent coeff )
547 {
548  for ( DGtal::Dimension i = 0; i < dim; ++i )
549  this->myArray[ i ] -= coeff;
550  return *this;
551 }
552 //------------------------------------------------------------------------------
553 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
554 template <
555  typename OtherComponent,
556  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type>
557 DGtal::PointVector<dim, TComponent, TContainer>&
558 DGtal::PointVector<dim, TComponent, TContainer>::operator*= ( OtherComponent coeff )
559 {
560  for ( DGtal::Dimension i = 0; i < myArray.size(); ++i )
561  myArray[ i ] *= coeff;
562  return *this;
563 }
564 //------------------------------------------------------------------------------
565 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
566 template <
567  typename OtherComponent, typename OtherStorage,
568  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type>
569 DGtal::PointVector<dim, TComponent, TContainer>&
570 DGtal::PointVector<dim, TComponent, TContainer>::operator*= ( PointVector<dim, OtherComponent, OtherStorage> const& v )
571 {
572  for ( DGtal::Dimension i = 0; i < myArray.size(); ++i )
573  myArray[ i ] *= v[ i ];
574  return *this;
575 }
576 //------------------------------------------------------------------------------
577 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
578 template <
579  typename OtherComponent,
580  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type>
581 DGtal::PointVector<dim, TComponent, TContainer>&
582 DGtal::PointVector<dim, TComponent, TContainer>::operator/= ( OtherComponent coeff )
583 {
584  for ( DGtal::Dimension i = 0; i < myArray.size(); ++i )
585  myArray[ i ] /= coeff;
586  return *this;
587 }
588 //------------------------------------------------------------------------------
589 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
590 template <
591  typename OtherComponent, typename OtherStorage,
592  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type>
593 DGtal::PointVector<dim, TComponent, TContainer>&
594 DGtal::PointVector<dim, TComponent, TContainer>::operator/= ( PointVector<dim, OtherComponent, OtherStorage> const& v )
595 {
596  for ( DGtal::Dimension i = 0; i < myArray.size(); ++i )
597  myArray[ i ] /= v[ i ];
598  return *this;
599 }
600 //------------------------------------------------------------------------------
601 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
602 template < typename OtherComponent, typename OtherStorage >
603 inline auto
604 DGtal::PointVector<dim, TComponent, TContainer>::dot( const DGtal::PointVector<dim, OtherComponent, OtherStorage>& v ) const
605  -> decltype( DGtal::dotProduct(*this, v) )
606 {
607  return DGtal::dotProduct(*this, v);
608 }
609 //------------------------------------------------------------------------------
610 template < DGtal::Dimension ptDim,
611  typename LeftEuclideanRing, typename LeftContainer,
612  typename RightEuclideanRing, typename RightContainer >
613 inline
614 DGtal::ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>
615 DGtal::dotProduct ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
616  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
617  {
618  using EuclideanRing = ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>;
619  auto dotprod = NumberTraits<EuclideanRing>::ZERO;
620  for ( DGtal::Dimension i = 0; i < ptDim; ++i )
621  dotprod += lhs[ i ] * rhs[ i ];
622  return dotprod;
623  }
624 //------------------------------------------------------------------------------
625 template < DGtal::Dimension ptDim,
626  typename LeftEuclideanRing, typename LeftContainer,
627  typename RightEuclideanRing, typename RightContainer >
628 inline double
629 DGtal::cosineSimilarity ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
630  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
631  {
632  double radians = 0.;
633  if ( lhs.norm() > 0. && rhs.norm() > 0. )
634  radians = rhs.dot ( lhs ) / ( lhs.norm() * rhs.norm() );
635  else
636  throw std::runtime_error ( "Operation involving a null vector is not defined!" );
637  return std::acos ( std::min ( std::max ( radians, -1. ), 1. ) );
638 }
639 
640 //------------------------------------------------------------------------------
641 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
642 template < typename OtherComponent, typename OtherStorage >
643 inline double
644 DGtal::PointVector<dim, TComponent, TContainer>::cosineSimilarity( const DGtal::PointVector<dim, OtherComponent, OtherStorage>& v ) const
645  {
646  return DGtal::cosineSimilarity(*this, v);
647  }
648 //------------------------------------------------------------------------------
649 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
650 template < typename OtherComponent, typename OtherStorage >
651 inline auto
652 DGtal::PointVector<dim, TComponent, TContainer>::crossProduct( const DGtal::PointVector<dim, OtherComponent, OtherStorage>& v ) const
653  -> decltype( DGtal::crossProduct(*this, v) )
654 {
655  return DGtal::crossProduct(*this, v);
656 }
657 //------------------------------------------------------------------------------
658 template <
659  typename LeftEuclideanRing, typename LeftContainer,
660  typename RightEuclideanRing, typename RightContainer >
661 inline auto
662 DGtal::crossProduct ( DGtal::PointVector<3, LeftEuclideanRing, LeftContainer> const& lhs,
663  DGtal::PointVector<3, RightEuclideanRing, RightContainer> const& rhs )
664  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
665  {
666  auto crossprod = constructFromArithmeticConversion(lhs, rhs);
667  for ( DGtal::Dimension i = 0; i < 3; ++i )
668  crossprod[i] =
669  lhs[ (i+1)%3 ] * rhs[ (i+2)%3 ]
670  - lhs[ (i+2)%3 ] * rhs[ (i+1)%3 ];
671  return crossprod;
672  }
673 //------------------------------------------------------------------------------
674 template <
675  typename LeftEuclideanRing, typename LeftContainer,
676  typename RightEuclideanRing, typename RightContainer >
677 inline
678 DGtal::PointVector<3, DGtal::ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>>
679 DGtal::crossProduct ( DGtal::PointVector<2, LeftEuclideanRing, LeftContainer> const& lhs,
680  DGtal::PointVector<2, RightEuclideanRing, RightContainer> const& rhs )
681  {
682  return PointVector<3, ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>>(
683  0,
684  0,
685  lhs[0]*rhs[1] - lhs[1]*rhs[0]
686  );
687  }
688 //------------------------------------------------------------------------------
689 template < DGtal::Dimension ptDim,
690  typename LeftEuclideanRing, typename LeftContainer,
691  typename RightEuclideanRing, typename RightContainer >
692 inline auto
693 DGtal::operator+ ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
694  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
695  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
696  {
697  using EuclideanRing = ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>;
698  return constructFromArithmeticConversion(lhs, rhs, lhs, rhs, std::plus<EuclideanRing>());
699  }
700 //------------------------------------------------------------------------------
701 template < DGtal::Dimension ptDim,
702  typename LeftEuclideanRing, typename LeftContainer,
703  typename RightEuclideanRing, typename RightContainer >
704 inline auto
705 DGtal::operator- ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
706  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
707  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
708  {
709  using EuclideanRing = ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>;
710  return constructFromArithmeticConversion(lhs, rhs, lhs, rhs, std::minus<EuclideanRing>());
711  }
712 //------------------------------------------------------------------------------
713 template < DGtal::Dimension ptDim,
714  typename LeftEuclideanRing, typename LeftContainer,
715  typename RightEuclideanRing, typename RightContainer >
716 inline auto
717 DGtal::operator* ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
718  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
719  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
720  {
721  using EuclideanRing = ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>;
722  return constructFromArithmeticConversion(lhs, rhs, lhs, rhs, std::multiplies<EuclideanRing>());
723  }
724 //------------------------------------------------------------------------------
725 template < DGtal::Dimension ptDim,
726  typename LeftEuclideanRing, typename LeftContainer,
727  typename RightEuclideanRing, typename RightContainer >
728 inline auto
729 DGtal::operator/ ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
730  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
731  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
732  {
733  using EuclideanRing = ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>;
734  return constructFromArithmeticConversion(lhs, rhs, lhs, rhs, std::divides<EuclideanRing>());
735  }
736 //------------------------------------------------------------------------------
737 template < DGtal::Dimension ptDim,
738  typename LeftEuclideanRing, typename LeftContainer,
739  typename RightScalar >
740 inline auto
741 DGtal::operator+ ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
742  RightScalar const& rhs )
743  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
744  {
745  return constructFromArithmeticConversion(lhs, rhs, lhs, [&rhs] (LeftEuclideanRing v) { return v + rhs; });
746  }
747 //------------------------------------------------------------------------------
748 template < DGtal::Dimension ptDim,
749  typename LeftScalar,
750  typename RightEuclideanRing, typename RightContainer >
751 inline auto
752 DGtal::operator+ ( LeftScalar const& lhs,
753  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
754  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
755  {
756  return constructFromArithmeticConversion(lhs, rhs, rhs, [&lhs] (RightEuclideanRing v) { return lhs + v; });
757  }
758 //------------------------------------------------------------------------------
759 template < DGtal::Dimension ptDim,
760  typename LeftEuclideanRing, typename LeftContainer,
761  typename RightScalar >
762 inline auto
763 DGtal::operator- ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
764  RightScalar const& rhs )
765  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
766  {
767  return constructFromArithmeticConversion(lhs, rhs, lhs, [&rhs] (LeftEuclideanRing v) { return v - rhs; });
768  }
769 //------------------------------------------------------------------------------
770 template < DGtal::Dimension ptDim,
771  typename LeftScalar,
772  typename RightEuclideanRing, typename RightContainer >
773 inline auto
774 DGtal::operator- ( LeftScalar const& lhs,
775  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
776  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
777  {
778  return constructFromArithmeticConversion(lhs, rhs, rhs, [&lhs] (RightEuclideanRing v) { return lhs - v; });
779  }
780 //------------------------------------------------------------------------------
781 template < DGtal::Dimension ptDim,
782  typename LeftEuclideanRing, typename LeftContainer,
783  typename RightScalar >
784 inline auto
785 DGtal::operator* ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
786  RightScalar const& rhs )
787  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
788  {
789  return constructFromArithmeticConversion(lhs, rhs, lhs, [&rhs] (LeftEuclideanRing v) { return v * rhs; });
790  }
791 //------------------------------------------------------------------------------
792 template < DGtal::Dimension ptDim,
793  typename LeftScalar,
794  typename RightEuclideanRing, typename RightContainer >
795 inline auto
796 DGtal::operator* ( LeftScalar const& lhs,
797  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
798  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
799  {
800  return constructFromArithmeticConversion(lhs, rhs, rhs, [&lhs] (RightEuclideanRing v) { return lhs * v; });
801  }
802 //------------------------------------------------------------------------------
803 template < DGtal::Dimension ptDim,
804  typename LeftEuclideanRing, typename LeftContainer,
805  typename RightScalar >
806 inline auto
807 DGtal::operator/ ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
808  RightScalar const& rhs )
809  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
810  {
811  return constructFromArithmeticConversion(lhs, rhs, lhs, [&rhs] (LeftEuclideanRing v) { return v / rhs; });
812  }
813 //------------------------------------------------------------------------------
814 template < DGtal::Dimension ptDim,
815  typename LeftScalar,
816  typename RightEuclideanRing, typename RightContainer >
817 inline auto
818 DGtal::operator/ ( LeftScalar const& lhs,
819  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
820  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
821  {
822  return constructFromArithmeticConversion(lhs, rhs, rhs, [&lhs] (RightEuclideanRing v) { return lhs / v; });
823  }
824 //------------------------------------------------------------------------------
825 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
826 inline
827 DGtal::PointVector<dim, TComponent,TContainer>
828 DGtal::PointVector<dim, TComponent,TContainer>::operator-() const
829 {
830  return Self(*this, functors::UnaryMinus<Component>());
831 }
832 //------------------------------------------------------------------------------
833 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
834 inline
835 void
836 DGtal::PointVector<dim, TComponent, TContainer>::reset()
837 {
838  for ( DGtal::Dimension i = 0; i < myArray.size(); ++i )
839  myArray[ i ] = NumberTraits< Component >::ZERO;
840 }
841 //------------------------------------------------------------------------------
842 template < DGtal::Dimension ptDim,
843  typename LeftEuclideanRing, typename LeftContainer,
844  typename RightEuclideanRing, typename RightContainer >
845 inline auto
846 DGtal::inf( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
847  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
848  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
849 {
850  using EuclideanRing = ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>;
851  return DGtal::constructFromArithmeticConversion(lhs, rhs, lhs, rhs, functors::Min<EuclideanRing>());
852 }
853 //------------------------------------------------------------------------------
854 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
855 template < typename OtherComponent, typename OtherStorage >
856 inline auto
857 DGtal::PointVector<dim, TComponent, TContainer>::inf( const DGtal::PointVector<dim, OtherComponent, OtherStorage>& aPoint ) const
858  -> decltype( DGtal::inf(*this, aPoint) )
859 {
860  return DGtal::inf(*this, aPoint);
861 }
862 //------------------------------------------------------------------------------
863 template < DGtal::Dimension ptDim,
864  typename LeftEuclideanRing, typename LeftContainer,
865  typename RightEuclideanRing, typename RightContainer >
866 inline auto
867 DGtal::sup( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
868  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
869  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
870 {
871  using EuclideanRing = ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>;
872  return DGtal::constructFromArithmeticConversion(lhs, rhs, lhs, rhs, functors::Max<EuclideanRing>());
873 }
874 //------------------------------------------------------------------------------
875 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
876 template < typename OtherComponent, typename OtherStorage >
877 inline auto
878 DGtal::PointVector<dim, TComponent, TContainer>::sup( const DGtal::PointVector<dim, OtherComponent, OtherStorage>& aPoint ) const
879  -> decltype( DGtal::sup(*this, aPoint) )
880 {
881  return DGtal::sup(*this, aPoint);
882 }
883 //------------------------------------------------------------------------------
884 template < DGtal::Dimension ptDim,
885  typename LeftEuclideanRing, typename LeftContainer,
886  typename RightEuclideanRing, typename RightContainer >
887 inline bool
888 DGtal::isLower( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
889  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
890 {
891  for ( DGtal::Dimension i = 0; i < ptDim; ++i )
892  if ( rhs[ i ] < lhs[ i ] )
893  return false;
894  return true;
895 }
896 //------------------------------------------------------------------------------
897 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
898 template < typename OtherComponent, typename OtherStorage >
899 inline bool
900 DGtal::PointVector<dim, TComponent, TContainer>::isLower( const DGtal::PointVector<dim, OtherComponent, OtherStorage> & p ) const
901 {
902  return DGtal::isLower(*this, p);
903 }
904 //------------------------------------------------------------------------------
905 template < DGtal::Dimension ptDim,
906  typename LeftEuclideanRing, typename LeftContainer,
907  typename RightEuclideanRing, typename RightContainer >
908 inline bool
909 DGtal::isUpper( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
910  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
911 {
912  for ( DGtal::Dimension i = 0; i < ptDim; ++i )
913  if ( rhs[ i ] > lhs[ i ] )
914  return false;
915  return true;
916 }
917 //------------------------------------------------------------------------------
918 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
919 template < typename OtherComponent, typename OtherStorage >
920 inline bool
921 DGtal::PointVector<dim, TComponent, TContainer>::isUpper( const DGtal::PointVector<dim, OtherComponent, OtherStorage> & p ) const
922 {
923  return DGtal::isUpper(*this, p);
924 }
925 //------------------------------------------------------------------------------
926 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
927 inline
928 typename DGtal::PointVector<dim, TComponent, TContainer>::Component
929 DGtal::PointVector<dim, TComponent, TContainer>::max( ) const
930 {
931  return *std::max_element(this->begin(), this->end());
932 }
933 //------------------------------------------------------------------------------
934 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
935 inline
936 typename DGtal::PointVector<dim, TComponent, TContainer>::Component
937 DGtal::PointVector<dim, TComponent, TContainer>::min( ) const
938 {
939  return *std::min_element(this->begin(), this->end());
940 }
941 //------------------------------------------------------------------------------
942 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
943 inline
944 typename DGtal::PointVector<dim, TComponent, TContainer>::Iterator
945 DGtal::PointVector<dim, TComponent, TContainer>::maxElement( )
946 {
947  return std::max_element(this->begin(), this->end());
948 }
949 //------------------------------------------------------------------------------
950 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
951 inline
952 typename DGtal::PointVector<dim, TComponent, TContainer>::Iterator
953 DGtal::PointVector<dim, TComponent, TContainer>::minElement( )
954 {
955  return std::min_element(this->begin(), this->end());
956 }
957 //------------------------------------------------------------------------------
958 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
959 inline
960 void
961 DGtal::PointVector<dim, TComponent, TContainer>::
962 negate()
963 {
964  for ( DGtal::Dimension i = 0; i < dimension; ++i )
965  this->myArray[ i ] = - this->myArray[ i ];
966 }
967 //------------------------------------------------------------------------------
968 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
969 inline
970 double
971 DGtal::PointVector<dim, TComponent, TContainer>::squaredNorm () const
972 {
973  ASSERT ( dim > 0 );
974  double tmp = 0.0;
975  for ( DGtal::Dimension i = 0; i < dimension; i++ )
976  tmp += std::pow(NumberTraits<Component>::castToDouble(myArray[ i ]), 2);
977  return tmp;
978 }
979 //------------------------------------------------------------------------------
980 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
981 inline
982 double
983 DGtal::PointVector<dim, TComponent, TContainer>::norm (
984  const typename Self::NormType aType ) const
985 {
986  double tmp = 0.0;
987 
988  ASSERT ( dim > 0 );
989 
990  switch ( aType )
991  {
992  case L_2:
993  for ( DGtal::Dimension i = 0; i < dimension; i++ )
994  tmp += NumberTraits<Component>::castToDouble(myArray[ i ]) *
995  NumberTraits<Component>::castToDouble(myArray[ i ]);
996  tmp = ( double ) sqrt ( tmp );
997  break;
998  case L_1:
999  for ( DGtal::Dimension i = 0; i < dimension; i++ )
1000  tmp += fabs ( NumberTraits<Component>::castToDouble(myArray[ i ] ));
1001  break;
1002  case L_infty:
1003  tmp = fabs( NumberTraits<Component>::castToDouble( myArray[ 0 ]));
1004  for ( DGtal::Dimension i = 1; i < dimension; i++ )
1005  if ( tmp < fabs ( NumberTraits<Component>::castToDouble(myArray[ i ] ) ))
1006  tmp = fabs ( NumberTraits<Component>::castToDouble(myArray[ i ] ));
1007  break;
1008  }
1009  return tmp;
1010 }
1011 //------------------------------------------------------------------------------
1012 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1013 inline
1014 typename DGtal::PointVector<dim, TComponent, TContainer>::UnsignedComponent
1015 DGtal::PointVector<dim, TComponent, TContainer>::norm1() const
1016 {
1017  ASSERT ( dimension > 0 );
1018  UnsignedComponent val
1019  ( ( myArray[ 0 ] >= 0 ) ? myArray[ 0 ] : UnsignedComponent(-myArray[ 0 ]) );
1020  for ( DGtal::Dimension i = 1; i < dimension; ++i )
1021  val += ( myArray[ i ] >= 0 )
1022  ? myArray[ i ]
1023  : UnsignedComponent(-myArray[ i ]);
1024  return val;
1025 }
1026 //------------------------------------------------------------------------------
1027 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1028 inline
1029 typename DGtal::PointVector<dim, TComponent, TContainer>::UnsignedComponent
1030 DGtal::PointVector<dim, TComponent, TContainer>::normInfinity() const
1031 {
1032  ASSERT ( dimension > 0 );
1033  UnsignedComponent tmp;
1034  UnsignedComponent val( ( myArray[ 0 ] >= 0 ) ? myArray[ 0 ] : -myArray[ 0 ] );
1035  for ( DGtal::Dimension i = 1; i < dimension; ++i )
1036  {
1037  tmp = ( myArray[ i ] >= 0 ) ? myArray[ i ] : -myArray[ i ] ;
1038  if ( tmp > val )
1039  val = tmp;
1040  }
1041  return val;
1042 }
1043 //------------------------------------------------------------------------------
1044 
1045 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1046 inline
1047 typename DGtal::PointVector<dim, double, std::array<double,dim> >
1048 DGtal::PointVector<dim, TComponent, TContainer>::getNormalized() const
1049 {
1050  PointVector<dim,double,std::array<double,dim> > normalized =(*this);
1051  normalized /= normalized.norm();
1052  return normalized;
1053 }
1054 //------------------------------------------------------------------------------
1055 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1056 inline
1057 DGtal::PointVector<dim,TComponent, TContainer>
1058 DGtal::PointVector<dim,TComponent, TContainer>::diagonal( Component val )
1059 {
1060  Self p;
1061  for ( DGtal::Dimension i = 0; i < dim; ++i )
1062  p.myArray[ i ] = val;
1063  return p;
1064 }
1065 //------------------------------------------------------------------------------
1066 template<DGtal::Dimension dim,typename TComponent, typename TContainer>
1067 inline
1068 DGtal::PointVector<dim,TComponent, TContainer>
1069 DGtal::PointVector<dim,TComponent, TContainer>::base( Dimension k, Component val )
1070 {
1071  Self p;
1072  p.myArray[ k ] = val;
1073  return p;
1074 }
1075 //------------------------------------------------------------------------------
1076 template<DGtal::Dimension dim,typename TComponent, typename TContainer>
1077 inline
1078 void
1079 DGtal::PointVector<dim,TComponent, TContainer>::selfDisplay( std::ostream & out ) const
1080 {
1081  out << "[PointVector] {";
1082  for (DGtal::Dimension i = 0; i < dimension ; ++i)
1083  out << myArray[ i ] << (i == dimension - 1 ? "" : ", ");
1084  out << "}";
1085 }
1086 
1087 //------------------------------------------------------------------------------
1088 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1089 inline
1090 std::string
1091 DGtal::PointVector<dim, TComponent, TContainer>::className() const
1092 {
1093  return "PointVector";
1094 }
1095 
1096 //------------------------------------------------------------------------------
1097 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1098 inline
1099 std::ostream&
1100 DGtal::operator<<( std::ostream & out,
1101  const PointVector<dim, TComponent, TContainer>& object )
1102 {
1103  object.selfDisplay( out );
1104  return out;
1105 }
1106 //------------------------------------------------------------------------------
1107 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1108 inline
1109 bool
1110 DGtal::PointVector<dim, TComponent, TContainer>::isValid() const
1111 {
1112  return true;
1113 }
1114 //------------------------------------------------------------------------------