library of assembled shared sources

http://lass.cocamware.com

line_segment_2d.inl

Go to the documentation of this file.
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 #ifndef LASS_GUARDIAN_OF_INCLUSION_PRIM_LINE_SEGMENT_2D_INL
00044 #define LASS_GUARDIAN_OF_INCLUSION_PRIM_LINE_SEGMENT_2D_INL
00045 
00046 #include "line_segment_2d.h"
00047 #include "point_2dh.h"
00048 #include "../num/floating_point_consistency.h"
00049 
00050 namespace lass
00051 {
00052 namespace prim
00053 {
00054 
00055 template <typename T, class PP>
00056 LineSegment2D<T, PP>::LineSegment2D():
00057     tail_(),
00058     head_()
00059 {
00060     LASS_ASSERT(tail_.isZero());
00061     LASS_ASSERT(head_.isZero());
00062 }
00063 
00064 
00065 
00066 template <typename T, class PP>
00067 LineSegment2D<T, PP>::LineSegment2D(const TPoint& tail, const TPoint& head):
00068     tail_(tail),
00069     head_(head)
00070 {
00071 }
00072 
00073 
00074 
00075 template <typename T, class PP> inline
00076 const typename LineSegment2D<T, PP>::TPoint&
00077 LineSegment2D<T, PP>::tail() const
00078 {
00079     return tail_;
00080 }
00081 
00082 
00083 
00084 template <typename T, class PP> inline
00085 typename LineSegment2D<T, PP>::TPoint&
00086 LineSegment2D<T, PP>::tail()
00087 {
00088     return tail_;
00089 }
00090 
00091 
00092 
00093 template <typename T, class PP> inline
00094 const typename LineSegment2D<T, PP>::TPoint&
00095 LineSegment2D<T, PP>::head() const
00096 {
00097     return head_;
00098 }
00099 
00100 
00101 
00102 template <typename T, class PP> inline
00103 typename LineSegment2D<T, PP>::TPoint&
00104 LineSegment2D<T, PP>::head()
00105 {
00106     return head_;
00107 }
00108 
00109 
00110 
00111 /** Return point on ray by it's parameter.
00112  *  @return origin + t * direction
00113  */
00114 template <typename T, class PP>
00115 const typename LineSegment2D<T, PP>::TPoint
00116 LineSegment2D<T, PP>::point(TParam t) const
00117 {
00118     TParameterPolicy::enforceRange(t, TNumTraits::zero, TNumTraits::one);
00119     return tail_ + t * vector();
00120 }
00121 
00122 
00123 
00124 /** Return parameter of @e projection of @a iPoint on line segment.
00125  *  @warning the result can be out of bound [0, 1] regardless the parameter policy used.
00126  */
00127 template <typename T, class PP>
00128 const typename LineSegment2D<T, PP>::TValue
00129 LineSegment2D<T, PP>::t(const TPoint& point) const
00130 {
00131     const TVector v = vector();
00132     const TValue t1 =  dot(point - tail_, v);
00133     const TValue t2 = -dot(point - head_, v);
00134     const TValue t = std::max(t1,t2) / (t1 + t2);
00135     return t1 > t2 ? t : TNumTraits::one - t;
00136 }
00137 
00138 
00139 
00140 /** Return vector from tail to head.
00141  */
00142 template <typename T, class PP>
00143 const typename LineSegment2D<T, PP>::TVector
00144 LineSegment2D<T, PP>::vector() const
00145 {
00146     return head_ - tail_;
00147 }
00148 
00149 
00150 
00151 /** Return length of line segment.
00152  */
00153 template <typename T, class PP>
00154 const typename LineSegment2D<T, PP>::TValue
00155 LineSegment2D<T, PP>::length() const
00156 {
00157     const TVector v = vector();
00158     return v.norm();
00159 }
00160 
00161 
00162 
00163 template <typename T, class PP>
00164 T squaredDistance(const LineSegment2D<T, PP>& segment, const Point2D<T>& point)
00165 {
00166     typedef typename LineSegment2D<T, PP>::TVector TVector;
00167     typedef typename LineSegment2D<T, PP>::TValue TValue;
00168 
00169     const TVector edge = segment.vector();
00170     const TVector v = point - segment.tail();
00171     const TValue t = dot(v, edge);
00172     const TValue tMax = dot(edge, edge);
00173     if (t <= 0)
00174     {
00175         return v.squaredNorm();
00176     }
00177     if (t >= tMax)
00178     {
00179         return squaredDistance(segment.head(), point);
00180     }
00181     return (v - edge * (t / tMax)).squaredNorm();
00182 }
00183 
00184 
00185 
00186 template <typename T, class PP>
00187 T distance(const LineSegment2D<T, PP>& segment, const Point2D<T>& point)
00188 {
00189     return num::sqrt(squaredDistance(segment, point));
00190 }
00191 
00192 
00193 
00194 /** intersection of two line segments
00195  *  @relates LineSegment2D
00196  *  @param a [in]   line segment A
00197  *  @param b [in]   line segment B
00198  *  @param aT [out] parameter of intersection point on line segment A
00199  *  @param bT [out] parameter of intersection point on line segment B
00200  *  @return @arg rNone      the line segments don't intersect, they have no points in common.
00201  *                          @a tA and @a tB are not assigned.
00202  *          @arg rOne       both line segments have exactly one point in common.
00203  *                          @a tA and @a tB contain parameters of intersection point.
00204  *          @arg rInfinite  the line segments have more than one point in common, they overlap.
00205  *                          @a tA and @a tB are not assigned.
00206  */
00207 template <typename T, class PPa, class PPb>
00208 Result intersect(const LineSegment2D<T, PPa>& a, const LineSegment2D<T, PPb>& b, T& tA, T& tB)
00209 {
00210     typedef typename LineSegment2D<T, PPa>::TVector TVector;
00211     typedef typename LineSegment2D<T, PPa>::TValue TValue;
00212     typedef typename LineSegment2D<T, PPa>::TNumTraits TNumTraits;
00213     typedef num::Consistent<TValue> TConsistent;
00214 
00215     const TVector dirA(a.vector());
00216     const TVector dirB(b.vector());
00217 
00218     const TValue denominator = -perpDot(dirA, dirB);
00219     if (denominator == TNumTraits::zero)
00220     {
00221         const TValue tTail = a.t(b.tail());
00222         const TValue tHead = b.t(b.head());
00223         if ((tTail < TNumTraits::zero && tHead < TNumTraits::zero) ||
00224             (tTail > TNumTraits::one && tHead > TNumTraits::one))
00225         {
00226             return rNone; // complete seperated along axis
00227         }
00228         else
00229         {
00230             // overlapping on axis, yet, they can lay on "different" axes.
00231             //
00232             if (doubleTriangleArea(a.tail(), a.head(), b.tail()) == TNumTraits::zero)
00233             {
00234                 return rInfinite; // coincident axes
00235             }
00236             else
00237             {
00238                 return rNone; // parallel
00239             }
00240         }
00241     }
00242     else
00243     {
00244         const TVector difference = b.tail() - a.tail();
00245         const TConsistent candidateA = -perpDot(difference, dirB) / denominator;
00246         const TConsistent candidateB = perpDot(dirA, difference) / denominator;
00247         if (candidateA < TNumTraits::zero || candidateA > TNumTraits::one ||
00248             candidateB < TNumTraits::zero || candidateB > TNumTraits::one)
00249         {
00250             return rNone;
00251         }
00252         else
00253         {
00254             tA = candidateA.value();
00255             tB = candidateB.value();
00256             return rOne;
00257         }
00258     }
00259 }
00260 
00261 
00262 
00263 /** intersection of two line segments
00264  *  @relates Line2D
00265  *  @param a [in]   line segment A
00266  *  @param b [in]   line segment B
00267  *  @param point [out]  intersection point
00268  *  @return @arg rNone      the line segments don't intersect, they have no points in common.
00269  *                          @a point is not assigned.
00270  *          @arg rOne       both line segments have exactly one point in common.
00271  *                          @a point contains intersection point.
00272  *          @arg rInfinite  the line segments have more than one point in common, they overlap.
00273  *                          @a point is not assigned.
00274  */
00275 template <typename T, class PPa, class PPb>
00276 Result intersect(const LineSegment2D<T, PPa>& a, const LineSegment2D<T, PPb>& b, Point2D<T>& point)
00277 {
00278     T tA;
00279     T tB;
00280     const Result result = intersect(a, b, tA, tB);
00281     if (result == rOne)
00282     {
00283         Point2DH<T> intersection(a.point(tA));
00284         intersection += b.point(tB);
00285         point = intersection.affine(); // take average for more stable point.
00286     }
00287     return result;
00288 }
00289 
00290 
00291 /** @relates lass::prim::LineSegment2D
00292  */
00293 template <typename T, class PPa, class PPb> bool operator==(const LineSegment2D<T, PPa>& a, const LineSegment2D<T, PPb>& b)
00294 {
00295     return a.tail()==b.tail() && a.head()==b.head();
00296 }
00297 
00298 /** @relates lass::prim::LineSegment2D
00299  */
00300 template <typename T, class PPa, class PPb> bool operator!=(const LineSegment2D<T, PPa>& a, const LineSegment2D<T, PPb>& b)
00301 {
00302     return !(a==b);
00303 }
00304 
00305 
00306 /** @relates lass::prim::LineSegment2D
00307  */
00308 template<typename T, class PP>
00309 std::ostream& operator<<(std::ostream& stream, const LineSegment2D<T, PP>& segment)
00310 {
00311     LASS_ENFORCE_STREAM(stream) << "{T=" << segment.tail() << ", H=" << segment.head() << "}";
00312     return stream;
00313 }
00314 
00315 
00316 
00317 /** @relates lass::prim::LineSegment2D
00318  */
00319 template<typename T, class PP>
00320 io::XmlOStream& operator<<(io::XmlOStream& stream, const LineSegment2D<T, PP>& segment)
00321 {
00322     LASS_ENFORCE_STREAM(stream)
00323         << "<LineSegment2D>\n"
00324         << "<tail>" << segment.tail() << "</tail>\n"
00325         << "<head>" << segment.head() << "</head>\n"
00326         << "</LineSegment2D>\n";
00327 
00328     return stream;
00329 }
00330 
00331 
00332 /** @relates lass::prim::LineSegment2D
00333  */
00334 template<typename T, class PP>
00335 lass::io::MatlabOStream& operator<<(lass::io::MatlabOStream& stream, const LineSegment2D<T, PP>& segment)
00336 {
00337     LASS_ENFORCE_STREAM(stream) << "lasthandle = line(";
00338     stream << "[" << segment.tail().x << "," << segment.head().x << "],";
00339     stream << "[" << segment.tail().y << "," << segment.head().y << "],";
00340     stream << "'Color'," << stream.color() << ");\n";
00341     return stream;
00342 }
00343 
00344 
00345 }
00346 
00347 }
00348 
00349 #endif

Generated on Mon Nov 10 14:20:27 2008 for Library of Assembled Shared Sources by doxygen 1.5.7.1
SourceForge.net Logo