Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

line.H

Go to the documentation of this file.
00001 #ifndef LINE_H_IS_INCLUDED
00002 #define LINE_H_IS_INCLUDED
00003 
00004 /*!
00005  *  \file Line.H
00006  *  \brief Contains the definition of the Line class.
00007  *  \ingroup group_MLIB
00008  *
00009  */
00010 
00011 #include "mlib/global.H"
00012 
00013 namespace mlib {
00014 
00015 /*!
00016  *  \brief Templated class defining an oriented line and/or a line segment.
00017  *  \ingroup group_MLIB
00018  *
00019  *  The Line class keeps a point and a vector. For the Line object to be valid,
00020  *  the vector must not be null.
00021  *  
00022  *  The Line class is designed to be the base class of more specific types of
00023  *  lines.  Specifically, lines in different coordinate systems with different
00024  *  numbers of dimensions.  The template argument L is the type of the derived
00025  *  line class.  This allows Line to return new lines of the same type as the
00026  *  derived class.  The template arguments P and V are the types of the
00027  *  corresponding point and vector classes (respectively) for the coordinate
00028  *  system and number of dimensions of the derived line class.
00029  *
00030  */
00031    template <class L, class P, class V>
00032    class Line {
00033    
00034     public:
00035    
00036       //! \name Constructors
00037       //@{
00038          
00039       //! \brief Default constructor.  Creates a line with the results of the
00040       //! default constructors for the point and vector classes used.
00041       //!
00042       //! This most likely creates an invalid line (i.e. has a zero length 
00043       //! vector) at the origin.
00044       Line()                                                       {}
00045       
00046       //! \brief Constructor that creates a line containing the point \p p and
00047       //! moving along the direction of vector \p v.  Alternately creates a line
00048       //! segment with \p p as one endpoint and ( \p p + \p v ) as the other
00049       //! endpoint.
00050       Line(const P&  p, const V& v)  : _point ( p), _vector(v)     {}
00051       
00052       //! \brief Constructor that creates the line going through points \p p1
00053       //! and \p p2.  Alternately creates a line segment with endpoints \p p1
00054       //! and \p p2.
00055       Line(const P& p1, const P& p2) : _point (p1), _vector(p2-p1) {}
00056       
00057       //@}
00058    
00059       //! \name Accessor Functions
00060       //@{
00061          
00062       const P& point ()               const  { return _point; }
00063       P&       point ()                      { return _point; }
00064       const V& vector()               const  { return _vector; }
00065       V&       vector()                      { return _vector; }
00066       
00067       //@}
00068       
00069       //! \name Line Property Queries
00070       //@{
00071    
00072       //! \brief Is the line valid (i.e. has a vector with non-zero length).
00073       bool    is_valid()               const  { return !_vector.is_null(); }
00074    
00075       //! \brief Returns the second endpoint of the line when treated as a line
00076       //! segment.
00077       P        endpt ()               const  { return _point + _vector; }
00078 
00079       //! \brief Returns the midpoint of the line when treated as a line
00080       //! segment.
00081       P        midpt ()               const  { return _point + _vector*0.5; }
00082 
00083       //! \brief Returns the length of the line when treated as a line segment.
00084       double  length()                const  { return _vector.length(); }
00085       
00086       //@}
00087    
00088       //! \name Overloaded Comparison Operators
00089       //@{
00090       
00091       //! \brief Are the two line's points and vectors exactly equal?
00092       bool operator==(const Line<L,P,V>& l) const {
00093          return (l._point == _point && l._vector == _vector);
00094       }
00095       
00096       //@}
00097       
00098       //! \name Line Operations
00099       //@{
00100          
00101       //! \brief Returns the distance from the point to the line.
00102       //!
00103       //! If vector is null (line is not valid) returns distance to _point.
00104       double dist(const P& p) const { return project(p).dist(p); }
00105          
00106       //@}
00107       
00108       //! \name Nearest Point Functions
00109       //! Functions that find the nearest point on the line/line segment to
00110       //! something else.
00111       //@{
00112    
00113       //! \brief Returns closest point on line to given point p.
00114       //!
00115       //! If vector is null (line is not valid) returns _point.
00116       P project(const P& p) const {
00117          V vn(_vector.normalized());
00118          return _point + ((p-_point)*vn) *vn;
00119       }
00120       
00121       //! \brief Finds the nearest point on this line segment to the given point.
00122       //!
00123       //! If this line is invalid, returns first endpoint.
00124       P project_to_seg(const P& p) const {
00125          double vv = _vector.length_sqrd();
00126          if (vv < epsAbsSqrdMath())
00127             return _point;
00128          return _point + (_vector * clamp(((p - _point)*_vector)/vv, 0.0, 1.0));
00129       }
00130    
00131       //! \brief Finds the nearest point on this line segment to the given line.
00132       //!
00133       //! If this line is invalid, returns first endpoint.
00134       P project_to_seg(const L& l) const {
00135          return project_to_seg(intersect(l));
00136       }
00137       
00138       //@}
00139       
00140       //! \name Reflection Functions
00141       //! Functions that find the reflection over a line.
00142       //@{
00143 
00144      P reflection(const P& p) const {
00145       Line temp(p,project(p));
00146       temp.vector() *= 2.0;
00147       
00148       return temp.endpt();
00149       
00150       }
00151        
00152       
00153       //@}
00154 
00155       //! \name Intersection Functions
00156       //@{
00157    
00158       //! \brief Returns the closest point on this line to the given line l.
00159       //!
00160       //! For 3D lines it's rare that the 2 lines actually intersect,
00161       //! so this is not really named well.
00162       P intersect(const L& l) const  {
00163          const P& A = point();
00164          const P& B = l.point();
00165          const V  Y = vector().normalized();
00166          const V  W = l.vector().normalized();
00167          const V BA = B-A;
00168          const double vw = Y*W;
00169          const double vba= Y*BA;
00170          const double wba= W*BA;
00171          const double det = vw*vw - 1.0;
00172    
00173          if (fabs(det) < gEpsAbsMath) {
00174             return A;
00175          }
00176    
00177          const double as = (vw*wba - vba)/det;
00178          const P      AP = A + as*Y;
00179    
00180          return AP;
00181       }
00182    
00183       //! \brief Returns true if this line, treated as a segment,
00184       //! intersects the given line, also treated as a segment.
00185       //!
00186       //! On success, also fills in the intersection point.
00187       bool intersect_segs(const L& l, P& inter) const {
00188          P ap = intersect(l);
00189          P bp = l.intersect(*((L*)this));
00190          if (ap.is_equal(bp)) {    // Lines intersect, do the line segments?
00191             inter = ap;
00192    
00193             // Is ap on both segments?
00194             double len1 = vector().length();
00195             double len2 = l.vector().length();
00196             double dot1 = (ap - point()) * vector() / len1;
00197             if (dot1 <= len1 && dot1 >= 0) {
00198                double dot2 = (ap - l.point()) * l.vector() / len2;
00199                if (dot2 <= len2 && dot2 >= 0) 
00200                   return 1;
00201             } 
00202          } 
00203          return 0;
00204       }
00205    
00206       //! \brief Returns true if this line, treated as a segment,
00207       //! intersects the given line, also treated as a line.
00208       //!
00209       //! On success, also fills in the intersection point.
00210       bool intersect_seg_line(const L& l, P& inter) const {
00211          P ap = intersect(l);
00212          P bp = l.intersect(*((L*)this));
00213          if (ap.is_equal(bp)) {    // Lines intersect, do the line segments?
00214             inter = ap;
00215    
00216             // Is ap on both segments?
00217             double len1 = vector().length();
00218             double dot1 = (ap - point()) * vector() / len1;
00219             if (dot1 <= len1 && dot1 >= 0) {
00220                return 1;
00221             } 
00222          } 
00223          return 0;
00224       }
00225    
00226    
00227       //! \brief Same as Line<L,P,V>::intersect_segLine(const L& l, P& inter)
00228       //! except without the argument to return the intersection point.
00229       bool intersect_segs(const L& l) const {
00230          P foo;
00231          return intersect_segs(l, foo);
00232       }
00233       
00234       //@}
00235 
00236     protected:
00237    
00238       P  _point;
00239       V  _vector;
00240       
00241    };
00242 
00243 } // namespace mlib
00244 
00245 //YYY - Using new iostream wrapper
00246 #include "std/iostream.H"
00247 //#include <iostream.h>
00248 
00249 namespace mlib {
00250 
00251 //! \brief Stream insertion operator for Line class.
00252 //! \relates Line
00253    template <class L, class P, class V>
00254    ostream& operator<<(ostream& os, const Line<L,P,V>& l) 
00255    {
00256       return os << "Line("<<l.point()<<","<<l.vector()<<")";
00257    }
00258 
00259 } // namespace mlib
00260 
00261 #endif // LINE_H_IS_INCLUDED
00262 
00263 /* end of file Line.H */
00264 

Generated on Mon Sep 18 11:39:32 2006 for jot by  doxygen 1.4.4