00001
00002 #ifndef vgl_conic_txx_
00003 #define vgl_conic_txx_
00004
00005
00006
00007
00008 #include "vgl_conic.h"
00009
00010 #include <vcl_cmath.h>
00011 #include <vcl_iostream.h>
00012 #include <vcl_compiler.h>
00013
00014 static const char *vgl_conic_name[] =
00015 {
00016 "invalid conic",
00017 "real ellipse",
00018 "real circle",
00019 "imaginary ellipse",
00020 "imaginary circle",
00021 "hyperbola",
00022 "parabola",
00023 "real intersecting lines",
00024 "complex intersecting lines",
00025 "real parallel lines",
00026 "complex parallel lines",
00027 "coincident lines"
00028 };
00029
00030
00031
00032
00033
00034 template <class T>
00035 vcl_string vgl_conic<T>::real_type() const { return vgl_conic_name[(int)type_]; }
00036
00037 template <class T>
00038 typename vgl_conic<T>::vgl_conic_type vgl_conic<T>::type_by_name(vcl_string const& name)
00039 {
00040 for (int i = (int)no_type; i < num_conic_types; i++)
00041 if (name == vgl_conic_name[i])
00042 return (typename vgl_conic<T>::vgl_conic_type)i;
00043 return no_type;
00044 }
00045
00046 template <class T>
00047 vcl_string vgl_conic<T>::type_by_number(typename vgl_conic<T>::vgl_conic_type type)
00048 {
00049 if (type <= 0 || type >= num_conic_types) return vgl_conic_name[no_type];
00050 return vgl_conic_name[type];
00051 }
00052
00053
00054
00055 template <class T>
00056 bool vgl_conic<T>::operator==(vgl_conic<T> const& that) const
00057 {
00058 if ( type() != that.type() ) return false;
00059 return a()*that.b() == b()*that.a()
00060 && a()*that.c() == c()*that.a()
00061 && a()*that.d() == d()*that.a()
00062 && a()*that.e() == e()*that.a()
00063 && a()*that.f() == f()*that.a()
00064 && b()*that.c() == c()*that.b()
00065 && b()*that.d() == d()*that.b()
00066 && b()*that.e() == e()*that.b()
00067 && b()*that.f() == f()*that.b()
00068 && c()*that.d() == d()*that.c()
00069 && c()*that.e() == e()*that.c()
00070 && c()*that.f() == f()*that.c()
00071 && d()*that.e() == e()*that.d()
00072 && d()*that.f() == f()*that.d()
00073 && e()*that.f() == f()*that.e();
00074 }
00075
00076
00077
00078 template <class T>
00079 void vgl_conic<T>::set(T ta, T tb, T tc, T td, T te, T tf)
00080 {
00081 a_ = ta; b_ = tb; c_ = tc; d_ = td; e_ = te; f_ = tf;
00082 set_type_from_equation();
00083 }
00084
00085
00086
00087 template <class T>
00088 vgl_conic<T>::vgl_conic(T const co[])
00089 : type_(no_type), a_(co[0]), b_(co[1]), c_(co[2]), d_(co[3]), e_(co[4]), f_(co[5])
00090 {
00091 set_type_from_equation();
00092 }
00093
00094
00095
00096 template <class T>
00097 vgl_conic<T>::vgl_conic(T ta, T tb, T tc, T td, T te, T tf)
00098 : type_(no_type), a_(ta), b_(tb), c_(tc), d_(td), e_(te), f_(tf)
00099 {
00100 set_type_from_equation();
00101 }
00102
00103
00104 template <class T>
00105 vgl_conic<T>::vgl_conic(vgl_homg_point_2d<T> const& co, T rx, T ry, T theta)
00106 {
00107 if (co.w() == 0) {
00108 a_ = co.y()*co.y();
00109 b_ = -2*co.x()*co.y();
00110 c_ = co.x()*co.x();
00111
00112
00113 theta /= vcl_sqrt(co.x()*co.x()+co.y()*co.y());
00114 d_ = -2*a_*rx - b_*ry + 2*theta*co.x();
00115 e_ = -2*c_*ry - b_*rx + 2*theta*co.y();
00116
00117 f_ = -a_*rx*rx-b_*rx*ry-c_*ry*ry-d_*rx-e_*ry;
00118 }
00119 else {
00120 rx = (rx < 0) ? (-rx*rx) : (rx > 0) ? (rx*rx) : 0;
00121 ry = (ry < 0) ? (-ry*ry) : (ry > 0) ? (ry*ry) : 0;
00122
00123 double ct = vcl_cos(-theta);
00124 double st = vcl_sin(-theta);
00125 T u = co.x();
00126 T v = co.y();
00127 a_ = T(rx*st*st + ry*ct*ct);
00128 b_ = T(2*(rx-ry)*ct*st);
00129 c_ = T(rx*ct*ct + ry*st*st);
00130 d_ = T(-2*(rx*st*st + ry*ct*ct)*u - 2*(rx-ry)*ct*st*v);
00131 e_ = T(-2*(rx-ry)*ct*st*u - 2*(rx*ct*ct + ry*st*st)*v);
00132 f_ = T((rx*st*st +ry*ct*ct)*u*u + 2*(rx-ry)*ct*st*u*v + (rx*ct*ct + ry*st*st)*v*v - rx*ry);
00133 }
00134 set_type_from_equation();
00135 }
00136
00137
00138
00139
00140
00141
00142 template <class T>
00143 void vgl_conic<T>::set_type_from_equation()
00144 {
00145 T A = a_, B = b_/2, C = c_, D = d_/2, E = e_/2, F = f_;
00146
00147
00148 T det = A*(C*F - E*E) - B*(B*F - D*E) + D*(B*E - C*D);
00149 T J = A*C - B*B;
00150 T K = (C*F - E*E) + (A*F - D*D);
00151 T I = A + C;
00152
00153 if (det != 0) {
00154 if (J > 0) {
00155 if (det*I < 0) {
00156 if (A==C && B==0) type_ = real_circle;
00157 else type_ = real_ellipse;
00158 }
00159 else {
00160 if (A==C && B==0) type_ = imaginary_circle;
00161 else type_ = imaginary_ellipse;
00162 }
00163 }
00164 else if (J < 0) type_ = hyperbola;
00165 else type_ = parabola;
00166 }
00167 else {
00168 if (J < 0) type_ = real_intersecting_lines;
00169 else if (J > 0) type_ = complex_intersecting_lines;
00170 else {
00171 if ( A == 0 && B == 0 && C == 0 ) {
00172 if ( D !=0 || E != 0 ) type_ = real_intersecting_lines;
00173 else if (F != 0) type_ = coincident_lines;
00174 else type_ = no_type;
00175 }
00176 else if (K < 0) type_ = real_parallel_lines;
00177 else if (K > 0) type_ = complex_parallel_lines;
00178 else type_ = coincident_lines;
00179 }
00180 }
00181 }
00182
00183 template <class T>
00184 bool vgl_conic<T>::contains(vgl_homg_point_2d<T> const& p) const
00185 {
00186 return p.x()*p.x()*a_+p.x()*p.y()*b_+p.y()*p.y()*c_+p.x()*p.w()*d_+p.y()*p.w()*e_+p.w()*p.w()*f_ == 0;
00187 }
00188
00189 template <class T>
00190 bool vgl_conic<T>::is_degenerate() const
00191 {
00192 T A = a_, B = b_/2, C = c_, D = d_/2, E = e_/2, F = f_;
00193 T det = A*(C*F - E*E) - B*(B*F - D*E) + D*(B*E - C*D);
00194 return det==0;
00195 }
00196
00197
00198
00199 template <class T>
00200 bool vgl_conic<T>::
00201 ellipse_geometry(double& xc, double& yc, double& major_axis_length,
00202 double& minor_axis_length, double& angle_in_radians)
00203 {
00204 if (type_!=real_ellipse && type_ != real_circle)
00205 return false;
00206
00207
00208 double A = static_cast<double>(a_), B = static_cast<double>(b_)*0.5,
00209 C = static_cast<double>(c_), D = static_cast<double>(d_)*0.5,
00210 F = static_cast<double>(f_), E = static_cast<double>(e_)*0.5;
00211 if (A < 0)
00212 A=-A, B=-B, C=-C, D=-D, E=-E, F=-F;
00213
00214 double det = A*(C*F - E*E) - B*(B*F- D*E) + D*(B*E-C*D);
00215 double D2 = A*C - B*B;
00216 xc = (E*B - C*D)/D2;
00217 yc = (D*B - A*E)/D2;
00218
00219 double trace = A + C;
00220 double disc = vcl_sqrt(trace*trace - 4.0*D2);
00221 double cmaj = (trace+disc)*D2/(2*det); if (cmaj < 0) cmaj = -cmaj;
00222 double cmin = (trace-disc)*D2/(2*det); if (cmin < 0) cmin = -cmin;
00223 minor_axis_length = 1.0/vcl_sqrt(cmaj>cmin?cmaj:cmin);
00224 major_axis_length = 1.0/vcl_sqrt(cmaj>cmin?cmin:cmaj);
00225
00226
00227 angle_in_radians = -0.5 * vcl_atan2(2*B, C-A);
00228
00229
00230 return true;
00231 }
00232
00233
00234
00235
00236 template <class T>
00237 vcl_list<vgl_homg_line_2d<T> > vgl_conic<T>::components() const
00238 {
00239 if (!is_degenerate() ||
00240 type() == complex_intersecting_lines ||
00241 type() == complex_parallel_lines)
00242 return vcl_list<vgl_homg_line_2d<T> >();
00243
00244 T A = a_, B = b_/2, C = c_, D = d_/2, E = e_/2, F = f_;
00245
00246 if (type() == coincident_lines) {
00247
00248 vgl_homg_line_2d<T> l;
00249 if (A!=0 || B!=0 || D!=0)
00250 l = vgl_homg_line_2d<T>(A,B,D);
00251 else if (C!=0 || E!=0)
00252 l = vgl_homg_line_2d<T>(B,C,E);
00253 else
00254 l = vgl_homg_line_2d<T>(D,E,F);
00255 return vcl_list<vgl_homg_line_2d<T> >(2,l);
00256 }
00257
00258
00259 vgl_homg_point_2d<T> cntr = centre();
00260
00261 if (type() == real_parallel_lines)
00262 {
00263
00264
00265 if (A!=0 || D!=0) {
00266 vgl_homg_line_2d<T> l1(cntr, vgl_homg_point_2d<T>(-D+vcl_sqrt(D*D-A*F),0,A)),
00267 l2(cntr, vgl_homg_point_2d<T>(-D-vcl_sqrt(D*D-A*F),0,A));
00268 vcl_list<vgl_homg_line_2d<T> > v(1,l1); v.push_back(l2);
00269 return v;
00270 }
00271 else {
00272 vgl_homg_line_2d<T> l1(cntr, vgl_homg_point_2d<T>(0,-E+vcl_sqrt(E*E-C*F),C)),
00273 l2(cntr, vgl_homg_point_2d<T>(0,-E-vcl_sqrt(E*E-C*F),C));
00274 vcl_list<vgl_homg_line_2d<T> > v(1,l1); v.push_back(l2);
00275 return v;
00276 }
00277 }
00278
00279
00280 if (A==0 && B==0 && C==0) {
00281 vcl_list<vgl_homg_line_2d<T> > v(1,vgl_homg_line_2d<T>(0,0,1));
00282 v.push_back(vgl_homg_line_2d<T>(d_,e_,f_));
00283 return v;
00284 }
00285
00286
00287 vgl_homg_line_2d<T> l1(cntr, vgl_homg_point_2d<T>(-B+vcl_sqrt(B*B-A*C),A,0)),
00288 l2(cntr, vgl_homg_point_2d<T>(-B-vcl_sqrt(B*B-A*C),A,0));
00289 vcl_list<vgl_homg_line_2d<T> > v(1,l1); v.push_back(l2);
00290 return v;
00291 }
00292
00293
00294
00295
00296 template <class T>
00297 bool vgl_conic<T>::is_central() const
00298 {
00299 return type_ == real_ellipse|| type_ == imaginary_ellipse|| type_ == hyperbola
00300 || type_ == real_circle || type_ == imaginary_circle
00301 || type_ == real_intersecting_lines|| type_ == complex_intersecting_lines;
00302 }
00303
00304
00305 template <class T>
00306 void vgl_conic<T>::translate_by(T x, T y)
00307 {
00308 d_ += 2*a_*x + b_*y;
00309 f_ += c_ * y*y - a_ * x*x + d_ * x + e_ * y;
00310 e_ += 2*c_*y + b_*x;
00311
00312 }
00313
00314 template <class T>
00315 vgl_conic<T> vgl_conic<T>::dual_conic() const
00316 {
00317 T A = a_, B = b_/2, C = c_, D = d_/2, E = e_/2, F = f_;
00318 return vgl_conic<T>(E*E-C*F, 2*(B*F-D*E), D*D-A*F, 2*(C*D-B*E), 2*(A*E-B*D), B*B-A*C);
00319 }
00320
00321
00322 template <class T>
00323 vgl_homg_line_2d<T> vgl_conic<T>::polar_line(vgl_homg_point_2d<T> const& p) const
00324 {
00325 return vgl_homg_line_2d<T> (p.x()*a_ +p.y()*b_/2+p.w()*d_/2,
00326 p.x()*b_/2+p.y()*c_ +p.w()*e_/2,
00327 p.x()*d_/2+p.y()*e_/2+p.w()*f_ );
00328 }
00329
00330
00331 template <class T>
00332 vgl_homg_point_2d<T> vgl_conic<T>::polar_point(vgl_homg_line_2d<T> const& l) const
00333 {
00334 if (!is_degenerate()) {
00335 vgl_conic<T> co = this->dual_conic();
00336 return vgl_homg_point_2d<T> (l.a()*co.a() +l.b()*co.b()/2+l.c()*co.d()/2,
00337 l.a()*co.b()/2+l.b()*co.c() +l.c()*co.e()/2,
00338 l.a()*co.d()/2+l.b()*co.e()/2+l.c()*co.f() );
00339 }
00340 else
00341 if (a_==0 && b_==0 && d_==0)
00342 return vgl_homg_point_2d<T>(1,0,0);
00343 else if (a_*c_*4==b_*b_ && a_*e_*2==b_*d_)
00344 return vgl_homg_point_2d<T>(b_*f_*2-e_*d_, d_*d_-a_*f_*4, a_*e_*2-b_*d_);
00345 else
00346 return vgl_homg_point_2d<T>(b_*e_-c_*d_*2, b_*d_-a_*e_*2, a_*c_*4-b_*b_);
00347 }
00348
00349
00350 template <class T>
00351 double vgl_conic<T>::curvature_at(vgl_point_2d<T> const& p) const
00352 {
00353
00354 const T &a_xx = a_;
00355 const T &a_xy = b_;
00356 const T &a_yy = c_;
00357 const T &a_xw = d_;
00358 const T &a_yw = e_;
00359
00360 const T x = p.x();
00361 const T y = p.y();
00362
00363 double f_x = 2*a_xx*x + a_xy*y + a_xw;
00364 double f_y = 2*a_yy*y + a_xy*x + a_yw;
00365 double f_xy = a_xy;
00366 double f_xx = 2*a_xx;
00367 double f_yy = 2*a_yy;
00368
00369 double f_x_2 = f_x*f_x;
00370 double f_y_2 = f_y*f_y;
00371 double denom = f_x_2 + f_y_2;
00372 denom = vcl_sqrt(denom*denom*denom);
00373
00374
00375 return (f_xx*f_y_2 - 2*f_x*f_y*f_xy + f_yy*f_x_2) / denom;
00376 }
00377
00378
00379
00380 template <class T>
00381 vcl_ostream& operator<<(vcl_ostream& s, vgl_conic<T> const& co)
00382 {
00383 s << "<vgl_conic ";
00384 if (co.a() == 1) s << "X^2";
00385 else if (co.a() == -1) s << "-X^2";
00386 else if (co.a() != 0) s << co.a() << "X^2";
00387 if (co.b() > 0) s << '+';
00388 if (co.b() == 1) s << "XY";
00389 else if (co.b() == -1) s << "-XY";
00390 else if (co.b() != 0) s << co.b() << "XY";
00391 if (co.c() > 0) s << '+';
00392 if (co.c() == 1) s << "Y^2";
00393 else if (co.c() == -1) s << "-Y^2";
00394 else if (co.c() != 0) s << co.c() << "Y^2";
00395 if (co.d() > 0) s << '+';
00396 if (co.d() == 1) s << "XW";
00397 else if (co.d() == -1) s << "-XW";
00398 else if (co.d() != 0) s << co.d() << "XW";
00399 if (co.e() > 0) s << '+';
00400 if (co.e() == 1) s << "YW";
00401 else if (co.e() == -1) s << "-YW";
00402 else if (co.e() != 0) s << co.e() << "YW";
00403 if (co.f() > 0) s << '+';
00404 if (co.f() == 1) s << "W^2";
00405 else if (co.f() == -1) s << "-W^2";
00406 else if (co.f() != 0) s << co.f() << "W^2";
00407 return s << "=0 " << co.real_type() << "> ";
00408 }
00409
00410
00411 template <class T>
00412 vcl_istream& operator>>(vcl_istream& is, vgl_conic<T>& co)
00413 {
00414 T ta, tb, tc, td, te, tf; is >> ta >> tb >> tc >> td >> te >> tf;
00415 co.set(ta,tb,tc,td,te,tf); return is;
00416 }
00417
00418 #undef VGL_CONIC_INSTANTIATE
00419 #define VGL_CONIC_INSTANTIATE(T) \
00420 template class vgl_conic<T >; \
00421 template vcl_ostream& operator<<(vcl_ostream&, const vgl_conic<T >&); \
00422 template vcl_istream& operator>>(vcl_istream&, vgl_conic<T >&)
00423
00424 #endif // vgl_conic_txx_
00425