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

_QGAR_point.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_point.TCC
00030  * @brief  Implementation of global functions which compute points.
00031  *
00032  * Computational geometry equations can be found in the FAQ section
00033  * of comp.graphics.algorithms and are based on
00034  * [<a href="Bibliography.html#Kirk-1992">Kirk,&nbsp;1992</a>],
00035  * pages 199-202, and
00036  * [<a href="Bibliography.html#ORourke-1994">O'Rourke,&nbsp;1994</a>],
00037  * pages 249-51.
00038  *
00039  * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Gérald Masini">Gérald Masini</a>
00040  * @date   February 03, 2005  18:53
00041  * @since  Qgar 2.2
00042  */
00043 
00044 
00045 
00046 // QGAR
00047 #include <qgarlib/math.H>
00048 
00049 
00050 
00051 namespace qgar
00052 {
00053 
00054 
00055 // -------------------------------------------------------------------
00056 // A R C S   A N D   C I R C L E S
00057 // -------------------------------------------------------------------
00058 
00059 
00060 // CENTER OF THE CIRCLE PASSING THROUGH THREE GIVEN POINTS
00061 // =======================================================
00062 // Return 'false' if the 3 points are collinear, 'true' otherwise
00063 
00064 
00065 // GENERIC VERSION
00066 
00067 template <class T>
00068 bool
00069 qgCircleCenter(const GenPoint<T>&  t,
00070                const GenPoint<T>&  p,
00071                const GenPoint<T>&  q,
00072                GenPoint<double>&  aCenter)
00073 {
00074   double tX = static_cast<double>(t.x());
00075   double tY = static_cast<double>(t.y());
00076 
00077   double pX = static_cast<double>(p.x());
00078   double pY = static_cast<double>(p.y());
00079 
00080   double qX = static_cast<double>(q.x());
00081   double qY = static_cast<double>(q.y());
00082 
00083   // The coordinates of the center of the circle passing through
00084   // points t, p, and q are:
00085   //
00086   //     A = pX - tX
00087   //     B = pY - tY
00088   //     C = qX - tX
00089   //     D = qY - tY
00090   //     E = A*(tX + pX) + B*(tY + pY)
00091   //     F = C*(tX + qX) + D*(tY + qY)
00092   //     G = 2 * (A*(qY - pY) - B*(qX - pX))
00093   //
00094   //     centerX = (D*E - B*F) / G
00095   //     centerY = (A*F - C*E) / G
00096   //
00097   // If G is zero then the three points are collinear
00098   // and no finite-radius circle through them exists
00099 
00100   double A = pX - tX;
00101   double B = pY - tY;
00102   double G = 2. * (A * (qY - pY) - B * (qX - pX));
00103 
00104   if (qgEq0(G))
00105     {
00106       return false;  // Collinear points
00107     }
00108 
00109   double C = qX - tX;
00110   double D = qY - tY;
00111   double E = A * (tX + pX) + B * (tY + pY);
00112   double F = C * (tX + qX) + D * (tY + qY);
00113 
00114   aCenter.setXY((D*E - B*F) / G, (A*F - C*E) / G);
00115 
00116   return true;
00117 }
00118 
00119 
00120 // SPECIALIZED VERSION, TO PRESERVE EFFICIENCY WHEN USING DOUBLES
00121 // => no local variables needed
00122 
00123 template <>
00124 inline bool
00125 qgCircleCenter<double>(const GenPoint<double>&  t,
00126                        const GenPoint<double>&  p,
00127                        const GenPoint<double>&  q,
00128                        GenPoint<double>&  aCenter)
00129 {
00130   double A = p.x() - t.x();
00131   double B = p.y() - t.y();
00132   double G = 2. * (A * (q.y() - p.y()) - B * (q.x() - p.x()));
00133 
00134   if (qgEq0(G))
00135     {
00136       return false;  // Collinear points
00137     }
00138 
00139   double C = q.x() - t.x();
00140   double D = q.y() - t.y();
00141   double E = A * (t.x() + p.x()) + B * (t.y() + p.y());
00142   double F = C * (t.x() + q.x()) + D * (t.y() + q.y());
00143 
00144   aCenter.setXY((D*E - B*F) / G, (A*F - C*E) / G);
00145 
00146   return true;
00147 }
00148 
00149 
00150 // -------------------------------------------------------------------
00151 // I N T E R S E C T I O N S
00152 // -------------------------------------------------------------------
00153 
00154 
00155 // INTERSECTION OF THE LINES SUPPORTING TWO GIVEN SEGMENTS
00156 // =======================================================
00157 // Return 'false' if the lines supporting the segments are
00158 // approximately collinear/parallel according to threshold
00159 // 'anAngle'. Otherwise, assign the intersection point to
00160 // 'aPt' and return 'true'.
00161 
00162 template <class T>
00163 bool
00164 qgIntersect(const GenSegment<T>& ab,
00165             const GenSegment<T>& cd,
00166             GenPoint<double>& i,
00167             double anAngle)
00168 {
00169   // Are the lines approximately collinear or parallel?
00170   if (qgEq(ab.theta(), cd.theta(), anAngle) ||
00171       qgEq(std::fabs(ab.theta() - cd.theta()), Math::QG_PI, anAngle))
00172     {
00173       return false;
00174     }
00175 
00176   // ________________________________________________________________
00177   //
00178   // Each coordinate is separately casted: If only the result of the
00179   // of the operations of the numerator of 'r' were casted, overflows
00180   // may occur when dealing with large integers or floats
00181 
00182   double xA = ab.xSource();
00183   double yA = ab.ySource();
00184   double xB = ab.xTarget();
00185   double yB = ab.yTarget();
00186 
00187   double xC = cd.xSource();
00188   double yC = cd.ySource();
00189   double xD = cd.xTarget();
00190   double yD = cd.yTarget();
00191   // ________________________________________________________________
00192 
00193   // Let A,B,C,D be 2-space position vectors.
00194   // Then the directed line segments AB & CD are given by:
00195   //
00196   //   AB = A + r(B - A), r in [0,1]
00197   //   CD = C + s(D - C), s in [0,1]
00198   //
00199   // If AB & CD intersect, then
00200   //
00201   //   A + r(B-A) = C + s(D-C): XA + r(XB - XA) = XC + s(XD - XC)
00202   //                            YA + r(YB - YA) = YC + s(YD - YC)
00203   //                            for r,s in [0,1]
00204   //
00205   // Solving the above for r and s yields
00206   //
00207   //       (YA - YC)(XD - XC) - (XA - XC)(YD - YC)
00208   //   r = ---------------------------------------    [EQN5]
00209   //       (XB - XA)(YD - YC) - (YB - YA)(XD - XC)
00210   //
00211   //       (YA - YC)(XB - XA) - (XA - XC)(YB - YA)
00212   //   s = ---------------------------------------    [EQN6]
00213   //       (XB - XA)(YD - YC) - (YB - YA)(XD - XC)
00214   //
00215   // Let I be the position vector of the intersection point, then
00216   //
00217   //   I = A + r(B - A):  XI = XA + r(XB - XA)   [EQN7]
00218   //                      YI = YA + r(YB - YA)   [EQN8]
00219   //
00220   // In EQN5 and EQN6, the denominator is:
00221   //   d = (XB - XA)(YD - YC) - (YB - YA)(XD - XC)
00222   //
00223   // Let abDX = XB - XA, adDY = YB - YA, cdDX = XD - XC, cdDY = YD - YC
00224   //   d = abDX*cdDY - abDY*cdDX
00225   //
00226   // EQN5 is: r = ((YA - YC)(XD - XC) - (XA - XC)(YD - YC)) / d
00227   //          r = (cdDX(YA - YC) - cdDY(XA - XC)) / d
00228   //
00229   // EQN7 is: XI = XA + r(XB - XA) = XA + r*abDX
00230   // EQN8 is: YI = YA + r(YB - YA) = YA + r*abDY
00231   //
00232   // By examining the values of r & s, you can also determine some
00233   // other limiting conditions:
00234   //
00235   //     If 0 <= r <= 1 & 0 <= s <=1          intersection exists
00236   //     If r < 0 or r > 1 or s < 0 or s > 1  line segments do not intersect
00237   //
00238   //     If the denominator in EQN5 is zero, AB & CD are parallel
00239   //     If the numerator in EQN5 is also zero, AB & CD are coincident
00240   //
00241   // If the intersection point of the 2 lines are needed (lines in this
00242   // context mean infinite lines) regardless whether the two line
00243   // segments intersect,
00244   // then if r > 1, I is located on extension of AB
00245   //      if r < 0, I is located on extension of BA
00246   //      if s > 1, I is located on extension of CD
00247   //      if s < 0, I is located on extension of DC
00248   //
00249   // Also note that the denominators of EQN5 & EQN6 are identical.
00250 
00251   double abDX = xB - xA;
00252   double abDY = yB - yA;
00253   double cdDX = xD - xC;
00254   double cdDY = yD - yC;
00255   
00256   double r =  ((cdDX * (yA - yC)) - (cdDY * (xA - xC)))
00257             /
00258               ((abDX * cdDY) - (abDY * cdDX));
00259 
00260   i.setXY(xA + (r * abDX), yA + (r * abDY));
00261 
00262   return true;
00263 }
00264 
00265 
00266 // SPECIALIZED VERSION, TO PRESERVE EFFICIENCY WHEN USING DOUBLES:
00267 // NO LOCAL VARIABLES NEEDED
00268 
00269 template <>
00270 inline bool
00271 qgIntersect<double>(const GenSegment<double>& ab,
00272                     const GenSegment<double>& cd,
00273                     GenPoint<double>& i,
00274                     double anAngle)
00275 {
00276   // Are the lines approximately collinear or parallel?
00277 
00278   if (qgEq(ab.theta(), cd.theta(), anAngle) ||
00279       qgEq(std::fabs(ab.theta() - cd.theta()), Math::QG_PI, anAngle))
00280     {
00281       return false;
00282     }
00283 
00284   double abDX = ab.dx();
00285   double abDY = ab.dy();
00286   double cdDX = cd.dx();
00287   double cdDY = cd.dy();
00288   
00289   double r =  (  (cdDX * (ab.ySource() - cd.ySource()))
00290                -
00291                  (cdDY * (ab.xSource() - cd.xSource())) )
00292             /
00293               ((abDX * cdDY) - (abDY * cdDX));
00294 
00295   i.setXY(ab.xSource() + (r * abDX), ab.ySource() + (r * abDY));
00296 
00297   return true;
00298 }
00299 
00300 
00301 // INTERSECTION OF THE LINES SUPPORTING TWO GIVEN Qgar SEGMENTS
00302 // ============================================================
00303 
00304 template <class T>
00305 inline bool
00306 qgIntersect(const GenQgarSegment<T>& aQSeg1,
00307             const GenQgarSegment<T>& aQSeg2,
00308             GenPoint<double>& aPt,
00309             double anAngle)
00310 {
00311   return qgIntersect(aQSeg1.accessGeomStructure(),
00312                      aQSeg2.accessGeomStructure(),
00313                      aPt,
00314                      anAngle);
00315 }
00316 
00317 
00318 // -------------------------------------------------------------------
00319 // M I D D L E   P O I N T S
00320 // -------------------------------------------------------------------
00321 
00322 
00323 // MIDDLE POINT OF A SEGMENT
00324 // =========================
00325 
00326 template <class T>
00327 inline GenPoint<double>
00328 qgMiddle(const GenSegment<T>& aSeg)
00329 {
00330   return qgMiddle(aSeg.accessSource(), aSeg.accessTarget());
00331 }
00332 
00333 
00334 // MIDDLE POINT OF A Qgar SEGMENT
00335 // ==============================
00336 
00337 template <class T>
00338 inline GenPoint<double>
00339 qgMiddle(const GenQgarSegment<T>& aQSeg)
00340 {
00341   return qgMiddle(aQSeg.accessSource(), aQSeg.accessTarget());
00342 }
00343 
00344 
00345 // MIDDLE POINT OF THE SEGMENT JOINING TWO POINTS
00346 // ==============================================
00347 
00348 template <class T>
00349 inline GenPoint<double>
00350 qgMiddle(const GenPoint<T>& aPt1, const GenPoint<T>& aPt2)
00351 {
00352   return GenPoint<double>((static_cast<double>(aPt1.xSource())
00353                            + static_cast<double>(aPt2.xTarget())) / 2.,
00354                           (static_cast<double>(aPt1.ySource())
00355                            + static_cast<double>(aPt2.yTarget())) / 2.);
00356 }
00357 
00358 
00359 // -------------------------------------------------------------------
00360 // P R O J E C T I O N S
00361 // -------------------------------------------------------------------
00362 
00363 
00364 // RETURN THE ORTHOGONAL PROJECTION OF A POINT ONTO A SEGMENT
00365 // ==========================================================
00366 
00367 template <class T>
00368 GenPoint<double>
00369 qgProjectPoint(const GenPoint<T>& aPt, const GenSegment<T>& aSeg)
00370 {
00371   GenPoint<double> p = GenPoint<double>(aPt);
00372   qgProject(p, aSeg);
00373 
00374   return p;
00375 }
00376 
00377 
00378 // ORTHOGONAL PROJECTION OF THE GIVEN POINT ONTO A SEGMENT
00379 // =======================================================
00380 
00381 
00382 template <class T>
00383 inline void
00384 qgProject(GenPoint<double>& aPt, const GenSegment<T>& aSeg)
00385 {
00386   qgProject(aPt, static_cast< GenSegment<double> >(aSeg));
00387 }
00388 
00389 
00390 // SPECIALIZED VERSION, TO PRESERVE EFFICIENCY WHEN USING DOUBLES
00391 
00392 
00393 template <>
00394 inline void
00395 qgProject<double>(GenPoint<double>& aPt, const GenSegment<double>& aSeg)
00396 {
00397   // ___________________________________________________________________
00398   //
00399   // Let the point be C (XC,YC) and the line be AB (XA,YA) to (XB,YB).
00400   // The length of the line segment AB is L:
00401   //
00402   //     L = ((XB-XA)**2 + (YB-YA)**2)**0.5
00403   // and
00404   //     r = ((YA - YC)(YA - YB) - (XA - XC)(XB - XA)) / L**2  [EQN1]
00405   //     s = ((YA - YC)(XB - XA) - (XA - XC)(YB - YA)) / L**2  [EQN2]
00406   //
00407   // Let I be the point of perpendicular projection of C onto AB:
00408   //
00409   //     XI = XA + r(XB - XA)  [EQN3]
00410   //     YI = YA + r(YB - YA)  [EQN4]
00411   // ___________________________________________________________________
00412 
00413   // Let dx = XB-XA, dy = YA-YB  in [EQN1]
00414 
00415   double dx =   aSeg.dx();
00416   double dy = - aSeg.dy();
00417 
00418   // =>  r = (dy * (YA-YC) - dx * (XA-XC)) / L**2  [EQN1]
00419 
00420   double l = aSeg.length();
00421   double r =   (   dy * (aSeg.ySource() - aPt.y()) 
00422                  - dx * (aSeg.xSource() - aPt.x()) )
00423              / (l * l);
00424     
00425   // =>  XI = XA + r * dx  [EQN3]
00426   // =>  YI = YA + r * dy  [EQN4]
00427 
00428   aPt.setX(aSeg.xSource() + (r * dx));
00429   aPt.setY(aSeg.ySource() - (r * dy));
00430 }
00431   
00432 
00433 
00434 // RETURN THE ORTHOGONAL PROJECTION OF A POINT ONTO A Qgar SEGMENT
00435 // ===============================================================
00436 
00437 
00438 template <class T>
00439 inline GenPoint<double>
00440 qgProjectPoint(const GenPoint<T>& aPt, const GenQgarSegment<T>& aQSeg)
00441 {
00442   return qgProjectPoint(aPt, aQSeg.accessGeomStructure());
00443 }
00444 
00445 
00446 // ORTHOGONAL PROJECTION OF THE GIVEN POINT ONTO A SEGMENT
00447 // =======================================================
00448 
00449 
00450 template <class T>
00451 inline void
00452 qgProject(GenPoint<double>& aPt,
00453           const GenQgarSegment<T>& aQSeg)
00454 {
00455   qgProject(aPt, aQSeg.accessGeomStructure());
00456 }
00457 
00458 
00459 // -------------------------------------------------------------------
00460 
00461 
00462 } // namespace qgar