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

_QGAR_GenSegment.TCC

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------+
00002  | Library QgarLib, graphics analysis and recognition                  |
00003  | Copyright (C) 2002  Qgar Project, LORIA                             |
00004  |                                                                     |
00005  | This library is free software; you can redistribute it and/or       |
00006  | modify it under the terms of the GNU Lesser General Public          |
00007  | License version 2.1, as published by the Free Software Foundation.  |
00008  |                                                                     |
00009  | This library is distributed in the hope that it will be useful,     |
00010  | but WITHOUT ANY WARRANTY; without even the implied warranty of      |
00011  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                |
00012  | See the GNU Lesser General Public License for more details.         |
00013  |                                                                     |
00014  | The GNU Lesser General Public License is included in the file       |
00015  | LICENSE.LGPL, in the root directory of the Qgar packaging. See      |
00016  | http://www.gnu.org/licenses/lgpl.html for the terms of the licence. |
00017  | To receive a paper copy, write to the Free Software Foundation,     |
00018  | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.       |
00019  |                                                                     |
00020  | Contact Project Qgar for any information:                           |
00021  |   LORIA - équipe Qgar                                               |
00022  |   B.P. 239, 54506 Vandoeuvre-lès-Nancy Cedex, France                |
00023  |   email: qgar-contact@loria.fr                                      |
00024  |   http://www.qgar.org/                                              |
00025  *---------------------------------------------------------------------*/
00026 
00027 
00028 /**
00029  * @file   _QGAR_GenSegment.TCC
00030  * @brief  Implementation of function members of class qgar::GenSegment.
00031  *
00032  * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Gérald Masini">Gérald Masini</a>
00033  * @date   December 14, 2004  18:28
00034  * @since  Qgar 2.2
00035  */
00036 
00037 
00038 
00039 // STD
00040 #include <cmath>
00041 // QGAR
00042 #include <qgarlib/ISerializable.H>
00043 #include <qgarlib/math.H>
00044 
00045 
00046 
00047 namespace qgar
00048 {
00049 
00050 
00051 // -------------------------------------------------------------------
00052 // C O N S T R U C T O R S
00053 // -------------------------------------------------------------------
00054 
00055 
00056 // DEFAULT CONSTRUCTOR
00057 
00058 template <class T>
00059 GenSegment<T>::GenSegment()
00060 {
00061    // VOID
00062 }
00063 
00064 
00065 // COPY-CONSTRUCTOR
00066 
00067 template <class T>
00068 GenSegment<T>::GenSegment(const GenSegment<T>& aSeg)
00069 
00070   : AbstractGenPrimitive<T>(aSeg)
00071 
00072 {
00073   // VOID
00074 }
00075 
00076 
00077 // INITIALIZE FROM A QGAR SEGMENT
00078 
00079 template <class T>
00080 GenSegment<T>::GenSegment(const GenQgarSegment<T>& aQSeg)
00081 
00082   : AbstractGenPrimitive<T>(aQSeg.accessSource(),
00083                             aQSeg.accessTarget())
00084 
00085 {
00086   // VOID
00087 }
00088 
00089 
00090 // INITIALIZE FROM SOURCE AND TARGET POINTS
00091 
00092 template <class T>
00093 GenSegment<T>::GenSegment(const GenPoint<T>& aSource,
00094                           const GenPoint<T>& aTarget)
00095 
00096   : AbstractGenPrimitive<T>(aSource, aTarget)
00097 
00098 {
00099   // VOID
00100 }
00101 
00102 
00103 // INITIALIZE FROM COORDINATES
00104 
00105 template <class T>
00106 GenSegment<T>::GenSegment(const T aXSource,
00107                           const T aYSource,
00108                           const T aXTarget,
00109                           const T aYTarget)
00110 
00111   : AbstractGenPrimitive<T>(aXSource, aYSource, aXTarget, aYTarget)
00112 
00113 {
00114   // VOID
00115 }
00116 
00117 
00118 // -------------------------------------------------------------------
00119 // D E S T R U C T O R 
00120 // -------------------------------------------------------------------
00121 
00122 
00123 template <class T> GenSegment<T>::~GenSegment()
00124 {
00125   // VOID
00126 }
00127 
00128 
00129 // -------------------------------------------------------------------
00130 // C O P Y
00131 // -------------------------------------------------------------------
00132 
00133 
00134 template <class T>  
00135 GenSegment<T>*
00136 GenSegment<T>::clone() const
00137 {
00138   return new GenSegment<T>(*this);
00139 }
00140 
00141 
00142 // -------------------------------------------------------------------
00143 // ACCESS TO GEOMETRICAL CHARACTERISTICS
00144 // -------------------------------------------------------------------
00145 
00146 
00147 // GET SEGMENT LENGTH
00148 
00149 template <class T>
00150 inline double
00151 GenSegment<T>::length() const
00152 {
00153   return hypot(this->dx(), this->dy());
00154 }
00155 
00156 
00157 // GET SEGMENT SQUARED LENGTH
00158 
00159 template <class T>
00160 double
00161 GenSegment<T>::sqr_length() const
00162 {
00163   double l = this->length();
00164   return l * l;
00165 }
00166  
00167 
00168 // SIGNED DISTANCE BETWEEN (0,0) AND ITS PERPENDICULAR
00169 // PROJECTION ONTO THE LINE SUPPORTING THE SEGMENT
00170 // Precomputed
00171 
00172 template <class T>
00173 double
00174 GenSegment<T>::rho() const
00175 {
00176   // Signed distance between point (0,0) and its perpendicular
00177   // projection onto the line supporting the current segment.
00178   // The value is negative if the line supporting the current
00179   // segment intersects the Y axis at a negative value.
00180 
00181   // Let A (XA,YA) be the source point,
00182   //     B (XB,YB) be the target point,
00183   //     C (XC,YC) be the origin of the coordinate system
00184   //     L be the length of AB
00185   //     I be the projection of C onto line AB
00186   //
00187   // s = ((YA-YC)(XB-XA)-(XA-XC)(YB-YA)) / L**2  [EQN2]
00188   // (XC,YC) == 0
00189   // s = (YA(XB-XA) - XA(YB-YA)) / L**2
00190   // s = (YA*XB - XA*YB) / L**2
00191   //
00192   // Distance from C to I:
00193   //   rho = s*L = (YA*XB - XA*YB) / L
00194 
00195   return
00196     (double) qgAbs((this->ySource() * this->xTarget()) - (this->xSource() * this->yTarget()))
00197     / this->length();
00198 
00199   // _________________________________________________________________
00200   //
00201   // Let A,B,C,D be 2-space position vectors.
00202   // The directed line segments AB & CD are given by:
00203   //
00204   //   AB = A + r(B - A), r in [0,1]
00205   //   CD = C + s(D - C), s in [0,1]
00206   //
00207   // If AB & CD intersect, then:
00208   //
00209   //   A + r(B - A) = C + s(D - C)
00210   //:  XA + r(XB - XA) = XC + s(XD - XC)
00211   //   YA + r(YB - YA) = YC + s(YD - YC)  for r,s in [0,1]
00212   //
00213   // Solving the above for r and s yields:
00214   //
00215   //       ((YA - YC)(XD - XC)) - ((XA - XC)(YD - YC))
00216   //   r = -------------------------------------------    [EQN5]
00217   //       ((XB - XA)(YD - YC)) - ((YB - YA)(XD - XC))
00218   //
00219   //       ((YA - YC)(XB - XA)) - ((XA - XC)(YB - YA))
00220   //   s = -------------------------------------------    [EQN6]
00221   //       ((XB - XA)(YD - YC)) - ((Y B -YA)(XD - XC))
00222   //
00223   // Let I be the position vector of the intersection point, then:
00224   //
00225   //   I = A + r(B - A)
00226   //   XI = XA + r(XB - XA)   [EQN7]
00227   //   YI = YA + r(YB - YA)   [EQN8]
00228   // _________________________________________________________________
00229   //
00230   // Intersection of the line supporting AB
00231   // and the Y axis supporting segment CD
00232   //
00233   //   (XC,YC) = (0,0)
00234   //   (XD,YD) = (0,-1)
00235   //
00236   // In EQN5 and EQN6, the denominator is:
00237   //   d = ((XB - XA)(YD - YC)) - ((YB - YA)(XD - XC))
00238   //   d = ((XB - XA)(-1))      - ((YB - YA)(0))
00239   //   d = XA - XB
00240   // EQN5 is:
00241   //   r = ((YA - YC)(XD - XC) - (XA - XC)(YD - YC)) / d
00242   //   r = ((YA)     (0)       - (XA)     (-1))      / (XA - XB)
00243   //   r = XA / (XA - XB)
00244   // EQN8 is:
00245   //   YI = YA + r(YB - YA)
00246   //   YI = YA + XA (YB - YA) / (XA - XB)
00247   //   YI = (YA (XA - XB) + XA (YB - YA)) / (XA - XB)
00248   //   YI = (XA*YB - XB*YA) / (XA - XB)
00249   //   YI = -rho / (XA - XB) = rho / (XB - XA)
00250   // _________________________________________________________________
00251   //
00252 
00253   // The distance is negative if the line supporting the
00254   // segment intersects the Y axis at a negative value.
00255   //
00256   // WARNING: When the line is parallel to the Y axis, the sign is +
00257   // when the segment is oriented towards positive Y coordinates and
00258   // its X coordinates are positive, or when the segment is oriented
00259   // towards negative Y coordinates ans its X coordinates are negative.
00260   //
00261   //  if (this->dx() < 0)
00262   //    {
00263   //      return -rho;
00264   //    }
00265   //  else
00266   //    {
00267   //      return rho;
00268   //    }
00269 }
00270 
00271 
00272 // -------------------------------------------------------------------
00273 // G E O M E T R Y :   A N G L E S 
00274 // -------------------------------------------------------------------
00275 
00276 
00277 // ANGLE BETWEEN THE X AXIS AND THE SEGMENT, IN [0, 2PI[ RADIANS
00278 
00279 template <class T>
00280 inline double
00281 GenSegment<T>::theta() const
00282 {
00283   return qgAngle(this->_source, this->_target);
00284 }
00285 
00286 
00287 // SAME AS PREVIOUS
00288 
00289 template <class T>
00290 inline double
00291 GenSegment<T>::angle() const
00292 {
00293   return this->theta();
00294 }
00295 
00296 
00297 // ANGLE BETWEEN THE X AXIS AND THE SEGMENT, IN DEGREES
00298 
00299 template <class T>
00300 inline double
00301 GenSegment<T>::thetaDegrees() const
00302 {
00303   return qgRadiansToDegrees(this->theta());
00304 }
00305 
00306 // SAME AS PREVIOUS
00307 
00308 template <class T>
00309 inline double
00310 GenSegment<T>::angleDegrees() const
00311 {
00312   return qgRadiansToDegrees(this->theta());
00313 }
00314 
00315 
00316 // ANGLE BETWEEN THE X AXIS AND THE SEGMENT, IN [0, PI[ RADIANS
00317 
00318 template <class T>
00319 inline double
00320 GenSegment<T>::slope() const
00321 {
00322   return qgSlope(this->accessSource(), this->accessTarget());
00323 }
00324 
00325 
00326 // ANGLE BETWEEN THE X AXIS AND THE SEGMENT, IN [0, 180[ DEGREES
00327 
00328 template <class T>
00329 inline double
00330 GenSegment<T>::slopeDegrees() const
00331 {
00332   return qgRadiansToDegrees(this->slope());
00333 }
00334 
00335 
00336 // -------------------------------------------------------------------
00337 // G E O M E T R I C A L   P R E D I C A T E S
00338 // -------------------------------------------------------------------
00339 
00340 
00341 // DOES THE GIVEN POINT APPROXIMATELY BELONGS TO THE CURRENT SEGMENT?
00342 
00343 template <class T>
00344 inline bool
00345 GenSegment<T>::contains(const GenPoint<T>& c, double aDist)
00346 {
00347   // ________________________________________________________________
00348   //
00349   // Each coordinate is separately casted: If only the result
00350   // of the operations of the numerator of 'r' were casted,
00351   // overflows may occur when dealing with large integers or floats
00352 
00353   double xA = static_cast<double>(this->xSource());
00354   double yA = static_cast<double>(this->ySource());
00355 
00356   double xB = static_cast<double>(this->xTarget());
00357   double yB = static_cast<double>(this->yTarget());
00358 
00359   double yC = static_cast<double>(c.y());
00360   double xC = static_cast<double>(c.x());
00361   // ________________________________________________________________
00362 
00363   // Let C  be the point (XC,YC)
00364   //     AB be the line (XA,YA) to (XB,YB)
00365   //     L  be the length of the line segment AB
00366   //
00367   // r = ((YA-YC)(YA-YB)-(XA-XC)(XB-XA)) / L**2  [EQN1]
00368   //
00369   // Let I be the point of perpendicular projection of C onto AB.
00370   //
00371   //   if r < 0         I is on backward extension of AB
00372   //   if r > 1         I is on ahead extension of AB
00373   //   if 0 <= r <= 1   I is on AB
00374 
00375   double l = this->length();
00376   double r = (((yA - yC) * (yA - yB)) - ((xA - xC) * (xB - xA))) / (l * l);
00377 
00378   if ((r >= 0.) && (r <= 1.))
00379     {
00380       // C is on AB
00381       // => it must be close to AB
00382       return qgDist(c,*this) <= aDist;
00383     }
00384   else 
00385     {
00386       // C is on a backward or ahead extension of AB
00387       // => it must close to A or to B
00388       return    ( qgDist(c,this->accessSource()) <= aDist )
00389              ||
00390                 ( qgDist(c,this->accessTarget()) <= aDist );
00391     }
00392 }
00393 
00394 
00395 // SPECIALIZED VERSION, TO PRESERVE EFFICIENCY WHEN USING DOUBLES
00396 // => no cast/local variable needed
00397 
00398 template <>
00399 inline bool
00400 GenSegment<double>::contains(const GenPoint<double>& c, double aDist)
00401 {
00402   double l = this->length();
00403   double r =   (  (-this->dy() * (this->ySource() - c.y()))
00404                 - ( this->dx() * (this->xSource() - c.x())))
00405              /
00406                (l * l);
00407 
00408   if ((r >= 0.) && (r <= 1.))
00409     {
00410       // C is on AB
00411       // => it must be close to AB
00412       return qgDist(c,*this) <= aDist;
00413     }
00414   else 
00415     {
00416       // C is on a backward or ahead extension of AB
00417       // => it must close to A or to B
00418       return    ( qgDist(c,this->accessSource()) <= aDist )
00419              ||
00420                 ( qgDist(c,this->accessTarget()) <= aDist );
00421     }
00422 }
00423   
00424 
00425 // -------------------------------------------------------------------
00426 // O P E R A T O R S 
00427 // -------------------------------------------------------------------
00428 
00429 
00430 // ASSIGNMENT
00431 
00432 template <class T>
00433 inline GenSegment<T>&
00434 GenSegment<T>::operator=(const GenSegment<T>& aSeg)
00435 {
00436 // ___________________________________________________________
00437 //
00438 // Test removed for more efficiency
00439 // ___________________________________________________________
00440 //
00441   // Are left hand side and right hand side different objects?
00442   //   if (this != &aSeg)
00443   //     {
00444 // ___________________________________________________________
00445 
00446   AbstractGenPrimitive<T>::operator=(aSeg);
00447 // ___________________________________________________________
00448 //
00449   //     }
00450 // ___________________________________________________________
00451 
00452   return *this;
00453 }
00454 
00455 
00456 // SAME AS FUNCTION qgar::GenSegment::eq
00457 
00458 template <class T>
00459 inline bool
00460 GenSegment<T>::operator==(const GenSegment<T>& aSeg) const
00461 {
00462   return eq(aSeg);
00463 }
00464 
00465 
00466 // SAME AS FUNCTION qgar::GenSegment::notEq
00467 
00468 template <class T>
00469 inline bool
00470 GenSegment<T>::operator!=(const GenSegment<T>& aSeg) const
00471 {
00472   return notEq(aSeg);
00473 }
00474   
00475 
00476 // -------------------------------------------------------------------
00477 // F U N C T I O N A L   O P E R A T O R S 
00478 // -------------------------------------------------------------------
00479 
00480 
00481 // EQUALITY
00482 
00483 template <class T>
00484 bool
00485 GenSegment<T>::eq(const GenSegment<T>& aSeg) const
00486 {
00487   return (this->_source == aSeg._source) 
00488     && (this->_target == aSeg._target);
00489 }
00490 
00491 
00492 // INEQUALITY
00493 
00494 template <class T>
00495 bool
00496 GenSegment<T>::notEq(const GenSegment<T>& aSeg) const
00497 {
00498   return (this->_source != aSeg._source) 
00499     || (this->_target != aSeg._target);
00500 }
00501 
00502 
00503 // -------------------------------------------------------------------
00504 // S E R I A L I Z A T I O N / D E S E R I A L I Z A T I O N
00505 // -------------------------------------------------------------------
00506 
00507 
00508 template <class T>
00509 std::istream& 
00510 GenSegment<T>::read(std::istream& anInStream)
00511 {
00512   qgReadObjName(anInStream, "Segment");
00513 
00514   qgReadObjData(anInStream, this->_source);
00515   qgReadObjData(anInStream, this->_target);
00516 
00517   return anInStream;
00518 }
00519 
00520 template <class T>
00521 std::ostream& 
00522 GenSegment<T>::write(std::ostream& anOutStream) const
00523 {
00524   anOutStream << "Segment("
00525               << this->_source
00526               << ")("
00527               << this->_target
00528               << ')';
00529   return anOutStream;
00530 }
00531 
00532 
00533 // VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
00534 // V                                                                 V
00535 // V            IMPLEMENTATION OF PURE VIRTUAL FUNCTIONS             V
00536 // V               INHERITED FROM AbstractGenPrimitive               V
00537 // V                                                                 V
00538 // VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
00539 
00540 
00541 // -------------------------------------------------------------------
00542 // G E O M E T R I C A L   S T R U C T U R E   U P D A T E S
00543 // -------------------------------------------------------------------
00544 
00545 
00546 // THE SOURCE HAS BEEN CHANGED
00547 
00548 template <class T>
00549 void
00550 GenSegment<T>::updateSource()
00551 {
00552   // NOTHING TO DO
00553 }
00554 
00555 
00556 // THE TARGET HAS BEEN CHANGED
00557 
00558 template <class T>
00559 void
00560 GenSegment<T>::updateTarget()
00561 {
00562   // NOTHING TO DO
00563 }
00564 
00565 
00566 // BOTH SOURCE AND TARGET HAVE BEEN CHANGED
00567 
00568 template <class T>
00569 void
00570 GenSegment<T>::updateSourceTarget()
00571 {
00572   // NOTHING TO DO
00573 }
00574 
00575 
00576 // -------------------------------------------------------------------
00577 // G E O M E T R Y :   T R A N S L A T I O N 
00578 // -------------------------------------------------------------------
00579 
00580 
00581 template <class T>
00582 inline void
00583 GenSegment<T>::translate(T aTransX, T aTransY)
00584 {
00585   this->setSourceTarget(this->xSource() + aTransX,
00586                         this->ySource() + aTransY,
00587                         this->xTarget() + aTransX,
00588                         this->yTarget() + aTransY);
00589 }
00590 
00591 
00592 // VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
00593 // V                                                                 V
00594 // VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
00595 
00596 
00597 } // namespace qgar