00001 #include "HomgOperator3D.h"
00002
00003
00004
00005 #include <vcl_cmath.h>
00006 #include <vcl_iostream.h>
00007 #include <vcl_vector.h>
00008 #include <vcl_utility.h>
00009 #include <vcl_algorithm.h>
00010
00011 #include <vnl/algo/vnl_svd.h>
00012 #include <vnl/vnl_matrix_fixed.h>
00013
00014 #include <mvl/HomgLine3D.h>
00015 #include <mvl/HomgPoint3D.h>
00016 #include <mvl/HomgPlane3D.h>
00017
00018
00019
00020
00021 void
00022 HomgOperator3D::sort_points(HomgPoint3D* points, int n)
00023 {
00024 if (n <= 0) return;
00025
00026
00027
00028 int num_finite = 0;
00029 HomgPoint3D finite_quadvec;
00030 for (int p_index = 0; p_index < n; p_index++) {
00031 HomgPoint3D* p = &points[p_index];
00032 if (p->w() != 0) {
00033 ++num_finite;
00034 finite_quadvec = *p;
00035 }
00036 }
00037 if (num_finite < n) {
00038 vcl_cerr << "WARNING HomgOperator3D::sort_points -- "
00039 << (n - num_finite) << " points at infinity\n";
00040 }
00041
00042 if (num_finite == 0) {
00043 vcl_cerr << "HomgOperator3D::sort_points: all points at infinity - no action\n";
00044 return;
00045 }
00046
00047 double distance_max = 0;
00048 HomgLine3D line;
00049 for (int p_index = 0; p_index < n; p_index++) {
00050 HomgPoint3D* p = &points[p_index];
00051 if (p->w() != 0) {
00052 double distance = HomgOperator3D::distance_squared(finite_quadvec, *p);
00053 if (distance > distance_max) {
00054 distance_max = distance;
00055
00056 line = HomgLine3D(finite_quadvec, *p);
00057 }
00058 }
00059 }
00060
00061
00062 vnl_double_3 finite_trivec = finite_quadvec.get_double3();
00063
00064
00065 vnl_double_3 dir = line.dir();
00066
00067 vnl_double_3 faraway_trivec = finite_trivec + 2.0 * distance_max * dir;
00068 HomgPoint3D faraway(faraway_trivec[0], faraway_trivec[1], faraway_trivec[2], 1.0);
00069
00070 typedef vcl_pair<float, int> pair_float_int;
00071 vcl_vector< pair_float_int > sort_table(n);
00072 vcl_vector< HomgPoint3D > tempoints(points, points + n);
00073
00074 for (int p_index = 0; p_index < n; p_index++) {
00075 HomgPoint3D* p = &points[p_index];
00076 if (p->w() != 0) {
00077 sort_table[p_index].first = (float)HomgOperator3D::distance_squared(faraway, *p);
00078 sort_table[p_index].second = p_index;
00079 }
00080 }
00081
00082 vcl_sort(sort_table.begin(), sort_table.end());
00083
00084 for (int sort_index = 0; sort_index < n; sort_index++) {
00085 pair_float_int* sort = &sort_table[sort_index];
00086 tempoints[sort_index] = points[sort->second];
00087 }
00088
00089 for (int i = 0; i < n; ++i)
00090 points[i] = tempoints[i];
00091 }
00092
00093
00094
00095
00096
00097 double
00098 HomgOperator3D::angle_between_oriented_lines (const HomgLine3D& l1, const HomgLine3D& l2)
00099 {
00100 HomgPoint3D const& dir1 = l1.get_point_infinite();
00101 HomgPoint3D const& dir2 = l2.get_point_infinite();
00102 double n = dir1.x()*dir1.x()+dir1.y()*dir1.y()+dir1.z()*dir1.z();
00103 n *= dir2.x()*dir2.x()+dir2.y()*dir2.y()+dir2.z()*dir2.z();
00104
00105 n = (dir1.x()*dir2.x()+dir1.y()*dir2.y()+dir1.z()*dir2.z())/vcl_sqrt(n);
00106 return vcl_acos(n);
00107 }
00108
00109
00110
00111
00112
00113
00114 double
00115 HomgOperator3D::distance_squared (const HomgPoint3D& point1, const HomgPoint3D& point2)
00116 {
00117 return (point1.get_double3() - point2.get_double3()).magnitude();
00118 }
00119
00120
00121
00122
00123
00124 HomgPoint3D
00125 HomgOperator3D::intersect_line_and_plane (const HomgLine3D &line, const HomgPlane3D& plane)
00126 {
00127
00128
00129
00130 const vnl_double_4& x1 = line.get_point_finite().get_vector();
00131 const vnl_double_4& x2 = line.get_point_infinite().get_vector();
00132 const vnl_double_4& p = plane.get_vector();
00133
00134 double numerator = -dot_product (x1, p);
00135 double denominator = dot_product (x2, p);
00136
00137
00138 double scale = 1.0/(numerator + denominator);
00139 numerator *= scale;
00140 denominator *= scale;
00141
00142 return denominator * x1 + numerator * x2;
00143 }
00144
00145
00146
00147
00148
00149
00150 HomgPoint3D
00151 HomgOperator3D::lines_to_point (const HomgLine3D& , const HomgLine3D& )
00152 {
00153 vcl_cerr << "Warning: HomgOperator3D::lines_to_point() not yet implemented\n";
00154 return HomgPoint3D();
00155 }
00156
00157
00158
00159
00160
00161
00162 HomgPoint3D
00163 HomgOperator3D::lines_to_point (const vcl_vector<HomgLine3D>& )
00164 {
00165 vcl_cerr << "Warning: HomgOperator3D::lines_to_point() not yet implemented\n";
00166 return HomgPoint3D();
00167 }
00168
00169
00170
00171
00172
00173 double
00174 HomgOperator3D::perp_dist_squared (const HomgPoint3D& , const HomgLine3D& )
00175 {
00176 vcl_cerr << "Warning: HomgOperator3D::perp_dist_squared() not yet implemented\n";
00177 return 0;
00178 }
00179
00180
00181
00182
00183
00184
00185 HomgLine3D
00186 HomgOperator3D::perp_line_through_point (const HomgLine3D& , const HomgPoint3D& ) { return HomgLine3D(); }
00187
00188
00189
00190
00191
00192
00193
00194 HomgPoint3D
00195 HomgOperator3D::perp_projection (const HomgLine3D& , const HomgPoint3D& )
00196 {
00197 vcl_cerr << "Warning: HomgOperator3D::perp_projection() not yet implemented\n";
00198 return HomgPoint3D();
00199 }
00200
00201
00202
00203
00204
00205
00206 HomgLine3D
00207 HomgOperator3D::planes_to_line (const HomgPlane3D& plane1, const HomgPlane3D& plane2)
00208 {
00209 vnl_matrix_fixed<double,2,4> M;
00210 M.set_row(0, plane1.get_vector());
00211 M.set_row(1, plane2.get_vector());
00212 vnl_svd<double> svd(M.as_ref());
00213 vnl_matrix_fixed<double,4,2> N = svd.nullspace(2);
00214 HomgPoint3D p1(N.get_column(0));
00215 HomgPoint3D p2(N.get_column(1));
00216 return HomgLine3D(p1, p2);
00217 }
00218
00219
00220
00221
00222
00223
00224 HomgLine3D
00225 HomgOperator3D::planes_to_line (const vcl_vector<HomgPlane3D>&)
00226 {
00227 vcl_cerr << "Warning: HomgOperator3D::planes_to_line() not yet implemented\n";
00228 return HomgLine3D();
00229 }
00230
00231
00232
00233
00234
00235
00236 HomgLine3D
00237 HomgOperator3D::points_to_line (const HomgPoint3D&, const HomgPoint3D&)
00238 {
00239 vcl_cerr << "Warning: HomgOperator3D::points_to_line() not yet implemented\n";
00240 return HomgLine3D();
00241 }
00242
00243
00244
00245
00246
00247 HomgLine3D
00248 HomgOperator3D::points_to_line (const vcl_vector<HomgPoint3D>&)
00249 {
00250 vcl_cerr << "Warning: HomgOperator3D::points_to_line() not yet implemented\n";
00251 return HomgLine3D();
00252 }
00253
00254
00255
00256
00257
00258 HomgPlane3D
00259 HomgOperator3D::points_to_plane (const HomgPoint3D&, const HomgPoint3D&, const HomgPoint3D&)
00260 {
00261 vcl_cerr << "Warning: HomgOperator3D::points_to_plane() not yet implemented\n";
00262 return HomgPlane3D();
00263 }
00264
00265
00266
00267
00268
00269
00270 HomgPlane3D
00271 HomgOperator3D::points_to_plane (const vcl_vector<HomgPoint3D>&)
00272 {
00273 vcl_cerr << "Warning: HomgOperator3D::points_to_plane() not yet implemented\n";
00274 return HomgPlane3D();
00275 }
00276
00277
00278
00279 HomgPoint3D
00280 HomgOperator3D::intersection_point (const HomgPlane3D& plane1, const HomgPlane3D& plane2, const HomgPlane3D& plane3)
00281 {
00282 vnl_matrix<double> A(3, 4);
00283 A(0,0) = plane1.x();
00284 A(0,1) = plane1.y();
00285 A(0,2) = plane1.z();
00286 A(0,3) = plane1.w();
00287
00288 A(1,0) = plane2.x();
00289 A(1,1) = plane2.y();
00290 A(1,2) = plane2.z();
00291 A(1,3) = plane2.w();
00292
00293 A(2,0) = plane3.x();
00294 A(2,1) = plane3.y();
00295 A(2,2) = plane3.z();
00296 A(2,3) = plane3.w();
00297
00298 vnl_svd<double> svd(A);
00299 return HomgPoint3D(svd.nullvector());
00300 }
00301
00302 HomgPoint3D
00303 HomgOperator3D::intersection_point (const vcl_vector<HomgPlane3D>& planes)
00304 {
00305 int n = planes.size();
00306 vnl_matrix<double> A(planes.size(), 4);
00307
00308 for (int i =0; i < n; ++i) {
00309 A(i,0) = planes[i].x();
00310 A(i,1) = planes[i].y();
00311 A(i,2) = planes[i].z();
00312 A(i,3) = planes[i].w();
00313 }
00314
00315 vnl_svd<double> svd(A);
00316 return HomgPoint3D(svd.nullvector());
00317 }
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 double HomgOperator3D::CrossRatio(const Homg3D& a, const Homg3D& b, const Homg3D& c, const Homg3D& d)
00337 {
00338 double x1 = a.x(), y1 = a.y(), z1 = a.z(), w1 = a.w();
00339 double x2 = b.x(), y2 = b.y(), z2 = b.z(), w2 = b.w();
00340 double x3 = c.x(), y3 = c.y(), z3 = c.z(), w3 = c.w();
00341 double x4 = d.x(), y4 = d.y(), z4 = d.z(), w4 = d.w();
00342 double x = x1 - x2; if (x<0) x = -x;
00343 double y = y1 - y2; if (y<0) y = -y;
00344 double z = z1 - z2; if (z<0) z = -z;
00345 double n = (x>y && x>z) ? (x1*w3-x3*w1)*(x2*w4-x4*w2) :
00346 (y>z) ? (y1*w3-y3*w1)*(y2*w4-y4*w2) :
00347 (z1*w3-z3*w1)*(z2*w4-z4*w2);
00348 double m = (x>y && x>z) ? (x1*w4-x4*w1)*(x2*w3-x3*w2) :
00349 (y>z) ? (y1*w4-y4*w1)*(y2*w3-y3*w2) :
00350 (z1*w4-z4*w1)*(z2*w3-z3*w2);
00351 if (n == 0 && m == 0)
00352 vcl_cerr << "CrossRatio not defined: three of the given points coincide\n";
00353 return n/m;
00354 }