contrib/gel/vsol/vsol_line_2d.cxx
Go to the documentation of this file.
00001 // This is gel/vsol/vsol_line_2d.cxx
00002 #include "vsol_line_2d.h"
00003 //:
00004 // \file
00005 #include <vcl_cassert.h>
00006 #include <vcl_cmath.h>
00007 #include <vcl_iostream.h>
00008 #include <vnl/vnl_math.h>
00009 #include <vbl/io/vbl_io_smart_ptr.h>
00010 #include <vsol/vsol_point_2d.h>
00011 #include <vgl/vgl_homg_point_2d.h>
00012 #include <vgl/vgl_vector_2d.h>
00013 #include <vgl/vgl_homg_line_2d.h>
00014 #include <vgl/vgl_line_segment_2d.h>
00015 #include <vgl/vgl_point_2d.h>
00016 
00017 //***************************************************************************
00018 // Initialization
00019 //***************************************************************************
00020 
00021 //---------------------------------------------------------------------------
00022 //: Default Constructor
00023 //---------------------------------------------------------------------------
00024 vsol_line_2d::vsol_line_2d()
00025 : vsol_curve_2d(),
00026   p0_(new vsol_point_2d),
00027   p1_(new vsol_point_2d)
00028 {
00029 }
00030 
00031 //---------------------------------------------------------------------------
00032 //: Constructor from the direction and the middle point
00033 //---------------------------------------------------------------------------
00034 vsol_line_2d::vsol_line_2d(vgl_vector_2d<double> const& new_direction,
00035                            const vsol_point_2d_sptr &new_middle)
00036 : vsol_curve_2d(),
00037   p0_(new vsol_point_2d(*(new_middle->plus_vector(-(new_direction)/2)))),
00038   p1_(new vsol_point_2d(*(new_middle->plus_vector((new_direction)/2))))
00039 {
00040 }
00041 
00042 //---------------------------------------------------------------------------
00043 //: Constructor from the direction and the middle point
00044 //---------------------------------------------------------------------------
00045 vsol_line_2d::vsol_line_2d(vgl_vector_2d<double> const& new_direction,
00046                            const vgl_point_2d<double> &new_middle)
00047 : vsol_curve_2d(),
00048   p0_(new vsol_point_2d(*(vsol_point_2d(new_middle).plus_vector(-(new_direction)/2)))),
00049   p1_(new vsol_point_2d(*(vsol_point_2d(new_middle).plus_vector((new_direction)/2))))
00050 {
00051 }
00052 
00053 //---------------------------------------------------------------------------
00054 //: Constructor from two vgl_point_2d (end points)
00055 //---------------------------------------------------------------------------
00056 vsol_line_2d::vsol_line_2d(vgl_point_2d<double> const& p0,
00057                            vgl_point_2d<double> const& p1)
00058 : vsol_curve_2d(),
00059   p0_(new vsol_point_2d(p0)),
00060   p1_(new vsol_point_2d(p1))
00061 {
00062 }
00063 
00064 //---------------------------------------------------------------------------
00065 //: Constructor
00066 //---------------------------------------------------------------------------
00067 vsol_line_2d::vsol_line_2d(vgl_line_segment_2d<double> const& l)
00068 : vsol_curve_2d(),
00069   p0_(new vsol_point_2d(l.point1())),
00070   p1_(new vsol_point_2d(l.point2()))
00071 {
00072 }
00073 
00074 //---------------------------------------------------------------------------
00075 //: Clone `this': creation of a new object and initialization
00076 //  See Prototype pattern
00077 //---------------------------------------------------------------------------
00078 vsol_spatial_object_2d* vsol_line_2d::clone() const
00079 {
00080   return new vsol_line_2d(*this);
00081 }
00082 
00083 //***************************************************************************
00084 // Access
00085 //***************************************************************************
00086 
00087 //---------------------------------------------------------------------------
00088 //: Middle point of the straight line segment
00089 //---------------------------------------------------------------------------
00090 vsol_point_2d_sptr vsol_line_2d::middle() const
00091 {
00092   return p0_->middle(*p1_);
00093 }
00094 
00095 //---------------------------------------------------------------------------
00096 //: direction of the straight line segment.
00097 //---------------------------------------------------------------------------
00098 vgl_vector_2d<double> vsol_line_2d::direction() const
00099 {
00100   return p0_->to_vector(*p1_);
00101 }
00102 
00103 //***************************************************************************
00104 // Comparison
00105 //***************************************************************************
00106 
00107 //---------------------------------------------------------------------------
00108 //: Has `this' the same points than `other' ?
00109 //---------------------------------------------------------------------------
00110 bool vsol_line_2d::operator==(vsol_line_2d const& other) const
00111 {
00112   if (this==&other)
00113     return true;
00114   return vsol_curve_2d::endpoints_equal(other);
00115 }
00116 
00117 //: spatial object equality
00118 
00119 bool vsol_line_2d::operator==(vsol_spatial_object_2d const& obj) const
00120 {
00121   return
00122     obj.cast_to_curve() && obj.cast_to_curve()->cast_to_line() &&
00123     *this == *obj.cast_to_curve()->cast_to_line();
00124 }
00125 
00126 //***************************************************************************
00127 // Status report
00128 //***************************************************************************
00129 
00130 //---------------------------------------------------------------------------
00131 //: Compute the bounding box of `this'
00132 //---------------------------------------------------------------------------
00133 void vsol_line_2d::compute_bounding_box() const
00134 {
00135   set_bounding_box(   p0_->x(), p0_->y());
00136   add_to_bounding_box(p1_->x(), p1_->y());
00137 }
00138 
00139 //---------------------------------------------------------------------------
00140 //: Return the length of `this'
00141 //---------------------------------------------------------------------------
00142 double vsol_line_2d::length() const
00143 {
00144   return p0_->distance(p1_);
00145 }
00146 
00147 //---------------------------------------------------------------------------
00148 //: Return the tangent angle in degrees  of `this'.
00149 //  By convention, the angle is in degrees and lies in the interval [0, 360].
00150 //---------------------------------------------------------------------------
00151 double vsol_line_2d::tangent_angle() const
00152 {
00153   static const double deg_per_rad = vnl_math::deg_per_rad;
00154   double dy = p1_->y()-p0_->y();
00155   double dx = p1_->x()-p0_->x();
00156 
00157   double ang;
00158   // do special cases separately, to avoid rounding errors:
00159   if      (dx == 0)  ang = dy<0 ? 270.0 : 90.0; // vertical line
00160   else if (dy == 0)  ang = dx<0 ? 180.0 :  0.0; // horizontal line
00161   else if (dy == dx) ang = dy<0 ? 225.0 : 45.0;
00162   else if (dy+dx==0) ang = dy<0 ? 315.0 :135.0;
00163   // the general case:
00164   else               ang = deg_per_rad * vcl_atan2(dy,dx);
00165   if (ang<0) ang+= 360.0;
00166   return ang;
00167 }
00168 
00169 //***************************************************************************
00170 // Status setting
00171 //***************************************************************************
00172 
00173 //---------------------------------------------------------------------------
00174 //: Set the first point of the straight line segment
00175 //---------------------------------------------------------------------------
00176 void vsol_line_2d::set_p0(vsol_point_2d_sptr const& new_p0)
00177 {
00178   p0_=new_p0;
00179 }
00180 
00181 //---------------------------------------------------------------------------
00182 //: Set the last point of the straight line segment
00183 //---------------------------------------------------------------------------
00184 void vsol_line_2d::set_p1(vsol_point_2d_sptr const& new_p1)
00185 {
00186   p1_=new_p1;
00187 }
00188 
00189 //---------------------------------------------------------------------------
00190 //: Set the length of `this'. Doesn't change middle point and orientation.
00191 //    If p0 and p1 are equal then the direction is set to (1,0)
00192 // Require: new_length>=0
00193 //---------------------------------------------------------------------------
00194 void vsol_line_2d::set_length(const double new_length)
00195 {
00196   // require
00197   assert(new_length>=0);
00198 
00199   vsol_point_2d_sptr m=middle();
00200   vgl_vector_2d<double> d =
00201     (*p0_)==(*p1_) ? vgl_vector_2d<double>(1.0,0.0)
00202                    : normalized(direction());
00203   d *= new_length;
00204 
00205   p0_=new vsol_point_2d(*(m->plus_vector(-d/2)));
00206   p1_=new vsol_point_2d(*(m->plus_vector(d/2)));
00207 }
00208 
00209 //***************************************************************************
00210 // Basic operations
00211 //***************************************************************************
00212 
00213 //---------------------------------------------------------------------------
00214 //: Is `p' in `this' ?
00215 //---------------------------------------------------------------------------
00216 bool vsol_line_2d::in(vsol_point_2d_sptr const& p) const
00217 {
00218   // `p' belongs to the straight line
00219   bool result=(p0_->y()-p1_->y())*p->x()+(p1_->x()-p0_->x())*p->y()
00220               +p0_->x()*p1_->y()         -p0_->y()*p1_->x()        ==0;
00221 
00222   if (result) // `p' belongs to the segment
00223   {
00224     double dot_product=(p->x()-p0_->x())*(p1_->x()-p0_->x())
00225                       +(p->y()-p0_->y())*(p1_->y()-p0_->y());
00226     result=(dot_product>=0)&&
00227            (dot_product<(vnl_math::sqr(p1_->x()-p0_->x())
00228                         +vnl_math::sqr(p1_->y()-p0_->y())));
00229   }
00230   return result;
00231 }
00232 
00233 //---------------------------------------------------------------------------
00234 //: Return the tangent to `this' at `p'.  Has to be deleted manually
00235 // Require: in(p)
00236 //---------------------------------------------------------------------------
00237 vgl_homg_line_2d<double> *
00238 vsol_line_2d::tangent_at_point(vsol_point_2d_sptr const& p) const
00239 {
00240   // require
00241   assert(in(p));
00242 
00243   return new vgl_homg_line_2d<double>(p0_->y()-p1_->y(),p1_->x()-p0_->x(),
00244                                       p0_->x()*p1_->y()-p0_->y()*p1_->x());
00245 }
00246 
00247 //--------------------------------------------------------------------
00248 //: compute an infinite homogeneous line corresponding to *this
00249 //--------------------------------------------------------------------
00250 vgl_homg_line_2d<double> vsol_line_2d::vgl_hline_2d() const
00251 {
00252   vgl_homg_point_2d<double> vp0(p0_->x(), p0_->y());
00253   vgl_homg_point_2d<double> vp1(p1_->x(), p1_->y());
00254   vgl_homg_line_2d<double> l(vp0, vp1);
00255   return l;
00256 }
00257 
00258 //--------------------------------------------------------------------
00259 //: compute a vgl line segment corresponding to *this
00260 //--------------------------------------------------------------------
00261 vgl_line_segment_2d<double> vsol_line_2d::vgl_seg_2d() const
00262 {
00263   vgl_homg_point_2d<double> vp0(p0_->x(), p0_->y());
00264   vgl_homg_point_2d<double> vp1(p1_->x(), p1_->y());
00265   vgl_line_segment_2d<double> l(vp0, vp1);
00266   return l;
00267 }
00268 
00269 
00270 //----------------------------------------------------------------
00271 // ================   Binary I/O Methods ========================
00272 //----------------------------------------------------------------
00273 
00274 //: Binary save self to stream.
00275 void vsol_line_2d::b_write(vsl_b_ostream &os) const
00276 {
00277   vsl_b_write(os, version());
00278   vsol_spatial_object_2d::b_write(os);
00279   vsl_b_write(os, p0_);
00280   vsl_b_write(os, p1_);
00281 }
00282 
00283 //: Binary load self from stream. (not typically used)
00284 void vsol_line_2d::b_read(vsl_b_istream &is)
00285 {
00286   if (!is)
00287     return;
00288   short ver;
00289   vsl_b_read(is, ver);
00290   switch (ver)
00291   {
00292    case 1:
00293     vsol_spatial_object_2d::b_read(is);
00294     vsl_b_read(is, p0_);
00295     vsl_b_read(is, p1_);
00296     break;
00297    default:
00298     vcl_cerr << "vsol_line_2d: unknown I/O version " << ver << '\n';
00299   }
00300 }
00301 //: Return IO version number;
00302 short vsol_line_2d::version() const
00303 {
00304   return 1;
00305 }
00306 
00307 //: Print an ascii summary to the stream
00308 void vsol_line_2d::print_summary(vcl_ostream &os) const
00309 {
00310   os << *this;
00311 }
00312 
00313 //: Binary save vsol_line_2d to stream.
00314 void
00315 vsl_b_write(vsl_b_ostream &os, const vsol_line_2d* p)
00316 {
00317   if (p==0) {
00318     vsl_b_write(os, false); // Indicate null pointer stored
00319   }
00320   else{
00321     vsl_b_write(os,true); // Indicate non-null pointer stored
00322     p->b_write(os);
00323   }
00324 }
00325 
00326 
00327 //: Binary load vsol_line_2d from stream.
00328 void
00329 vsl_b_read(vsl_b_istream &is, vsol_line_2d* &p)
00330 {
00331   delete p;
00332   bool not_null_ptr;
00333   vsl_b_read(is, not_null_ptr);
00334   if (not_null_ptr) {
00335     p = new vsol_line_2d();
00336     p->b_read(is);
00337   }
00338   else
00339     p = 0;
00340 }
00341 
00342 void vsol_line_2d::describe(vcl_ostream &strm, int blanking) const
00343 {
00344   if (blanking < 0) blanking = 0; while (blanking--) strm << ' ';
00345   strm << '[' << *(p0()) << ' ' << *(p1()) << ']' << vcl_endl;
00346 }