core/vgl/vgl_homg_line_2d.h
Go to the documentation of this file.
00001 // This is core/vgl/vgl_homg_line_2d.h
00002 #ifndef vgl_homg_line_2d_h
00003 #define  vgl_homg_line_2d_h
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief line in projective 2D space
00010 // \author Don Hamilton, Peter Tu
00011 //
00012 // \verbatim
00013 //  Modifications
00014 //   Peter Vanroose -  6 July 2001 - Added normal(), direction() and concurrent()
00015 //   Peter Vanroose -  4 July 2001 - Added assertions and cstr from non-homg line
00016 //   Peter Vanroose - 27 June 2001 - Added operator==
00017 // \endverbatim
00018 
00019 #include <vcl_iosfwd.h>
00020 #include <vgl/vgl_fwd.h> // forward declare vgl_homg_point_2d and vgl_line_2d
00021 #include <vcl_cassert.h>
00022 #include <vgl/vgl_vector_2d.h>
00023 
00024 //: Represents a homogeneous 2D line.
00025 template <class T>
00026 class vgl_homg_line_2d
00027 {
00028   //: the data associated with this line
00029   T a_;
00030   T b_;
00031   T c_;
00032 
00033  public:
00034 
00035   // Constructors/Initializers/Destructor------------------------------------
00036 
00037   //: Default constructor (Line 1.y==0, the X axis)
00038   inline vgl_homg_line_2d() : a_(0), b_(1), c_(0) {}
00039 
00040   //: Construct from three Types.
00041   //  The three given numbers should not be all 0
00042   inline vgl_homg_line_2d(T va, T vb, T vc) : a_(va), b_(vb), c_(vc) {assert(va||vb||vc);}
00043 
00044   //: Construct from 3-vector.
00045   //  The three given numbers should not be all 0
00046   inline vgl_homg_line_2d(const T v[3]) : a_(v[0]), b_(v[1]), c_(v[2]) {assert(a_||b_||c_);}
00047 
00048   //: Construct from non-homogeneous line
00049   vgl_homg_line_2d<T> (vgl_line_2d<T> const& p);
00050 
00051   //: Construct from two distinct points (join)
00052   //  The two points must be distinct!
00053   vgl_homg_line_2d(vgl_homg_point_2d<T> const& p1, vgl_homg_point_2d<T> const& p2);
00054 
00055 #if 0 // The defaults for these, as provided by the compiler, are all right:
00056   // Default copy constructor
00057   inline vgl_homg_line_2d(const vgl_homg_line_2d<T>& l) : a_(l.a()), b_(l.b()), c_(l.c()) {}
00058 
00059   // Default destructor
00060   inline ~vgl_homg_line_2d() {}
00061 
00062   // Default assignment operator
00063   inline vgl_homg_line_2d<T>& operator=(const vgl_homg_line_2d<T>& l) {
00064     set(l.a(),l.b(),l.c()); return *this;
00065   }
00066 #endif
00067 
00068   //: the comparison operator
00069   inline bool operator==(vgl_homg_line_2d<T> const& l) const
00070   {
00071     return (this==&l) ||
00072            (a()*l.c()==c()*l.a() && b()*l.c()==c()*l.b() && b()*l.a()==a()*l.b());
00073   }
00074 
00075   inline bool operator!=(vgl_homg_line_2d<T> const& other)const{return !operator==(other);}
00076 
00077   // Data Access-------------------------------------------------------------
00078 
00079   //: Parameter a of line a*x + b*y + c*w = 0
00080   inline T a() const {return a_;}
00081   //: Parameter b of line a*x + b*y + c*w = 0
00082   inline T b() const {return b_;}
00083   //: Parameter c of line a*x + b*y + c*w = 0
00084   inline T c() const {return c_;}
00085 
00086   //: unit vector describing line direction, or (0,0) if line at infinity
00087   inline vgl_vector_2d<double> direction() const { return normalized(vgl_vector_2d<double>(b_,-a_)); }
00088 
00089   //: unit vector orthogonal to line, or (0,0) if line at infinity
00090   inline vgl_vector_2d<double> normal() const { return normalized(vgl_vector_2d<double>(a_,b_)); }
00091 
00092   //: divide all coefficients by sqrt(a^2 + b^2)
00093   void normalize();
00094 
00095   //: Set a b c.
00096   //  The three given numbers should not be all 0
00097   //  Note that it does not make sense to set a, b or c separately
00098   inline void set(T va, T vb, T vc) {assert(va||vb||vc); a_=va; b_=vb; c_=vc;}
00099 
00100   //: Return true iff this line is the line at infinity
00101   //  This version checks (max(|a|,|b|) <= tol * |c|
00102   inline bool ideal(T tol = (T)0) const
00103   {
00104 #define vgl_Abs(x) (x<0?-x:x) // avoid #include of vcl_cmath.h AND vcl_cstdlib.h
00105     return vgl_Abs(a()) <= tol*vgl_Abs(c()) && vgl_Abs(b()) <= tol*vgl_Abs(c());
00106 #undef vgl_Abs
00107   }
00108 
00109   //:get two points on the line
00110   // These two points are normally the intersections
00111   // with the Y axis and X axis, respectively.  When the line is parallel to one
00112   // of these, the point with y=1 or x=1, resp. are taken.  When the line goes
00113   // through the origin, the second point is (b, -a, 1).  Finally, when the line
00114   // is the line at infinity, the returned points are (1,0,0) and (0,1,0).
00115   // Thus, whenever possible, the returned points are not at infinity.
00116   void get_two_points(vgl_homg_point_2d<T> &p1, vgl_homg_point_2d<T> &p2) const;
00117 };
00118 
00119 #define l vgl_homg_line_2d<T>
00120 
00121 //: Return true iff line is the line at infinity
00122 //  This version checks (max(|a|,|b|) <= tol * |c|
00123 // \relatesalso vgl_homg_line_2d
00124 template <class T>
00125 inline bool is_ideal(l const& line, T tol = (T)0) { return line.ideal(tol); }
00126 
00127 //: Are three lines concurrent, i.e., do they pass through a common point?
00128 // \relatesalso vgl_homg_line_2d
00129 template <class T>
00130 inline bool concurrent(l const& l1, l const& l2, l const& l3)
00131 {
00132   return l1.a()*(l2.b()*l3.c()-l3.b()*l2.c())
00133         +l2.a()*(l3.b()*l1.c()-l1.b()*l3.c())
00134         +l3.a()*(l1.b()*l2.c()-l2.b()*l1.c())==0;
00135 }
00136 
00137 //: Print line equation to stream
00138 // \relatesalso vgl_homg_line_2d
00139 template <class T>
00140 vcl_ostream& operator<<(vcl_ostream& s, l const& line);
00141 
00142 //: Load in line parameters from stream
00143 // \relatesalso vgl_homg_line_2d
00144 template <class T>
00145 vcl_istream& operator>>(vcl_istream& s, l& line);
00146 
00147 #undef l
00148 
00149 #define VGL_HOMG_LINE_2D_INSTANTIATE(T) extern "please include vgl/vgl_homg_line_2d.txx first"
00150 
00151 #endif //  vgl_homg_line_2d_h