DGtal  1.0.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>::operator[]( Dimension i ) const
276 {
277  ASSERT ( i < dim );
278  return myArray[i];
279 }
280 //------------------------------------------------------------------------------
281 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
282 inline
283 typename DGtal::PointVector<dim, TComponent, TContainer>::Component &
284 DGtal::PointVector<dim, TComponent, TContainer>::operator[]( Dimension i )
285 {
286  ASSERT ( i < dim );
287  return myArray[i];
288 }
289 //------------------------------------------------------------------------------
290 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
291 inline
292 DGtal::PointVector<dim, TComponent, TContainer>&
293 DGtal::PointVector<dim, TComponent, TContainer>::operator= ( const Self & pv )
294 {
295  myArray = pv.myArray;
296  return *this;
297 }
298 //------------------------------------------------------------------------------
299 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
300 template <
301  typename OtherComponent,
302  typename OtherContainer,
303  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type>
304 inline
305 DGtal::PointVector<dim, TComponent, TContainer> &
306 DGtal::PointVector<dim, TComponent, TContainer>::operator= ( const DGtal::PointVector<dim, OtherComponent, OtherContainer> & v )
307 {
308  for ( DGtal::Dimension i = 0; i < dimension; ++i )
309  {
310  this->myArray[ i ] = static_cast<Component>( v[ i ] );
311  }
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>::partialCopy
323 ( const DGtal::PointVector<dim, OtherComponent, OtherContainer> & pv,
324  const std::vector<DGtal::Dimension> &dimensions)
325 {
326  std::bitset<dim> dims = setDimensionsIn<dim>(dimensions);
327  for ( DGtal::Dimension i = 0; i < dim; ++i )
328  {
329  if ( dims.test(i) ) myArray[i] = static_cast<TComponent>(pv.myArray[i]);
330  }
331  return *this;
332 }
333 //------------------------------------------------------------------------------
334 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
335 template <
336  typename OtherComponent,
337  typename OtherContainer,
338  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type>
339 inline
340 DGtal::PointVector<dim, TComponent, TContainer>&
341 DGtal::PointVector<dim, TComponent, TContainer>::partialCopyInv
342 ( const DGtal::PointVector<dim, OtherComponent, OtherContainer> & pv,
343  const std::vector<DGtal::Dimension> &dimensions)
344 {
345  std::bitset<dim> dims = setDimensionsIn<dim>(dimensions);
346  for ( DGtal::Dimension i = 0; i < dim; ++i )
347  {
348  if ( !dims.test(i) ) myArray[i] = static_cast<TComponent>(pv.myArray[i]);
349  }
350  return *this;
351 }
352 //------------------------------------------------------------------------------
353 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
354 template <
355  typename OtherComponent,
356  typename OtherContainer,
357  typename UnaryFunctor >
358 inline
359 DGtal::PointVector<dim, TComponent, TContainer>&
360 DGtal::PointVector<dim, TComponent, TContainer>::partialCopy
361 ( const DGtal::PointVector<dim, OtherComponent, OtherContainer> & pv,
362  const std::vector<DGtal::Dimension> &dimensions,
363  const UnaryFunctor &f)
364 {
365  std::bitset<dim> dims = setDimensionsIn<dim>(dimensions);
366  for ( DGtal::Dimension i = 0; i < dim; ++i )
367  {
368  if ( dims.test(i) ) myArray[i] = static_cast<TComponent>(f(pv.myArray[i]));
369  }
370  return *this;
371 }
372 //------------------------------------------------------------------------------
373 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
374 template <
375  typename OtherComponent,
376  typename OtherContainer,
377  typename UnaryFunctor >
378 inline
379 DGtal::PointVector<dim, TComponent, TContainer>&
380 DGtal::PointVector<dim, TComponent, TContainer>::partialCopyInv
381 ( const DGtal::PointVector<dim, OtherComponent, OtherContainer> & pv,
382  const std::vector<DGtal::Dimension> &dimensions,
383  const UnaryFunctor &f)
384 {
385  std::bitset<dim> dims = setDimensionsIn<dim>(dimensions);
386  for ( DGtal::Dimension i = 0; i < dim; ++i )
387  {
388  if ( !dims.test(i) ) myArray[i] = static_cast<TComponent>(f(pv.myArray[i]));
389  }
390  return *this;
391 }
392 //------------------------------------------------------------------------------
393 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
394 template <typename TOtherComponent, typename TOtherContainer>
395 inline
396 bool
397 DGtal::PointVector<dim, TComponent, TContainer>::partialEqual
398 ( const DGtal::PointVector<dim, TOtherComponent, TOtherContainer> & pv,
399  const std::vector<DGtal::Dimension> &dimensions ) const
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] != pv.myArray[i]) return false;
405  }
406  return true;
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>::partialEqualInv
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 ptDim,
426  typename LeftEuclideanRing, typename LeftContainer,
427  typename RightEuclideanRing, typename RightContainer >
428 inline bool
429 DGtal::operator== ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
430  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
431  {
432  return std::equal( lhs.begin(), lhs.end(), rhs.begin() );
433  }
434 //------------------------------------------------------------------------------
435 template < DGtal::Dimension ptDim,
436  typename LeftEuclideanRing, typename LeftContainer,
437  typename RightEuclideanRing, typename RightContainer >
438 inline bool
439 DGtal::operator!= ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
440  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
441  {
442  return ! (lhs == rhs);
443  }
444 //------------------------------------------------------------------------------
445 template < DGtal::Dimension ptDim,
446  typename LeftEuclideanRing, typename LeftContainer,
447  typename RightEuclideanRing, typename RightContainer >
448 inline bool
449 DGtal::operator< ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
450  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
451  {
452  return std::lexicographical_compare( lhs.begin(), lhs.end(), rhs.begin(), rhs.end() );
453  }
454 //------------------------------------------------------------------------------
455 template < DGtal::Dimension ptDim,
456  typename LeftEuclideanRing, typename LeftContainer,
457  typename RightEuclideanRing, typename RightContainer >
458 inline bool
459 DGtal::operator> ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
460  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
461  {
462  return rhs < lhs;
463  }
464 //------------------------------------------------------------------------------
465 template < DGtal::Dimension ptDim,
466  typename LeftEuclideanRing, typename LeftContainer,
467  typename RightEuclideanRing, typename RightContainer >
468 inline bool
469 DGtal::operator<= ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
470  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
471  {
472  return ! ( lhs > rhs );
473  }
474 //------------------------------------------------------------------------------
475 template < DGtal::Dimension ptDim,
476  typename LeftEuclideanRing, typename LeftContainer,
477  typename RightEuclideanRing, typename RightContainer >
478 inline bool
479 DGtal::operator>= ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
480  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
481  {
482  return ! ( lhs < rhs );
483  }
484 //------------------------------------------------------------------------------
485 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
486 template <
487  typename OtherComponent, typename OtherStorage,
488  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type >
489 inline
490 DGtal::PointVector<dim, TComponent, TContainer>&
491 DGtal::PointVector<dim, TComponent, TContainer>::operator+= ( PointVector<dim, OtherComponent, OtherStorage> const& v )
492 {
493  for ( DGtal::Dimension i = 0; i < dim; ++i )
494  this->myArray[ i ] += v[ i ];
495  return *this;
496 }
497 //------------------------------------------------------------------------------
498 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
499 template <
500  typename OtherComponent,
501  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type >
502 inline
503 DGtal::PointVector<dim, TComponent, TContainer>&
504 DGtal::PointVector<dim, TComponent, TContainer>::operator+= ( OtherComponent coeff )
505 {
506  for ( DGtal::Dimension i = 0; i < dim; ++i )
507  this->myArray[ i ] += coeff;
508  return *this;
509 }
510 //------------------------------------------------------------------------------
511 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
512 template <
513  typename OtherComponent, typename OtherStorage,
514  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type >
515 inline
516 DGtal::PointVector<dim, TComponent, TContainer>&
517 DGtal::PointVector<dim, TComponent, TContainer>::operator-= ( PointVector<dim, OtherComponent, OtherStorage> const& v )
518 {
519  for ( DGtal::Dimension i = 0; i < dim; ++i )
520  this->myArray[ i ] -= v[ i ];
521  return *this;
522 }
523 //------------------------------------------------------------------------------
524 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
525 template <
526  typename OtherComponent,
527  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type >
528 inline
529 DGtal::PointVector<dim, TComponent, TContainer>&
530 DGtal::PointVector<dim, TComponent, TContainer>::operator-= ( OtherComponent coeff )
531 {
532  for ( DGtal::Dimension i = 0; i < dim; ++i )
533  this->myArray[ i ] -= coeff;
534  return *this;
535 }
536 //------------------------------------------------------------------------------
537 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
538 template <
539  typename OtherComponent,
540  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type>
541 DGtal::PointVector<dim, TComponent, TContainer>&
542 DGtal::PointVector<dim, TComponent, TContainer>::operator*= ( OtherComponent coeff )
543 {
544  for ( DGtal::Dimension i = 0; i < myArray.size(); ++i )
545  myArray[ i ] *= coeff;
546  return *this;
547 }
548 //------------------------------------------------------------------------------
549 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
550 template <
551  typename OtherComponent, typename OtherStorage,
552  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type>
553 DGtal::PointVector<dim, TComponent, TContainer>&
554 DGtal::PointVector<dim, TComponent, TContainer>::operator*= ( PointVector<dim, OtherComponent, OtherStorage> const& v )
555 {
556  for ( DGtal::Dimension i = 0; i < myArray.size(); ++i )
557  myArray[ i ] *= v[ i ];
558  return *this;
559 }
560 //------------------------------------------------------------------------------
561 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
562 template <
563  typename OtherComponent,
564  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type>
565 DGtal::PointVector<dim, TComponent, TContainer>&
566 DGtal::PointVector<dim, TComponent, TContainer>::operator/= ( OtherComponent coeff )
567 {
568  for ( DGtal::Dimension i = 0; i < myArray.size(); ++i )
569  myArray[ i ] /= coeff;
570  return *this;
571 }
572 //------------------------------------------------------------------------------
573 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
574 template <
575  typename OtherComponent, typename OtherStorage,
576  typename std::enable_if< std::is_same< TComponent, DGtal::ArithmeticConversionType<TComponent, OtherComponent> >::value, int >::type>
577 DGtal::PointVector<dim, TComponent, TContainer>&
578 DGtal::PointVector<dim, TComponent, TContainer>::operator/= ( PointVector<dim, OtherComponent, OtherStorage> const& v )
579 {
580  for ( DGtal::Dimension i = 0; i < myArray.size(); ++i )
581  myArray[ i ] /= v[ i ];
582  return *this;
583 }
584 //------------------------------------------------------------------------------
585 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
586 template < typename OtherComponent, typename OtherStorage >
587 inline auto
588 DGtal::PointVector<dim, TComponent, TContainer>::dot( const DGtal::PointVector<dim, OtherComponent, OtherStorage>& v ) const
589  -> decltype( DGtal::dotProduct(*this, v) )
590 {
591  return DGtal::dotProduct(*this, v);
592 }
593 //------------------------------------------------------------------------------
594 template < DGtal::Dimension ptDim,
595  typename LeftEuclideanRing, typename LeftContainer,
596  typename RightEuclideanRing, typename RightContainer >
597 inline
598 DGtal::ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>
599 DGtal::dotProduct ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
600  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
601  {
602  using EuclideanRing = ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>;
603  auto dotprod = NumberTraits<EuclideanRing>::ZERO;
604  for ( DGtal::Dimension i = 0; i < ptDim; ++i )
605  dotprod += lhs[ i ] * rhs[ i ];
606  return dotprod;
607  }
608 //------------------------------------------------------------------------------
609 template < DGtal::Dimension ptDim,
610  typename LeftEuclideanRing, typename LeftContainer,
611  typename RightEuclideanRing, typename RightContainer >
612 inline double
613 DGtal::cosineSimilarity ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
614  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
615  {
616  double radians = 0.;
617  if ( lhs.norm() > 0. && rhs.norm() > 0. )
618  radians = rhs.dot ( lhs ) / ( lhs.norm() * rhs.norm() );
619  else
620  throw std::runtime_error ( "Operation involving a null vector is not defined!" );
621  return std::acos ( std::min ( std::max ( radians, -1. ), 1. ) );
622 }
623 
624 //------------------------------------------------------------------------------
625 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
626 template < typename OtherComponent, typename OtherStorage >
627 inline double
628 DGtal::PointVector<dim, TComponent, TContainer>::cosineSimilarity( const DGtal::PointVector<dim, OtherComponent, OtherStorage>& v ) const
629  {
630  return DGtal::cosineSimilarity(*this, v);
631  }
632 //------------------------------------------------------------------------------
633 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
634 template < typename OtherComponent, typename OtherStorage >
635 inline auto
636 DGtal::PointVector<dim, TComponent, TContainer>::crossProduct( const DGtal::PointVector<dim, OtherComponent, OtherStorage>& v ) const
637  -> decltype( DGtal::crossProduct(*this, v) )
638 {
639  return DGtal::crossProduct(*this, v);
640 }
641 //------------------------------------------------------------------------------
642 template <
643  typename LeftEuclideanRing, typename LeftContainer,
644  typename RightEuclideanRing, typename RightContainer >
645 inline auto
646 DGtal::crossProduct ( DGtal::PointVector<3, LeftEuclideanRing, LeftContainer> const& lhs,
647  DGtal::PointVector<3, RightEuclideanRing, RightContainer> const& rhs )
648  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
649  {
650  auto crossprod = constructFromArithmeticConversion(lhs, rhs);
651  for ( DGtal::Dimension i = 0; i < 3; ++i )
652  crossprod[i] =
653  lhs[ (i+1)%3 ] * rhs[ (i+2)%3 ]
654  - lhs[ (i+2)%3 ] * rhs[ (i+1)%3 ];
655  return crossprod;
656  }
657 //------------------------------------------------------------------------------
658 template <
659  typename LeftEuclideanRing, typename LeftContainer,
660  typename RightEuclideanRing, typename RightContainer >
661 inline
662 DGtal::PointVector<3, DGtal::ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>>
663 DGtal::crossProduct ( DGtal::PointVector<2, LeftEuclideanRing, LeftContainer> const& lhs,
664  DGtal::PointVector<2, RightEuclideanRing, RightContainer> const& rhs )
665  {
666  return PointVector<3, ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>>(
667  0,
668  0,
669  lhs[0]*rhs[1] - lhs[1]*rhs[0]
670  );
671  }
672 //------------------------------------------------------------------------------
673 template < DGtal::Dimension ptDim,
674  typename LeftEuclideanRing, typename LeftContainer,
675  typename RightEuclideanRing, typename RightContainer >
676 inline auto
677 DGtal::operator+ ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
678  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
679  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
680  {
681  using EuclideanRing = ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>;
682  return constructFromArithmeticConversion(lhs, rhs, lhs, rhs, std::plus<EuclideanRing>());
683  }
684 //------------------------------------------------------------------------------
685 template < DGtal::Dimension ptDim,
686  typename LeftEuclideanRing, typename LeftContainer,
687  typename RightEuclideanRing, typename RightContainer >
688 inline auto
689 DGtal::operator- ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
690  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
691  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
692  {
693  using EuclideanRing = ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>;
694  return constructFromArithmeticConversion(lhs, rhs, lhs, rhs, std::minus<EuclideanRing>());
695  }
696 //------------------------------------------------------------------------------
697 template < DGtal::Dimension ptDim,
698  typename LeftEuclideanRing, typename LeftContainer,
699  typename RightEuclideanRing, typename RightContainer >
700 inline auto
701 DGtal::operator* ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
702  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
703  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
704  {
705  using EuclideanRing = ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>;
706  return constructFromArithmeticConversion(lhs, rhs, lhs, rhs, std::multiplies<EuclideanRing>());
707  }
708 //------------------------------------------------------------------------------
709 template < DGtal::Dimension ptDim,
710  typename LeftEuclideanRing, typename LeftContainer,
711  typename RightEuclideanRing, typename RightContainer >
712 inline auto
713 DGtal::operator/ ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
714  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
715  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
716  {
717  using EuclideanRing = ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>;
718  return constructFromArithmeticConversion(lhs, rhs, lhs, rhs, std::divides<EuclideanRing>());
719  }
720 //------------------------------------------------------------------------------
721 template < DGtal::Dimension ptDim,
722  typename LeftEuclideanRing, typename LeftContainer,
723  typename RightScalar >
724 inline auto
725 DGtal::operator+ ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
726  RightScalar const& rhs )
727  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
728  {
729  return constructFromArithmeticConversion(lhs, rhs, lhs, [&rhs] (LeftEuclideanRing v) { return v + rhs; });
730  }
731 //------------------------------------------------------------------------------
732 template < DGtal::Dimension ptDim,
733  typename LeftScalar,
734  typename RightEuclideanRing, typename RightContainer >
735 inline auto
736 DGtal::operator+ ( LeftScalar const& lhs,
737  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
738  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
739  {
740  return constructFromArithmeticConversion(lhs, rhs, rhs, [&lhs] (RightEuclideanRing v) { return lhs + v; });
741  }
742 //------------------------------------------------------------------------------
743 template < DGtal::Dimension ptDim,
744  typename LeftEuclideanRing, typename LeftContainer,
745  typename RightScalar >
746 inline auto
747 DGtal::operator- ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
748  RightScalar const& rhs )
749  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
750  {
751  return constructFromArithmeticConversion(lhs, rhs, lhs, [&rhs] (LeftEuclideanRing v) { return v - rhs; });
752  }
753 //------------------------------------------------------------------------------
754 template < DGtal::Dimension ptDim,
755  typename LeftScalar,
756  typename RightEuclideanRing, typename RightContainer >
757 inline auto
758 DGtal::operator- ( LeftScalar const& lhs,
759  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
760  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
761  {
762  return constructFromArithmeticConversion(lhs, rhs, rhs, [&lhs] (RightEuclideanRing v) { return lhs - v; });
763  }
764 //------------------------------------------------------------------------------
765 template < DGtal::Dimension ptDim,
766  typename LeftEuclideanRing, typename LeftContainer,
767  typename RightScalar >
768 inline auto
769 DGtal::operator* ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
770  RightScalar const& rhs )
771  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
772  {
773  return constructFromArithmeticConversion(lhs, rhs, lhs, [&rhs] (LeftEuclideanRing v) { return v * rhs; });
774  }
775 //------------------------------------------------------------------------------
776 template < DGtal::Dimension ptDim,
777  typename LeftScalar,
778  typename RightEuclideanRing, typename RightContainer >
779 inline auto
780 DGtal::operator* ( LeftScalar const& lhs,
781  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
782  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
783  {
784  return constructFromArithmeticConversion(lhs, rhs, rhs, [&lhs] (RightEuclideanRing v) { return lhs * v; });
785  }
786 //------------------------------------------------------------------------------
787 template < DGtal::Dimension ptDim,
788  typename LeftEuclideanRing, typename LeftContainer,
789  typename RightScalar >
790 inline auto
791 DGtal::operator/ ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
792  RightScalar const& rhs )
793  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
794  {
795  return constructFromArithmeticConversion(lhs, rhs, lhs, [&rhs] (LeftEuclideanRing v) { return v / rhs; });
796  }
797 //------------------------------------------------------------------------------
798 template < DGtal::Dimension ptDim,
799  typename LeftScalar,
800  typename RightEuclideanRing, typename RightContainer >
801 inline auto
802 DGtal::operator/ ( LeftScalar const& lhs,
803  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
804  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
805  {
806  return constructFromArithmeticConversion(lhs, rhs, rhs, [&lhs] (RightEuclideanRing v) { return lhs / v; });
807  }
808 //------------------------------------------------------------------------------
809 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
810 inline
811 DGtal::PointVector<dim, TComponent,TContainer>
812 DGtal::PointVector<dim, TComponent,TContainer>::operator-() const
813 {
814  return Self(*this, functors::UnaryMinus<Component>());
815 }
816 //------------------------------------------------------------------------------
817 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
818 inline
819 void
820 DGtal::PointVector<dim, TComponent, TContainer>::reset()
821 {
822  for ( DGtal::Dimension i = 0; i < myArray.size(); ++i )
823  myArray[ i ] = NumberTraits< Component >::ZERO;
824 }
825 //------------------------------------------------------------------------------
826 template < DGtal::Dimension ptDim,
827  typename LeftEuclideanRing, typename LeftContainer,
828  typename RightEuclideanRing, typename RightContainer >
829 inline auto
830 DGtal::inf( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
831  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
832  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
833 {
834  using EuclideanRing = ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>;
835  return DGtal::constructFromArithmeticConversion(lhs, rhs, lhs, rhs, functors::Min<EuclideanRing>());
836 }
837 //------------------------------------------------------------------------------
838 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
839 template < typename OtherComponent, typename OtherStorage >
840 inline auto
841 DGtal::PointVector<dim, TComponent, TContainer>::inf( const DGtal::PointVector<dim, OtherComponent, OtherStorage>& aPoint ) const
842  -> decltype( DGtal::inf(*this, aPoint) )
843 {
844  return DGtal::inf(*this, aPoint);
845 }
846 //------------------------------------------------------------------------------
847 template < DGtal::Dimension ptDim,
848  typename LeftEuclideanRing, typename LeftContainer,
849  typename RightEuclideanRing, typename RightContainer >
850 inline auto
851 DGtal::sup( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
852  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
853  -> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) )
854 {
855  using EuclideanRing = ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing>;
856  return DGtal::constructFromArithmeticConversion(lhs, rhs, lhs, rhs, functors::Max<EuclideanRing>());
857 }
858 //------------------------------------------------------------------------------
859 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
860 template < typename OtherComponent, typename OtherStorage >
861 inline auto
862 DGtal::PointVector<dim, TComponent, TContainer>::sup( const DGtal::PointVector<dim, OtherComponent, OtherStorage>& aPoint ) const
863  -> decltype( DGtal::sup(*this, aPoint) )
864 {
865  return DGtal::sup(*this, aPoint);
866 }
867 //------------------------------------------------------------------------------
868 template < DGtal::Dimension ptDim,
869  typename LeftEuclideanRing, typename LeftContainer,
870  typename RightEuclideanRing, typename RightContainer >
871 inline bool
872 DGtal::isLower( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
873  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
874 {
875  for ( DGtal::Dimension i = 0; i < ptDim; ++i )
876  if ( rhs[ i ] < lhs[ i ] )
877  return false;
878  return true;
879 }
880 //------------------------------------------------------------------------------
881 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
882 template < typename OtherComponent, typename OtherStorage >
883 inline bool
884 DGtal::PointVector<dim, TComponent, TContainer>::isLower( const DGtal::PointVector<dim, OtherComponent, OtherStorage> & p ) const
885 {
886  return DGtal::isLower(*this, p);
887 }
888 //------------------------------------------------------------------------------
889 template < DGtal::Dimension ptDim,
890  typename LeftEuclideanRing, typename LeftContainer,
891  typename RightEuclideanRing, typename RightContainer >
892 inline bool
893 DGtal::isUpper( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
894  DGtal::PointVector<ptDim, RightEuclideanRing, RightContainer> const& rhs )
895 {
896  for ( DGtal::Dimension i = 0; i < ptDim; ++i )
897  if ( rhs[ i ] > lhs[ i ] )
898  return false;
899  return true;
900 }
901 //------------------------------------------------------------------------------
902 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
903 template < typename OtherComponent, typename OtherStorage >
904 inline bool
905 DGtal::PointVector<dim, TComponent, TContainer>::isUpper( const DGtal::PointVector<dim, OtherComponent, OtherStorage> & p ) const
906 {
907  return DGtal::isUpper(*this, p);
908 }
909 //------------------------------------------------------------------------------
910 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
911 inline
912 typename DGtal::PointVector<dim, TComponent, TContainer>::Component
913 DGtal::PointVector<dim, TComponent, TContainer>::max( ) const
914 {
915  return *std::max_element(this->begin(), this->end());
916 }
917 //------------------------------------------------------------------------------
918 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
919 inline
920 typename DGtal::PointVector<dim, TComponent, TContainer>::Component
921 DGtal::PointVector<dim, TComponent, TContainer>::min( ) const
922 {
923  return *std::min_element(this->begin(), this->end());
924 }
925 //------------------------------------------------------------------------------
926 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
927 inline
928 typename DGtal::PointVector<dim, TComponent, TContainer>::Iterator
929 DGtal::PointVector<dim, TComponent, TContainer>::maxElement( )
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>::Iterator
937 DGtal::PointVector<dim, TComponent, TContainer>::minElement( )
938 {
939  return std::min_element(this->begin(), this->end());
940 }
941 //------------------------------------------------------------------------------
942 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
943 inline
944 void
945 DGtal::PointVector<dim, TComponent, TContainer>::
946 negate()
947 {
948  for ( DGtal::Dimension i = 0; i < dimension; ++i )
949  this->myArray[ i ] = - this->myArray[ i ];
950 }
951 //------------------------------------------------------------------------------
952 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
953 inline
954 double
955 DGtal::PointVector<dim, TComponent, TContainer>::squaredNorm () const
956 {
957  ASSERT ( dim > 0 );
958  double tmp = 0.0;
959  for ( DGtal::Dimension i = 0; i < dimension; i++ )
960  tmp += std::pow(NumberTraits<Component>::castToDouble(myArray[ i ]), 2);
961  return tmp;
962 }
963 //------------------------------------------------------------------------------
964 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
965 inline
966 double
967 DGtal::PointVector<dim, TComponent, TContainer>::norm (
968  const typename Self::NormType aType ) const
969 {
970  double tmp = 0.0;
971 
972  ASSERT ( dim > 0 );
973 
974  switch ( aType )
975  {
976  case L_2:
977  for ( DGtal::Dimension i = 0; i < dimension; i++ )
978  tmp += NumberTraits<Component>::castToDouble(myArray[ i ]) *
979  NumberTraits<Component>::castToDouble(myArray[ i ]);
980  tmp = ( double ) sqrt ( tmp );
981  break;
982  case L_1:
983  for ( DGtal::Dimension i = 0; i < dimension; i++ )
984  tmp += fabs ( NumberTraits<Component>::castToDouble(myArray[ i ] ));
985  break;
986  case L_infty:
987  tmp = fabs( NumberTraits<Component>::castToDouble( myArray[ 0 ]));
988  for ( DGtal::Dimension i = 1; i < dimension; i++ )
989  if ( tmp < fabs ( NumberTraits<Component>::castToDouble(myArray[ i ] ) ))
990  tmp = fabs ( NumberTraits<Component>::castToDouble(myArray[ i ] ));
991  break;
992  }
993  return tmp;
994 }
995 //------------------------------------------------------------------------------
996 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
997 inline
998 typename DGtal::PointVector<dim, TComponent, TContainer>::UnsignedComponent
999 DGtal::PointVector<dim, TComponent, TContainer>::norm1() const
1000 {
1001  ASSERT ( dimension > 0 );
1002  UnsignedComponent val
1003  ( ( myArray[ 0 ] >= 0 ) ? myArray[ 0 ] : UnsignedComponent(-myArray[ 0 ]) );
1004  for ( DGtal::Dimension i = 1; i < dimension; ++i )
1005  val += ( myArray[ i ] >= 0 )
1006  ? myArray[ i ]
1007  : UnsignedComponent(-myArray[ i ]);
1008  return val;
1009 }
1010 //------------------------------------------------------------------------------
1011 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1012 inline
1013 typename DGtal::PointVector<dim, TComponent, TContainer>::UnsignedComponent
1014 DGtal::PointVector<dim, TComponent, TContainer>::normInfinity() const
1015 {
1016  ASSERT ( dimension > 0 );
1017  UnsignedComponent tmp;
1018  UnsignedComponent val( ( myArray[ 0 ] >= 0 ) ? myArray[ 0 ] : -myArray[ 0 ] );
1019  for ( DGtal::Dimension i = 1; i < dimension; ++i )
1020  {
1021  tmp = ( myArray[ i ] >= 0 ) ? myArray[ i ] : -myArray[ i ] ;
1022  if ( tmp > val )
1023  val = tmp;
1024  }
1025  return val;
1026 }
1027 //------------------------------------------------------------------------------
1028 
1029 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1030 inline
1031 typename DGtal::PointVector<dim, double, std::array<double,dim> >
1032 DGtal::PointVector<dim, TComponent, TContainer>::getNormalized() const
1033 {
1034  PointVector<dim,double,std::array<double,dim> > normalized =(*this);
1035  normalized /= normalized.norm();
1036  return normalized;
1037 }
1038 //------------------------------------------------------------------------------
1039 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1040 inline
1041 DGtal::PointVector<dim,TComponent, TContainer>
1042 DGtal::PointVector<dim,TComponent, TContainer>::diagonal( Component val )
1043 {
1044  Self p;
1045  for ( DGtal::Dimension i = 0; i < dim; ++i )
1046  p.myArray[ i ] = val;
1047  return p;
1048 }
1049 //------------------------------------------------------------------------------
1050 template<DGtal::Dimension dim,typename TComponent, typename TContainer>
1051 inline
1052 DGtal::PointVector<dim,TComponent, TContainer>
1053 DGtal::PointVector<dim,TComponent, TContainer>::base( Dimension k, Component val )
1054 {
1055  Self p;
1056  p.myArray[ k ] = val;
1057  return p;
1058 }
1059 //------------------------------------------------------------------------------
1060 template<DGtal::Dimension dim,typename TComponent, typename TContainer>
1061 inline
1062 void
1063 DGtal::PointVector<dim,TComponent, TContainer>::selfDisplay( std::ostream & out ) const
1064 {
1065  out << "[PointVector] {";
1066  for (DGtal::Dimension i = 0; i < dimension ; ++i)
1067  out << myArray[ i ] << (i == dimension - 1 ? "" : ", ");
1068  out << "}";
1069 }
1070 
1071 //------------------------------------------------------------------------------
1072 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1073 inline
1074 std::string
1075 DGtal::PointVector<dim, TComponent, TContainer>::className() const
1076 {
1077  return "PointVector";
1078 }
1079 
1080 //------------------------------------------------------------------------------
1081 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1082 inline
1083 std::ostream&
1084 DGtal::operator<<( std::ostream & out,
1085  const PointVector<dim, TComponent, TContainer>& object )
1086 {
1087  object.selfDisplay( out );
1088  return out;
1089 }
1090 //------------------------------------------------------------------------------
1091 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1092 inline
1093 bool
1094 DGtal::PointVector<dim, TComponent, TContainer>::isValid() const
1095 {
1096  return true;
1097 }
1098 //------------------------------------------------------------------------------