contrib/gel/vsol/vsol_conic_2d.cxx

Go to the documentation of this file.
00001 // This is gel/vsol/vsol_conic_2d.cxx
00002 #include "vsol_conic_2d.h"
00003 //:
00004 // \file
00005 
00006 #include <vnl/vnl_math.h>
00007 #include <vbl/io/vbl_io_smart_ptr.h>
00008 #include <vsol/vsol_point_2d.h>
00009 #include <vgl/vgl_vector_2d.h>
00010 #include <vgl/vgl_homg_point_2d.h>
00011 #include <vgl/vgl_homg_line_2d.h>
00012 #include <vgl/io/vgl_io_conic.h>
00013 #include <vgl/algo/vgl_homg_operators_2d.h>
00014 #include <vcl_cmath.h> // for vcl_abs(double)
00015 #include <vcl_cassert.h>
00016 
00017 //---------------------------------------------------------------------------
00018 //: Are `x' and `y' almost equal ?
00019 //  The comparison uses an adaptive epsilon
00020 //---------------------------------------------------------------------------
00021 inline static bool are_equal(double x, double y)
00022 {
00023   // epsilon is a fixed fraction of the absolute average of x and y
00024   const double epsilon=1e-6*(vcl_abs(x)+vcl_abs(y));
00025   // <=epsilon but not <epsilon, to compare to null values
00026   return vcl_abs(x-y)<=epsilon;
00027 }
00028 
00029 //---------------------------------------------------------------------------
00030 //: Is `x' almost zero ?
00031 //  The comparison uses a fixed epsilon, as the adaptive one from
00032 //  are_equal() makes no sense here.
00033 //---------------------------------------------------------------------------
00034 inline static bool is_zero(double x) { return vcl_abs(x)<=1e-6; }
00035 
00036 //***************************************************************************
00037 // Initialization
00038 //***************************************************************************
00039 
00040 //---------------------------------------------------------------------------
00041 //: Ellipse/hyperbola constructor from centre, size and orientation.
00042 //  This constructor can only be used for non-degenerate, real ellipses and
00043 //  hyperbolas: if rx and ry have the same sign, an ellipse is defined
00044 //  (and any ellipse can uniquely be specified this way);
00045 //  rx is the length of one main axis, ry of the other axis.
00046 //  Hyperbolas are obtained if rx and ry have opposite sign; the positive
00047 //  one determines the distance from bots tops to the centre, and the other
00048 //  one specified the 'minor' axis length.
00049 //---------------------------------------------------------------------------
00050 vsol_conic_2d::vsol_conic_2d(vsol_point_2d const& c, double rx, double ry, double theta) :
00051   vsol_curve_2d(), vgl_conic<double>(vgl_homg_point_2d<double>(c.x(),c.y(),1.0), rx, ry, theta)
00052 {
00053 }
00054 
00055 //---------------------------------------------------------------------------
00056 //: Set ellipse/hyperbola from centre, size and orientation.
00057 //  Can only be used for non-degenerate, real ellipses and
00058 //  hyperbolas: if rx and ry have the same sign, an ellipse is defined
00059 //  (and any ellipse can uniquely be specified this way);
00060 //  rx is the length of one main axis, ry of the other axis.
00061 //  Hyperbolas are obtained if rx and ry have opposite sign; the positive
00062 //  one determines the distance from bots tops to the centre, and the other
00063 //  one specified the 'minor' axis length.
00064 //---------------------------------------------------------------------------
00065 void vsol_conic_2d::set_central_parameters(vsol_point_2d const& c, double rx, double ry, double theta)
00066 {
00067   vgl_conic<double> g(vgl_homg_point_2d<double>(c.x(),c.y(),1.0), rx, ry, theta);
00068   set(g.a(),g.b(),g.c(),g.d(),g.e(),g.f());
00069 }
00070 
00071 //---------------------------------------------------------------------------
00072 //: Parabola constructor from direction, top and excentricity parameter.
00073 //  This constructor can only be used for non-degenerate parabolas:
00074 //  specify the direction of the symmetry axis, the top, and an excentricity
00075 //  parameter theta.
00076 //---------------------------------------------------------------------------
00077 vsol_conic_2d::vsol_conic_2d(vgl_vector_2d<double> const& dir,
00078                              vsol_point_2d const& top, double theta) :
00079   vsol_curve_2d(), vgl_conic<double>(vgl_homg_point_2d<double>(dir.x(),dir.y(),0.0), top.x(), top.y(), theta)
00080 {
00081 }
00082 
00083 //---------------------------------------------------------------------------
00084 //: Set parabola from direction, top and excentricity parameter.
00085 //  This can only be used for non-degenerate parabolas:
00086 //  specify the direction of the symmetry axis, the top, and an excentricity
00087 //  parameter theta.
00088 //---------------------------------------------------------------------------
00089 void vsol_conic_2d::set_parabola_parameters(vgl_vector_2d<double> const& dir,
00090                                             vsol_point_2d const& top, double theta)
00091 {
00092   vgl_conic<double> g(vgl_homg_point_2d<double>(dir.x(),dir.y(),0.0), top.x(), top.y(), theta);
00093   set(g.a(),g.b(),g.c(),g.d(),g.e(),g.f());
00094 }
00095 
00096 //---------------------------------------------------------------------------
00097 //: Clone `this': creation of a new object and initialization
00098 // See Prototype pattern
00099 //---------------------------------------------------------------------------
00100 vsol_spatial_object_2d* vsol_conic_2d::clone() const
00101 {
00102   return new vsol_conic_2d(*this);
00103 }
00104 
00105 //***************************************************************************
00106 // Comparison
00107 //***************************************************************************
00108 
00109 //---------------------------------------------------------------------------
00110 //: Has `this' the same coefficients and (geometrical) end points than `other'?
00111 //  The test anticipates that the conic may have null endpoints
00112 //---------------------------------------------------------------------------
00113 bool vsol_conic_2d::operator==(vsol_conic_2d const& other) const
00114 {
00115   if (this==&other)
00116     return true;
00117   // Delegate to both parent classes:
00118   bool conic_eq = vgl_conic<double>::operator==(other);
00119   // Check endpoints
00120   bool epts_eq = vsol_curve_2d::endpoints_equal(other);
00121   return conic_eq&&epts_eq;
00122 }
00123 
00124 //: spatial object equality
00125 
00126 bool vsol_conic_2d::operator==(vsol_spatial_object_2d const& obj) const
00127 {
00128   return
00129     obj.cast_to_curve() && obj.cast_to_curve()->cast_to_conic() &&
00130     *this == *obj.cast_to_curve()->cast_to_conic();
00131 }
00132 
00133 //***************************************************************************
00134 // Status report
00135 //***************************************************************************
00136 
00137 //---------------------------------------------------------------------------
00138 //: Find the real type of the conic from its coefficients
00139 //---------------------------------------------------------------------------
00140 vsol_conic_2d::vsol_conic_type vsol_conic_2d::real_type() const
00141 {
00142   if (type() == vgl_conic<double>::real_circle)
00143     return real_circle;
00144   else if (type() == vgl_conic<double>::real_ellipse)
00145     return real_ellipse;
00146   else if (type() == vgl_conic<double>::imaginary_circle)
00147     return complex_circle;
00148   else if (type() == vgl_conic<double>::imaginary_ellipse)
00149     return complex_ellipse;
00150   else if (type() == vgl_conic<double>::hyperbola)
00151     return hyperbola;
00152   else if (type() == vgl_conic<double>::parabola)
00153     return parabola;
00154   else if (type() == vgl_conic<double>::real_intersecting_lines)
00155     return real_intersecting_lines;
00156   else if (type() == vgl_conic<double>::complex_intersecting_lines)
00157     return complex_intersecting_lines;
00158   else if (type() == vgl_conic<double>::coincident_lines)
00159     return coincident_lines;
00160   else if (type() == vgl_conic<double>::real_parallel_lines)
00161     return real_parallel_lines;
00162   else if (type() == vgl_conic<double>::complex_parallel_lines)
00163     return complex_parallel_lines;
00164   else return invalid; // 'degenerate' was is not a good name: some of the above are already degenerate!
00165 }
00166 
00167 //---------------------------------------------------------------------------
00168 //: Is `this' an real ellipse ?
00169 //---------------------------------------------------------------------------
00170 bool vsol_conic_2d::is_real_ellipse() const
00171 {
00172   vsol_conic_type tmp=real_type();
00173   return (tmp==real_ellipse)||(tmp==real_circle);
00174 }
00175 
00176 //---------------------------------------------------------------------------
00177 //: Is `this' a real circle ?
00178 //---------------------------------------------------------------------------
00179 bool vsol_conic_2d::is_real_circle() const
00180 {
00181   return real_type()==real_circle;
00182 }
00183 
00184 //---------------------------------------------------------------------------
00185 //: Is `this' a complex ellipse ?
00186 //---------------------------------------------------------------------------
00187 bool vsol_conic_2d::is_complex_ellipse() const
00188 {
00189   vsol_conic_type tmp=real_type();
00190   return (tmp==complex_ellipse)||(tmp==complex_circle);
00191 }
00192 
00193 //---------------------------------------------------------------------------
00194 //: Is `this' a complex circle ?
00195 //---------------------------------------------------------------------------
00196 bool vsol_conic_2d::is_complex_circle() const
00197 {
00198   return real_type()==complex_circle;
00199 }
00200 
00201 //---------------------------------------------------------------------------
00202 //: Is `this' a parabola ?
00203 //---------------------------------------------------------------------------
00204 bool vsol_conic_2d::is_parabola() const
00205 {
00206   return real_type()==parabola;
00207 }
00208 
00209 //---------------------------------------------------------------------------
00210 //: Is `this' a hyperbola ?
00211 //---------------------------------------------------------------------------
00212 bool vsol_conic_2d::is_hyperbola() const
00213 {
00214   return real_type()==hyperbola;
00215 }
00216 
00217 //---------------------------------------------------------------------------
00218 //: Is `this' an real intersecting lines ?
00219 //---------------------------------------------------------------------------
00220 bool vsol_conic_2d::is_real_intersecting_lines() const
00221 {
00222   return real_type()==real_intersecting_lines;
00223 }
00224 
00225 //---------------------------------------------------------------------------
00226 //: Is `this' an complex intersecting lines ?
00227 //---------------------------------------------------------------------------
00228 bool vsol_conic_2d::is_complex_intersecting_lines() const
00229 {
00230   return real_type()==complex_intersecting_lines;
00231 }
00232 
00233 //---------------------------------------------------------------------------
00234 //: Is `this' an coincident lines ?
00235 //---------------------------------------------------------------------------
00236 bool vsol_conic_2d::is_coincident_lines() const
00237 {
00238   return real_type()==coincident_lines;
00239 }
00240 
00241 //---------------------------------------------------------------------------
00242 //: Return 3 ellipse parameters: centre (`cx',`cy'), orientation `phi', size (`width',`height')
00243 // Require: is_real_ellipse()
00244 //---------------------------------------------------------------------------
00245 void vsol_conic_2d::ellipse_parameters(double &cx,
00246                                        double &cy,
00247                                        double &phi,
00248                                        double &width,
00249                                        double &height) const
00250 {
00251   // require
00252   assert(is_real_ellipse());
00253 
00254   const double b2=b()/2;
00255   const double d2=d()/2;
00256   const double e2=e()/2;
00257   const double det=a()*c()-b2*b2;
00258   if (is_zero(b2*b2/det)) // only for accuracy
00259   {
00260     cx=-d2/a();
00261     cy=-e2/c();
00262   }
00263   else
00264   {
00265     cx=(b2*e2-c()*d2)/det;
00266     cy=(b2*d2-a()*e2)/det;
00267   }
00268 
00269   double f0=a()*cx*cx+b()*cx*cy+c()*cy*cy+d()*cx+e()*cy+f();
00270 
00271   if (is_zero(f0)) // avoid dividing by zero
00272     f0=1;
00273   const double a0=-a()/f0;
00274   const double b0=-b2/f0;
00275   const double c0=-c()/f0;
00276 
00277   // Now rotate the ellipse such that the main axis is horizontal.
00278   if (are_equal(a0,c0)&&is_zero(b0))
00279     phi=0; // circle
00280   else
00281     phi=vcl_atan2(-2*b0,c0-a0)/2; //ellipse
00282 
00283   const double cosphi=vcl_cos(phi);
00284   const double sinphi=vcl_sin(phi);
00285   width =vcl_sqrt(1.0/(a0*cosphi*cosphi+2*b0*cosphi*sinphi+c0*sinphi*sinphi));
00286   height=vcl_sqrt(1.0/(a0*sinphi*sinphi-2*b0*cosphi*sinphi+c0*cosphi*cosphi));
00287 }
00288 //-----------------------------------------------------------------------
00289 // Return the angular position given a point on the ellipse
00290 double vsol_conic_2d::ellipse_angular_position(vsol_point_2d_sptr const& pt) const
00291 {
00292   // require
00293   assert(is_real_ellipse());
00294 
00295   // Find the closest point to pt on the ellipse
00296   vsol_point_2d_sptr closest = this->closest_point_on_curve(pt);
00297   assert(closest);
00298   double x = closest->x(), y = closest->y();
00299 
00300   // Extract the ellipse parameters
00301   double cx, cy, major_axis, minor_axis, angle;
00302   this->ellipse_parameters(cx, cy, angle, major_axis, minor_axis);
00303 
00304   x -= cx; y -= cy;
00305 
00306   //In this shifted frame:
00307   double phi =
00308     vcl_atan2(major_axis*(vcl_cos(angle)*y-vcl_sin(angle)*x),
00309               minor_axis*(vcl_cos(angle)*x + vcl_sin(angle)*y));
00310   if (phi<0.0)
00311     phi += 2.0*vnl_math::pi;
00312   return phi;
00313 }
00314 
00315 //---------------------------------------------------------------------------
00316 //: Return 3 hyperbola parameters: centre (`cx',`cy'), orientation `phi', size (`half-axis',`half-secondary-axis')
00317 // Require: is_hyperbola()
00318 //---------------------------------------------------------------------------
00319 void vsol_conic_2d::hyperbola_parameters(double &cx,
00320                                          double &cy,
00321                                          double &phi,
00322                                          double &width,
00323                                          double &height) const
00324 {
00325   // require
00326   assert(is_hyperbola());
00327 
00328   const double b2=b()/2;
00329   const double d2=d()/2;
00330   const double e2=e()/2;
00331   const double det=a()*c()-b2*b2;
00332 
00333   cx=(b2*e2-c()*d2)/det;
00334   cy=(b2*d2-a()*e2)/det;
00335 
00336   double f0=a()*cx*cx+b()*cx*cy+c()*cy*cy+d()*cx+e()*cy+f();
00337 
00338   if (is_zero(f0)) // this should not happen
00339     f0=1;
00340   const double a0=-a()/f0;
00341   const double b0=-b2/f0;
00342   const double c0=-c()/f0;
00343 
00344   // Now rotate the hyperbola such that the main axis is horizontal.
00345   if (is_zero(b0)) { // axis already horizontal or vertical
00346     if (a0 > 0) phi = 0;
00347     else        phi = vcl_atan2(0.0,1.0); // 90 degrees
00348   }
00349   else
00350     phi=vcl_atan2(2*b0,a0-c0)/2;
00351 
00352   const double cosphi=vcl_cos(phi);
00353   const double sinphi=vcl_sin(phi);
00354   width = vcl_sqrt( 1.0/(a0*cosphi*cosphi+2*b0*cosphi*sinphi+c0*sinphi*sinphi));
00355   height=-vcl_sqrt(-1.0/(a0*sinphi*sinphi-2*b0*cosphi*sinphi+c0*cosphi*cosphi));
00356 }
00357 
00358 //---------------------------------------------------------------------------
00359 //: Return 2 parabola parameters: top (`cx',`cy'), orientation (`cosphi',`sinphi')
00360 // Require: is_parabola()
00361 //---------------------------------------------------------------------------
00362 void vsol_conic_2d::parabola_parameters(double & /* cx */,
00363                                         double & /* cy */,
00364                                         double &cosphi,
00365                                         double &sinphi) const
00366 {
00367   // require
00368   assert(is_parabola());
00369 
00370   // Note that for a parabola B*B == 4*A*C, hence the quadratic part
00371   // of the equation is a square: (nX+mY)^2, with n=sqrt(A), m=sqrt(C)
00372   // Hence norm cannot be zero since the parabola is not degererate:
00373   const double norm=a()+c();
00374   // The parabola direction is then (-m,n):
00375   cosphi=-vcl_sqrt(c()/norm);
00376   sinphi=vcl_sqrt(a()/norm);
00377   // Finally, the top can be found as the point with tangent direction
00378   // orthogonal to the direction of the axis:
00379   // TODO
00380   vcl_cerr << "vsol_conic_2d::parabola_parameters() not yet fully implemented\n";
00381 }
00382 
00383 //---------------------------------------------------------------------------
00384 //: Return the length of `this'.
00385 // Currently only implemented for ellipse segment
00386 // and accurate to 0.001 of the major axis length.  Alternatively provide
00387 // code for the incomplete elliptic integral of the second kind. However,
00388 // that would be numerical integration anyway.
00389 //---------------------------------------------------------------------------
00390 double vsol_conic_2d::length() const
00391 {
00392   assert(is_real_ellipse());
00393     // compute the angle at p0
00394   vsol_point_2d_sptr p0 = this->p0();
00395  double start_angle = this->ellipse_angular_position(p0);
00396 
00397   // compute the angle at p1
00398   vsol_point_2d_sptr p1 = this->p1();
00399   double end_angle = this->ellipse_angular_position(p1);
00400   if (end_angle<=start_angle)
00401     end_angle += 2.0*vnl_math::pi;
00402 
00403   double xc, yc, angle, major_axis, minor_axis;
00404   this->ellipse_parameters(xc, yc, angle, major_axis, minor_axis);
00405   double dphi = 0.001;
00406   double sum = 0.0;
00407   //sum the arc length on the ellipse boundary
00408   for (double phi = start_angle; phi<=end_angle; phi+=dphi)
00409   {
00410     double temp1 =
00411       minor_axis*vcl_cos(angle)*vcl_cos(phi)+ major_axis*vcl_sin(angle)*vcl_sin(phi);
00412     double temp2 = major_axis*vcl_sin(angle+phi);
00413     //the incremental arc length
00414     double dl = vcl_sqrt(temp1*temp1 + temp2*temp2);
00415     sum += dl*dphi;
00416   }
00417   return sum;
00418 }
00419 
00420 //---------------------------------------------------------------------------
00421 //: Return the matrix associated with the coefficients.
00422 //---------------------------------------------------------------------------
00423 vnl_double_3x3 vsol_conic_2d::matrix() const
00424 {
00425   vnl_double_3x3 result;
00426 
00427   // row 0
00428   result.put(0,0,a());
00429   result.put(0,1,b()/2);
00430   result.put(0,2,d()/2);
00431   // row 1
00432   result.put(1,0,b()/2);
00433   result.put(1,1,c());
00434   result.put(1,2,e()/2);
00435   // row 2
00436   result.put(2,0,d()/2);
00437   result.put(2,1,e()/2);
00438   result.put(2,2,f());
00439 
00440   return result;
00441 }
00442 
00443 //***************************************************************************
00444 // Status setting
00445 //***************************************************************************
00446 
00447 //---------------------------------------------------------------------------
00448 //: Set the first point of the curve
00449 // Require: in(new_p0)
00450 //---------------------------------------------------------------------------
00451 void vsol_conic_2d::set_p0(vsol_point_2d_sptr const& new_p0)
00452 {
00453   // require
00454   assert(in(new_p0));
00455 
00456   p0_=new_p0;
00457 }
00458 
00459 //---------------------------------------------------------------------------
00460 //: Set the last point of the curve
00461 // Require: in(new_p1)
00462 //---------------------------------------------------------------------------
00463 void vsol_conic_2d::set_p1(vsol_point_2d_sptr const& new_p1)
00464 {
00465   // require
00466   assert(in(new_p1));
00467 
00468   p1_=new_p1;
00469 }
00470 
00471 //***************************************************************************
00472 // Basic operations
00473 //***************************************************************************
00474 
00475 //---------------------------------------------------------------------------
00476 //: Return the centre or symmetry point of a central conic.
00477 //---------------------------------------------------------------------------
00478 vsol_point_2d_sptr vsol_conic_2d::midpoint() const
00479 {
00480   vgl_homg_point_2d<double> p = this->centre();
00481   return new vsol_point_2d(p.x()/p.w(), p.y()/p.w());
00482 }
00483 
00484 //---------------------------------------------------------------------------
00485 //: Is `p' in `this' ? (ie `p' verifies the equation, within some margin)
00486 //---------------------------------------------------------------------------
00487 bool vsol_conic_2d::in(vsol_point_2d_sptr const& p) const
00488 {
00489   const double x=p->x();
00490   const double y=p->y();
00491   return is_zero(a()*x*x+b()*x*y+c()*y*y+d()*x+e()*y+f());
00492 }
00493 
00494 //---------------------------------------------------------------------------
00495 //: Return the tangent to the conic in the point p, if p is on the conic.
00496 //  In general, returns the polar line of the point w.r.t. the conic.
00497 //---------------------------------------------------------------------------
00498 vgl_homg_line_2d<double> *
00499 vsol_conic_2d::tangent_at_point(vsol_point_2d_sptr const& p) const
00500 {
00501   return new vgl_homg_line_2d<double>(
00502     vgl_conic<double>::tangent_at(vgl_homg_point_2d<double>(p->x(),p->y(),1.0)));
00503 }
00504 
00505 //---------------------------------------------------------------------------
00506 //: Return the set of (real) intersection points of this conic with a line
00507 //---------------------------------------------------------------------------
00508 vcl_list<vsol_point_2d_sptr>
00509 vsol_conic_2d::intersection(vsol_line_2d const& l) const
00510 {
00511   vgl_homg_point_2d<double> p0(l.p0()->x(), l.p0()->y(), 1.0),
00512                             p1(l.p1()->x(), l.p1()->y(), 1.0);
00513   vgl_homg_line_2d<double> line(p0,p1);
00514   vcl_list<vgl_homg_point_2d<double> > vv =
00515     vgl_homg_operators_2d<double>::intersection(*this,line);
00516   vcl_list<vsol_point_2d_sptr> v;
00517   vcl_list<vgl_homg_point_2d<double> >::iterator it = vv.begin();
00518   for (; !(it == vv.end()); ++it) {
00519     if ((*it).w() != 0)  v.push_back(new vsol_point_2d((*it)));
00520   }
00521   return v;
00522 }
00523 
00524 //---------------------------------------------------------------------------
00525 //: Return the set of (real) intersection points of two conics
00526 //---------------------------------------------------------------------------
00527 vcl_list<vsol_point_2d_sptr>
00528 vsol_conic_2d::intersection(vsol_conic_2d const& c) const
00529 {
00530   vcl_list<vgl_homg_point_2d<double> > vv =
00531     vgl_homg_operators_2d<double>::intersection(*this,c);
00532   vcl_list<vsol_point_2d_sptr> v;
00533   vcl_list<vgl_homg_point_2d<double> >::iterator it = vv.begin();
00534   for (; !(it == vv.end()); ++it) {
00535     if ((*it).w() != 0)  v.push_back(new vsol_point_2d((*it)));
00536   }
00537   return v;
00538 }
00539 
00540 //---------------------------------------------------------------------------
00541 //: Return the point on the conic boundary which is closest to the given point
00542 //---------------------------------------------------------------------------
00543 vsol_point_2d_sptr
00544 vsol_conic_2d::closest_point_on_curve(vsol_point_2d_sptr const& pt) const
00545 {
00546   //First check to see if the point is already on the conic boundary
00547   if (this->in(pt))
00548     return pt;
00549   // The nearest point must have a polar line which is orthogonal to its
00550   // connection line with the given point; all points with this property form
00551   // a certain conic  (actually a hyperbola) :
00552   vcl_list<vsol_point_2d_sptr> candidates; // all intersection points
00553   if (b()==0 && a()==c()) {
00554     // this ellipse is a circle ==> degenerate hyperbola (line + line at infinity)
00555     candidates = intersection(vsol_line_2d(midpoint(),pt));
00556   } else {
00557     // Non-degenerate hyperbola:
00558     vsol_conic_2d conic(b()/2,
00559                         c()-a(),
00560                         -b()/2,
00561                         a()*pt->y()-b()/2*pt->x()+e()/2,
00562                         b()/2*pt->y()-c()*pt->x()-d()/2,
00563                         d()/2*pt->y()-e()/2*pt->x());
00564     // Now it suffices to intersect the hyperbola with "this" ellipse:
00565     candidates = conic.intersection(*this);
00566   }
00567   // And find the intersection point closest to the given location:
00568   vsol_point_2d_sptr p = 0;
00569   double dist = 1e31; // infinity
00570   vcl_list<vsol_point_2d_sptr>::iterator it = candidates.begin();
00571   for (; it != candidates.end(); ++it) {
00572     double d = (*it)->distance(pt);
00573     if (d < dist) { p = (*it); dist = d; }
00574   }
00575   return p;
00576 }
00577 
00578 //---------------------------------------------------------------------------
00579 //: Return the shortest distance of the point to the conic boundary
00580 //---------------------------------------------------------------------------
00581 double vsol_conic_2d::distance(vsol_point_2d_sptr const& pt) const
00582 {
00583   vsol_point_2d_sptr p = closest_point_on_curve(pt);
00584   return p->distance(pt);
00585 }
00586 
00587 //---------------------------------------------------------------------------
00588 //: Return the main symmetry axis, if not degenerate.
00589 //---------------------------------------------------------------------------
00590 vsol_line_2d_sptr vsol_conic_2d::axis() const
00591 {
00592   double cx, cy, phi, wd, ht;
00593   if (this->is_real_ellipse()) {
00594     this->ellipse_parameters(cx, cy, phi, wd, ht);
00595     vgl_vector_2d<double> v(vcl_cos(phi),vcl_sin(phi));
00596     return new vsol_line_2d(v,midpoint());
00597   }
00598   else if (this->is_hyperbola()) {
00599     this->hyperbola_parameters(cx, cy, phi, wd, ht);
00600     vgl_vector_2d<double> v(vcl_cos(phi),vcl_sin(phi));
00601     return new vsol_line_2d(v,midpoint());
00602   }
00603   else if (this->is_parabola()) {
00604     this->parabola_parameters(cx, cy, wd, ht);
00605     vgl_vector_2d<double> v(wd,ht);
00606     return new vsol_line_2d(v,new vsol_point_2d(cx,cy));
00607   }
00608   else return 0;
00609 }
00610 
00611 //----------------------------------------------------------------
00612 // ================   Binary I/O Methods ========================
00613 //----------------------------------------------------------------
00614 
00615 //: Binary save self to stream.
00616 void vsol_conic_2d::b_write(vsl_b_ostream &os) const
00617 {
00618   vsl_b_write(os, version());
00619   vsl_b_write(os, static_cast<vgl_conic<double> >(*this));
00620   vsl_b_write(os, p0_);
00621   vsl_b_write(os, p1_);
00622 }
00623 
00624 //: Binary load self from stream (not typically used)
00625 void vsol_conic_2d::b_read(vsl_b_istream &is)
00626 {
00627   if (!is)
00628     return;
00629   short ver;
00630   vsl_b_read(is, ver);
00631   switch (ver)
00632   {
00633    default:
00634     assert(!"vsol_conic I/O version should be 1");
00635    case 1:
00636     vgl_conic<double> q;
00637     vsl_b_read(is, q);
00638     vsl_b_read(is, p0_);
00639     vsl_b_read(is, p1_);
00640     this->set(q.a(), q.b(), q.c(), q.d(), q.e(), q.f());
00641   }
00642 }
00643 
00644 //: Return IO version number;
00645 short vsol_conic_2d::version() const
00646 {
00647   return 1;
00648 }
00649 
00650 //: Print an ascii summary to the stream
00651 void vsol_conic_2d::print_summary(vcl_ostream &os) const
00652 {
00653   os << *this;
00654 }
00655 
00656 //external functions
00657 
00658 //: Binary save vsol_conic_2d* to stream.
00659 void
00660 vsl_b_write(vsl_b_ostream &os, const vsol_conic_2d* c)
00661 {
00662   if (!c){
00663     vsl_b_write(os, false); // Indicate null conic stored
00664   }
00665   else{
00666     vsl_b_write(os,true); // Indicate non-null conic stored
00667     c->b_write(os);
00668   }
00669 }
00670 
00671 //: Binary load vsol_conic_2d* from stream.
00672 void
00673 vsl_b_read(vsl_b_istream &is, vsol_conic_2d* &c)
00674 {
00675   delete c;
00676   bool not_null_ptr;
00677   vsl_b_read(is, not_null_ptr);
00678   if (not_null_ptr) {
00679     c = new vsol_conic_2d();
00680     c->b_read(is);
00681   }
00682   else
00683     c = 0;
00684 }
00685 

Generated on Mon Oct 6 05:14:43 2008 for contrib/gel/vsol by  doxygen 1.5.1