LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiDelaunayTriangulation.h

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

Generated on Sat Apr 10 15:25:21 2010 for LTI-Lib by Doxygen 1.6.1