core/vgl/vgl_point_2d.txx
Go to the documentation of this file.
00001 // This is core/vgl/vgl_point_2d.txx
00002 #ifndef vgl_point_2d_txx_
00003 #define vgl_point_2d_txx_
00004 //:
00005 // \file
00006 
00007 #include "vgl_point_2d.h"
00008 #include <vgl/vgl_homg_point_2d.h>
00009 #include <vgl/vgl_line_2d.h>
00010 #include <vgl/vgl_homg_line_2d.h>
00011 
00012 #include <vcl_iostream.h>
00013 #include <vcl_iomanip.h>
00014 
00015 //: Construct from homogeneous point
00016 template <class Type>
00017 vgl_point_2d<Type>::vgl_point_2d(vgl_homg_point_2d<Type> const& p)
00018   : x_(p.x()/p.w()), y_(p.y()/p.w()) // could be infinite!
00019 {
00020 }
00021 
00022 //: Construct from 2 lines (intersection).
00023 template <class Type>
00024 vgl_point_2d<Type>::vgl_point_2d(vgl_line_2d<Type> const& l1,
00025                                  vgl_line_2d<Type> const& l2)
00026 {
00027   vgl_homg_line_2d<Type> h1(l1.a(), l1.b(), l1.c());
00028   vgl_homg_line_2d<Type> h2(l2.a(), l2.b(), l2.c());
00029   vgl_homg_point_2d<Type> p(h1, h2); // do homogeneous intersection
00030   set(p.x()/p.w(), p.y()/p.w()); // could be infinite!
00031 }
00032 
00033 template <class T>
00034 double cross_ratio(vgl_point_2d<T>const& p1, vgl_point_2d<T>const& p2,
00035                    vgl_point_2d<T>const& p3, vgl_point_2d<T>const& p4)
00036 {
00037   // least squares solution: (Num_x-CR*Den_x)^2 + (Num_y-CR*Den_y)^2 minimal.
00038   double Num_x = (p1.x()-p3.x())*(p2.x()-p4.x());
00039   double Num_y = (p1.y()-p3.y())*(p2.y()-p4.y());
00040   double Den_x = (p1.x()-p4.x())*(p2.x()-p3.x());
00041   double Den_y = (p1.y()-p4.y())*(p2.y()-p3.y());
00042   if (Den_x == Den_y) return 0.5*(Num_x+Num_y)/Den_x;
00043   else return (Den_x*Num_x+Den_y*Num_y)/(Den_x*Den_x+Den_y*Den_y);
00044 }
00045 
00046 //: Write "<vgl_point_2d x,y> " to stream
00047 template <class Type>
00048 vcl_ostream&  operator<<(vcl_ostream& s, vgl_point_2d<Type> const& p)
00049 {
00050   return s << "<vgl_point_2d "<< p.x() << ',' << p.y() << "> ";
00051 }
00052 
00053 //: Read from stream, possibly with formatting
00054 //  Either just reads two blank-separated numbers,
00055 //  or reads two comma-separated numbers,
00056 //  or reads two numbers in parenthesized form "(123, 321)"
00057 template <class Type>
00058 vcl_istream& vgl_point_2d<Type>::read(vcl_istream& is)
00059 {
00060   if (! is.good()) return is; // (TODO: should throw an exception)
00061   bool paren = false;
00062   Type tx, ty;
00063   is >> vcl_ws; // jump over any leading whitespace
00064   if (is.eof()) return is; // nothing to be set because of EOF (TODO: should throw an exception)
00065   if (is.peek() == '(') { is.ignore(); paren=true; }
00066   is >> vcl_ws >> tx >> vcl_ws;
00067   if (is.eof()) return is;
00068   if (is.peek() == ',') is.ignore();
00069   is >> vcl_ws >> ty >> vcl_ws;
00070   if (paren) {
00071     if (is.eof()) return is;
00072     if (is.peek() == ')') is.ignore();
00073     else                  return is; // closing parenthesis is missing (TODO: throw an exception)
00074   }
00075   set(tx,ty);
00076   return is;
00077 }
00078 
00079 //: Read x y from stream
00080 template <class Type>
00081 vcl_istream&  operator>>(vcl_istream& is,  vgl_point_2d<Type>& p)
00082 {
00083   return p.read(is);
00084 }
00085 
00086 #undef VGL_POINT_2D_INSTANTIATE
00087 #define VGL_POINT_2D_INSTANTIATE(T) \
00088 template class vgl_point_2d<T >; \
00089 template double cross_ratio(vgl_point_2d<T >const&, vgl_point_2d<T >const&, \
00090                             vgl_point_2d<T >const&, vgl_point_2d<T >const&); \
00091 template vcl_ostream& operator<<(vcl_ostream&, const vgl_point_2d<T >&); \
00092 template vcl_istream& operator>>(vcl_istream&, vgl_point_2d<T >&)
00093 
00094 #endif // vgl_point_2d_txx_