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