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