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_distance.TCC 00030 * @brief Implementation of global functions to compute distances 00031 * between primitives. 00032 * 00033 * Computational geometry equations can be found in the FAQ section 00034 * of comp.graphics.algorithms. They are based on 00035 * [<a href="Bibliography.html#Kirk-1992">Kirk, 1992</a>], 00036 * pages 199-202, and 00037 * [<a href="Bibliography.html#ORourke-1994">O'Rourke, 1994</a>], 00038 * pages 249-51. 00039 * 00040 * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Gérald Masini">Gérald Masini</a> 00041 * @date February 03, 2005 17:58 00042 * @since Qgar 2.2 00043 */ 00044 00045 00046 00047 // STD 00048 #include <cmath> 00049 00050 00051 00052 namespace qgar 00053 { 00054 00055 00056 // ------------------------------------------------------------------- 00057 // DIFFERENCE BETWEEN X COORDINATES OF THE GIVEN POINTS 00058 // ------------------------------------------------------------------- 00059 00060 00061 template <class T> 00062 inline T 00063 qgDX(const GenPoint<T>& aPt1, const GenPoint<T>& aPt2) 00064 { 00065 return aPt1.x() - aPt2.x(); 00066 } 00067 00068 00069 // ------------------------------------------------------------------- 00070 // DIFFERENCE BETWEEN Y COORDINATES OF THE GIVEN POINTS 00071 // ------------------------------------------------------------------- 00072 00073 00074 template <class T> 00075 inline T 00076 qgDY(const GenPoint<T>& aPt1, const GenPoint<T>& aPt2) 00077 { 00078 return aPt1.y() - aPt2.y(); 00079 } 00080 00081 00082 // ------------------------------------------------------------------- 00083 // DISTANCE BETWEEN TWO POINTS 00084 // ------------------------------------------------------------------- 00085 00086 00087 template <class T> 00088 double 00089 qgDist(const GenPoint<T>& aPt1, const GenPoint<T>& aPt2) 00090 { 00091 return hypot(static_cast<double>(qgDX(aPt1,aPt2)), 00092 static_cast<double>(qgDY(aPt1,aPt2))); 00093 } 00094 00095 00096 // ------------------------------------------------------------------- 00097 // DISTANCE BETWEEN POINT aPt AND ITS A PERPENDICULAR PROJECTION 00098 // ONTO THE LINE PASSING THROUGH POINTS aPt1 AND aPt2 00099 // ------------------------------------------------------------------- 00100 00101 00102 // Let C be the point (XC,YC) 00103 // AB be the line segment (XA,YA) to (XB,YB) 00104 // L be the length of AB 00105 // 00106 // L = ((XB-XA)**2 + (YB-YA)**2)**0.5 00107 // and 00108 // s = ((YA-YC)(XB-XA) - (XA-XC)(YB-YA)) / L**2 00109 // 00110 // Let I be the point of perpendicular projection of C onto AB 00111 // d be the distance from C to I 00112 // 00113 // d = s * L 00114 // d = ((YA-YC)(XB-XA) - (XA-XC)(YB-YA)) / L 00115 00116 00117 template <class T> 00118 double 00119 qgDist(const GenPoint<T>& c, 00120 const GenPoint<T>& a, 00121 const GenPoint<T>& b) 00122 { 00123 // Each coordinate is separately casted: If only the result of the 00124 // of the operations of the numerator of 'd' were casted, an 00125 // overflow may occur when dealing with large integers or floats 00126 00127 double xA = static_cast<double>(a.x()); 00128 double yA = static_cast<double>(a.y()); 00129 00130 double xB = static_cast<double>(b.x()); 00131 double yB = static_cast<double>(b.y()); 00132 00133 double yC = static_cast<double>(c.y()); 00134 double xC = static_cast<double>(c.x()); 00135 00136 return std::fabs( (((yA - yC) * (xB - xA)) - ((xA - xC) * (yB - yA))) 00137 / 00138 qgDist(a,b) ); 00139 } 00140 00141 00142 // SPECIALIZED VERSION, TO PRESERVE EFFICIENCY WHEN USING DOUBLES 00143 // => no local variables needed 00144 00145 template <> 00146 inline double 00147 qgDist<double>(const GenPoint<double>& c, 00148 const GenPoint<double>& a, 00149 const GenPoint<double>& b) 00150 { 00151 return 00152 std::fabs( ( ((a.y() - c.y()) * (b.x() - a.x())) 00153 - ((a.x() - c.x()) * (b.y() - a.y())) ) 00154 / 00155 qgDist(a,b) ); 00156 } 00157 00158 00159 // ------------------------------------------------------------------- 00160 // DISTANCE BETWEEN POINT (0,0) AND ITS PERPENDICULAR 00161 // PROJECTION ONTO THE LINE SUPPORTING A SEGMENT 00162 // ------------------------------------------------------------------- 00163 00164 00165 template <class T> 00166 inline double 00167 qgDist(const GenSegment<T>& aSeg) 00168 { 00169 return std::fabs(aSeg.rho()); 00170 } 00171 00172 00173 // ------------------------------------------------------------------- 00174 // DISTANCE BETWEEN POINT (0,0) AND ITS PERPENDICULAR 00175 // PROJECTION ONTO THE LINE SUPPORTING A Qgar SEGMENT 00176 // ------------------------------------------------------------------- 00177 00178 00179 template <class T> 00180 inline double 00181 qgDist(const GenQgarSegment<T>& aQSeg) 00182 { 00183 return qgDist(aQSeg.accessGeomStructure()); 00184 } 00185 00186 00187 // ------------------------------------------------------------------- 00188 // DISTANCE BETWEEN A POINT AND ITS PERPENDICULAR 00189 // PROJECTION ONTO THE LINE SUPPORTING A SEGMENT 00190 // ------------------------------------------------------------------- 00191 00192 00193 template <class T> 00194 inline double 00195 qgDist(const GenPoint<T>& aPt, const GenSegment<T>& aSeg) 00196 { 00197 return qgDist(aPt, aSeg.accessSource(), aSeg.accessTarget()); 00198 } 00199 00200 00201 // ------------------------------------------------------------------- 00202 // DISTANCE BETWEEN A POINT AND ITS PERPENDICULAR 00203 // PROJECTION ONTO THE LINE SUPPORTING A Qgar SEGMENT 00204 // ------------------------------------------------------------------- 00205 00206 00207 template <class T> 00208 inline double 00209 qgDist(const GenPoint<T>& c, const GenQgarSegment<T>& aQSeg) 00210 { 00211 return qgDist(c, aQSeg.accessGeomStructure()); 00212 } 00213 00214 00215 // ------------------------------------------------------------------- 00216 // SQUARED DISTANCE BETWEEN TWO POINTS 00217 // ------------------------------------------------------------------- 00218 00219 00220 template <class T> 00221 double 00222 qgSqr_dist(const GenPoint<T>& aPt1, const GenPoint<T>& aPt2) 00223 { 00224 double dX = qgDX(aPt1,aPt2); 00225 double dY = qgDY(aPt1,aPt2); 00226 00227 return (dX * dX) + (dY * dY); 00228 } 00229 00230 00231 // ------------------------------------------------------------------- 00232 00233 00234 } // namespace qgar