latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 2003, 2004, 2005, 2006 00003 * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany 00004 * 00005 * This file is part of the LTI-Computer Vision Library (LTI-Lib) 00006 * 00007 * The LTI-Lib is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public License (LGPL) 00009 * as published by the Free Software Foundation; either version 2.1 of 00010 * the License, or (at your option) any later version. 00011 * 00012 * The LTI-Lib is distributed in the hope that it will be 00013 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00014 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with the LTI-Lib; see the file LICENSE. If 00019 * not, write to the Free Software Foundation, Inc., 59 Temple Place - 00020 * Suite 330, Boston, MA 02111-1307, USA. 00021 */ 00022 00023 00024 /*-------------------------------------------------------------------- 00025 * project ....: LTI-Lib: Image Processing and Computer Vision Library 00026 * file .......: ltiDelaunayTriangulation.h 00027 * authors ....: Daniel Beier 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 7.5.2003 00030 * revisions ..: $Id: ltiDelaunayTriangulation.h,v 1.13 2006/02/08 12:16:48 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_DELAUNAY_TRIANGULATION_H_ 00034 #define _LTI_DELAUNAY_TRIANGULATION_H_ 00035 00036 #include "ltiPoint.h" 00037 #include "ltiMatrix.h" 00038 #include <vector> 00039 #include <list> 00040 00041 #include "ltiFunctor.h" 00042 00043 namespace lti { 00044 /** 00045 * This class performs a delaunay triangulation on a given 00046 * std::vector<tpoint<T> >. A triangulation T of a given set of 00047 * points P is called Delaunay if the circumcircle of any triangle 00048 * of T does not contain a point of P. The triangulation is 00049 * therefore angle-optimal. A triangulation T is angle-optimal if 00050 * the sorted vector of angles A(T)=(alpha_1,alpha_2,...,alpha_3m) 00051 * is the largest angle-vector. An angle vector A(T) is larger then 00052 * A(T') if there exists an i so that alpha_j = alpha'_j for every j 00053 * < i and alpha_i > alpha'_i. Optimal triangulations avoid "skinny" 00054 * triangles. The implemented algorithm is in O(n*log(n)) where n is 00055 * the number of points. The discription of the algorithm can be 00056 * found in: de Berg, van Krefeld: Computational Geometry (Chapter 00057 * 9: Delaunay Triangulations). 00058 * 00059 * \b Note: Depending on the supplied data this algorithm may fail 00060 * due to numerical and implementation issues. It usually works well 00061 * for points that correspond to pixel positions in a image. For 00062 * other uses adjusting the parameters::epsilon and 00063 * parameters::specialPointsFactor will probably lead to a 00064 * satisfactory result. 00065 * 00066 * This failure can manifest itself in two ways: 00067 * - An assertion (l != 4) is thrown in debug mode (a segmentation 00068 * fault in release). Probably need higher value for 00069 * parameters::specialPointsFactor 00070 * - There are edges missing on the convex hull, solve as above. 00071 */ 00072 template <class T> 00073 class delaunayTriangulation : public functor { 00074 public: 00075 /** 00076 * the parameters for the class delaunayTriangulation 00077 */ 00078 class parameters : public functor::parameters { 00079 public: 00080 /** 00081 * default constructor 00082 */ 00083 parameters() : functor::parameters() { 00084 epsilon=0.001f; 00085 specialPointsFactor=100.f; 00086 }; 00087 00088 /** 00089 * copy constructor 00090 * @param other the parameters object to be copied 00091 */ 00092 parameters(const parameters& other) : functor::parameters() { 00093 copy(other); 00094 }; 00095 00096 /** 00097 * destructor 00098 */ 00099 ~parameters() {}; 00100 00101 /** 00102 * returns name of this type 00103 */ 00104 const char* getTypeName() const { 00105 return "delaunayTriangulation::parameters"; 00106 }; 00107 00108 /** 00109 * copy the contents of a parameters object 00110 * @param other the parameters object to be copied 00111 * @return a reference to this parameters object 00112 */ 00113 parameters& copy(const parameters& other) { 00114 # ifndef _LTI_MSC_6 00115 // MS Visual C++ 6 is not able to compile this... 00116 functor::parameters::copy(other); 00117 # else 00118 // ...so we have to use this workaround. 00119 // Conditional on that, copy may not be virtual. 00120 functor::parameters& (functor::parameters::* p_copy) 00121 (const functor::parameters&) = functor::parameters::copy; 00122 (this->*p_copy)(other); 00123 # endif 00124 00125 epsilon = other.epsilon; 00126 specialPointsFactor = other.specialPointsFactor; 00127 00128 return *this; 00129 }; 00130 00131 /** 00132 * copy the contents of a parameters object 00133 * @param other the parameters object to be copied 00134 * @return a reference to this parameters object 00135 */ 00136 parameters& operator=(const parameters& other) { 00137 return copy(other); 00138 }; 00139 00140 /** 00141 * returns a pointer to a clone of the parameters 00142 */ 00143 virtual functor::parameters* clone() const { 00144 return new parameters(*this); 00145 }; 00146 00147 /** 00148 * write the parameters in the given ioHandler 00149 * @param handler the ioHandler to be used 00150 * @param complete if true (the default) the enclosing begin/end will 00151 * be also written, otherwise only the data block will be written. 00152 * @return true if write was successful 00153 */ 00154 # ifndef _LTI_MSC_6 00155 virtual bool write(ioHandler& handler, const bool complete=true) const 00156 # else 00157 /** 00158 * this function is required by MSVC only, as a workaround for a 00159 * very awful bug, which exists since MSVC V.4.0, and still by 00160 * V.6.0 with all bugfixes (so called "service packs") remains 00161 * there... This method is also public due to another bug, so please 00162 * NEVER EVER call this method directly: use write() instead 00163 */ 00164 bool writeMS(ioHandler& handler, const bool complete=true) const 00165 # endif 00166 { 00167 bool b = true; 00168 if (complete) { 00169 b = handler.writeBegin(); 00170 } 00171 00172 if (b) { 00173 lti::write(handler,"specialPointsFactor",specialPointsFactor); 00174 lti::write(handler,"epsilon",epsilon); 00175 } 00176 00177 # ifndef _LTI_MSC_6 00178 // This is the standard C++ code, which MS Visual C++ 6 is not able to 00179 // compile... 00180 b = b && functor::parameters::write(handler,false); 00181 # else 00182 bool (functor::parameters::* p_writeMS)(ioHandler&,const bool) const = 00183 functor::parameters::writeMS; 00184 b = b && (this->*p_writeMS)(handler,false); 00185 # endif 00186 00187 if (complete) { 00188 b = b && handler.writeEnd(); 00189 } 00190 00191 return b; 00192 } 00193 00194 # ifdef _LTI_MSC_6 00195 virtual bool write(ioHandler& handler, const bool complete=true) const { 00196 // ...we need this workaround to cope with another really awful MSVC bug. 00197 return writeMS(handler,complete); 00198 } 00199 # endif 00200 00201 /** 00202 * read the parameters from the given ioHandler 00203 * @param handler the ioHandler to be used 00204 * @param complete if true (the default) the enclosing begin/end will 00205 * be also written, otherwise only the data block will be written. 00206 * @return true if write was successful 00207 */ 00208 //virtual bool read(ioHandler& handler,const bool complete=true); 00209 # ifndef _LTI_MSC_6 00210 virtual bool read(ioHandler& handler, const bool complete=true) 00211 # else 00212 /** 00213 * this function is required by MSVC only, as a workaround for a 00214 * very awful bug, which exists since MSVC V.4.0, and still by 00215 * V.6.0 with all bugfixes (so called "service packs") remains 00216 * there... This method is also public due to another bug, so please 00217 * NEVER EVER call this method directly: use read() instead 00218 */ 00219 bool readMS(ioHandler& handler, const bool complete=true) 00220 # endif 00221 { 00222 bool b = true; 00223 if (complete) { 00224 b = handler.readBegin(); 00225 } 00226 00227 if (b) { 00228 lti::read(handler,"specialPointsFactor",specialPointsFactor); 00229 lti::read(handler,"epsilon",epsilon); 00230 } 00231 00232 # ifndef _LTI_MSC_6 00233 // This is the standard C++ code, which MS Visual C++ 6 is not able to 00234 // compile... 00235 b = b && functor::parameters::read(handler,false); 00236 # else 00237 bool (functor::parameters::* p_readMS)(ioHandler&,const bool) = 00238 functor::parameters::readMS; 00239 b = b && (this->*p_readMS)(handler,false); 00240 # endif 00241 00242 if (complete) { 00243 b = b && handler.readEnd(); 00244 } 00245 00246 return b; 00247 } 00248 00249 # ifdef _LTI_MSC_6 00250 virtual bool read(ioHandler& handler, const bool complete=true) { 00251 // ...we need this workaround to cope with another really awful MSVC 00252 // bug. 00253 return readMS(handler,complete); 00254 } 00255 # endif 00256 00257 // ------------------------------------------------ 00258 // the parameters 00259 // ------------------------------------------------ 00260 00261 //TODO: comment the parameters of your functor 00262 // If you add more parameters manually, do not forget to do following: 00263 // 1. indicate in the default constructor the default values 00264 // 2. make sure that the copy member also copy your new parameters 00265 // 3. make sure that the read and write members also read and 00266 // write your parameters 00267 00268 00269 /** 00270 * The algorithm uses a virtual triangle consisting of three 00271 * special points. It must at least include all given 00272 * points. However, the distance of these points from the actual 00273 * points influences the bahaviour of the algorithm with respect 00274 * to small dents in the convex hull. 00275 * 00276 * A large value will give you the complete, correct Delaunay 00277 * triangulation. A small value excludes triangles that share 00278 * one edge with the convex hull and have a 'large' angle 00279 * opposite that edge. This behavior can be useful in some 00280 * applications where 'degenerate' triangles are not useful. 00281 * 00282 * Default: 100. Gives the correct result for most applications 00283 */ 00284 float specialPointsFactor; 00285 00286 /** 00287 * This value is used for determining when a point falls on an 00288 * edge. Thus the construction of the triangulation can be 00289 * influenced quite strongly by this value. 00290 * 00291 * Note that the values depends on the given data. 00292 * 00293 * Default: 0.001. Works well for pixel position ranges 00294 */ 00295 float epsilon; 00296 }; 00297 00298 private: 00299 //this class defines a directed acyclic graph (DAG) which helps to 00300 //locate triangles that contain a given point. 00301 class dagNode { 00302 public: 00303 //references to the three points of the triangle. Whenever this 00304 //method is used it is assumed that a std::vector<tpoint> exists 00305 //somewhere that corresponds to the indices stored in 00306 //pointIndex[3] 00307 int pointIndex[3]; 00308 00309 //if a node is a leaf then it stores a reference to a triangle 00310 //of the current triangulation. If it is an inner node this 00311 //class-attribute is not used. 00312 int triVecIndex; 00313 00314 //child nodes 00315 std::list<dagNode*> children; 00316 }; 00317 00318 public: 00319 00320 /** 00321 * default constructor 00322 */ 00323 delaunayTriangulation(); 00324 00325 /** 00326 * Construct a functor using the given parameters 00327 */ 00328 delaunayTriangulation(const parameters& par); 00329 00330 /** 00331 * copy constructor 00332 * @param other the object to be copied 00333 */ 00334 delaunayTriangulation(const delaunayTriangulation& other); 00335 00336 /** 00337 * destructor 00338 */ 00339 virtual ~delaunayTriangulation(); 00340 00341 /** 00342 * returns the name of this type ("delaunayTriangulation") 00343 */ 00344 virtual const char* getTypeName() const; 00345 00346 //TODO: comment your apply methods! 00347 00348 /** 00349 * Performing a delaunay triangulation on the given set of points 00350 * and storing the result in 'triangles'. 00351 * @param src the source data. 00352 * @param triangles a std::vector containing the triangles as a 00353 * result of the delaunay triangulation. the indices 0..2 belong 00354 * to the first triangle, 3..5 to the second, and so on. 00355 * @return true if successful or false otherwise. 00356 */ 00357 bool apply(const std::vector<tpoint<T> >& src,std::vector<int>& triangles); 00358 00359 /** 00360 * copy data of "other" functor. 00361 * @param other the functor to be copied 00362 * @return a reference to this functor object 00363 */ 00364 delaunayTriangulation& copy(const delaunayTriangulation& other); 00365 00366 /** 00367 * alias for copy member 00368 * @param other the functor to be copied 00369 * @return a reference to this functor object 00370 */ 00371 delaunayTriangulation& operator=(const delaunayTriangulation& other); 00372 00373 /** 00374 * returns a pointer to a clone of this functor. 00375 */ 00376 virtual functor* clone() const; 00377 00378 /** 00379 * returns used parameters 00380 */ 00381 const parameters& getParameters() const; 00382 00383 //void testTriangulation(const std::vector<tpoint<T> >& src, 00384 // const std::vector<int>& tri) const; 00385 00386 private: 00387 00388 void initialize(const std::vector<tpoint<T> >& src, 00389 std::vector<int>& triangles); 00390 00391 // The algorithm starts with a triangle defined by three points 00392 // (private class-members) so that all points from the given point 00393 // list are inside this triangle. This routine computes these 00394 // three points. 00395 void calcSpecialPoints(const std::vector<tpoint<T> >& src); 00396 00397 // splitting one triangle into three when point r (inside of 00398 // triangle) is inserted. 00399 void split1to3(const std::vector<tpoint<T> >& src, 00400 std::vector<int>& triangles, int r, dagNode* leaf); 00401 00402 // splitting two triangles into four when point r (on edge p1,p2) 00403 // is inserted 00404 void split2to4(const std::vector<tpoint<T> >& src, 00405 std::vector<int>& triangles, 00406 int r, int p1, int p2, int k, int l, 00407 dagNode* leaf1, dagNode* leaf2); 00408 00409 // Tests if a point is inside a triangle 00410 int insideTest(const int ind_p, const std::vector<tpoint<T> >& src, 00411 const int ind1, const int ind2, const int ind3, T& minDist) const; 00412 00413 // flip an edge if delaunay property is violated 00414 void legalizeEdge(const std::vector<tpoint<T> >& src, int r, int p1, int p2, std::vector<int>& triangles); 00415 00416 // test if an edge violates the delaunay property 00417 bool isIllegal(const std::vector<tpoint<T> >& src, int r, int p1, int p2, int l); 00418 00419 // Find the circle that circumscribes 3 points 00420 bool getCircle(const std::vector<tpoint<T> >& src, int p1, int p2, int p3, tpoint<T>& center, double& rad) const; 00421 00422 // calculate the squared euclidean distance 00423 inline double euclDistSquare(const tpoint<T>& p1, const tpoint<T>& p2) const; 00424 00425 // insertion sort with three elements 00426 void sort3(int& i1, int& i2, int& i3) const; 00427 00428 // clean-up memory 00429 void deleteDAG(); 00430 00431 // this directed acyclic graph keeps track of all the 00432 // triangulations made. Its root is the triangle special points. 00433 // Every time a triangle splits into two or three triangles when a 00434 // new point is inserted the leaf node of the graph belonging to 00435 // this triangle becomes an inside node and two or three child 00436 // nodes are created (Two if the point is on an edge and three 00437 // otherwise). 00438 dagNode* dagRoot; 00439 00440 // special points that define an initial large triangle for the algorithm 00441 tpoint<T> specialPoint[3]; 00442 00443 // for quick access to all leaves of the DAG with point i this 00444 // vector is used 00445 std::vector<std::list<dagNode*> > dagAccessList; 00446 00447 // to free memory at the end store all nodes that were created with 00448 // new in this list 00449 std::list<dagNode*> dagEraseList; 00450 00451 }; 00452 } 00453 00454 #endif