core/vgl/vgl_homg_point_1d.h
Go to the documentation of this file.
00001 // This is core/vgl/vgl_homg_point_1d.h
00002 #ifndef vgl_homg_point_1d_h_
00003 #define vgl_homg_point_1d_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief a point in homogeneous 1-D space, i.e., a homogeneous pair \a (x,w)
00010 // \author Peter Vanroose
00011 // \date   8 July 2001
00012 //
00013 // \verbatim
00014 // Modifications
00015 // \endverbatim
00016 
00017 #include <vcl_iosfwd.h>
00018 #include <vcl_cassert.h>
00019 #include <vcl_vector.h>
00020 
00021 //: Represents a homogeneous 1-D point, i.e., a homogeneous pair \a (x,w)
00022 template <class T>
00023 class vgl_homg_point_1d
00024 {
00025   T x_;
00026   T w_;
00027 
00028  public:
00029   //: Default constructor with (0,1)
00030   inline vgl_homg_point_1d() : x_(0), w_(T(1)) {}
00031 
00032   //: Construct from one (nonhomogeneous) or two (homogeneous) T's.
00033   inline vgl_homg_point_1d(T px, T pw = T(1)) : x_(px), w_(pw) {}
00034 
00035   //: Construct from homogeneous 2-array.
00036   inline vgl_homg_point_1d(const T v[2]) : x_(v[0]), w_(v[1]) {}
00037 
00038 #if 0 // the compiler defaults are better...
00039   // Default copy constructor
00040   inline vgl_homg_point_1d(const vgl_homg_point_1d<T>& that) : x_(p.x()), w_(p.w()) {}
00041 
00042   // Destructor
00043   inline ~vgl_homg_point_1d() {}
00044 
00045   // Default assignment operator
00046   inline vgl_homg_point_1d<T>& operator=(const vgl_homg_point_1d<T>& p) {
00047     set(p.x(),p.w()); return *this; }
00048 #endif
00049 
00050   //: comparison
00051   inline bool operator==(vgl_homg_point_1d<T> const& p) const {
00052     return this==&p || x()*p.w() == w()*p.x(); }
00053   inline bool operator!=(vgl_homg_point_1d<T> const& p)const { return !operator==(p); }
00054 
00055   // Data Access-------------------------------------------------------------
00056 
00057   inline T x() const { return x_; }
00058   inline T w() const { return w_; }
00059 
00060   //: Set \a x,w
00061   // Note that it does not make sense to set \a x or \a w individually.
00062   inline void set(T px, T pw) { x_ = px, w_ = pw; }
00063   inline void set(T const p[2]) { x_ = p[0]; w_ = p[1]; }
00064 
00065   //: Return true iff the point is at infinity (an ideal point).
00066   // The method checks whether |w| <= tol * |x|
00067   inline bool ideal(T tol = T(0)) const {
00068 #define vgl_Abs(x) (x<0?-x:x) // avoid #include of vcl_cmath.h AND vcl_cstdlib.h
00069     return vgl_Abs(w()) <= tol * vgl_Abs(x());
00070 #undef vgl_Abs
00071   }
00072 };
00073 
00074 //  +-+-+ point_1d simple I/O +-+-+
00075 
00076 //: Write "<vgl_homg_point_1d (x,w) > " to stream
00077 // \relatesalso vgl_homg_point_1d
00078 template <class T>
00079 vcl_ostream& operator<<(vcl_ostream& s, vgl_homg_point_1d<T> const& p);
00080 
00081 //: Read x w from stream
00082 // \relatesalso vgl_homg_point_1d
00083 template <class T>
00084 vcl_istream& operator>>(vcl_istream& s, vgl_homg_point_1d<T>& p);
00085 
00086 //  +-+-+ homg_point_1d arithmetic +-+-+
00087 
00088 //: Return true iff the point is at infinity (an ideal point).
00089 // The method checks whether |w| <= tol * |x|
00090 // \relatesalso vgl_homg_point_1d
00091 template <class T> inline
00092 bool is_ideal(vgl_homg_point_1d<T> const& p, T tol = T(0)) { return p.ideal(tol); }
00093 
00094 //: The difference of two points is the distance between the two.
00095 // This function is only valid if the points are not at infinity.
00096 // \relatesalso vgl_homg_point_1d
00097 template <class T> inline
00098 T operator-(vgl_homg_point_1d<T> const& p1,
00099             vgl_homg_point_1d<T> const& p2) {
00100   assert(p1.w() && p2.w());
00101   return p1.x()/p1.w()-p2.x()/p2.w();
00102 }
00103 
00104 //: Adding a number to a 1-D point translates that point.
00105 // If the point is at infinity, nothing happens.
00106 // Note that number + point is not defined!  It's always point + number.
00107 // \relatesalso vgl_homg_point_1d
00108 template <class T> inline
00109 vgl_homg_point_1d<T> operator+(vgl_homg_point_1d<T> const& p, T v)
00110 { return vgl_homg_point_1d<T>(p.x()+v*p.w(), p.w()); }
00111 
00112 //: Adding a number to a 1-D point translates that point.
00113 // If the point is at infinity, nothing happens.
00114 // \relatesalso vgl_homg_point_1d
00115 template <class T> inline
00116 vgl_homg_point_1d<T>& operator+=(vgl_homg_point_1d<T>& p, T v)
00117 { p.set(p.x()+v*p.w(), p.w()); return p; }
00118 
00119 //: Subtracting a number from a point is the same as adding the inverse number
00120 // \relatesalso vgl_homg_point_1d
00121 template <class T> inline
00122 vgl_homg_point_1d<T> operator-(vgl_homg_point_1d<T> const& p, T v)
00123 { return p + (-v); }
00124 
00125 //: Subtracting a number from a point is the same as adding the inverse number
00126 // \relatesalso vgl_homg_point_1d
00127 template <class T> inline
00128 vgl_homg_point_1d<T>& operator-=(vgl_homg_point_1d<T>& p, T v)
00129 { return p += (-v); }
00130 
00131 //  +-+-+ homg_point_1d geometry +-+-+
00132 
00133 //: cross ratio of four points
00134 // This number is projectively invariant, and it is the coordinate of p4
00135 // in the reference frame where p2 is the origin (coordinate 0), p3 is
00136 // the unity (coordinate 1) and p1 is the point at infinity.
00137 // This cross ratio is often denoted as ((p1, p2; p3, p4)) (which also
00138 // equals ((p3, p4; p1, p2)) or ((p2, p1; p4, p3)) or ((p4, p3; p2, p1)) )
00139 // and is calculated as
00140 //  \verbatim
00141 //                      p1 - p3   p2 - p3      (p1-p3)(p2-p4)
00142 //                      ------- : --------  =  --------------
00143 //                      p1 - p4   p2 - p4      (p1-p4)(p2-p3)
00144 // \endverbatim
00145 // If three of the given points coincide, the cross ratio is not defined.
00146 // \relatesalso vgl_homg_point_1d
00147 
00148 template <class T> inline
00149 double cross_ratio(vgl_homg_point_1d<T>const& p1, vgl_homg_point_1d<T>const& p2,
00150                    vgl_homg_point_1d<T>const& p3, vgl_homg_point_1d<T>const& p4)
00151 { return (p1.x()*p3.w()-p3.x()*p1.w())*(p2.x()*p4.w()-p4.x()*p2.w())
00152        /((p1.x()*p4.w()-p4.x()*p1.w())*(p2.x()*p3.w()-p3.x()*p2.w())); }
00153 
00154 //: Return the relative distance to p1 wrt p1-p2 of p3.
00155 //  p2 should not equal p1.
00156 //  This is the coordinate of p3 in the affine 1D reference frame (p1,p2).
00157 //  If p3=p1, the ratio is 0; if p1=p3, the ratio is 1.
00158 //  The mid point of p1 and p2 has ratio 0.5.
00159 //  Note that the return type is double, not T, since the ratio of e.g.
00160 //  two int's need not be an int.
00161 // \relatesalso vgl_homg_point_1d
00162 template <class T> inline
00163 double ratio(vgl_homg_point_1d<T> const& p1,
00164              vgl_homg_point_1d<T> const& p2,
00165              vgl_homg_point_1d<T> const& p3)
00166 { return (p3-p1)/(p2-p1); }
00167 
00168 //: Are three points collinear?  This is always true.
00169 // \relatesalso vgl_homg_point_1d
00170 template <class T> inline
00171 bool collinear(vgl_homg_point_1d<T> const&,
00172                vgl_homg_point_1d<T> const&,
00173                vgl_homg_point_1d<T> const&)
00174 { return true; }
00175 
00176 //: Return the point at a given ratio wrt two other points.
00177 //  By default, the mid point (ratio=0.5) is returned.
00178 //  Note that the third argument is T, not double, so the midpoint of e.g.
00179 //  two vgl_homg_point_1d<int> is not a valid concept.  But the reflection point
00180 //  of p2 wrt p1 is: in that case f=-1.
00181 // \relatesalso vgl_homg_point_1d
00182 template <class T> inline
00183 vgl_homg_point_1d<T> midpoint(vgl_homg_point_1d<T> const& p1,
00184                               vgl_homg_point_1d<T> const& p2,
00185                               T f = 0.5)
00186 { return p1 + f*(p2-p1); }
00187 
00188 //: Return the point at the centre of gravity of two given points.
00189 // Identical to midpoint(p1,p2).
00190 // If one point or both points are at infinity, that point is returned.
00191 // \relatesalso vgl_homg_point_1d
00192 template <class T> inline
00193 vgl_homg_point_1d<T> centre(vgl_homg_point_1d<T> const& p1,
00194                             vgl_homg_point_1d<T> const& p2)
00195 {
00196   if (p1 == p2) return p1;
00197   return vgl_homg_point_1d<T> (p1.x()*p2.w() + p2.x()*p1.w(), p1.w()*p2.w()*2);
00198 }
00199 
00200 //: Return the point at the centre of gravity of a set of given points.
00201 // There are no rounding errors when T is e.g. int, if all w() are 1.
00202 // \relatesalso vgl_homg_point_1d
00203 template <class T> inline
00204 vgl_homg_point_1d<T> centre(vcl_vector<vgl_homg_point_1d<T> > const& v)
00205 {
00206   int n=v.size();
00207   assert(n>0); // it is *not* correct to return the point (0,1) when n==0.
00208   T x = 0;
00209   for (int i=0; i<n; ++i) x+=v[i].x()/v[i].w();
00210   return vgl_homg_point_1d<T>(x,T(n));
00211 }
00212 
00213 #define VGL_HOMG_POINT_1D_INSTANTIATE(T) extern "please include vgl/vgl_homg_point_1d.txx first"
00214 
00215 #endif // vgl_homg_point_1d_h_