MEPP2 Project
MatrixOperations.hpp
Go to the documentation of this file.
1 // Copyright (c) 2012-2019 University of Lyon and CNRS (France).
2 // All rights reserved.
3 //
4 // This file is part of MEPP2; you can redistribute it and/or modify
5 // it under the terms of the GNU Lesser General Public License as
6 // published by the Free Software Foundation; either version 3 of
7 // the License, or (at your option) any later version.
8 //
9 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
10 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 #pragma once
12 
13 #include "degree_rad_conversion.h" // rad2deg()
14 
15 #include <iostream>
16 #include <vector>
17 #include <limits>
18 #include <algorithm> // std::sort
19 #include <cassert>
20 #include <cmath> // floor
21 
22 #ifndef ABS_GUY
23 #define ABS_GUY fabs
24 #endif
25 #ifndef SQRT_GUY
26 #define SQRT_GUY sqrt
27 #endif
28 #ifndef MACH_EPS_DOUBLE
29 #define MACH_EPS_DOUBLE 2e-16
30 #endif
31 #ifndef MACH_EPS_FLOAT
32 #define MACH_EPS_FLOAT 2e-7
33 #endif
34 
35 namespace FEVV {
36 namespace Math {
37 
38 namespace Vector {
39 namespace Stats {
41 template< class ElementType >
42 static std::vector< ElementType >
43 unique(const std::vector< ElementType > &v)
44 {
45  std::vector< ElementType > ret;
46  size_t nb_e = v.size();
47  if(nb_e == 0)
48  return ret;
49 
50  ret.push_back(v[0]);
51  for(size_t i = 1; i < nb_e; ++i)
52  {
53  bool is_unique = true;
54  for(size_t j = 0; j < ret.size(); j++)
55  {
56  if(fabs(v[i] - ret[j]) < MACH_EPS_FLOAT)
57  {
58  is_unique = false;
59  break;
60  }
61  }
62  if(is_unique)
63  {
64  ret.push_back(v[i]);
65  }
66  }
67 
68  return ret;
69 }
71 template< typename ElementType, int DIM >
72 static ElementType
73 maximum(const ElementType v[DIM])
74 {
75  ElementType result = std::numeric_limits< ElementType >::min();
76  for(size_t i = 0; i < DIM; ++i)
77  {
78  if(v[i] > result)
79  {
80  result = v[i];
81  }
82  }
83  return result;
84 }
85 template< typename ElementType >
86 static ElementType
87 maximum(const std::vector< ElementType > &v)
88 {
89  ElementType result = std::numeric_limits< ElementType >::min();
90  const size_t dim = v.size();
91  for(size_t i = 0; i < dim; ++i)
92  {
93  if(v[i] > result)
94  {
95  result = v[i];
96  }
97  }
98  return result;
99 }
101 template< typename ElementType, int DIM >
102 static ElementType
103 minimum(const ElementType v[DIM])
104 {
105  ElementType result = std::numeric_limits< ElementType >::max();
106  for(size_t i = 0; i < DIM; ++i)
107  {
108  if(v[i] < result)
109  {
110  result = v[i];
111  }
112  }
113  return result;
114 }
115 template< typename ElementType >
116 static ElementType
117 minimum(const std::vector< ElementType > &v)
118 {
119  ElementType result = std::numeric_limits< ElementType >::max();
120  const size_t dim = v.size();
121  for(size_t i = 0; i < dim; ++i)
122  {
123  if(v[i] < result)
124  {
125  result = v[i];
126  }
127  }
128  return result;
129 }
131 template< typename ElementType, int DIM >
132 static ElementType
133 mean(const ElementType v[DIM])
134 {
135  ElementType result = 0;
136  for(size_t i = 0; i < DIM; ++i)
137  {
138  result += v[i];
139  }
140  if(DIM > 0)
141  return result / static_cast< ElementType >(DIM);
142  else
143  return result;
144 }
145 template< typename ElementType >
146 static ElementType
147 mean(const std::vector< ElementType > &v)
148 {
149  ElementType result = 0;
150  const size_t dim = v.size();
151  for(size_t i = 0; i < dim; ++i)
152  {
153  result += v[i];
154  }
155  if(dim > 0)
156  return result / static_cast< ElementType >(dim);
157  else
158  return result;
159 }
161 template< typename ElementType >
162 static ElementType
163 mean2(const std::vector< ElementType > &v)
164 {
165  ElementType result = 0;
166  const size_t dim = v.size();
167  for(size_t i = 0; i < dim; ++i)
168  {
169  result += v[i] * v[i];
170  }
171  if(dim > 0)
172  return result / static_cast< ElementType >(dim);
173  else
174  return result;
175 }
176 
177 template< typename ElementType >
178 static ElementType
179 mean4(const std::vector< ElementType > &v)
180 {
181  ElementType result = 0;
182  const size_t dim = v.size();
183  for(size_t i = 0; i < dim; ++i)
184  {
185  result += v[i] * v[i] * v[i] * v[i];
186  }
187  if(dim > 0)
188  return result / static_cast< ElementType >(dim);
189  else
190  return result;
191 }
193 template< typename ElementType >
194 static ElementType
195 mean_sqrt(const std::vector< ElementType > &v)
196 {
197  ElementType result = 0;
198  const size_t dim = v.size();
199  for(size_t i = 0; i < dim; ++i)
200  {
201  result += sqrt(v[i]);
202  }
203  if(dim > 0)
204  return result / static_cast< ElementType >(dim);
205  else
206  return result;
207 }
209 template< typename ElementType >
210 static ElementType
211 mean_sqrt_sqrt(const std::vector< ElementType > &v)
212 {
213  ElementType result = 0;
214  const size_t dim = v.size();
215  for(size_t i = 0; i < dim; ++i)
216  {
217  result += sqrt(sqrt(v[i]));
218  }
219  if(dim > 0)
220  return result / static_cast< ElementType >(dim);
221  else
222  return result;
223 }
225 template< typename ElementType, int DIM >
226 static ElementType
227 weighted_mean(const ElementType v[DIM], const ElementType weights[DIM])
228 {
229  ElementType result = 0;
230  ElementType sum_weights = 0;
231  for(size_t i = 0; i < DIM; ++i)
232  {
233  result += v[i] * weights[i];
234  sum_weights += weights[i];
235  }
237  return result / sum_weights;
238  else
239  return result;
240 }
241 template< typename ElementType >
242 static ElementType
243 weighted_mean(const std::vector< ElementType > &v,
244  const std::vector< ElementType > &weights)
245 {
246  ElementType result = 0;
247  ElementType sum_weights = 0;
248  const size_t dim = ((v.size() <= weights.size()) ? v.size() : weights.size());
249  for(size_t i = 0; i < dim; ++i)
250  {
251  result += v[i] * weights[i];
252  sum_weights += weights[i];
253  }
255  return result / sum_weights;
256  else
257  return result;
258 }
259 
264 template< class ElementType >
265 static ElementType
266 median(std::vector< ElementType > v)
267 {
268  std::sort(v.begin(), v.end());
269  if(v.size() % 2 == 0)
270  {
271  return static_cast< ElementType >(
272  (v[v.size() / 2] + v[(v.size() / 2) - 1]) /
273  2.0f); // in case if someone use an int type for ElementType...
274  }
275  else
276  {
277  return v[v.size() / 2];
278  }
279 }
280 
281 template< class ElementType >
282 static ElementType
283 percentile(std::vector< ElementType > v, float k)
284 {
285  std::sort(v.begin(), v.end());
286  if(k > 1.f)
287  k = 1.f;
288  else if(k < 0.f)
289  k = 0.f;
290  return v[(int)floor(k * (float)v.size())];
291 }
293 template< class T >
294 struct IndexCmp
295 {
296  T V;
297  IndexCmp(const T &v) : V(v) {}
298  bool operator()(const unsigned int a, const unsigned int b) const
299  {
300  return V[a] < V[b];
301  }
302 };
303 /*
304 template <class T>
305 inline unsigned int* sortArrayIndices(T* A, size_t size) {
306  vector<unsigned int> VI(size);
307  for (size_t i = 0; i < size; i++) {
308  VI[i] = i;
309  }
310  vector<T> V(A, A+size);
311  std::sort( VI.begin(), VI.end(), IndexCmp<vector<T>&>(V) );
312  unsigned int *I = new unsigned int[size];
313  for (size_t i = 0; i < size; i++) {
314  I[i] = VI[i];
315  }
316  return I;
317 }*/
318 
319 template< class T >
320 inline std::vector< unsigned int >
321 sort_vector_indices(std::vector< T > &v)
322 {
323  std::vector< unsigned int > vi(v.size());
324  for(size_t i = 0; i < v.size(); i++)
325  {
326  vi[i] = i;
327  }
328  std::sort(vi.begin(), vi.end(), IndexCmp< std::vector< T > & >(v));
329  return vi;
330 }
331 template< class ElementType >
332 static ElementType
333 weightedmedian(const std::vector< ElementType > &v,
334  const std::vector< ElementType > &weights)
335 {
336  std::vector< unsigned int > vi = sort_vector_indices(v);
337  double sumw = 0.0, csumw = 0.0;
338  size_t i, nb_e = weights.size();
339  for(i = 0; i < nb_e; ++i)
340  {
341  sumw += (double)weights[i];
342  }
343  for(i = 0; i < nb_e; ++i)
344  {
345  csumw += (double)weights[vi[i]] / (double)sumw;
346  if(csumw >= .5f)
347  break;
348  }
349  return v[vi[i]];
350 }
352 template< class ElementType >
353 static ElementType
354 variance(const std::vector< ElementType > &v,
355  ElementType mean_value,
356  bool unbiased = true)
357 {
358  ElementType result = 0;
359  size_t nb_e = v.size();
360  if(nb_e <= 1)
361  {
362  std::cerr << "Vector::Stats::variance: at least 2 elements are needed for "
363  "computing the unbiased variance."
364  << std::endl;
365  }
366  else
367  {
368  for(size_t i = 0; i < nb_e; ++i)
369  {
370  result += (v[i] - mean_value) * (v[i] - mean_value);
371  }
372  if(unbiased)
373  result /= (static_cast< ElementType >(nb_e) - 1);
374  else
375  result /= static_cast< ElementType >(nb_e);
376  }
377  return result;
378 }
379 
380 template< class ElementType >
381 inline ElementType
382 skewness(const std::vector< ElementType > &v,
383  ElementType mean_value,
384  ElementType biased_variance_value)
385 {
386  ElementType result = 0;
387  size_t nb_e = v.size();
388  for(size_t i = 0; i < nb_e; ++i)
389  {
390  result += (v[i] - mean_value) * (v[i] - mean_value) * (v[i] - mean_value);
391  }
392  result /= static_cast< ElementType >(nb_e);
393  result /= sqrt(biased_variance_value * biased_variance_value *
394  biased_variance_value +
395  static_cast< float >(1e-30));
396  return result;
397 }
398 
399 template< class ElementType >
400 inline ElementType
401 kurtosis(const std::vector< ElementType > &v,
402  ElementType mean_value,
403  ElementType biased_variance_value)
404 {
405  ElementType result = 0;
406  size_t nb_e = v.size();
407  for(size_t i = 0; i < nb_e; ++i)
408  {
409  result += (v[i] - mean_value) * (v[i] - mean_value) * (v[i] - mean_value) *
410  (v[i] - mean_value);
411  }
412  result /= (nb_e * biased_variance_value * biased_variance_value +
413  static_cast< float >(1e-30));
414  return result;
415 }
416 } // namespace Stats
419 template< typename ElementType, int DIM >
420 static ElementType
421 dot_product(const ElementType v1[DIM], const ElementType v2[DIM])
422 {
423  ElementType s = 0;
424  for(int i = 0; i < DIM; ++i)
425  s += v1[i] * v2[i];
426  return s;
427 }
429 template< typename ElementType >
430 static ElementType
431 dot_product(const std::vector< ElementType > &v1,
432  const std::vector< ElementType > &v2)
433 {
434  ElementType s = 0;
435  size_t nb_e = v1.size();
436  if(nb_e > v2.size())
437  nb_e = v2.size();
438 
439  for(size_t i = 0; i < nb_e; ++i)
440  s += v1[i] * v2[i];
441  return s;
442 }
443 
444 template< typename GeometryTraits >
445 static typename GeometryTraits::Scalar
447  const typename GeometryTraits::Vector &v2,
448  const GeometryTraits &gt)
449 {
450  return gt.dot_product(v1, v2);
451 }
452 
458 template< typename ElementType, int DIM >
459 static std::vector< ElementType >
460 cross_product(const ElementType v1[DIM], const ElementType v2[DIM])
461 {
462  size_t nb_e = 3; // the bilinear cross product exists only in 3D and 7D (but
463  // we do not consider 7D for the time being)
464  if(nb_e != DIM)
465  assert(false);
466 
467  std::vector< ElementType > res(nb_e);
468 
469  for(size_t i = 0; i < nb_e; ++i)
470  res[i] = v1[(1 + i) % nb_e] * v2[(2 + i) % nb_e] -
471  v1[(2 + i) % nb_e] * v2[(1 + i) % nb_e];
472 
473  return res;
474 }
475 
477 template< typename ElementType >
478 static std::vector< ElementType >
479 cross_product(const std::vector< ElementType > &v1,
480  const std::vector< ElementType > &v2)
481 {
482  size_t nb_e = 3; // the bilinear cross product exists only in 3D and 7D (but
483  // we do not consider 7D for the time being)
484  if((nb_e != v1.size()) || (nb_e != v2.size()))
485  assert(false);
486 
487  std::vector< ElementType > res(nb_e);
488 
489  for(size_t i = 0; i < nb_e; ++i)
490  res[i] = v1[(1 + i) % nb_e] * v2[(2 + i) % nb_e] -
491  v1[(2 + i) % nb_e] * v2[(1 + i) % nb_e];
492 
493  return res;
494 }
495 
496 template< typename GeometryTraits >
497 static typename GeometryTraits::Vector
499  const typename GeometryTraits::Vector &v2,
500  const GeometryTraits &gt)
501 {
502  return gt.cross_product(v1, v2);
503 }
504 
506 template< typename ElementType, int DIM >
507 static std::vector< ElementType >
508 sub(const ElementType v1[DIM], const ElementType v2[DIM])
509 {
510  std::vector< ElementType > res(DIM);
511 
512  for(size_t i = 0; i < DIM; ++i)
513  res[i] = v1[i] - v2[i];
514 
515  return res;
516 }
517 
519 template< typename ElementType >
520 static std::vector< ElementType >
521 sub(const std::vector< ElementType > &v1, const std::vector< ElementType > &v2)
522 {
523  size_t nb_e = v1.size();
524  if(nb_e > v2.size())
525  nb_e = v2.size();
526 
527  std::vector< ElementType > res(nb_e);
528 
529  for(size_t i = 0; i < nb_e; ++i)
530  res[i] = v1[i] - v2[i];
531 
532  return res;
533 }
534 
536 template< typename GeometryTraits >
537 static typename GeometryTraits::Vector
538 sub(const typename GeometryTraits::Point &p1,
539  const typename GeometryTraits::Point &p2,
540  const GeometryTraits &gt)
541 {
542  return gt.sub_p(p1, p2);
543 }
544 
546 template< typename ElementType, int DIM >
547 static std::vector< ElementType >
548 add(const ElementType v1[DIM], const ElementType v2[DIM])
549 {
550  std::vector< ElementType > res(DIM);
551 
552  for(size_t i = 0; i < DIM; ++i)
553  res[i] = v1[i] + v2[i];
554 
555  return res;
556 }
557 
559 template< typename ElementType >
560 static std::vector< ElementType >
561 add(const std::vector< ElementType > &v1, const std::vector< ElementType > &v2)
562 {
563  size_t nb_e = v1.size();
564  if(nb_e > v2.size())
565  nb_e = v2.size();
566 
567  std::vector< ElementType > res(nb_e);
568 
569  for(size_t i = 0; i < nb_e; ++i)
570  res[i] = v1[i] + v2[i];
571 
572  return res;
573 }
574 
576 template< typename GeometryTraits >
577 static typename GeometryTraits::Point
578 add(const typename GeometryTraits::Point &p,
579  const typename GeometryTraits::Vector &v,
580  const GeometryTraits &gt)
581 {
582  return gt.add_pv(p, v);
583 }
584 
586 template< typename ElementType, int DIM >
587 static double
588 l2_distance(const ElementType v1[DIM], const ElementType v2[DIM])
589 {
590 
591 
592  std::vector< ElementType > sub_res(Vector::sub< ElementType, DIM >(v1, v2));
593  return sqrt(dot_product< ElementType >(sub_res, sub_res));
594 }
595 
597 template< typename ElementType, int DIM >
598 static double
599 l2_distance(const ElementType v[DIM])
600 {
601  return sqrt(dot_product< ElementType, DIM >(v, v));
602 }
603 
605 template< typename GeometryTraits >
606 static double
608  const typename GeometryTraits::Point &p2,
609  const GeometryTraits &gt)
610 {
611  return gt.length(p1, p2);
612 }
613 
615 template< typename ElementType >
616 static double
617 l2_distance(const std::vector< ElementType > &v1,
618  const std::vector< ElementType > &v2)
619 {
620  std::vector< ElementType > sub_res(sub(v1, v2));
621  return sqrt(dot_product< ElementType >(sub_res, sub_res));
622 }
623 
625 template< typename GeometryTraits >
626 static double
627 l2_distance(const typename GeometryTraits::Vector &v, const GeometryTraits &gt)
628 {
629  return gt.length(v);
630 }
631 
633 template< typename ElementType >
634 static double
635 l2_distance(const std::vector< ElementType > &v)
636 {
637  return sqrt(dot_product< ElementType >(v, v));
638 }
639 
643 template< typename GeometryTraits >
644 static typename GeometryTraits::Vector
645 normalize(const typename GeometryTraits::Vector &v, const GeometryTraits &gt)
646 {
647  return gt.normalize(v);
648 }
649 
651 template< typename ElementType >
652 static bool
653 are_collinear(const std::vector< ElementType > &v1,
654  const std::vector< ElementType > &v2
655 )
656 { /*
657  // follow algorithm presented here:
658  http://math.stackexchange.com/questions/208577/find-if-three-points-in-3-dimensional-space-are-collinear
659  // yet this algorithm does not seam to work properly (some non aligned
660  points are detected aligned) ElementType A = 0, B=0, C=0 ; size_t
661  nbE=V1.size() ; if(V2.size()<nbE) nbE=V2.size() ;
662 
663  for(size_t i=0; i<nbE; ++i)
664  {
665  A += V1[i]*V1[i] ;
666  B += V2[i]*V1[i] ;
667  C += V2[i]*V2[i] ;
668  }
669  if ((fabs(B) < MACH_EPS_FLOAT)) // the 2 vectors are orthogonal
670  return false;
671  B *= 2 ;
672  return (fabs(B*B - 4 * A*C)< MACH_EPS_FLOAT) ;*/
673  return Vector::l2_distance(Vector::cross_product< ElementType >(v1, v2)) <
675 }
676 
677 template< typename GeometryTraits >
678 static bool
680  const typename GeometryTraits::Vector &v2
681 )
682 {
683  return are_collinear(
684  std::vector< typename GeometryTraits::Scalar >{v1[0], v1[1], v1[2]},
685  std::vector< typename GeometryTraits::Scalar >{v2[0], v2[1], v2[2]});
686 }
687 
689 template< typename ElementType >
690 static bool
691 are_aligned(const std::vector< ElementType > &p1,
692  const std::vector< ElementType > &p2,
693  const std::vector< ElementType > &p3)
694 {
695  return are_collinear< ElementType >(sub< ElementType >(p2, p1),
696  sub< ElementType >(p1, p3));
697 }
698 
699 template< typename GeometryTraits >
700 static bool
701 are_aligned(const typename GeometryTraits::Point &p1,
702  const typename GeometryTraits::Point &p2,
703  const typename GeometryTraits::Point &p3)
704 {
705  return are_aligned(
706  std::vector< typename GeometryTraits::Scalar >{p1[0], p1[1], p1[2]},
707  std::vector< typename GeometryTraits::Scalar >{p2[0], p2[1], p2[2]},
708  std::vector< typename GeometryTraits::Scalar >{p3[0], p3[1], p3[2]});
709 }
710 
712 template< typename ElementType >
713 static std::vector< ElementType >
714 scalar_mult(const std::vector< ElementType > &v1, ElementType coef)
715 {
716  size_t nb_e = v1.size();
717 
718  std::vector< ElementType > res(nb_e);
719 
720  for(size_t i = 0; i < nb_e; ++i)
721  res[i] = v1[i] * coef;
722 
723  return res;
724 }
725 
726 template< typename GeometryTraits >
727 static typename GeometryTraits::Vector
729  double coef,
730  const GeometryTraits &gt)
731 {
732  return gt.scalar_mult(v, coef);
733 }
736 template< typename ElementType, int DIM >
737 static double
738 get_angle_from_unit_vectors(const ElementType v1[DIM],
739  const ElementType v2[DIM])
740 {
741  double cosphi = Vector::dot_product< ElementType, DIM >(v1, v2);
742  double sinphi =
743  Vector::l2_distance(Vector::cross_product< ElementType, DIM >(v1, v2));
744 
745  return std::atan2(sinphi, cosphi);
746 }
747 template< typename ElementType, int DIM >
748 static double
749 get_angle_in_degree_from_unit_vectors(const ElementType v1[DIM],
750  const ElementType v2[DIM])
751 {
752  return rad2deg(
753  (Vector::get_angle_from_unit_vectors< ElementType, DIM >(v1, v2)));
754 }
755 
757 template< typename ElementType >
758 static double
759 get_angle_from_unit_vectors(const std::vector< ElementType > &v1,
760  const std::vector< ElementType > &v2)
761 {
762  double cosphi = Vector::dot_product< ElementType >(v1, v2);
763  double sinphi =
764  Vector::l2_distance(Vector::cross_product< ElementType >(v1, v2));
765 
766  return std::atan2(sinphi, cosphi);
767 }
768 template< typename ElementType >
769 static double
770 get_angle_in_degree_from_unit_vectors(const std::vector< ElementType > &v1,
771  const std::vector< ElementType > &v2)
772 {
773  return rad2deg((Vector::get_angle_from_unit_vectors< ElementType >(v1, v2)));
774 }
777 template< class ElementType >
778 static double
779 get_angle_from_non_unit_vectors(const std::vector< ElementType > &v1,
780  const std::vector< ElementType > &v2)
781 {
782  std::vector< ElementType > copy_v1(v1);
783  double lv1 = std::sqrt(dot_product(copy_v1, copy_v1));
784  if(lv1 > MACH_EPS_FLOAT)
785  copy_v1 = scalar_mult(copy_v1, 1.f / lv1);
786  else
787  copy_v1 = std::vector< ElementType >(copy_v1.size(), 0);
788 
789  std::vector< ElementType > copy_v2(v2);
790 
791  double lv2 = std::sqrt(dot_product(copy_v2, copy_v2));
792  if(lv2 > MACH_EPS_FLOAT)
793  copy_v2 = scalar_mult(copy_v2, 1.f / lv2);
794  else
795  copy_v2 = std::vector< ElementType >(copy_v2.size(), 0);
796 
797  return get_angle_from_unit_vectors(copy_v1, copy_v2);
798 }
799 template< typename ElementType >
800 static double
801 get_angle_in_degree_from_non_unit_vectors(const std::vector< ElementType > &v1,
802  const std::vector< ElementType > &v2)
803 {
804  return rad2deg(
805  (Vector::get_angle_from_non_unit_vectors< ElementType >(v1, v2)));
806 }
807 template< class ElementType >
808 static double
810  const std::vector< ElementType > &p1,
811  const std::vector< ElementType > &p2, // point onto which angle is computed
812  const std::vector< ElementType > &p3)
813 {
814  std::vector< ElementType > v1 = sub(p1, p2);
815  std::vector< ElementType > v2 = sub(p3, p2);
816 
817  return get_angle_from_non_unit_vectors(v1, v2);
818 }
819 template< typename ElementType >
820 static double
822  const std::vector< ElementType > &p1,
823  const std::vector< ElementType > &p2, // point onto which angle is computed
824  const std::vector< ElementType > &p3)
825 {
826  return rad2deg((Vector::get_angle_from3positions< ElementType >(p1, p2, p3)));
827 }
829 // Rotate a coordinate system to be perpendicular to the given normal
830 // ElementType should be either float, double or long double
831 template< typename ElementType >
832 static void
834  const std::vector< ElementType >
835  &old_u,
836  const std::vector< ElementType >
838  &old_v,
839  const std::vector< ElementType > &new_norm,
841  std::vector< ElementType >
842  &new_u,
843  std::vector< ElementType >
844  &new_v
845 )
846 {
847  new_u = old_u;
848  new_v = old_v;
849  std::vector< ElementType > old_norm = cross_product(old_u, old_v);
850  ElementType ndot =
851  static_cast< ElementType >(dot_product(old_norm, new_norm));
852  if(ndot <= -1.0f)
853  {
854  new_u = -new_u;
855  new_v = -new_v;
856  return;
857  }
858  std::vector< ElementType > perp_old =
859  sub(new_norm, scalar_mult(old_norm, ndot));
860  std::vector< ElementType > dperp =
861  scalar_mult(add(old_norm, new_norm), 1.0f / (1 + ndot));
862  new_u =
863  sub(new_u,
864  scalar_mult(
865  dperp, static_cast< ElementType >(dot_product(new_u, perp_old))));
866  new_v =
867  sub(new_v,
868  scalar_mult(
869  dperp, static_cast< ElementType >(dot_product(new_v, perp_old))));
870 }
872 // Reproject a curvature tensor from the basis spanned by old_u and old_v
873 // (which are assumed to be unit-length and perpendicular) to the
874 // new_u, new_v basis.
875 // ElementType should be either float, double or long double
876 template< typename ElementType >
877 void
878 proj_curv(const std::vector< ElementType > &old_u,
879  const std::vector< ElementType > &old_v,
880  ElementType old_ku,
881  ElementType old_kuv,
882  ElementType old_kv,
883  const std::vector< ElementType > &new_u,
884  const std::vector< ElementType > &new_v,
885  ElementType &new_ku,
886  ElementType &new_kuv,
887  ElementType &new_kv
888 )
889 {
890  std::vector< ElementType > r_new_u, r_new_v;
891  rot_coord_sys(new_u, new_v, cross_product(old_u, old_v), r_new_u, r_new_v);
892 
893  ElementType u1 = static_cast< ElementType >(dot_product(r_new_u, old_u));
894  ElementType v1 = static_cast< ElementType >(dot_product(r_new_u, old_v));
895  ElementType u2 = static_cast< ElementType >(dot_product(r_new_v, old_u));
896  ElementType v2 = static_cast< ElementType >(dot_product(r_new_v, old_v));
897  new_ku = old_ku * u1 * u1 + old_kuv * (2.0f * u1 * v1) + old_kv * v1 * v1;
898  new_kuv = old_ku * u1 * u2 + old_kuv * (u1 * v2 + u2 * v1) + old_kv * v1 * v2;
899  new_kv = old_ku * u2 * u2 + old_kuv * (2.0f * u2 * v2) + old_kv * v2 * v2;
900 }
901 } // namespace Vector
902 
903 namespace Matrix {
904 namespace Square {
907 template< typename CoordinateType, size_t N >
908 static std::vector< CoordinateType >
909 covar(const CoordinateType point_coords[3 * N])
910 {
911  std::vector< CoordinateType > cd(9); // 3 x 3 matrix
912 
913  cd[0] = 0.0f;
914  for(size_t r = 0; r < N; r++)
915  cd[0] += point_coords[r * 3] * point_coords[r * 3];
916  for(size_t j = 0; j <= 1; j++)
917  {
918  cd[1 + j * 3] = 0.0f;
919  for(size_t r = 0; r < N; r++)
920  {
921  cd[1 + j * 3] += point_coords[1 + r * 3] * point_coords[j + r * 3];
922  }
923  }
924  for(size_t j = 0; j <= 2; j++)
925  {
926  cd[2 + j * 3] = 0.0f;
927  for(size_t r = 0; r < N; r++)
928  {
929  cd[2 + j * 3] += point_coords[2 + r * 3] * point_coords[j + r * 3];
930  }
931  }
932  cd[3] = cd[1];
933  cd[6] = cd[2];
934  cd[7] = cd[5];
935 
936  return cd;
937 }
938 
941 template< typename CoordinateType >
942 static std::vector< CoordinateType >
943 covar(const std::vector< CoordinateType > &point_coords)
944 {
945  std::vector< CoordinateType > cd(9); // 3 x 3 matrix
946  const size_t n = point_coords.size() / 3;
947  cd[0] = 0.0f;
948  for(size_t r = 0; r < n; r++)
949  cd[0] += point_coords[r * 3] * point_coords[r * 3];
950  for(size_t j = 0; j <= 1; j++)
951  {
952  cd[1 + j * 3] = 0.0f;
953  for(size_t r = 0; r < n; r++)
954  {
955  cd[1 + j * 3] += point_coords[1 + r * 3] * point_coords[j + r * 3];
956  }
957  }
958  for(size_t j = 0; j <= 2; j++)
959  {
960  cd[2 + j * 3] = 0.0f;
961  for(size_t r = 0; r < n; r++)
962  {
963  cd[2 + j * 3] += point_coords[2 + r * 3] * point_coords[j + r * 3];
964  }
965  }
966  cd[3] = cd[1];
967  cd[6] = cd[2];
968  cd[7] = cd[5];
969 
970  return cd;
971 }
974 template< typename ElementType, int DIM = 3 >
975 static void
976 vector_times_transpose_mult(const ElementType *p_vector,
977  ElementType pp_matrix[][DIM],
978  ElementType coeff)
979 {
980  int j;
981  for(int i = 0; i < DIM; ++i)
982  for(j = 0; j < DIM; ++j)
983  pp_matrix[i][j] = coeff * p_vector[i] * p_vector[j];
984 }
989 template< typename ElementType, int DIM = 3 >
990 static void
992  const ElementType pp_matrix[DIM][DIM],
993  const ElementType in_vertex[DIM],
995  ElementType out_vertex[DIM]
997 )
999 {
1000  int j;
1001  for(int i = 0; i < DIM; ++i) // for each matrix row
1002  {
1003  out_vertex[i] = 0; // sum init
1004  for(j = 0; j < DIM; ++j)
1005  out_vertex[i] += pp_matrix[i][j] * in_vertex[j];
1006  }
1007 }
1008 
1012 template< typename ElementType, int DIM, int N >
1013 static void
1015  const ElementType pp_matrix[DIM][DIM],
1016  const ElementType
1018  in_vertices[DIM][N],
1019  ElementType out_vertices[DIM]
1020  [N]
1021 )
1022 {
1023  int j;
1024  for(int i = 0; i < DIM; ++i) // for each matrix row
1025  {
1026  for(int n = 0; n < N; ++n)
1027  { // for each column vector
1028  out_vertices[i][n] = 0; // sum init
1029  for(j = 0; j < DIM; ++j)
1030  out_vertices[i][n] += pp_matrix[i][j] * in_vertices[j][n];
1031  }
1032  }
1033 }
1034 
1036 template< typename ElementType, int DIM >
1037 static void
1038 add(const ElementType p_matrix[][DIM], ElementType p_matrix_sum[][DIM])
1039 {
1040  int j;
1041  for(int i = 0; i < DIM; ++i)
1042  for(j = 0; j < DIM; ++j)
1043  p_matrix_sum[i][j] += p_matrix[i][j];
1044 }
1045 
1046 template< typename ElementType, int DIM >
1047 static bool
1048 is_diagonal(const ElementType p_matrix[DIM][DIM])
1049 {
1050  int j;
1051  for(int i = 0; i < DIM; ++i)
1052  for(j = 0; j < DIM; ++j)
1053  if((i != j) && fabs(p_matrix[i][j]) > MACH_EPS_FLOAT)
1054  return false;
1055  return true;
1056 }
1057 
1058 
1060 } // namespace Square
1061 } // namespace Matrix
1062 
1063 } // namespace Math
1064 } // namespace FEVV
1065 
MACH_EPS_FLOAT
#define MACH_EPS_FLOAT
Definition: MatrixOperations.hpp:32
FEVV::Math::Vector::Stats::minimum
static ElementType minimum(const ElementType v[DIM])
Definition: MatrixOperations.hpp:103
FEVV::Math::Vector::Stats::variance
static ElementType variance(const std::vector< ElementType > &v, ElementType mean_value, bool unbiased=true)
Definition: MatrixOperations.hpp:354
FEVV::Math::Vector::proj_curv
void proj_curv(const std::vector< ElementType > &old_u, const std::vector< ElementType > &old_v, ElementType old_ku, ElementType old_kuv, ElementType old_kv, const std::vector< ElementType > &new_u, const std::vector< ElementType > &new_v, ElementType &new_ku, ElementType &new_kuv, ElementType &new_kv)
Definition: MatrixOperations.hpp:878
Vector
AIFMesh::Vector Vector
Definition: Graph_properties_aif.h:22
FEVV::Math::Matrix::Square::transformation
static void transformation(const ElementType pp_matrix[DIM][DIM], const ElementType in_vertex[DIM], ElementType out_vertex[DIM])
Definition: MatrixOperations.hpp:991
FEVV::Math::Vector::l2_distance
static double l2_distance(const ElementType v1[DIM], const ElementType v2[DIM])
Compute ||v1 - v2||_L2 norm (distance between v1 and v2)
Definition: MatrixOperations.hpp:588
FEVV::Math::Vector::get_angle_in_degree_from3positions
static double get_angle_in_degree_from3positions(const std::vector< ElementType > &p1, const std::vector< ElementType > &p2, const std::vector< ElementType > &p3)
Definition: MatrixOperations.hpp:821
FEVV::Math::Vector::Stats::maximum
static ElementType maximum(const ElementType v[DIM])
Definition: MatrixOperations.hpp:73
FEVV::Math::Matrix::Square::vector_times_transpose_mult
static void vector_times_transpose_mult(const ElementType *p_vector, ElementType pp_matrix[][DIM], ElementType coeff)
Compute coef * V x V^t (V is a vertical DIM-D vector)
Definition: MatrixOperations.hpp:976
FEVV::Math::Vector::add
static std::vector< ElementType > add(const ElementType v1[DIM], const ElementType v2[DIM])
Compute v1 + v2 (addition)
Definition: MatrixOperations.hpp:548
FEVV::Math::Vector::Stats::mean4
static ElementType mean4(const std::vector< ElementType > &v)
Definition: MatrixOperations.hpp:179
FEVV::Math::Vector::are_collinear
static bool are_collinear(const std::vector< ElementType > &v1, const std::vector< ElementType > &v2)
Tells if 2 nD vectors are collinear or not.
Definition: MatrixOperations.hpp:653
FEVV::Math::Vector::Stats::mean
static ElementType mean(const ElementType v[DIM])
Definition: MatrixOperations.hpp:133
Point
AIFMesh::Point Point
Definition: Graph_properties_aif.h:21
FEVV::Math::Vector::get_angle_from3positions
static double get_angle_from3positions(const std::vector< ElementType > &p1, const std::vector< ElementType > &p2, const std::vector< ElementType > &p3)
Definition: MatrixOperations.hpp:809
FEVV::Math::Vector::Stats::percentile
static ElementType percentile(std::vector< ElementType > v, float k)
Definition: MatrixOperations.hpp:283
degree_rad_conversion.h
FEVV::Math::Vector::normalize
static GeometryTraits::Vector normalize(const typename GeometryTraits::Vector &v, const GeometryTraits &gt)
Definition: MatrixOperations.hpp:645
FEVV::Math::Matrix::Square::covar
static std::vector< CoordinateType > covar(const CoordinateType point_coords[3 *N])
Definition: MatrixOperations.hpp:909
FEVV::Math::Vector::cross_product
static std::vector< ElementType > cross_product(const ElementType v1[DIM], const ElementType v2[DIM])
Definition: MatrixOperations.hpp:460
FEVV::Math::Vector::sub
static std::vector< ElementType > sub(const ElementType v1[DIM], const ElementType v2[DIM])
Compute v1 - v2 (subtraction)
Definition: MatrixOperations.hpp:508
FEVV::Math::Vector::get_angle_from_unit_vectors
static double get_angle_from_unit_vectors(const ElementType v1[DIM], const ElementType v2[DIM])
V1 and V2 must be unit vectors!
Definition: MatrixOperations.hpp:738
FEVV
Interfaces for plugins These interfaces will be used for different plugins.
Definition: Assert.h:16
FEVV::Math::Vector::rot_coord_sys
static void rot_coord_sys(const std::vector< ElementType > &old_u, const std::vector< ElementType > &old_v, const std::vector< ElementType > &new_norm, std::vector< ElementType > &new_u, std::vector< ElementType > &new_v)
Definition: MatrixOperations.hpp:833
FEVV::Math::Vector::Stats::weighted_mean
static ElementType weighted_mean(const ElementType v[DIM], const ElementType weights[DIM])
Definition: MatrixOperations.hpp:227
FEVV::Math::Vector::scalar_mult
static std::vector< ElementType > scalar_mult(const std::vector< ElementType > &v1, ElementType coef)
Compute v1 * coef.
Definition: MatrixOperations.hpp:714
FEVV::Math::Vector::Stats::sort_vector_indices
std::vector< unsigned int > sort_vector_indices(std::vector< T > &v)
Definition: MatrixOperations.hpp:321
FEVV::DataStructures::AIF::AIFVector
Definition: AIFProperties.h:173
FEVV::Math::Vector::get_angle_in_degree_from_non_unit_vectors
static double get_angle_in_degree_from_non_unit_vectors(const std::vector< ElementType > &v1, const std::vector< ElementType > &v2)
Definition: MatrixOperations.hpp:801
FEVV::Math::Vector::Stats::mean_sqrt
static ElementType mean_sqrt(const std::vector< ElementType > &v)
Be careful, this function will not work if any of the values is negative.
Definition: MatrixOperations.hpp:195
FEVV::Math::Vector::get_angle_in_degree_from_unit_vectors
static double get_angle_in_degree_from_unit_vectors(const ElementType v1[DIM], const ElementType v2[DIM])
Definition: MatrixOperations.hpp:749
FEVV::Math::Vector::Stats::IndexCmp
Definition: MatrixOperations.hpp:295
FEVV::Math::Vector::are_aligned
static bool are_aligned(const std::vector< ElementType > &p1, const std::vector< ElementType > &p2, const std::vector< ElementType > &p3)
Tells if 3 nD points are aligned or not.
Definition: MatrixOperations.hpp:691
FEVV::Filters::fabs
double fabs(const v_Curv< HalfedgeGraph > &input)
Definition: curvature.hpp:54
FEVV::Math::Vector::Stats::weightedmedian
static ElementType weightedmedian(const std::vector< ElementType > &v, const std::vector< ElementType > &weights)
Definition: MatrixOperations.hpp:333
FEVV::Math::rad2deg
T rad2deg(T rad)
Definition: degree_rad_conversion.h:26
FEVV::Math::Vector::get_angle_from_non_unit_vectors
static double get_angle_from_non_unit_vectors(const std::vector< ElementType > &v1, const std::vector< ElementType > &v2)
V1 and V2 does not need to be unit vectors!
Definition: MatrixOperations.hpp:779
FEVV::Math::Vector::Stats::median
static ElementType median(std::vector< ElementType > v)
Definition: MatrixOperations.hpp:266
FEVV::Math::Vector::Stats::skewness
ElementType skewness(const std::vector< ElementType > &v, ElementType mean_value, ElementType biased_variance_value)
Definition: MatrixOperations.hpp:382
FEVV::Math::Vector::Stats::mean2
static ElementType mean2(const std::vector< ElementType > &v)
Definition: MatrixOperations.hpp:163
FEVV::Math::Vector::Stats::IndexCmp::IndexCmp
IndexCmp(const T &v)
Definition: MatrixOperations.hpp:297
FEVV::Math::Vector::Stats::mean_sqrt_sqrt
static ElementType mean_sqrt_sqrt(const std::vector< ElementType > &v)
Be careful, this function will not work if any of the values is negative.
Definition: MatrixOperations.hpp:211
FEVV::Math::Matrix::Square::is_diagonal
static bool is_diagonal(const ElementType p_matrix[DIM][DIM])
Definition: MatrixOperations.hpp:1048
FEVV::Math::Vector::Stats::IndexCmp::V
T V
Definition: MatrixOperations.hpp:296
FEVV::Math::Vector::Stats::unique
static std::vector< ElementType > unique(const std::vector< ElementType > &v)
Definition: MatrixOperations.hpp:43
FEVV::Math::Vector::Stats::IndexCmp::operator()
bool operator()(const unsigned int a, const unsigned int b) const
Definition: MatrixOperations.hpp:298
FEVV::Math::Vector::dot_product
static ElementType dot_product(const ElementType v1[DIM], const ElementType v2[DIM])
Compute v1 * v2 scalar product.
Definition: MatrixOperations.hpp:421
FEVV::Math::Matrix::Square::add
static void add(const ElementType p_matrix[][DIM], ElementType p_matrix_sum[][DIM])
add two matrices
Definition: MatrixOperations.hpp:1038
epsilon
const float epsilon
Definition: core.h:51
FEVV::Math::Vector::Stats::kurtosis
ElementType kurtosis(const std::vector< ElementType > &v, ElementType mean_value, ElementType biased_variance_value)
Definition: MatrixOperations.hpp:401