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_angle.TCC 00030 * @brief Implementation of global utilities for primitives. 00031 * 00032 * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Gérald Masini">Gérald Masini</a> 00033 * @date February 03, 2005 18:28 00034 * @since Qgar 2.2 00035 */ 00036 00037 00038 00039 // QGAR 00040 #include <qgarlib/math.H> 00041 00042 00043 00044 namespace qgar 00045 { 00046 00047 00048 /* 00049 * O 00050 * +---------------> X 00051 * |\ | 00052 * | \ <-' 00053 * | \ angle (in radians unless specified) 00054 * | \ 00055 * | 00056 * v 00057 * 00058 * Y 00059 * 00060 * - The origin of the coordinate system is at top left corner 00061 * - Angles are clockwise from the X axis 00062 */ 00063 00064 00065 00066 /* ------------------------------------------------------------------- 00067 * ANGLE WITH THE X AXIS AND A VECTOR 00068 * ------------------------------------------------------------------- 00069 * 00070 * ----->/ 00071 * O O / / 00072 * +---------------> X +---------|-------------> X 00073 * | \ | | | / | 00074 * | \ <-' angle | angle \_ /__/ 00075 * | \ | / 00076 * | + aPt1 | + aPt2 00077 * | \ | ^ 00078 * | \ | / 00079 * | v | / 00080 * v + aPt2 v + aPt1 00081 * 00082 * Y Y 00083 * 00084 * ------------------------------------------------------------------- 00085 */ 00086 00087 // IN [0, 2PI[ RADIANS 00088 00089 template <class T> 00090 double 00091 qgAngle(const GenPoint<T>& aPt1, const GenPoint<T>& aPt2) 00092 { 00093 double angle = atan2(static_cast<double>(aPt2.y() - aPt1.y()), 00094 static_cast<double>(aPt2.x() - aPt1.x())); 00095 00096 return (angle < 0.) ? (Math::QG_2PI + angle) : angle; 00097 } 00098 00099 00100 // IN [0, 360[ DEGREES 00101 00102 template <class T> 00103 inline double 00104 qgAngleDegrees(const GenPoint<T>& aPt1, const GenPoint<T>& aPt2) 00105 { 00106 return qgRadiansToDegrees(qgAngle(aPt1, aPt2)); 00107 } 00108 00109 00110 /* ------------------------------------------------------------------- 00111 * ANGLE BETWEEN TWO VECTORS DETERMINED BY 3 POINTS 00112 * ------------------------------------------------------------------- 00113 * 0 00114 * +---------------------> X +---------------------> X 00115 * | | ---- 00116 * | | / \ 00117 * | aPt1 | | v 00118 * | +--------->+ aPt2 | | +------->+ aPt3 00119 * | \ | | \ __\ 00120 * | \ <-' | \ 00121 * | \ | \ 00122 * | v | v 00123 * | + aPt3 | + aPt2 00124 * v v 00125 * 00126 * Y Y 00127 * 00128 * ------------------------------------------------------------------- 00129 */ 00130 00131 00132 // IN [0, 2PI[ RADIANS 00133 00134 template <class T> 00135 inline double 00136 qgAngle(const GenPoint<T>& aPt1, 00137 const GenPoint<T>& aPt2, 00138 const GenPoint<T>& aPt3) 00139 { 00140 return qgAngle(aPt1, aPt2, aPt1, aPt3); 00141 } 00142 00143 00144 // IN [0, 360[ DEGREES 00145 00146 template <class T> 00147 inline double 00148 qgAngleDegrees(const GenPoint<T>& aPt1, 00149 const GenPoint<T>& aPt2, 00150 const GenPoint<T>& aPt3) 00151 { 00152 return qgRadiansToDegrees(qgAngle(aPt1, aPt2, aPt3)); 00153 } 00154 00155 00156 /* ------------------------------------------------------------------- 00157 * ANGLE BETWEEN TWO VECTORS DETERMINED BY 4 POINTS 00158 * ------------------------------------------------------------------- 00159 * 00160 * 0 00161 * +----------------------> X +-------------------------> X 00162 * | | ---- 00163 * | | / \ 00164 * | aPt1 | | v aPt3 00165 * | \----+------>+ aPt2 | | \-----+------>+ aPt4 00166 * | \ | | \ __\ 00167 * | aPt3 + | | \ 00168 * | <--' | + aPt1 00169 * | \ | \ 00170 * | v | v 00171 * | + aPt4 | + aPt2 00172 * v v 00173 * 00174 * Y Y 00175 * 00176 * ------------------------------------------------------------------- 00177 */ 00178 00179 // IN [0, 2PI[ RADIANS 00180 00181 template <class T> 00182 double 00183 qgAngle(const GenPoint<T>& aPt1, 00184 const GenPoint<T>& aPt2, 00185 const GenPoint<T>& aPt3, 00186 const GenPoint<T>& aPt4) 00187 { 00188 double ang12 = qgAngle(aPt1, aPt2); 00189 double ang13 = qgAngle(aPt3, aPt4); 00190 00191 return 00192 (ang12 > ang13) 00193 ? (ang13 - ang12 + Math::QG_2PI) 00194 : (ang13 - ang12); 00195 } 00196 00197 00198 // IN [0, 360[ DEGREES 00199 00200 template <class T> 00201 inline double 00202 qgAngleDegrees(const GenPoint<T>& aPt1, 00203 const GenPoint<T>& aPt2, 00204 const GenPoint<T>& aPt3, 00205 const GenPoint<T>& aPt4) 00206 { 00207 return qgRadiansToDegrees(qgAngle(aPt1, aPt2, aPt3, aPt4)); 00208 } 00209 00210 00211 00212 /* ------------------------------------------------------------------- 00213 * ANGLE BETWEEN THE X AXIS AND A SEGMENT 00214 * ------------------------------------------------------------------- 00215 * 00216 * O O 00217 * +-----------------> X +-----------------> X 00218 * | \ | | \ | 00219 * | \ <-' angle | \ <-' angle 00220 * | \ | \ 00221 * | + aPt1 | + aPt2 00222 * | \ | \ 00223 * | \ | \ 00224 * | \ | \ 00225 * v + aPt2 v + aPt1 00226 * 00227 * Y Y 00228 * 00229 * ------------------------------------------------------------------- 00230 */ 00231 00232 // IN [0, 2PI[ RADIANS 00233 00234 template <class T> 00235 double 00236 qgSlope(const GenPoint<T>& aPt1, const GenPoint<T>& aPt2) 00237 { 00238 double s = qgAngle(aPt1, aPt2); 00239 00240 return (s >= Math::QG_PI) ? (s - Math::QG_PI) : s; 00241 } 00242 00243 00244 // IN [0, 360[ DEGREES 00245 00246 template <class T> 00247 inline double 00248 qgSlopeDegrees(const GenPoint<T>& aPt1, const GenPoint<T>& aPt2) 00249 { 00250 return qgRadiansToDegrees(qgSlope(aPt1, aPt2)); 00251 } 00252 00253 00254 // ------------------------------------------------------------------- 00255 00256 00257 } // namespace qgar