1 // This is core/vgl/vgl_affine_coordinates.hxx
2 #ifndef vgl_affine_coordinates_hxx_
3 #define vgl_affine_coordinates_hxx_
4 #include <cassert>
5 #include <cmath>
6 #include "vgl_affine_coordinates.h"
7 #include "vgl_vector_2d.h"
8 #include "vgl_vector_3d.h"
9 #include "vgl_tolerance.h"
10 // Points are all coplanar. The first three points in pts are the basis, pts[0] is the origin
11 template <class T>
vgl_affine_coordinates_2d(std::vector<vgl_point_2d<T>> const & pts,std::vector<vgl_point_2d<T>> & affine_pts)12 void vgl_affine_coordinates_2d(std::vector<vgl_point_2d<T> > const& pts, std::vector<vgl_point_2d<T> >& affine_pts)
13 {
14 assert(pts.size()>=3);
15 vgl_vector_2d<T> v0 = pts[1]-pts[0];
16 vgl_vector_2d<T> v1 = pts[2]-pts[0];
17 T dv0v0 = dot_product(v0,v0);
18 T dv0v1 = dot_product(v0,v1);
19 T dv1v1 = dot_product(v1,v1);
20 T det = dv0v0*dv1v1 - dv0v1*dv0v1;
21 T tol = vgl_tolerance<T>::position;
22 assert(fabs(det)>tol);
23 for(unsigned i =0; i<pts.size(); ++i){
24 vgl_vector_2d<T> vp = pts[i]-pts[0];
25 T dvpv0 = dot_product(vp, v0);
26 T dvpv1 = dot_product(vp, v1);
27 T alpha = (dvpv0*dv1v1-dv0v1*dvpv1)/det;
28 T beta = (dv0v0*dvpv1-dvpv0*dv0v1)/det;
29 affine_pts.push_back(vgl_point_2d<T>(alpha, beta));
30 }
31 }
32 // The first four points in pts are the basis.
33 template <class T>
vgl_affine_coordinates_3d(std::vector<vgl_point_3d<T>> const & pts,std::vector<vgl_point_3d<T>> & affine_pts)34 void vgl_affine_coordinates_3d(std::vector<vgl_point_3d<T> > const& pts, std::vector<vgl_point_3d<T> >& affine_pts)
35 {
36 assert(pts.size()>=4);
37 vgl_vector_3d<T> v0 = pts[1]-pts[0];
38 vgl_vector_3d<T> v1 = pts[2]-pts[0];
39 vgl_vector_3d<T> v2 = pts[3]-pts[0];
40 T dv0v0 = dot_product(v0,v0);
41 T dv0v1 = dot_product(v0,v1);
42 T dv0v2 = dot_product(v0,v2);
43 T dv1v1 = dot_product(v1,v1);
44 T dv1v2 = dot_product(v1,v2);
45 T dv2v2 = dot_product(v2,v2);
46 T det = -dv0v2*dv0v2*dv1v1 + 2*dv0v1*dv0v2*dv1v2 - dv0v0*dv1v2*dv1v2 - dv0v1*dv0v1*dv2v2 + dv0v0*dv1v1*dv2v2;
47 T tol = vgl_tolerance<T>::position;
48 assert(fabs(det)>tol);
49 for(unsigned i =0; i<pts.size(); ++i){
50 vgl_vector_3d<T> vp = pts[i]-pts[0];
51 T dvpv0 = dot_product(vp, v0);
52 T dvpv1 = dot_product(vp, v1);
53 T dvpv2 = dot_product(vp, v2);
54 T alpha = (-dv1v2*dv1v2*dvpv0 + dv1v1*dv2v2*dvpv0 + dv0v2*dv1v2*dvpv1 -
55 dv0v1*dv2v2*dvpv1 - dv0v2*dv1v1*dvpv2 + dv0v1*dv1v2*dvpv2)/det;
56 T beta = (dv0v2*dv1v2*dvpv0 - dv0v1*dv2v2*dvpv0 - dv0v2*dv0v2*dvpv1 +
57 dv0v0*dv2v2*dvpv1 + dv0v1*dv0v2*dvpv2 - dv0v0*dv1v2*dvpv2)/det;
58 T gamma = (-dv0v2*dv1v1*dvpv0 + dv0v1*dv1v2*dvpv0 + dv0v1*dv0v2*dvpv1 -
59 dv0v0*dv1v2*dvpv1 - dv0v1*dv0v1*dvpv2 + dv0v0*dv1v1*dvpv2)/det;
60 affine_pts.push_back(vgl_point_3d<T>(alpha, beta, gamma));
61 }
62 }
63
64 // Two 2-d pointsets define the 3-d basis. The first four points in pts1 and pts2 are the basis.
65 template <class T>
vgl_affine_coordinates_3d(std::vector<vgl_point_2d<T>> const & pts1,std::vector<vgl_point_2d<T>> const & pts2,std::vector<vgl_point_3d<T>> & affine_pts)66 void vgl_affine_coordinates_3d(std::vector<vgl_point_2d<T> > const& pts1, std::vector<vgl_point_2d<T> > const& pts2,
67 std::vector<vgl_point_3d<T> >& affine_pts)
68 {
69 unsigned n1 = pts1.size(), n2 = pts2.size();
70 assert(n1>=4);
71 assert(n1==n2);
72 T tol = vgl_tolerance<T>::position;
73 //normalize 2-d pointsets
74 T x1=T(0), x2=T(0), y1 = T(0), y2 = T(0);
75 T dist_1 = T(0), dist_2 = T(0);
76 for(unsigned i = 0; i<n1;++i){
77 x1+=pts1[i].x(); y1+=pts1[i].y();
78 x2+=pts2[i].x(); y2+=pts2[i].y();
79 }
80 vgl_point_2d<T> cent_1(x1/n1, y1/n1), cent_2(x2/n1, y2/n1);
81 for(unsigned i = 0; i<n1;++i){
82 dist_1+=(pts1[i]-cent_1).length();
83 dist_2+=(pts2[i]-cent_2).length();
84 }
85 dist_1/=n1; dist_2/=n2;
86 std::vector<vgl_point_2d<T> > norm_pts1, norm_pts2;
87 for(unsigned i = 0; i<n1;++i){
88 vgl_point_2d<T> np1(pts1[i].x()-cent_1.x(), pts1[i].y()-cent_1.y());
89 if(dist_1>tol)
90 np1.set(np1.x()/dist_1, np1.y()/dist_1);
91 vgl_point_2d<T> np2(pts2[i].x()-cent_2.x(), pts2[i].y()-cent_2.y());
92 if(dist_2>tol)
93 np2.set(np2.x()/dist_2, np2.y()/dist_2);
94 norm_pts1.push_back(np1);
95 norm_pts2.push_back(np2);
96 }
97 // 2-d basis for pts1
98 vgl_vector_2d<T> v01 = norm_pts1[1]-norm_pts1[0];
99 vgl_vector_2d<T> v11 = norm_pts1[2]-norm_pts1[0];
100 T dv01v01 = dot_product(v01,v01);
101 T dv01v11 = dot_product(v01,v11);
102 T dv11v11 = dot_product(v11,v11);
103 T det1 = dv01v01*dv11v11 - dv01v11*dv01v11;
104 assert(fabs(det1)>tol);
105 //affine coordinates for V2' (pts1)
106 vgl_vector_2d<T> v21 = norm_pts1[3]-norm_pts1[0];
107 T dv21v01 = dot_product(v01, v21);
108 T dv21v11 = dot_product(v11, v21);
109 T alpha_1 = (dv21v01*dv11v11-dv01v11*dv21v11)/det1;
110 T beta_1 = (dv01v01*dv21v11-dv21v01*dv01v11)/det1;
111 // 2-d basis for pts2
112 vgl_vector_2d<T> v02 = norm_pts2[1]-norm_pts2[0];
113 vgl_vector_2d<T> v12 = norm_pts2[2]-norm_pts2[0];
114 T dv02v02 = dot_product(v02,v02);
115 T dv02v12 = dot_product(v02,v12);
116 T dv12v12 = dot_product(v12,v12);
117 T det2 = dv02v02*dv12v12 - dv02v12*dv02v12;
118 assert(fabs(det2)>tol);
119 //affine coordinates for V2 (pts2)
120 vgl_vector_2d<T> v22 = norm_pts2[3]-norm_pts2[0];
121 T dv22v02 = dot_product(v02, v22);
122 T dv22v12 = dot_product(v12, v22);
123 T alpha_2 = (dv22v02*dv12v12-dv02v12*dv22v12)/det2;
124 T beta_2 = (dv02v02*dv22v12-dv22v02*dv02v12)/det2;
125 //length of V2'V2 in pts2
126 vgl_vector_2d<T> V2pV2 = (alpha_2-alpha_1)*v02 + (beta_2-beta_1)*v12;
127 T L2 = V2pV2.length();
128 assert(L2>tol);// otherwise the views are the same or the basis points are coplanar
129 //determine sign of L2
130 T s2 = (alpha_2-alpha_1), fs2 = fabs(s2);
131 if(fs2<tol){
132 s2 = (beta_2-beta_1);
133 fs2 = fabs(s2);
134 if(fs2<tol){
135 s2 = 1.0;
136 fs2 = 1.0;
137 }
138 }
139 L2 *= s2/fs2;
140 for(unsigned i = 0; i<n1; ++i){
141 //affine coordinates for p in pts1
142 vgl_vector_2d<T> vp1 = norm_pts1[i]-norm_pts1[0];
143 T dvp1v01 = dot_product(vp1, v01);
144 T dvp1v11 = dot_product(vp1, v11);
145 T alpha_p1 = (dvp1v01*dv11v11-dv01v11*dvp1v11)/det1;
146 T beta_p1 = (dv01v01*dvp1v11-dvp1v01*dv01v11)/det1;
147 //affine coordinates for p in pts2
148 vgl_vector_2d<T> vp2 = norm_pts2[i]-norm_pts2[0];
149 T dvp2v02 = dot_product(vp2, v02);
150 T dvp2v12 = dot_product(vp2, v12);
151 T alpha_p2 = (dvp2v02*dv12v12-dv02v12*dvp2v12)/det2;
152 T beta_p2 = (dv02v02*dvp2v12-dvp2v02*dv02v12)/det2;
153 // length of PP' in pts 2
154 vgl_vector_2d<T> PpP = (alpha_p2-alpha_p1)*v02 + (beta_p2-beta_p1)*v12;
155 T Lp = PpP.length();
156 //determine sign of PP'
157 T sp = (alpha_p2-alpha_p1), fsp = fabs(sp);
158 if(fsp<tol){
159 sp = (beta_p2-beta_p1);
160 fsp = fabs(sp);
161 if(fsp<tol){
162 sp = 1.0;
163 fsp= 1.0;
164 }
165 }
166 Lp *= sp/fsp;
167 T gamma_p = Lp/L2;
168 T alpha_p = (alpha_p1-gamma_p*alpha_1);
169 T beta_p = (beta_p1-gamma_p*beta_1);
170 affine_pts.push_back(vgl_point_3d<T>(alpha_p, beta_p, gamma_p));
171 }
172 }
173 #undef VGL_AFFINE_COORDINATES_INSTANTIATE
174 #define VGL_AFFINE_COORDINATES_INSTANTIATE(T) \
175 template void vgl_affine_coordinates_2d(std::vector<vgl_point_2d<T> > const& pts, std::vector<vgl_point_2d<T> >& affine_pts); \
176 template void vgl_affine_coordinates_3d(std::vector<vgl_point_3d<T> > const& pts, std::vector<vgl_point_3d<T> >& affine_pts); \
177 template void vgl_affine_coordinates_3d(std::vector<vgl_point_2d<T> > const& pts1, std::vector<vgl_point_2d<T> > const& pts2, \
178 std::vector<vgl_point_3d<T> >& affine_pts)
179 #endif // vgl_affine_coordinates_h_
180