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 .......: ltiMinimumSpanningTree.h 00027 * authors ....: Jens Paustenbach 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 8.4.2003 00030 * revisions ..: $Id: ltiMinimumSpanningTree.h,v 1.8 2006/02/08 12:36:45 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_MINIMUM_SPANNING_TREE_H_ 00034 #define _LTI_MINIMUM_SPANNING_TREE_H_ 00035 00036 #include "ltiFunctor.h" 00037 #include "ltiL2Distance.h" 00038 #include "ltiWeightedGraph.h" 00039 00040 namespace lti { 00041 00042 /** 00043 * This class computes minimum spanning trees. There are two ways 00044 * two compute a minimum spanning trees. Either reduce a given 00045 * weighted graph to its minimum spanning tree or compute the 00046 * minimum spanning tree direct from a given data set. If you only 00047 * want to reduce a weighted graph, just use the apply methods. If 00048 * you want to compute the tree from a given data set (keys and 00049 * values), there a three possibilities. 00050 * -# The keys (data points) are elements of a std::vector 00051 * Then use the apply method of this class. 00052 * -# A matrix where each row represents one key (data point). Use the 00053 * class minimumSpanningTreeOfKeyValuetype 00054 * -# A matrix where each element represents one key (data point). 00055 * In this case use the class minimumSpanningTreeOfKeytype 00056 * 00057 * A minimum spanning tree has the following template types: 00058 * - \a K: the key used for building the MST 00059 * - \a V: the value or data contained in each node of the tree 00060 * default is int for an id. 00061 * - \a Distantor: policy class for the calculation of the distance 00062 * between two keys in the tree (see below). Default is the square 00063 * of the L2 distance lti::l2SquareDistantor. 00064 * 00065 * The Distantor must implement the operator() which takes two 00066 * arguments of type K and calculates their distance. It must define 00067 * a type Distantor::distance_type which is also the return type of 00068 * the operator. See lti::l2SquareDistantor for an example. 00069 */ 00070 template <class K, class V=int, class Distantor=l2SquareDistantor<K> > 00071 class minimumSpanningTree : public functor { 00072 public: 00073 00074 /** 00075 * return type of a call to the distantor, Distantor::distance_type 00076 */ 00077 typedef typename Distantor::distance_type distance_type; 00078 00079 /** 00080 * the parameters for the class minimumSpanningTree 00081 */ 00082 class parameters : public functor::parameters { 00083 public: 00084 /** 00085 * default constructor 00086 */ 00087 parameters() : functor::parameters() { 00088 00089 nbNeighbors = 7; 00090 useCompleteGraph = false; 00091 } 00092 00093 /** 00094 * copy constructor 00095 * @param other the parameters object to be copied 00096 */ 00097 parameters(const parameters& other) : functor::parameters() { 00098 copy(other); 00099 } 00100 00101 /** 00102 * destructor 00103 */ 00104 ~parameters() { 00105 } 00106 00107 /** 00108 * returns name of this type 00109 */ 00110 const char* getTypeName() const { 00111 return "minimumSpanningTree<K,V,Distantor>::parameters"; 00112 } 00113 00114 /** 00115 * copy the contents of a parameters object 00116 * @param other the parameters object to be copied 00117 * @return a reference to this parameters object 00118 */ 00119 parameters& copy(const parameters& other) { 00120 # ifndef _LTI_MSC_6 00121 // MS Visual C++ 6 is not able to compile this... 00122 functor::parameters::copy(other); 00123 # else 00124 // ...so we have to use this workaround. 00125 // Conditional on that, copy may not be virtual. 00126 functor::parameters& (functor::parameters::* p_copy) 00127 (const functor::parameters&) = 00128 functor::parameters::copy; 00129 (this->*p_copy)(other); 00130 # endif 00131 00132 nbNeighbors = other.nbNeighbors; 00133 useCompleteGraph = other.useCompleteGraph; 00134 00135 return *this; 00136 } 00137 00138 /** 00139 * copy the contents of a parameters object 00140 * @param other the parameters object to be copied 00141 * @return a reference to this parameters object 00142 */ 00143 parameters& operator=(const parameters& other) { 00144 return copy(other); 00145 } 00146 00147 /** 00148 * returns a pointer to a clone of the parameters 00149 */ 00150 virtual functor::parameters* clone() const { 00151 return new parameters(*this); 00152 } 00153 00154 # ifndef _LTI_MSC_6 00155 /** 00156 * write the parameters in the given ioHandler 00157 * @param handler the ioHandler to be used 00158 * @param complete if true (the default) the enclosing begin/end will 00159 * be also written, otherwise only the data block will be written. 00160 * @return true if write was successful 00161 */ 00162 virtual bool write(ioHandler& handler,const bool complete=true) const 00163 # else 00164 /** 00165 * this function is required by MSVC only, as a workaround for a 00166 * very awful bug, which exists since MSVC V.4.0, and still by 00167 * V.6.0 with all bugfixes (so called "service packs") remains 00168 * there... This method is also public due to another bug, so please 00169 * NEVER EVER call this method directly: use write() instead 00170 */ 00171 bool writeMS(ioHandler& handler,const bool complete=true) const 00172 # endif 00173 { 00174 bool b = true; 00175 if (complete) { 00176 b = handler.writeBegin(); 00177 } 00178 00179 if (b) { 00180 00181 lti::write(handler,"nbNeighbors",nbNeighbors); 00182 lti::write(handler,"useCompleteGraph",useCompleteGraph); 00183 } 00184 00185 # ifndef _LTI_MSC_6 00186 // This is the standard C++ code, which MS Visual C++ 6 is not able to 00187 // compile... 00188 b = b && functor::parameters::write(handler,false); 00189 # else 00190 bool (functor::parameters::* p_writeMS)(ioHandler&,const bool) const = 00191 functor::parameters::writeMS; 00192 b = b && (this->*p_writeMS)(handler,false); 00193 # endif 00194 00195 if (complete) { 00196 b = b && handler.writeEnd(); 00197 } 00198 00199 return b; 00200 } 00201 00202 # ifdef _LTI_MSC_6 00203 /** 00204 * write the parameters in the given ioHandler 00205 * @param handler the ioHandler to be used 00206 * @param complete if true (the default) the enclosing begin/end will 00207 * be also written, otherwise only the data block will be written. 00208 * @return true if write was successful 00209 */ 00210 bool write(ioHandler& handler, 00211 const bool complete=true) const { 00212 // ...we need this workaround to cope with another really 00213 // awful MSVC bug. 00214 return writeMS(handler,complete); 00215 } 00216 # endif 00217 00218 # ifndef _LTI_MSC_6 00219 /** 00220 * read the parameters from the given ioHandler 00221 * @param handler the ioHandler to be used 00222 * @param complete if true (the default) the enclosing begin/end will 00223 * be also written, otherwise only the data block will be written. 00224 * @return true if write was successful 00225 */ 00226 virtual bool read(ioHandler& handler,const bool complete=true) 00227 # else 00228 /** 00229 * this function is required by MSVC only, as a workaround for a 00230 * very awful bug, which exists since MSVC V.4.0, and still by 00231 * V.6.0 with all bugfixes (so called "service packs") remains 00232 * there... This method is also public due to another bug, so please 00233 * NEVER EVER call this method directly: use read() instead 00234 */ 00235 bool readMS(ioHandler& handler,const bool complete=true) 00236 # endif 00237 { 00238 bool b = true; 00239 if (complete) { 00240 b = handler.readBegin(); 00241 } 00242 00243 if (b) { 00244 00245 lti::read(handler,"nbNeighbors",nbNeighbors); 00246 lti::read(handler,"useCompleteGraph",useCompleteGraph); 00247 } 00248 00249 # ifndef _LTI_MSC_6 00250 // This is the standard C++ code, which MS Visual C++ 6 is not able to 00251 // compile... 00252 b = b && functor::parameters::read(handler,false); 00253 # else 00254 bool (functor::parameters::* p_readMS)(ioHandler&,const bool) = 00255 functor::parameters::readMS; 00256 b = b && (this->*p_readMS)(handler,false); 00257 # endif 00258 00259 if (complete) { 00260 b = b && handler.readEnd(); 00261 } 00262 00263 return b; 00264 } 00265 00266 // ------------------------------------------------ 00267 // the parameters 00268 // ------------------------------------------------ 00269 00270 /** 00271 * The number of neighboring points each point is connected with, 00272 * before minimization 00273 */ 00274 int nbNeighbors; 00275 00276 /** 00277 * If true, first a complete graph of the input data is computed, 00278 * for searching the minimum spanning tree. If false an approximation 00279 * is used of the complete graph is used. In most cases this approxiation 00280 * leads to the correct minimum spanning tree. 00281 * default is false. 00282 */ 00283 bool useCompleteGraph; 00284 00285 }; 00286 00287 /** 00288 * default constructor 00289 */ 00290 minimumSpanningTree(); 00291 00292 /** 00293 * Construct a functor using the given parameters 00294 */ 00295 minimumSpanningTree(const parameters& par); 00296 00297 /** 00298 * copy constructor 00299 * @param other the object to be copied 00300 */ 00301 minimumSpanningTree(const minimumSpanningTree& other); 00302 00303 /** 00304 * destructor 00305 */ 00306 virtual ~minimumSpanningTree(); 00307 00308 /** 00309 * returns the name of this type ("minimumSpanningTree") 00310 */ 00311 virtual const char* getTypeName() const; 00312 00313 /** 00314 * Computes the minimum spanning tree from the given data. The resulting 00315 * tree is returned in this graph. 00316 */ 00317 virtual bool apply(const std::vector<K>& src, 00318 const std::vector<V>& datas, 00319 weightedGraph<K,V,distance_type>& graph) const; 00320 00321 /** 00322 * Computes the minimum spanning tree from the given Graph. The resulting 00323 * tree is returned in graph dest. 00324 */ 00325 virtual bool apply( 00326 const weightedGraph<K,V,distance_type>& src, 00327 weightedGraph<K,V,distance_type>& dest) const; 00328 00329 /** 00330 * Computes the minimum spanning tree from the given Graph. The resulting 00331 * tree is returned in this graph. 00332 */ 00333 virtual bool apply(weightedGraph<K,V,distance_type>& srcDest) const; 00334 00335 /** 00336 * copy data of "other" functor. 00337 * @param other the functor to be copied 00338 * @return a reference to this functor object 00339 */ 00340 minimumSpanningTree& copy(const minimumSpanningTree& other); 00341 00342 /** 00343 * alias for copy member 00344 * @param other the functor to be copied 00345 * @return a reference to this functor object 00346 */ 00347 minimumSpanningTree& operator=(const minimumSpanningTree& other); 00348 00349 /** 00350 * returns a pointer to a clone of this functor. 00351 */ 00352 virtual functor* clone() const; 00353 00354 /** 00355 * returns used parameters 00356 */ 00357 const parameters& getParameters() const; 00358 00359 protected: 00360 00361 /** 00362 * The value type of the key type. 00363 */ 00364 typedef typename K::value_type key_value_type; 00365 00366 /** 00367 * the type of a node of the weightedGraph used in the MST 00368 */ 00369 typedef typename weightedGraph<K,V,distance_type>::node node_type; 00370 00371 /** 00372 * Distantor 00373 */ 00374 Distantor distantor; 00375 00376 /** 00377 * Builds up a graph that can be used for computing the minimum spanning 00378 * tree. This graph is not complete. But in most cases the edges that 00379 * this graph contains, are all edges that are needed for finding the 00380 * correct minimum spanning tree. 00381 * The advantage of this version is that searching for the minimum 00382 * spanning tree will be much faster. 00383 * For this tree all points are connected with their neighbors. The 00384 * number of neighbors it is connected to can be set by the parameter 00385 * nbNeighbors. After that it is guaranteed that the graph is a 00386 * connected graph. 00387 */ 00388 bool buildGraph(const std::vector<K>& src, 00389 const std::vector<V>& datas, 00390 weightedGraph<K,V,distance_type>& graph) const; 00391 00392 /** 00393 * Builds a complete graph of the input data. 00394 */ 00395 bool buildCompleteGraph(const std::vector<K>& src, 00396 const std::vector<V>& datas, 00397 weightedGraph<K,V,distance_type>& graph) const; 00398 00399 00400 }; 00401 } 00402 00403 #include "ltiMinimumSpanningTree_template.h" 00404 00405 #endif