library of assembled shared sources |
http://lass.cocamware.com |
00001 /** @file 00002 * @author Bram de Greve (bramz@users.sourceforge.net) 00003 * @author Tom De Muer (tomdemuer@users.sourceforge.net) 00004 * 00005 * *** BEGIN LICENSE INFORMATION *** 00006 * 00007 * The contents of this file are subject to the Common Public Attribution License 00008 * Version 1.0 (the "License"); you may not use this file except in compliance with 00009 * the License. You may obtain a copy of the License at 00010 * http://lass.sourceforge.net/cpal-license. The License is based on the 00011 * Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover 00012 * use of software over a computer network and provide for limited attribution for 00013 * the Original Developer. In addition, Exhibit A has been modified to be consistent 00014 * with Exhibit B. 00015 * 00016 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 00017 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific 00018 * language governing rights and limitations under the License. 00019 * 00020 * The Original Code is LASS - Library of Assembled Shared Sources. 00021 * 00022 * The Initial Developer of the Original Code is Bram de Greve and Tom De Muer. 00023 * The Original Developer is the Initial Developer. 00024 * 00025 * All portions of the code written by the Initial Developer are: 00026 * Copyright (C) 2004-2007 the Initial Developer. 00027 * All Rights Reserved. 00028 * 00029 * Contributor(s): 00030 * 00031 * Alternatively, the contents of this file may be used under the terms of the 00032 * GNU General Public License Version 2 or later (the GPL), in which case the 00033 * provisions of GPL are applicable instead of those above. If you wish to allow use 00034 * of your version of this file only under the terms of the GPL and not to allow 00035 * others to use your version of this file under the CPAL, indicate your decision by 00036 * deleting the provisions above and replace them with the notice and other 00037 * provisions required by the GPL License. If you do not delete the provisions above, 00038 * a recipient may use your version of this file under either the CPAL or the GPL. 00039 * 00040 * *** END LICENSE INFORMATION *** 00041 */ 00042 00043 00044 00045 /** @class lass::prim::Line2D 00046 * @brief 2D Line 00047 * @author Bram de Greve [BdG] 00048 * @date 2003 00049 * 00050 * I assume if you look to this class, you'll wonder ... "where the heck did all the code go?" 00051 * Hah, I'll tell ya. There is more than one possible model to represent a line. We can 00052 * use a cartesian equation @c N.P+S=0, or we can use a parametric equation @c P=S+t*U. 00053 * This class lets you choose what implementation you want: a pure cartesian model, a pure 00054 * parametric model, or a model that combines both. This is done by moving all code to 00055 * implemenations impl::Line2DCartesian, impl::Line2DParametric or impl::Line2DCombined. Line2D 00056 * will inherit its implementation of the model you've choosen. You can select the one you 00057 * want by specifying the template parameter @e EquationPolicy. You can either use Cartesian 00058 * (which is the default), Parametric or Combined. Each of them will model the line 00059 * differently. They all provide the same interface, but might have different results. They 00060 * might have different memory footprints, different performances, and are optimized for 00061 * different purposes. Cartesian will select an implementation that only uses the cartesian 00062 * equation and will be the smallest and the fastest for most purposes (that's why it is the 00063 * default :). But sometimes, you might more like the Parametric model, because it has 00064 * better support for direction vectors, but it'll have to calculate the normal on the spot if 00065 * you need it. Combined is the workhorse for heavy duties and implements both.. 00066 * 00067 * @section template arguments 00068 * 00069 * - @a T: the underlying data type, the proton. 00070 * - @a @ref EquationPolicy: chooses the model: Cartesian, Parametric or Combined 00071 * - @a @ref NormalizingPolicy: enables automatic normalizing or not: Normalized or Unnormalized 00072 * 00073 * @section common_interface common interface 00074 * 00075 * Anyway, let me give you some general info on this whole Line2D thing. Though there are 00076 * three different implentations, they all have the same interface. We'll explore them by this 00077 * common interface: 00078 * 00079 * @subsection type_definitions type definitions 00080 * 00081 * - @c TSelf: the type of @a this 00082 * - @c TImpl: type of implemantion, can be impl::Line2DCartesian, impl::Line2DParametric or 00083 * impl::Line2DCombined. 00084 * - @c TNormalizingPolicy: the type you've used as NormalizingPolicy. 00085 * - @c TPoint: type of a afine point in space. 00086 * - @c TVector: type of a vector in space. 00087 * - @c TValue: same as util::CallTraits<T>::TValue. 00088 * - @c TParam: same as util::CallTraits<T>::TParam. 00089 * - @c TReference: same as util::CallTraits<T>::TReference. 00090 * - @c TConstReference: same as util::CallTraits<T>::TConstReference. 00091 * - @c TNumTraits: same as num::NumTraits<T>. 00092 * 00093 * @subsection constructors 00094 * 00095 * @par Line2D(): 00096 * the default constructor brings the line in an invalid state. normal and/or direction vector 00097 * will have zero length, which indicates for this invalid state. 00098 * 00099 * @par Line2D(const TPoint& iSupport, const TPoint& iPoint): 00100 * construct a line through two points. The parametric equation @a P=S+t*U is going to 00101 * be constructed as following: iSupport will be the support point @a S, and direction vector @a U 00102 * will be drawn from the support point to @a iPoint: @a U = @a iPointU - @a iSupport. The cartesian 00103 * equation @a N.P+d==0 is constructed as following: the normal @a N=perpDot(U) and @a d is determined 00104 * by demaning that @a N.S+d==0. 00105 * 00106 * @par Line2D(const TPoint& iSupport, const TVector& iDirection): 00107 * constructs a line through one support point and one direction vector (the parametric equation, 00108 * anyone? :). For the parametric equation @a P=S+t*U, we have @a iSupport for @a S, @a iDirection 00109 * for @a U. Again the cartesian equation @a N.P+d==0 is given by @a N=perpDot(U) and 00110 * @a N.S+d==0. 00111 * 00112 * @par Line2D(const TPoint& iSupport, const TVector& iNormal): 00113 * constructs a line through a support point and a normal vector. For the parametric equation 00114 * @a P=S+t*U, we have @a iSupport for @a S, and @a U=-perpDot(N). The cartesian @a N.P+d==0 is 00115 * simple, we have @a iNormal for @a N and @a d can be found by @a N.S+d==0. 00116 * 00117 * @par Line2D(const TVector& iNormal, TParam iD): 00118 * construct a line by a normal vector and fourth value (cartesian equation? :). For the 00119 * parametric equation @a P=S+t*U, all have to generated: for @a S we use the point @a -iD*iNormal 00120 * that is the closest point of the line to the origin, @a U is given by @a U=-perpDot(N). 00121 * For the cartesian equation @a N.P+d==0, we of course use @a N = @a iNormal and @a d = @a iD. 00122 * 00123 * @subsection accessors 00124 * 00125 * After construction, all vectors are normalized depending on the @a NormalizingPolicy you've 00126 * choosen as template argument. if the normal vector @a N is scaled, then @a d is scaled as well, so 00127 * it still represents the same line. 00128 * 00129 * Now, we have a series of accessors that give you access to the internal data of the line, 00130 * including support point, direction vectors, normal vector, ... Only Line2DCombined will be 00131 * able to pull these directly from its internals, but the others don't have all data aboard, so 00132 * they have to generate them. Be carefull, because it's not always what you suspect. 00133 * 00134 * @par const TPoint support(): 00135 * returns the support point of the line. If you used a support point for the construction of the 00136 * line, models Line2DParametric and Line2DCombined will give you back this original one, 00137 * exactly till the last bit. Line2DCartesian doesn't keep track of support points, so it has to 00138 * create one if you ask for it. It uses @a -d*N, the point of the line that is closest to the 00139 * origin. Mind you that this one probably will not be the same as the original one, totally 00140 * different even! Of course, if you used a cartesian equation to construct the line (without any 00141 * support point), then all three models need to generate a support point at some point: @a -d*N. 00142 * In that case, all three models @e will return the same support point. 00143 * 00144 * @par const TVector direction(): 00145 * get the direction vector of the line. almost same story as for @c support(). If you've created 00146 * the line by a direction vector ot two points (which leads to the direction vector), then models 00147 * Line2DParametric and Line2DCombined will give you back these originals 00148 * (for Unnormalized lines only! but in case of Normalized lines, they still correspond with the 00149 * original directions). Line2DCartesian has to regenerate them, but it will result in the same 00150 * direction vector as the others. 00151 * 00152 * @par void getCartesian(TVector& oNormal, TReference oD): 00153 * gets normal vector and d-value for the cartesian equation. Now, this is the first one 00154 * Line2DCartesian has aboard itself. Line2DCombined also has it, but now it's up to 00155 * Line2DParametric to generate some stuff :) Though, it's less worse than the other way around. 00156 * This is because the parametric equation contains more information on the support point, and 00157 * doesn't have to 'invent' anything like Line2DCartesian has to. Actually, in theory, all three 00158 * models should return the same normal and d-value. In practice however, we have to deal with 00159 * numerical imprecisions. so the result of Line2DParametric can differ a little in the last bits. 00160 * not a big difference, but enough to be inequal. 00161 * 00162 * @par const TVector normal(): 00163 * returns only the normal vector of the cartesian equation. For Line2DParametric we have again 00164 * the same remark as for getDirections and getReciprocals: it uses getCartesian anyway, so that 00165 * might be faster if you both need the normal and d-value. 00166 * 00167 * @par TValue d(): 00168 * same as normal(), but returns only the value @a d instead of the normal vector. 00169 * 00170 * @subsection methods_cartesian cartesian methods 00171 * 00172 * So far the accessors. let's get to cooler stuff. For most of this stuff, we need the cartesian 00173 * equation. Line2DCartesian and Line2DCombined have it on board, but Line2DParametric will 00174 * have to generate it each call. Keep that in mind! 00175 * 00176 * @par Side classify(const TPoint& iPoint): 00177 * tells at which side of the line we can find the point iPoint: the front (sFront), the back 00178 * (sBack), or right on the surface (sSurface). the front is the side where the normal sticks or 00179 * points to. The back is the other one. iPoint is exactly one the surface if @a N.iPoint+d==0. 00180 * Since we need the parametric equation, Line2DParametric might have a performance hit here. 00181 * 00182 * @par TValue equation(const TPoint& iPoint): 00183 * fills in the point @a iPoint in the cartesian equation and returns the resutl. @a N.iPoint+d will 00184 * usually not be equal to zero (it's only zero for points on the line). This method returns what 00185 * it is equal to. i.e. it returns @a N.iPoint+d. For Normalized lines this is the same as the 00186 * distance of @a iPoint to the line, but not for Unnormalized lines, keep that in mind! If you 00187 * need the distance, used @c signedDistances() as described below. Again you might have a 00188 * performance hit for the Line2DParametric model because of the need of the cartesian equation. 00189 * 00190 * @par TValue signedDistance(const TPoint& iPoint): 00191 * returns the distance of the point to the line, but signed. it will be positive for points in 00192 * front of the line, and negative for the ones in the back (also see: @c classify()). The 00193 * real (absolute) distances is simply the absolute value of the result. For Normalized lines 00194 * @c signedDistances() will be equal to @c equation(). But for Unnormalized lines 00195 * signedDistances still divides through the normal's length Again performance hit for 00196 * Line2DParametric because of the need of the cartesian equation. 00197 * 00198 * @par TVector reject(const TPoint& iPoint): 00199 * returns rejection of @a iPoint by the line. This is a bit tricky to explain. If you have a 00200 * support point @a S, then this rejection is the part of @a iPoint-S that is parallel to the normal 00201 * vector (or orthogonal to the line). This would be the same as the rejection of @a iPoint-S 00202 * (given by @c reject(iPoint-S), see below). But more descriptive might be: it is the vector you 00203 * have to add to the projection of this point on the line (given by @c project(iPoint), see below), 00204 * to get back @a iPoint: @c iPoint==project(iPoint)+reject(iPoint). Again performance hit for 00205 * Line2DParametric because of the cartesian equation. 00206 * 00207 * @par TVector reject(const TVector& iVector): 00208 * returns rejection of @a iVector by the line. This is already somewhat easier. the rejection of 00209 * @a iVector is that part of @a iVector that is parallel to the normal vector of the line. You can 00210 * also say that it is the orthogonal projection of @a iVector on the normal vector. Or the part of 00211 * iVector that is orthogonal to the line. Again performance hit for Line2DParametric because 00212 * of the cartersian equation. 00213 * 00214 * @par TPoint project(const TPoint& iPoint): 00215 * return the orthogonal projection of @a iPoint on the line. It is the point on the line that is 00216 * the closest one to @a iPoint. If you draw a line through @a iPoint parallel to the normal vector, 00217 * this projection is the point where this line intersects the line. It is know that in theory 00218 * @c iPoint==project(iPoint)+reject(iPoint). Again performance hit for Line2DParametric because 00219 * of the cartesian equation. 00220 * 00221 * @par TVector project(const TVector& iVector): 00222 * return the orthogonal projection of @a iVector on the line. It is the part of @a iVector that is 00223 * parallel to the line, or orthogonal to the normal vector. It is known that in theory 00224 * @c iVector==project(iVector)+reject(iVector). Again performance hit for Line2DParametric because 00225 * of the cartesian equation. 00226 * 00227 * @par TPoint reflect(const TPoint& iPoint): 00228 * return the reflection of @a iPoint in the line. It is the point at the same distance of the 00229 * line, but at the exact opposite side of the line. If you draw a line through iPoint parallel 00230 * to the normal vector, it's the only other point on that line that is at the same (absolute) 00231 * distance of the line. If you walk from iPoint to the intersection point of the line and the 00232 * line, and you walk further the same distance again, you arrive at reflection of iPoint. It is 00233 * known that in theory @c reflect(iPoint)==project(iPoint)-reject(iPoint). Again performance hit 00234 * for Line2DParametric because of the cartesian equation. 00235 * 00236 * @par TVector reflect(const TVector& iVector): 00237 * return the reflection of @a iVector in the line. It's the vector of which the orthogonal part to 00238 * the line is flipped. It is know that @c reflect(iVector)==project(iVector)-reject(iVector). 00239 * Again performance hit for Line2DParametric because of the cartesian equation. 00240 * 00241 * @subsection methods_parametric parametric methods 00242 * 00243 * So far functions for the cartesian boys. Now some stuff for parametric fellows. It's about how 00244 * we can get a point of the line if we now its parametr @a t, and how we can find @t if we know 00245 * the point on the line. 00246 * 00247 * @par TPoint point(TParam iT): 00248 * returns a point of the parametric equation @c P=S+iT*U. In case of 00249 * Line2DCartesian, we have the same remarks as for @a direction(): not only we have 00250 * a performance hit, we probably also have to deal with totally different direction vectors than 00251 * the ones we have put in the constructor. 00252 * 00253 * @par TValue t(const TPoint& iPoint): 00254 * returns a value @a t so that @c iPoint==S+t*U. In theory, if you put this back in @c point(), 00255 * you should end up with the projection of @a iPoint: @c point(t(iPoint))==project(iPoint) ? 00256 * Well, this is not totally true. In practice, numerical imprecisions will probably give you a 00257 * slightly different result. You'll be very close, but the last bits will differ enough to make the 00258 * them inequal. But with some epsilons, you'll be alright. 00259 * 00260 * @subsection misc_methods misc. methods 00261 * 00262 * @par void flip(): 00263 * flips the line so that the front becomes the back and the back becomes the front. For the 00264 * cartesian equation, this is done by negating the normal and d: @c N=-N and @c d=-d. 00265 * Of the parametric equation, direction vector U is flipped: @c U=-U. 00266 * 00267 * @par bool isValid(): 00268 * returns true if the interal data represents a valid line, and false if not. A line is valid 00269 * if none of the direction vectors nor the normal vector are zero vectors. And above of that, 00270 * the direction vectors may not be colinear. Of course, we only test internal data. We will not 00271 * generate direction vectors (in case of Line2DCartesian), just to test the if they are valid. 00272 * We can safely do that, because we know that if the normal vector is valid, then the generated 00273 * directions will be too. 00274 * 00275 * @subsection free functions 00276 * 00277 * There are some free functions listed below: distances and intersections. 00278 * They are common for all lines and can handle mixed equation policies (two lines with different 00279 * equation policies). 00280 */ 00281 00282 00283 00284 #ifndef LASS_GUARDIAN_OF_INCLUSION_PRIM_LINE_2D_H 00285 #define LASS_GUARDIAN_OF_INCLUSION_PRIM_LINE_2D_H 00286 00287 #include "prim_common.h" 00288 #include "point_2d.h" 00289 #include "equation_policy.h" 00290 #include "normalizing_policy.h" 00291 #include "impl/line_2d_impl.h" 00292 00293 00294 namespace lass 00295 { 00296 namespace prim 00297 { 00298 00299 template 00300 < 00301 typename T, 00302 class EquationPolicy = Cartesian, 00303 class NormalizingPolicy = Normalized 00304 > 00305 class Line2D: public impl::Line2DImpl<T, EquationPolicy, NormalizingPolicy>::Type 00306 { 00307 public: 00308 typedef Line2D<T, EquationPolicy, NormalizingPolicy> TSelf; 00309 typedef typename impl::Line2DImpl<T, EquationPolicy, NormalizingPolicy>::Type TImpl; 00310 00311 typedef typename TImpl::TPoint TPoint; 00312 typedef typename TImpl::TVector TVector; 00313 typedef typename TImpl::TParam TParam; 00314 typedef typename TImpl::TValue TValue; 00315 typedef typename TImpl::TReference TReference; 00316 typedef typename TImpl::TConstReference TConstReference; 00317 typedef typename TImpl::TNumTraits TNumTraits; 00318 00319 00320 template <typename U> 00321 struct Rebind 00322 { 00323 typedef Line2D<U, EquationPolicy, NormalizingPolicy> Type; 00324 }; 00325 00326 Line2D(); 00327 Line2D(const TPoint& iSupport, const TPoint& iPoint); 00328 Line2D(const TPoint& iSupport, const TVector& iDir); 00329 Line2D(const TVector& iNormal, const TPoint& iSupport); 00330 Line2D(const TVector& iNormal, TParam iD); 00331 00332 const Side classify(const TPoint& iPoint) const; 00333 const TValue signedDistance(const TPoint& iPoint) const; 00334 const TValue squaredDistance(const TPoint& iPoint) const; 00335 const Side classify(const TPoint& iPoint, TParam iRelativeTolerance) const; 00336 const TValue signedDistance(const TPoint& iPoint, TParam iRelativeTolerance) const; 00337 const TValue squaredDistance(const TPoint& iPoint, TParam iRelativeTolerance) const; 00338 00339 /* 00340 typedef NormalizingPolicy TNormalizingPolicy; 00341 00342 typedef Point2D<T> TPoint; 00343 typedef TPoint::TVector TVector; 00344 00345 typedef TPoint::TValue TValue; 00346 typedef TPoint::TParam TParam; 00347 typedef TPoint::TReference TReference; 00348 typedef TPoint::TConstReference TConstReference; 00349 typedef TPoint::TNumTraits TNumTraits; 00350 00351 enum { dimension = TPoint::dimension }; 00352 00353 const TPoint support() const; 00354 const TVector direction() const; 00355 00356 void getCartesian(TVector& oNormal, TReference oD) const; 00357 const TVector& normal() const; 00358 TConstReference d() const; 00359 00360 Side classify(const TPoint& iPoint) const; 00361 TValue equation(const TPoint& iPoint) const; 00362 TValue signedDistance(const TPoint& iPoint) const; 00363 TValue squaredDistance(const TPoint& iPoint) const; 00364 00365 TVector reject(const TPoint& iPoint) const; 00366 TVector reject(const TVector& iVector) const; 00367 TPoint project(const TPoint& iPoint) const; 00368 TVector project(const TVector& iVector) const; 00369 TPoint reflect(const TPoint& iPoint) const; 00370 TVector reflect(const TVector& iVector) const; 00371 00372 TPoint point(TParam iT) const; 00373 TValue t(const TPoint& iPoint) const; 00374 00375 void flip(); 00376 bool isValid() const; 00377 */ 00378 }; 00379 00380 00381 00382 template <typename T, class EP, class NP> 00383 T signedDistance(const Point2D<T>& iA, const Line2D<T, EP, NP>& iB); 00384 00385 template <typename T, class EPa, class NPa, class EPb, class NPb> 00386 T signedDistance(const Line2D<T, EPa, NPa>& iA, const Line2D<T, EPb, NPb>& iB); 00387 00388 template <typename T, class EPa, class NPa, class EPb, class NPb> 00389 Result intersect(const Line2D<T, EPa, NPa>& iA, const Line2D<T, EPb, NPb>& iB, 00390 T& oTa, T& oTb); 00391 00392 template <typename T, class EPa, class NPa, class EPb, class NPb> 00393 Result intersect(const Line2D<T, EPa, NPa>& iA, const Line2D<T, EPb, NPb>& iB, 00394 Point2D<T>& oPoint); 00395 00396 template <typename T> 00397 io::XmlOStream& operator<<(io::XmlOStream& ioOStream, const Line2D<T, Cartesian>& iLine); 00398 template <typename T> 00399 io::XmlOStream& operator<<(io::XmlOStream& ioOStream, const Line2D<T, Parametric>& iLine); 00400 template <typename T> 00401 io::XmlOStream& operator<<(io::XmlOStream& ioOStream, const Line2D<T, Combined>& iLine); 00402 00403 00404 00405 } 00406 00407 } 00408 00409 #include "line_2d.inl" 00410 00411 #ifdef LASS_GUARDIAN_OF_INCLUSION_PRIM_RAY_2D_H 00412 # include "line_2d_ray_2d.h" 00413 #endif 00414 00415 #endif 00416 00417 // --- END OF FILE ------------------------------------------------------------------------------
Generated on Mon Nov 10 14:20:09 2008 for Library of Assembled Shared Sources by 1.5.7.1 |