OpenMesh
|
00001 /*===========================================================================*\ 00002 * * 00003 * OpenMesh * 00004 * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * 00005 * www.openmesh.org * 00006 * * 00007 *---------------------------------------------------------------------------* 00008 * This file is part of OpenMesh. * 00009 * * 00010 * OpenMesh is free software: you can redistribute it and/or modify * 00011 * it under the terms of the GNU Lesser General Public License as * 00012 * published by the Free Software Foundation, either version 3 of * 00013 * the License, or (at your option) any later version with the * 00014 * following exceptions: * 00015 * * 00016 * If other files instantiate templates or use macros * 00017 * or inline functions from this file, or you compile this file and * 00018 * link it with other files to produce an executable, this file does * 00019 * not by itself cause the resulting executable to be covered by the * 00020 * GNU Lesser General Public License. This exception does not however * 00021 * invalidate any other reasons why the executable file might be * 00022 * covered by the GNU Lesser General Public License. * 00023 * * 00024 * OpenMesh is distributed in the hope that it will be useful, * 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00027 * GNU Lesser General Public License for more details. * 00028 * * 00029 * You should have received a copy of the GNU LesserGeneral Public * 00030 * License along with OpenMesh. If not, * 00031 * see <http://www.gnu.org/licenses/>. * 00032 * * 00033 \*===========================================================================*/ 00034 00035 /*===========================================================================*\ 00036 * * 00037 * $Revision: 362 $ * 00038 * $Date: 2011-01-26 10:21:12 +0100 (Mi, 26 Jan 2011) $ * 00039 * * 00040 \*===========================================================================*/ 00041 00060 //============================================================================= 00061 // 00062 // CLASS HeapT 00063 // 00064 //============================================================================= 00065 00066 #ifndef OPENMESH_UTILS_HEAPT_HH 00067 #define OPENMESH_UTILS_HEAPT_HH 00068 00069 00070 //== INCLUDES ================================================================= 00071 00072 #include "Config.hh" 00073 #include <vector> 00074 #include <OpenMesh/Core/System/omstream.hh> 00075 00076 //== NAMESPACE ================================================================ 00077 00078 namespace OpenMesh { // BEGIN_NS_OPENMESH 00079 namespace Utils { // BEGIN_NS_UTILS 00080 00081 //== CLASS DEFINITION ========================================================= 00082 00083 00092 template <class HeapEntry> 00093 struct HeapInterfaceT 00094 { 00096 bool less(const HeapEntry& _e1, const HeapEntry& _e2); 00097 00099 bool greater(const HeapEntry& _e1, const HeapEntry& _e2); 00100 00102 int get_heap_position(const HeapEntry& _e); 00103 00105 void set_heap_position(HeapEntry& _e, int _i); 00106 }; 00107 00108 00109 00132 template <class HeapEntry, class HeapInterface=HeapEntry> 00133 class HeapT : private std::vector<HeapEntry> 00134 { 00135 private: 00136 typedef std::vector<HeapEntry> Base; 00137 00138 public: 00139 00141 HeapT() : HeapVector() {} 00142 00144 HeapT(const HeapInterface& _interface) 00145 : HeapVector(), interface_(_interface) 00146 {} 00147 00149 ~HeapT(){}; 00150 00151 00153 void clear() { HeapVector::clear(); } 00154 00156 bool empty() const { return HeapVector::empty(); } 00157 00159 unsigned int size() const { return HeapVector::size(); } 00160 00162 void reserve(unsigned int _n) { HeapVector::reserve(_n); } 00163 00165 void reset_heap_position(HeapEntry _h) 00166 { interface_.set_heap_position(_h, -1); } 00167 00169 bool is_stored(HeapEntry _h) 00170 { return interface_.get_heap_position(_h) != -1; } 00171 00173 void insert(HeapEntry _h) 00174 { 00175 push_back(_h); 00176 upheap(size()-1); 00177 } 00178 00180 HeapEntry front() const 00181 { 00182 assert(!empty()); 00183 return entry(0); 00184 } 00185 00187 void pop_front() 00188 { 00189 assert(!empty()); 00190 reset_heap_position(entry(0)); 00191 if (size() > 1) 00192 { 00193 entry(0, entry(size()-1)); 00194 Base::pop_back(); 00195 downheap(0); 00196 } 00197 else 00198 { 00199 Base::pop_back(); 00200 } 00201 } 00202 00204 void remove(HeapEntry _h) 00205 { 00206 int pos = interface_.get_heap_position(_h); 00207 reset_heap_position(_h); 00208 00209 assert(pos != -1); 00210 assert((unsigned int) pos < size()); 00211 00212 // last item ? 00213 if ((unsigned int) pos == size()-1) 00214 { 00215 Base::pop_back(); 00216 } 00217 else 00218 { 00219 entry(pos, entry(size()-1)); // move last elem to pos 00220 Base::pop_back(); 00221 downheap(pos); 00222 upheap(pos); 00223 } 00224 } 00225 00229 void update(HeapEntry _h) 00230 { 00231 int pos = interface_.get_heap_position(_h); 00232 assert(pos != -1); 00233 assert((unsigned int)pos < size()); 00234 downheap(pos); 00235 upheap(pos); 00236 } 00237 00239 bool check() 00240 { 00241 bool ok(true); 00242 unsigned int i, j; 00243 for (i=0; i<size(); ++i) 00244 { 00245 if (((j=left(i))<size()) && interface_.greater(entry(i), entry(j))) 00246 { 00247 omerr() << "Heap condition violated\n"; 00248 ok=false; 00249 } 00250 if (((j=right(i))<size()) && interface_.greater(entry(i), entry(j))) 00251 { 00252 omerr() << "Heap condition violated\n"; 00253 ok=false; 00254 } 00255 } 00256 return ok; 00257 } 00258 00259 protected: 00261 HeapInterface interface_; 00262 00263 private: 00264 // typedef 00265 typedef std::vector<HeapEntry> HeapVector; 00266 00267 00269 void upheap(unsigned int _idx); 00270 00271 00273 void downheap(unsigned int _idx); 00274 00275 00277 inline HeapEntry entry(unsigned int _idx) const 00278 { 00279 assert(_idx < size()); 00280 return (Base::operator[](_idx)); 00281 } 00282 00283 00285 inline void entry(unsigned int _idx, HeapEntry _h) 00286 { 00287 assert(_idx < size()); 00288 Base::operator[](_idx) = _h; 00289 interface_.set_heap_position(_h, _idx); 00290 } 00291 00292 00294 inline unsigned int parent(unsigned int _i) { return (_i-1)>>1; } 00296 inline unsigned int left(unsigned int _i) { return (_i<<1)+1; } 00298 inline unsigned int right(unsigned int _i) { return (_i<<1)+2; } 00299 00300 }; 00301 00302 00303 00304 00305 //== IMPLEMENTATION ========================================================== 00306 00307 00308 template <class HeapEntry, class HeapInterface> 00309 void 00310 HeapT<HeapEntry, HeapInterface>:: 00311 upheap(unsigned int _idx) 00312 { 00313 HeapEntry h = entry(_idx); 00314 unsigned int parentIdx; 00315 00316 while ((_idx>0) && 00317 interface_.less(h, entry(parentIdx=parent(_idx)))) 00318 { 00319 entry(_idx, entry(parentIdx)); 00320 _idx = parentIdx; 00321 } 00322 00323 entry(_idx, h); 00324 } 00325 00326 00327 //----------------------------------------------------------------------------- 00328 00329 00330 template <class HeapEntry, class HeapInterface> 00331 void 00332 HeapT<HeapEntry, HeapInterface>:: 00333 downheap(unsigned int _idx) 00334 { 00335 HeapEntry h = entry(_idx); 00336 unsigned int childIdx; 00337 unsigned int s = size(); 00338 00339 while(_idx < s) 00340 { 00341 childIdx = left(_idx); 00342 if (childIdx >= s) break; 00343 00344 if ((childIdx+1 < s) && 00345 (interface_.less(entry(childIdx+1), entry(childIdx)))) 00346 ++childIdx; 00347 00348 if (interface_.less(h, entry(childIdx))) break; 00349 00350 entry(_idx, entry(childIdx)); 00351 _idx = childIdx; 00352 } 00353 00354 entry(_idx, h); 00355 } 00356 00357 00358 //============================================================================= 00359 } // END_NS_UTILS 00360 } // END_NS_OPENMESH 00361 //============================================================================= 00362 #endif // OSG_HEAP_HH defined 00363 //============================================================================= 00364