Follow this link to skip to the main content

2d_point.h

Go to the documentation of this file.
00001 // -*-c++-*-
00002 //---------------------------< /-/ CLARAty /-/ >------------------------------
00003 /**
00004  * @file  2d_point.h
00005  *
00006  * Defines 2D point class for planar coordinate point manipulation.
00007  *
00008  * <br>@b Designer(s):  Stanley Lippman
00009  * <br>@b Author(s):    Stanley Lippman
00010  * <br>@b Date:         October 22, 2001
00011  *
00012  * <b>Software License:</b><br>
00013  *
00014  * <code> http://claraty.jpl.nasa.gov/license/open_src/  or 
00015  *        file: license/open_src.txt </code>
00016  *
00017  * &copy; 2006, Jet Propulsion Laboratory, California Institute of Technology<br>
00018  *
00019  * $Revision: 1.8 $
00020  */
00021 //-----------------------------------------------------------------------------
00022 
00023 #ifndef N_2D_POINT_H
00024 #define N_2D_POINT_H
00025 
00026 #include "claraty/share.h"
00027 #include <iostream>
00028 #include <math.h>
00029 
00030 #include "claraty/fdm.h"
00031 #include "claraty/math_limits.h"
00032 
00033 namespace claraty {
00034 
00035 /*
00036  * @defgroup points Points
00037  * @ingroup Base
00038  *
00039  * 2D Point Math
00040  */
00041 //@{
00042 //@}
00043 
00044 // forward declarations
00045 
00046 template < class T >
00047 class N_2D_Point;
00048 
00049 typedef N_2D_Point< double > N_2D_Point_d;
00050 typedef N_2D_Point< float >  N_2D_Point_f;
00051 typedef N_2D_Point< int >    N_2D_Point_i;
00052 
00053 
00054 // independent operator functions
00055 // for class N_2D_Point objects ...
00056 
00057 template < class T >
00058 inline bool operator==( const N_2D_Point< T >&, const N_2D_Point< T >& );
00059 
00060 template < class T >
00061 inline N_2D_Point<T> operator+( const N_2D_Point<T>&, const N_2D_Point<T>& );
00062 
00063 template < class T >
00064 inline N_2D_Point<T> operator-( const N_2D_Point<T>&, const N_2D_Point<T>& );
00065 
00066 template < class T >
00067 inline N_2D_Point<T> operator-( const N_2D_Point<T>& );
00068 
00069 template < class T >
00070 inline N_2D_Point<T> operator*( double, const N_2D_Point<T>& );
00071 
00072 template < class T >
00073 inline N_2D_Point<T> operator/( const N_2D_Point<T>&, double );
00074 
00075 
00076 /*
00077  * 
00078  * @ingroup points
00079  */
00080 template < class T >
00081 class  N_2D_Point 
00082 {
00083 public:
00084   enum{ X, Y };
00085   
00086   /*
00087    * Constructs a 2D point setting the first element to e0 and the second
00088    * to e1, if given.
00089    * @param e0 the first element
00090    * @param e1 the second element
00091    */
00092   explicit N_2D_Point( T e0 = T(), T e1 = T() ) 
00093   { _elems[ 0 ] = e0; _elems[ 1 ] = e1; }
00094 
00095   /*
00096    * Returns the number of elements in the 2D vector (2).
00097    * @return the size of the vector (2)
00098    */
00099   int size() const { return 2; }
00100 
00101   /*
00102    * References a variable of the point by indexing
00103    * @param ix the index used to reference
00104    * @return the variable of point referenced by index
00105    */
00106   T  operator()( int ix ) const { return _elems[ ix ];  }
00107     
00108   /*
00109    * References a variable of the point by indexing
00110    * @param ix the index used to reference
00111    * @return the variable of point referenced by index
00112    */
00113   T& operator()( int ix )       { return _elems[ ix ];  }
00114     
00115   /*
00116    * Returns the x component of the point
00117    * @return the x component of the point
00118    */
00119   T  x() const { return _elems[ 0 ]; }
00120   
00121   /*
00122    *  Returns the x component of the point
00123    *  @return the x component of the point
00124    */
00125   T& x()       { return _elems[ 0 ]; }
00126   
00127   /*
00128    * Returns the y component of the point
00129    * @return the y component of the point
00130    */
00131   T& y()       { return _elems[ 1 ]; }
00132     
00133   /*
00134    * Returns the y component of the point
00135    * @return the y component of the point
00136    */
00137   T  y() const { return _elems[ 1 ]; }
00138 
00139   /*
00140    * Returns the x component of the point
00141    * @return the x component of the point
00142    */
00143   T get_x() const { return _elems[ 0 ]; }
00144     
00145   /*
00146    * Returns the y component of the point
00147    * @return the y component of the point
00148    */
00149   T get_y() const { return _elems[ 1 ]; }
00150 
00151   /*
00152    * Sets the first element of the point to x
00153    * @param x the x component of the point
00154    */
00155   void set( T x ) { _elems[ 0 ] = x; }
00156 
00157   /*
00158    * Sets the first and second elements of the point to x and y
00159    * @param x the x component of the point
00160    * @param y the y component of the point
00161    */
00162   void set( T x, T y ) { 
00163     _elems[ 0 ] = x;  _elems[ 1 ] = y; 
00164   }
00165 
00166   /*
00167    * Subtracts the y element from the variable inv_y.
00168    * @param inv_y variable by which y is subtracted
00169    */
00170   void      invert_y( T inv_y ) { _elems[ 1 ] = inv_y - _elems[ 1 ]; }
00171 
00172   T  length() const;
00173   T  length2() const;
00174 
00175   double angle() const;
00176   
00177   bool      normalize();
00178   N_2D_Point normalize_copy() const;
00179 
00180   T  dot( const N_2D_Point& ) const;
00181   
00182   T  distance ( const N_2D_Point& ) const;
00183   T  distance2( const N_2D_Point& ) const;
00184   N_2D_Point interpolate( const N_2D_Point&, T s ) const;
00185   N_2D_Point extrapolate( const T angle, T s ) const;
00186   
00187   bool intersect(const N_2D_Point &line1_a,
00188                  const N_2D_Point &line1_b,
00189                  const N_2D_Point &line2_a,
00190                  const N_2D_Point &line2_b,
00191                  N_2D_Point & result) const;
00192   
00193   N_2D_Point&   operator+=( const N_2D_Point& );
00194   N_2D_Point&   operator-=( const N_2D_Point& );
00195   N_2D_Point&   operator+=( T );
00196   N_2D_Point&   operator-=( T );
00197   N_2D_Point&   operator*=( T );
00198   N_2D_Point&   operator/=( T );
00199   
00200   N_2D_Point  rotate( double ang )     const;
00201   
00202   // Rotation -- from Ames ...
00203   /*
00204    * Rotates a point 90 degrees clockwise.
00205    * @return the rotated point
00206    */
00207   N_2D_Point rotate_cw_90()  const { return N_2D_Point(  _elems[1], -_elems[0] ); }
00208   
00209   /*
00210    * Rotates a point 90 degrees counter-clockwise.
00211    * @return the rotated point
00212    */
00213   N_2D_Point rotate_ccw_90() const { return N_2D_Point( -_elems[1],  _elems[0] ); }
00214 
00215   /*
00216    * Rotates a point by a given angle clockwise.
00217    * @param angle the angle the point is rotated
00218    * @return the rotated point
00219    */
00220   N_2D_Point rotate_cw( float angle ) const
00221   { 
00222     return N_2D_Point(
00223                      (T)(_elems[0] * cos(angle) +  _elems[1] * sin(angle)),
00224                      (T)(_elems[1] * cos(angle) -  _elems[0] * sin(angle))); 
00225   }
00226 
00227   /*
00228    * Rotates a point by a given angle counter-clockwise.
00229    * @param angle the angle the point is rotated
00230    * @return the rotated point
00231    */
00232   N_2D_Point rotate_ccw( float angle ) const
00233   { 
00234     return N_2D_Point(
00235                      (T)(_elems[0] * cos(angle) - _elems[1] * sin(angle)),
00236                      (T)(_elems[1] * cos(angle) + _elems[0] * sin(angle))); 
00237   }
00238 
00239   /*
00240    * Rotates point clockwise around a point p by a given angle.
00241    * @param angle the angle the point is rotated
00242    * @param p the point around which point is rotated
00243    * @return the rotated point
00244    */
00245   N_2D_Point rotate_cw_around_point( float angle, N_2D_Point p ) const
00246   { return ( *this-p ).rotate_cw( angle ) + p; }
00247 
00248   /*
00249    * Rotates point counter-clockwise around a point p by a given angle.
00250    * @param angle the angle the point is rotated
00251    * @param p the point around which point is rotated
00252    *  @return the rotated point
00253    */
00254   N_2D_Point rotate_ccw_around_point( float angle, N_2D_Point p) const
00255   { return ( *this-p ).rotate_ccw( angle ) + p; }
00256 
00257   T distance_to_unit_vector( const N_2D_Point& ) const;
00258   T closest_point_to_line( const N_2D_Point&, const N_2D_Point& ) const;
00259   T distance2_to_line( const N_2D_Point&, const N_2D_Point&, N_2D_Point* = 0 ) const;
00260 
00261   bool     is_origin() const;
00262   std::ostream& display(const char *pmsg, std::ostream &os = std::cout) const;
00263   std::ostream& display_unformatted(std::ostream &os) const;
00264 
00265   inline double angle_to(const N_2D_Point &a) const;
00266 
00267 private:
00268   T _elems[ 2 ];
00269 };
00270 
00271 /*
00272  * Returns the length of the point.
00273  * @return the length of the point
00274 */
00275 template < class T >
00276 inline T 
00277 N_2D_Point<T>::
00278 length() const 
00279 { 
00280   return (T)(sqrt( _elems[0]*_elems[0] + _elems[1]*_elems[1])); 
00281 }
00282 
00283 /*
00284  * Returns the length of the point squared.
00285  * @return the squared length of the point
00286  */
00287 template < class T >
00288 inline T N_2D_Point<T>::
00289 length2() const 
00290 { 
00291   return _elems[0]*_elems[0] + _elems[1]*_elems[1]; 
00292 }
00293 
00294 /*
00295  *   Returns the angle of the point
00296  *  @return the angle of the point
00297  */
00298 template < class T >
00299 inline double N_2D_Point<T>::
00300 angle() const
00301 {
00302   // TODO: handle x==y==0 gracefully (return an arbitrary angle)
00303   // Under linux (glibc2.2), atan2(0,0) appears to return 0, which is great
00304   return atan2(y(), x());
00305 }
00306 
00307 /*
00308  * Returns the angle from existing point to another point.
00309  *  @param a point to which the delta angle is calculated
00310  *  @return the angle from existing point to point a
00311  */
00312 template<class T>
00313 inline double N_2D_Point<T>::
00314 angle_to(const N_2D_Point<T> &a) const
00315 {
00316   double delta_angle= a.angle() - angle();
00317   if (delta_angle <= -M_PI) delta_angle += 2*M_PI;
00318   else if (delta_angle >= M_PI) delta_angle -= 2*M_PI;
00319   return delta_angle;
00320 }
00321 
00322 /*
00323  * Returns the dot product of 2 points.
00324  * @param v the second point
00325  * @return the dog product
00326  */
00327 template < class T >
00328 inline T N_2D_Point<T>::
00329 dot( const N_2D_Point &v ) const 
00330 { 
00331   return ( _elems[0]*v._elems[0] + _elems[1]*v._elems[1] ); 
00332 }
00333 
00334 /*
00335  *   Returns the distance between two points squared.
00336  *  @param p the point to which distance is measured
00337  *  @return the squared distance between the points
00338  */
00339 template < class T >
00340 inline T N_2D_Point<T>::
00341 distance2( const N_2D_Point &p ) const 
00342 {
00343   double d0 = p._elems[0] - _elems[0];
00344   double d1 = p._elems[1] - _elems[1];
00345   
00346   return (T)(d0*d0 + d1*d1);
00347 }
00348 
00349 // Return is -pi to pi
00350 // Positive angle means A is clockwise from point
00351 // Negative means A is CCW from point
00352 
00353 /*
00354  *  Returns the distance between two points.
00355  *  @param p the point to which distance is measured
00356  *  @return the distance between the points
00357  */
00358 template < class T >
00359 inline T N_2D_Point<T>::
00360 distance( const N_2D_Point &p ) const 
00361 {
00362   double d0 = p._elems[0] - _elems[0];
00363   double d1 = p._elems[1] - _elems[1];
00364   
00365   return (T)(sqrt( d0*d0 + d1*d1 ));
00366 }
00367 
00368 //
00369 //  Linearly interpolates between line endpoints:
00370 //    np.x = (p'.x - p.x)*s + p', ... etc
00371 //    where np = new point, p' = instance point,
00372 //           p = supplied endpoint, and
00373 //           s = interpolation fraction
00374 //
00375 
00376 /*
00377  *  Linearly interpolates between line endpoints (already supplied).
00378  *  @param p the instance point
00379  *  @param s the interpolation fraction (function assumes this is between 0 and 1)
00380  *  @return new point after interpolation
00381 */
00382 template < class T >
00383 inline N_2D_Point<T> N_2D_Point<T>::
00384 interpolate( const N_2D_Point &p, T s ) const 
00385 {
00386   return N_2D_Point<T>
00387     (( p._elems[0]-_elems[0] ) * s+_elems[0],
00388      ( p._elems[1]-_elems[1] ) * s+_elems[1] );
00389 }
00390 
00391 /*
00392  * Linearly extrapolate from a point along a line that is at a given
00393  *  angle for a distance s. 
00394  *  Note that the angle is measured as zero at the X-axis and
00395  *  increasing positively as the angle rotates about the origin to the
00396  *  Y-axis.
00397  *    np.x = p'.x + s*cos(angle), ... etc
00398  *    where np     = new point, p' = instance point,
00399  *           angle = supplied angle, and
00400  *           s     = extrapolation distance
00401  */
00402 template < class T >
00403 inline N_2D_Point<T> N_2D_Point<T>::
00404 extrapolate( const T angle, T s ) const 
00405 {
00406   return N_2D_Point<T> (
00407                               _elems[0] + s*cos(angle),
00408                               _elems[1] + s*sin(angle));
00409 }
00410 
00411 /*
00412  * Compute the intersection point of 2 lines. Each line is defined by
00413  * 2 points. If the lines are parallel, the intersection is at
00414  * infinity so return false. If an intersection point is found,
00415  * return true.
00416  */
00417 template < class T >
00418 inline bool N_2D_Point<T>::
00419 intersect(const N_2D_Point &line1_a,
00420           const N_2D_Point &line1_b,
00421           const N_2D_Point &line2_a,
00422           const N_2D_Point &line2_b,
00423           N_2D_Point & result) const 
00424 {
00425   // If lines are parallel, return false indicating that they do not
00426   // intersect.
00427   T delta_x1 = line1_a.x() - line1_b.x();
00428   T delta_x2 = line2_a.x() - line2_b.x();
00429   T delta_y1 = line1_a.y() - line1_b.y();
00430   T delta_y2 = line2_a.y() - line2_b.y();
00431 
00432   T angle_difference =
00433     atan2(delta_y1, delta_x1) - atan2(delta_y2, delta_x2);
00434   
00435   while (angle_difference > M_PI)
00436     angle_difference -= M_2_PI;
00437   while (angle_difference <= -M_PI)
00438     angle_difference += M_2_PI;
00439 
00440   if (fabs(angle_difference) < DOUBLE_EPSILON)
00441     return false;
00442 
00443   if (fabs(fabs(angle_difference) - M_PI) < DOUBLE_EPSILON)
00444     return false;
00445 
00446   // Compute the denominator determinant
00447   T denominator = delta_x1 * delta_y2 - delta_x2 * delta_y1;
00448 
00449   // Verify that the denominator is not near singular
00450   if (fabs(denominator) < DOUBLE_EPSILON)
00451     return false;
00452 
00453   // Compute the intersection point
00454   T sub_det_1 = line1_a.x() * line1_b.y() - line1_b.x() * line1_a.y();
00455   T sub_det_2 = line2_a.x() * line2_b.y() - line2_b.x() * line2_a.y();
00456 
00457   result._elems[0]
00458     = ((sub_det_1*delta_x2)-(sub_det_2*delta_x1))/denominator;
00459   result._elems[1]
00460     = ((sub_det_1*delta_y2)-(sub_det_2*delta_y1))/denominator;
00461 
00462   return true;
00463 }
00464 
00465 
00466 
00467 
00468 //
00469 // Returns perpendicular distance from this point to 
00470 // given unit vector which passes through origin.
00471 //
00472 /*
00473  *   Calculates the distance from point to given unit vector.
00474  *  @param v the unit vector
00475  *  @return perpendicular distance from this point to given unit vector
00476  */
00477 template < class T >
00478 inline T N_2D_Point<T>::
00479 distance_to_unit_vector( const N_2D_Point &v) const 
00480 {
00481   T d = _elems[0]*v._elems[1] - _elems[1]*v._elems[0];
00482   return d < 0 ? -d : d ;
00483 }
00484 
00485 /*
00486  * Normalizes this vector.
00487  * @return true if the vector has been normalized; false otherwise
00488  */
00489 template < class T >
00490 inline bool N_2D_Point<T>::
00491 normalize() 
00492 {
00493   bool   status = false;
00494   double vec_len = length();
00495   
00496   if ( vec_len > EPSILON ) {
00497     _elems[0] = (T)(_elems[0] / vec_len); 
00498     _elems[1] = (T)(_elems[1] / vec_len); 
00499     status = true;
00500   }
00501   
00502   return status;
00503 }
00504 
00505 /*
00506  *   Returns a copy of the normalized vector.
00507  * @return a copy of the normalize vector
00508  */
00509 template < class T >
00510 inline N_2D_Point<T> N_2D_Point<T>::
00511 normalize_copy() const 
00512 {
00513   N_2D_Point<T> test;
00514   double vec_len = length();
00515   if (vec_len > EPSILON){
00516     
00517     test(0) = (T)(_elems[0]/vec_len);
00518     test(1) = (T)(_elems[1]/vec_len);
00519   }
00520   return test;
00521   // this was the original code. it executes both branches of the if statement.  but i don't know why.
00522   //    return vec_len > EPSILON
00523   //    ? N_2D_Point( (T)(_elems[0]/vec_len, _elems[1]/vec_len))
00524   //    : N_2D_Point();
00525 }
00526 
00527 /*
00528  * Rotates a point by a specified angle.
00529  * @param ang angle by which the point is rotated
00530  * @return the rotated point
00531  */
00532 template < class T >
00533 inline N_2D_Point<T> N_2D_Point<T>::
00534 rotate( double ang ) const 
00535 {
00536   double cosa = cos( ang ); double sina = sin( ang );
00537   
00538   return N_2D_Point( (T)(_elems[0]*cosa - _elems[1]*sina),
00539                     (T)(_elems[0]*sina + _elems[1]*cosa) );
00540 }
00541 
00542 /*
00543  *  Checks that this point is the origin.
00544  *  @return true if this is the origin; false otherwise 
00545  */
00546 template < class T >
00547 inline bool N_2D_Point<T>::
00548 is_origin() const 
00549 { 
00550   return ! _elems[0] && ! _elems[1]; 
00551 }
00552 
00553 /*
00554  * Checks that 2 2D points are the same.
00555  * @param v0 the first 2D point
00556  * @param v1 the second 2D point
00557  * @return true if the 2 points are the same; false otherwise
00558  */
00559 template < class T >
00560 inline bool 
00561 operator==( const N_2D_Point<T> &v0, const N_2D_Point<T> &v1 ) 
00562 {
00563   return ( v0(0)==v1(0) ) && ( v0(1)==v1(1) );
00564 }
00565 
00566 /*
00567  *  Adds 2 2D points together.
00568  *  @param v0 the first 2D point
00569  *  @param v1 the second 2D point
00570  *  @return the point resulting from addition
00571  */
00572 template < class T >
00573 inline N_2D_Point<T> 
00574 operator+( const N_2D_Point<T> &v0, const N_2D_Point<T> &v1 ) 
00575 {
00576   return N_2D_Point<T>( v0(0)+v1(0), v0(1)+v1(1) );
00577 }
00578 
00579 /*
00580  * Subtracts one point from the other.
00581  * @param v0 the point subtracted from
00582  * @param v1 the point being subtracted
00583  * @return the point resulting from subtraction
00584  */
00585 template < class T >
00586 inline N_2D_Point<T>
00587 operator-( const N_2D_Point<T> &v0, const N_2D_Point<T> &v1 ) 
00588 {
00589   return N_2D_Point<T>(v0(0)-v1(0), v0(1)-v1(1));
00590 }
00591 
00592 /*
00593  * Negates the x and y comp. of a point
00594  * @param v the point negated
00595  * @return the negated point
00596  */
00597 template < class T >
00598 inline N_2D_Point<T>
00599 operator-( const N_2D_Point<T> &v ) 
00600 { 
00601   return N_2D_Point<T>( -v(0), -v(1)); 
00602 }
00603 
00604 /*
00605  * Adds given point (v1) to existing point on left-hand side.
00606  * @param v1 the vector to be added
00607  * @return the resulting point from addition
00608  */
00609 template < class T >
00610 inline N_2D_Point<T>& N_2D_Point<T>::
00611 operator+=( const N_2D_Point<T> &v1 ) 
00612 {
00613   _elems[0] += v1(0); _elems[1] += v1(1); 
00614   return *this;
00615 }
00616 
00617 /*
00618  * Subtracts given point (v1) from existing point on left-hand side.
00619  *  @param v1 the vector to be subtracted
00620  *  @return the point resulting from subtraction
00621  */
00622 template < class T >
00623 inline N_2D_Point<T>& N_2D_Point<T>::
00624 operator-=( const N_2D_Point &v1 ) 
00625 {
00626   _elems[0] -= v1(0); _elems[1] -= v1(1); return *this;
00627 }
00628 
00629 /*
00630  * Adds given scalar (s) to existing point on left-hand side.
00631  * @param s the scalar to be added
00632  * @return the resulting point from addition
00633  */
00634 template < class T >
00635 inline N_2D_Point<T>& N_2D_Point<T>::
00636 operator+=( T s ) 
00637 {
00638   _elems[0] += s; _elems[1] += s; 
00639   return *this;
00640 }
00641 
00642 /*
00643  * Subtracts given scalar (s) from existing point on left-hand side.
00644  * @param s the scalar to be subtracted
00645  * @return the resulting point from addition
00646  */
00647 template < class T >
00648 inline N_2D_Point<T>& N_2D_Point<T>::
00649 operator-=( T s ) 
00650 {
00651   _elems[0] -= s; _elems[1] -= s; 
00652   return *this;
00653 }
00654 
00655 /*
00656  *  Multiplies the 2D point by a given number. 
00657  *  @param v the 2D point multiplied
00658  *  @param s number the point is multiplied by
00659  *  @return the point resulting from multiplication
00660  */
00661 template < class T >
00662 inline N_2D_Point<T>
00663 operator*( const N_2D_Point<T> &v, double s ) 
00664 {
00665     return N_2D_Point<T>(v(0)*s, v(1)*s);
00666 }
00667 
00668 /*
00669  * Multiplies the 2D point by a given number.
00670  * @param s number the point is multiplied by
00671  * @param v the 2D point multiplied
00672  * @return the point resulting from multiplication
00673  */
00674 template < class T >
00675 inline N_2D_Point<T>
00676 operator*( double s, const N_2D_Point<T> &v ) 
00677 {
00678   return N_2D_Point<T>( (T)(v(0)*s), 
00679                               (T)(v(1)*s) );
00680 }
00681 
00682 /*
00683  * Multiplies the point on left-hand side by given value (s).
00684  * @param s value by which point is multiplied
00685  * @return the point resulting from multiplication
00686 */
00687 template < class T >
00688 inline N_2D_Point<T>& N_2D_Point<T>::
00689 operator*=( T s )
00690 {
00691   _elems[0] *= s; _elems[1] *= s; return *this;
00692 }
00693 
00694 /*
00695  * Divides the 2D point by a given number
00696  * @param v the 2D point divided
00697  * @param s number the point is divided  by
00698  * @return the point resulting from division
00699  */
00700 template < class T >
00701 inline N_2D_Point<T>
00702 operator/( const N_2D_Point<T> &v, double s ) 
00703 {
00704   return N_2D_Point<T>( v.x()/s, v.y()/s );
00705 }
00706 
00707 /*
00708  * Divides the point on left-hand side by given value (s).
00709  * @param s value by which point is divided
00710  * @return the point resulting from division
00711  */
00712 template < class T >
00713 inline N_2D_Point<T>& N_2D_Point<T>::
00714 operator/=( T s ) 
00715 {
00716   _elems[0] /= s; _elems[1] /= s; return *this;
00717 }
00718 
00719 /*
00720  * Finds the closest point on the line ab to this point and returns
00721  * the distance to the point from a.
00722  * @param a one endpoint of the line
00723  * @param b another endpoint of the line
00724  * @return the distance from the closest point on the line to this point from a
00725  */
00726 template < class T >
00727 inline T N_2D_Point<T>::
00728 closest_point_to_line( const N_2D_Point<T> &a, const N_2D_Point<T> &b ) const
00729 {
00730   N_2D_Point<T> v( b - a );
00731   double d2 = v.length2();
00732   return (T)(d2 < 1.0E-6
00733                     ? 0.
00734                     : v.dot( *this-a )/d2);
00735 }
00736 
00737 /*
00738  * Returns the square of the distance from this position
00739  * to the line from 'a' to 'b'. If 'p' is a non-zero pointer,
00740  * the closest position on the line is set in 'p'.
00741  * @param a one point on the line ab
00742  * @param b second point on the line ab
00743  * @param p if p the closest position on the line if p is non-zero
00744  * @return the square of the distance from this position to the line ab
00745  */
00746 template < class T >
00747 inline T N_2D_Point<T>::
00748 distance2_to_line( const N_2D_Point<T> &a, const N_2D_Point<T> &b, N_2D_Point<T> *p ) const {
00749   double s = closest_point_to_line( a, b );
00750   N_2D_Point<T> p_on_line = a + s*( b - a );
00751   
00752   if ( p != 0 )
00753     *p = p_on_line;
00754   
00755   return distance2( p_on_line );
00756 }
00757 
00758 template < typename elem_type >
00759 inline std::ostream& N_2D_Point<elem_type>::display_unformatted(std::ostream &os)
00760   const
00761 {
00762   return os  << _elems[0] << " " << _elems[1];
00763 }
00764 
00765 template < typename elem_type >
00766 inline std::ostream& N_2D_Point<elem_type>::
00767 display( const char* pmsg, std::ostream &os ) const
00768 {
00769   if ( pmsg )
00770     os << pmsg;
00771   
00772   os  << "[x: "
00773       << _elems[0] << "  y: "
00774       << _elems[1] << "]";
00775   
00776   return os;
00777 }
00778 
00779 template < typename elem_type >
00780 inline std::ostream& operator<<(std::ostream &os, const N_2D_Point<elem_type> &p)
00781 {
00782   return p.display( NULL, os );
00783 }
00784 
00785 template <class T>
00786 inline std::istream& operator>>(std::istream& is, N_2D_Point<T>& p)
00787 {
00788   return is >> p.x() >> p.y();
00789 }
00790 
00791 template <class T>
00792 bool io_object(FDM_Untyped_Node node, N_2D_Point<T>& rhs)
00793 {
00794   FDM_Array a(node);
00795   bool ok = a.element(rhs(0));
00796   ok &= a.element(rhs(1));
00797   return ok;
00798 }
00799 
00800 template <class T>
00801 inline bool cl_isnan(const N_2D_Point<T> &pt) {
00802   return cl_isnan(pt.x()) || cl_isnan(pt.y());
00803 }
00804 
00805 template <class T>
00806 inline void cl_setnan(N_2D_Point<T> &pt) {
00807   cl_setnan(pt.x());
00808   cl_setnan(pt.y());
00809 }
00810 
00811 //-----------------------------------------------------------------------------
00812 
00813 #include "claraty/operator_def.h"
00814 
00815 #define CL_OP_GENERATE          ( CL_OP_NOT_EQUAL )
00816 #define CL_OP_TEMPLATE          template < typename T >
00817 #define CL_OP_CLASS             N_2D_Point<T>
00818 #include "claraty/operator.h"
00819 
00820 #define CL_OP_TEMPLATE          template < typename T >
00821 #define CL_OP_CLASS             N_2D_Point<T>
00822 #define CL_OP_SCALAR            T
00823 #include "claraty/scalar_operator.h"
00824 
00825 } // namespace claraty
00826 
00827 #endif // N2D_POINT_H