cgv
Loading...
Searching...
No Matches
align.h
1#pragma once
2
3#include <cgv/math/fvec.h>
4#include <cgv/math/quaternion.h>
5#include <cgv/math/fmat.h>
6#include <cgv/math/det.h>
7#include <cgv/math/svd.h>
8
9namespace cgv {
10 namespace math {
11
13 template <typename T>
14 fvec<T, 3> mean(const std::vector<fvec<T, 3> >& P, T inv_n = T(1) / P.size())
15 {
16 fvec<T, 3> mu(T(0));
17 for (unsigned i = 0; i < P.size(); ++i)
18 mu += P[i];
19 mu *= inv_n;
20 return mu;
21 }
22
24 template <typename T, cgv::type::uint32_type N, cgv::type::uint32_type M>
25 void svd(const fmat<T, N, M>& A, fmat<T, N, N>& U, fvec<T, M>& D, fmat<T, M, M>& V_t, bool ordering = true, int maxiter = 30)
26 {
27 mat<T> _A(N, M, &A(0, 0)), _U, _V;
28 diag_mat<T> _D;
29 svd(_A, _U, _D, _V, ordering, maxiter);
30 U = fmat<T, N, N>(N, N, &_U(0, 0));
32 for (j = 0; j < M; ++j) {
33 D(j) = _D(j);
34 for (i = 0; i < M; ++i)
35 V_t(j, i) = _V(i, j);
36 }
37 }
38
40
52 template <typename T, typename T_SVD = T>
53 void align(
54 const std::vector<fvec<T, 3> >& source_points, const std::vector<fvec<T, 3> >& target_points, // input point sets
55 fmat<T, 3, 3>& O, fvec<T, 3>& t, T* scale_ptr = nullptr, // output transformation
56 bool allow_reflection = false) // configuration
57 {
58 // ensure that source_points and target_points have same number of points and that we have at least 3 point pairs
59 assert(source_points.size() == target_points.size() && source_points.size() > 2);
60 T inv_n = T(1) / source_points.size();
61 // compute mean points
62 fvec<T, 3> mu_source = mean(source_points, inv_n);
63 fvec<T, 3> mu_target = mean(target_points, inv_n);
64 // compute covariance matrix and variances of point sets
65 fmat<T, 3, 3> Sigma(T(0));
66 T sigma_S = 0, sigma_T = 0;
67 for (size_t i = 0; i < source_points.size(); ++i) {
68 Sigma += fmat<T, 3, 3>(target_points[i] - mu_target, source_points[i] - mu_source);
69 sigma_S += sqr_length(source_points[i] - mu_source);
70 sigma_T += sqr_length(target_points[i] - mu_target);
71 }
72 Sigma *= inv_n;
73 sigma_S *= inv_n;
74 sigma_T *= inv_n;
75 // compute SVD of covariance matrix
76 fvec<T_SVD, 3> D;
77 fmat<T_SVD, 3, 3> U, V_t;
78 svd(fmat<T_SVD,3,3>(Sigma), U, D, V_t);
79 // account for reflections
80 fmat<T_SVD, 3, 3> S;
81 S.identity();
82 if (!allow_reflection && det(mat<T>(3,3,&Sigma(0,0))) < 0)
83 S(2, 2) = T_SVD(-1);
84 // compute results
85 O = fmat<T,3,3>(U*S*V_t);
86 if (scale_ptr) {
87 *scale_ptr = T(D(0) + D(1) + S(2, 2)*D(2)) / sigma_S;
88 t = mu_target - *scale_ptr * O * mu_source;
89 }
90 else
91 t = mu_target - O*mu_source;
92 }
93 }
94}
complete implementation of method actions that only call one method when entering a node
Definition action.h:113
the cgv namespace
Definition print.h:11