library of assembled shared sources

http://lass.cocamware.com

triangle_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 
00044 
00045 #ifndef LASS_GUARDIAN_OF_INCLUSION_PRIM_TRIANGLE_2D_INL
00046 #define LASS_GUARDIAN_OF_INCLUSION_PRIM_TRIANGLE_2D_INL
00047 
00048 #include "prim_common.h"
00049 #include "triangle_2d.h"
00050 #include "line_2d.h"
00051 
00052 namespace lass
00053 {
00054 namespace prim
00055 {
00056 
00057 /** constructs an empty triangle.
00058  *  all vertices are (0, 0) and thus equal.
00059  */
00060 template <typename T>
00061 Triangle2D<T>::Triangle2D()
00062 {
00063 }
00064 
00065 
00066 
00067 /** Constructs a triangle through three points in positive sequence.
00068  */
00069 template <typename T>
00070 Triangle2D<T>::Triangle2D(const TPoint& iA, const TPoint& iB, const TPoint& iC)
00071 {
00072     vertices_[0] = iA;
00073     vertices_[1] = iB;
00074     vertices_[2] = iC;
00075 }
00076 
00077 
00078 
00079 /** @copydoc SimplePolygon2D::operator[]
00080  */
00081 template <typename T>
00082 const typename Triangle2D<T>::TPoint& Triangle2D<T>::operator[](int iIndexOfVertex) const
00083 {
00084     LASS_ASSERT(isInRange(iIndexOfVertex));
00085     return vertices_[iIndexOfVertex];
00086 }
00087 
00088 
00089 
00090 /** @copydoc SimplePolygon2D::operator[]
00091  */
00092 template <typename T>
00093 typename Triangle2D<T>::TPoint& Triangle2D<T>::operator[](int iIndexOfVertex)
00094 {
00095     LASS_ASSERT(isInRange(iIndexOfVertex));
00096     return vertices_[iIndexOfVertex];
00097 }
00098 
00099 
00100 
00101 /** @copydoc SimplePolygon2D::at
00102  */
00103 template <typename T>
00104 const typename Triangle2D<T>::TPoint& Triangle2D<T>::at(int iIndexOfVertex) const
00105 {
00106     const int i = num::mod(iIndexOfVertex, static_cast<unsigned>(size_));
00107     LASS_ASSERT(isInRange(i));
00108     return vertices_[i];
00109 }
00110 
00111 
00112 
00113 /** @copydoc SimplePolygon2D::at
00114  */
00115 template <typename T>
00116 typename Triangle2D<T>::TPoint& Triangle2D<T>::at(int iIndexOfVertex)
00117 {
00118     const int i = num::mod(iIndexOfVertex, static_cast<unsigned>(size_));
00119     LASS_ASSERT(isInRange(i));
00120     return vertices_[i];
00121 }
00122 
00123 
00124 
00125 /** @copydoc SimplePolygon2D::edge
00126  */
00127 template <typename T>
00128 const typename Triangle2D<T>::TLineSegment Triangle2D<T>::edge(int iIndexOfTailVertex) const
00129 {
00130     return TLineSegment(at(iIndexOfTailVertex), at(iIndexOfTailVertex + 1));
00131 }
00132 
00133 
00134 
00135 /** @copydoc SimplePolygon2D::vector
00136  */
00137 template <typename T>
00138 const typename Triangle2D<T>::TVector Triangle2D<T>::vector(int iIndexOfTailVertex) const
00139 {
00140     return at(iIndexOfTailVertex + 1) - at(iIndexOfTailVertex);
00141 }
00142 
00143 
00144 
00145 /** @copydoc SimplePolygon2D::isEmpty
00146  *  @par Triangle specific:
00147  *      if all vertices are equal, we assume the triangle is empty
00148  */
00149 template <typename T>
00150 const bool Triangle2D<T>::isEmpty() const
00151 {
00152     return vertices_[0] == vertices_[1] && vertices_[0] == vertices_[2];
00153 }
00154 
00155 
00156 
00157 /** @copydoc SimplePolygon2D::size
00158  */
00159 template <typename T>
00160 const int Triangle2D<T>::size() const
00161 {
00162     return size_;
00163 }
00164 
00165 
00166 
00167 /** @copydoc SimplePolygon2D::signedArea
00168  */
00169 template <typename T>
00170 const typename Triangle2D<T>::TValue Triangle2D<T>::signedArea() const
00171 {
00172     LASS_ASSERT(size_ == 3);
00173     return perpDot(vertices_[1] - vertices_[0], vertices_[2] - vertices_[0]) / T(2);
00174 }
00175 
00176 
00177 
00178 /** @copydoc SimplePolygon2D::area
00179  */
00180 template <typename T>
00181 const typename Triangle2D<T>::TValue Triangle2D<T>::area() const
00182 {
00183     return num::abs(signedArea());
00184 }
00185 
00186 
00187 
00188 /** @copydoc SimplePolygon2D::perimeter
00189  */
00190 template <typename T>
00191 const typename Triangle2D<T>::TValue Triangle2D<T>::perimeter() const
00192 {
00193     return distance(vertices_[0], vertices_[1]) +
00194            distance(vertices_[1], vertices_[2]) +
00195            distance(vertices_[2], vertices_[0]);
00196 }
00197 
00198 
00199 
00200 /** @copydoc SimplePolygon2D::vertexCentroid
00201  */
00202 template <typename T>
00203 const typename Triangle2D<T>::TPointH
00204 Triangle2D<T>::vertexCentroid() const
00205 {
00206     TPointH result = vertices_[0] + vertices_[1] + vertices_[2];
00207     return result;
00208 }
00209 
00210 
00211 
00212 /** @copydoc SimplePolygon2D::vertexCentroid
00213  */
00214 template <typename T> inline
00215 const typename Triangle2D<T>::TPointH
00216 Triangle2D<T>::surfaceCentroid() const
00217 {
00218     return vertexCentroid();
00219 }
00220 
00221 
00222 
00223 /** @copydoc SimplePolygon2D::isSimple
00224  *  @par Triangle specific:
00225  *      A triangle always is simple
00226  */
00227 template <typename T>
00228 const bool Triangle2D<T>::isSimple() const
00229 {
00230     return true;
00231 }
00232 
00233 
00234 
00235 /** @copydoc SimplePolygon2D::isConvex
00236  *  @par Triangle specific:
00237  *      A triangle always is convex
00238  */
00239 template <typename T>
00240 const bool Triangle2D<T>::isConvex() const
00241 {
00242     return true;
00243 }
00244 
00245 
00246 
00247 /** @copydoc SimplePolygon2D::orientation
00248  */
00249 template <typename T>
00250 const Orientation Triangle2D<T>::orientation() const
00251 {
00252     const TValue area = signedArea();
00253     if (area > TNumTraits::zero)
00254     {
00255         return oCounterClockWise;
00256     }
00257     else if (area < TNumTraits::zero)
00258     {
00259         return oClockWise;
00260     }
00261     else
00262     {
00263         return oInvalid;
00264     }
00265 }
00266 
00267 
00268 
00269 /** @copydoc SimplePolygon2D::isReflex
00270  *  @par Triangle specific:
00271  *      triangles never have reflex vertices, so always returns false.
00272  */
00273 template <typename T>
00274 const bool Triangle2D<T>::isReflex(int iIndexOfVertex) const
00275 {
00276     return false;
00277 }
00278 
00279 
00280 
00281 /** return true when a point is inside or on the edge of a triangle.
00282  */
00283 template <typename T>
00284 const bool Triangle2D<T>::contains(const TPoint& iP) const
00285 {
00286     return
00287         perpDot(vertices_[1] - vertices_[0], iP - vertices_[0]) >= TNumTraits::zero &&
00288         perpDot(vertices_[2] - vertices_[1], iP - vertices_[1]) >= TNumTraits::zero &&
00289         perpDot(vertices_[0] - vertices_[2], iP - vertices_[2]) >= TNumTraits::zero;
00290 }
00291 
00292 
00293 
00294 template <typename T>
00295 const Side Triangle2D<T>::classify(const TPoint& iP) const
00296 {
00297     return contains(iP) ? sInside : sOutside;
00298 }
00299 
00300 
00301 
00302 /** flip orientation of polygon.
00303  */
00304 template <typename T>
00305 void Triangle2D<T>::flip()
00306 {
00307     std::swap(vertices_[0], vertices_[2]);
00308 }
00309 
00310 
00311 
00312 // --- private -------------------------------------------------------------------------------------
00313 
00314 /** return if index of vertex is in range of the std::vector
00315  */
00316 template <typename T>
00317 const bool Triangle2D<T>::isInRange(int iIndexOfVertex) const
00318 {
00319     return iIndexOfVertex >= 0 && iIndexOfVertex < size_;
00320 }
00321 
00322 
00323 
00324 // --- free ----------------------------------------------------------------------------------------
00325 
00326 /** @relates lass::prim::Triangle2D
00327  */
00328 template <typename T>
00329 const T squaredDistance(const Triangle2D<T>& triangle, const Point2D<T>& point)
00330 {
00331     typedef typename Triangle2D<T>::TPoint TPoint;
00332     typedef typename Triangle2D<T>::TVector TVector;
00333     typedef typename Triangle2D<T>::TValue TValue;
00334     typedef typename Triangle2D<T>::TNumTraits TNumTraits;
00335 
00336     TValue sqrBest = TNumTraits::infinity;
00337     for (int k1 = 0, k0 = 2; k1 < 3; k0 = k1++)
00338     {
00339         const TPoint& tail = triangle[k0];
00340         const TPoint& head = triangle[k1];
00341         const TVector vector = point - tail;
00342         const TVector edge = head - tail;
00343         const TValue t = dot(vector, edge);
00344         const TValue tMax = dot(edge, edge);
00345         if (t > 0 && t < tMax)
00346         {
00347             const TVector rejected = vector - edge * (t / tMax);
00348             sqrBest = std::min(sqrBest, rejected.squaredNorm());
00349         }
00350         sqrBest = std::min(sqrBest, vector.squaredNorm());
00351     }
00352 
00353     return sqrBest;
00354 }
00355 
00356 
00357 
00358 /** @relates lass::prim::Triangle2D
00359  */
00360 template <typename T>
00361 const T distance(const Triangle2D<T>& triangle, const Point2D<T>& point)
00362 {
00363     return num::sqrt(squaredDistance(triangle, point));
00364 }
00365 
00366 
00367 
00368 /** @relates lass::prim::Triangle2D
00369  */
00370 template <typename T>
00371 io::XmlOStream& operator<<(io::XmlOStream& ioOStream, const Triangle2D<T>& iTriangle)
00372 {
00373     LASS_ENFORCE_STREAM(ioOStream) << "<Triangle2D>\n";
00374     for (unsigned i = 0; i < 3; ++i)
00375     {
00376         ioOStream << "<vertex id='" << i << "'>" << iTriangle[i] << "</vertex>\n";
00377     }
00378     ioOStream << "</Triangle2D>\n";
00379     return ioOStream;
00380 }
00381 
00382 
00383 
00384 /** @relates lass::prim::Triangle2D
00385  */
00386 template <typename T>
00387 std::ostream& operator<<(std::ostream& ioOStream, const Triangle2D<T>& iTriangle)
00388 {
00389     LASS_ENFORCE_STREAM(ioOStream) 
00390         << "{" << iTriangle[0] << ", " << iTriangle[1] << ", " << iTriangle[2] << "}";
00391     return ioOStream;
00392 }
00393 
00394 /** @relates lass::prim::Triangle2D
00395  */
00396 template<typename T>
00397 lass::io::MatlabOStream& operator<<(lass::io::MatlabOStream& oOStream,
00398                                     const Triangle2D<T>& iTriangle)
00399 {
00400     LASS_ENFORCE_STREAM(oOStream) << "lasthandle = patch(";
00401     oOStream << "[" << iTriangle[0].x << "," << iTriangle[1].x << "," << iTriangle[2].x << "],";
00402     oOStream << "[" << iTriangle[0].y << "," << iTriangle[1].y << "," << iTriangle[2].y << "],";
00403     oOStream << oOStream.color() << ");\n";
00404     return oOStream;
00405 }
00406 
00407 
00408 /** @relates lass::prim::Triangle2D
00409 *   Returns the surface of the partial Voronoi cell constructed around vertex 
00410 *   iIndexOfVertex (say vertex a in triangle abc).  Then the surface is determined by
00411 *   the quad built by a, the two midpoints on ab and ac and the intersection of the two
00412 *   perpendicular bisectors.
00413 */
00414 template <typename T>
00415 T partialVoronoiArea(const Triangle2D<T> iT, int iIndexOfVertex)
00416 {
00417     // compute the two midpoints
00418     typedef typename Triangle2D<T>::TPoint  TPoint;
00419     typedef typename Triangle2D<T>::TPointH TPointH;
00420     typedef typename Triangle2D<T>::TVector TVector;
00421     typedef Line2D<T> TLine;
00422     TPoint a = iT.at(iIndexOfVertex);
00423     TPoint b = iT.at(iIndexOfVertex+1);
00424     TPoint c = iT.at(iIndexOfVertex-1);
00425 
00426     TPointH abh = a+b;
00427     TPointH ach = a+c;
00428     TPoint ab = abh.affine();
00429     TPoint ac = ach.affine();
00430     TLine pbisAb(ab, (b-a).perp());
00431     TLine pbisAc(ac, (c-a).perp());
00432 
00433     TPoint m;
00434     LASS_ENFORCE(rOne == intersect(pbisAb, pbisAc,m));
00435 
00436     Triangle2D<T> aAbm(a,ab,m);
00437     Triangle2D<T> amAc(a,m,ac);
00438 
00439     return aAbm.area()+amAc.area();
00440 }
00441 
00442 }
00443 
00444 }
00445 
00446 #endif
00447 
00448 // EOF

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