OpenWalnut 1.3.1
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #ifndef WFIBERCLUSTER_H 00026 #define WFIBERCLUSTER_H 00027 00028 #include <list> 00029 #include <string> 00030 #include <vector> 00031 00032 #include <boost/shared_ptr.hpp> 00033 #include <boost/thread.hpp> 00034 00035 #include "../../common/WColor.h" 00036 #include "../../common/WTransferable.h" 00037 #include "../WDataSetFiberVector.h" 00038 00039 00040 /** 00041 * Represents a cluster of indices of a WDataSetFiberVector. 00042 */ 00043 class WFiberCluster: public WTransferable // NOLINT 00044 { 00045 friend class WFiberClusterTest; 00046 public: 00047 /** 00048 * Shared pointer abbreviation. 00049 */ 00050 typedef boost::shared_ptr< WFiberCluster > SPtr; 00051 00052 /** 00053 * Const shared pointer abbreviation. 00054 */ 00055 typedef boost::shared_ptr< const WFiberCluster > ConstSPtr; 00056 00057 /** 00058 * This is the list of indices of fibers. 00059 */ 00060 typedef std::list< size_t > IndexList; 00061 00062 /** 00063 * Const iterator on the index list. 00064 */ 00065 typedef IndexList::const_iterator IndexListConstIterator; 00066 00067 /** 00068 * Constructs an cluster with one fiber and a reference to the fiber dataset 00069 * to compute the intercluster distance. 00070 * 00071 * \param index The index of the first fiber belonging to this cluster 00072 */ 00073 explicit WFiberCluster( size_t index ); 00074 00075 /** 00076 * Constructs a cluster with the specified set of indices and the given color. 00077 * 00078 * \param indices the indices initially used for this clustering 00079 * \param color the color of this cluster 00080 */ 00081 WFiberCluster( const IndexList& indices, const WColor& color = WColor() ); 00082 00083 /** 00084 * Constructs a clustering with the given set of indices. The indexlist is generated using the given iterators. It copies the elements in 00085 * [indicesBegin,indicesEnd). 00086 * 00087 * \param indicesBegin begin iterator in the predefined index set 00088 * \param indicesEnd end iterator in the predefined index set 00089 * \param color the color of this cluster 00090 */ 00091 WFiberCluster( IndexListConstIterator indicesBegin, 00092 IndexListConstIterator indicesEnd, const WColor& color = WColor() ); 00093 00094 /** 00095 * Copies the specified \ref WFiberCluster Instance. The copy does not contain a valid centerline or longest line. 00096 * 00097 * \param other the other instance to clone. 00098 */ 00099 WFiberCluster( const WFiberCluster& other ); 00100 00101 /** 00102 * Constructs an empty cluster. 00103 */ 00104 WFiberCluster(); 00105 00106 /** 00107 * Destructs. Frees used locks/mutex. 00108 */ 00109 virtual ~WFiberCluster(); 00110 00111 /** 00112 * Returns true if there are no fibers in that cluster, false otherwise. 00113 * 00114 * \return true if empty 00115 */ 00116 bool empty() const; 00117 00118 /** 00119 * Merge the fibers of the other cluster with the fibers of this cluster. 00120 * Afterwards the other cluster is empty. 00121 * 00122 * \param other The other WFiberCluster which should merged into this one 00123 */ 00124 void merge( WFiberCluster &other ); // NOLINT 00125 00126 /** 00127 * Copy the elements denoted by the two iterators to this cluster. In contrast to the other merge() methods, this will not clean the source 00128 * list. 00129 * 00130 * \param indicesBegin begin iterator in the predefined index set 00131 * \param indicesEnd end iterator in the predefined index set 00132 */ 00133 void merge( IndexListConstIterator indicesBegin, IndexListConstIterator indicesEnd ); 00134 00135 /** 00136 * Returns a const reference of all indices inside this cluster 00137 * 00138 * \return the index list 00139 */ 00140 const IndexList& getIndices() const; 00141 00142 /** 00143 * Reset the indices belonging to that cluster 00144 * 00145 * \param indices list of indices 00146 */ 00147 void setIndices( const IndexList& indices ); 00148 00149 /** 00150 * Sort the indices of fibers associated with this cluster in ascending 00151 * order. 00152 */ 00153 void sort(); 00154 00155 /** 00156 * \return Number of fibers associated with this cluster. 00157 */ 00158 size_t size() const; 00159 00160 /** 00161 * Make this cluster empty. Note: The real fibers from fiber dataset are 00162 * not deleted. 00163 */ 00164 void clear(); 00165 00166 /** 00167 * Sets the color of which all fibers of this clusters should be painted 00168 * with. 00169 * 00170 * \param color The color for all fibers of this cluster. 00171 */ 00172 void setColor( WColor color ); 00173 00174 /** 00175 * Gets the color of which all fibers of this clusters should be painted 00176 * with. 00177 * 00178 * \return cluster color. 00179 */ 00180 WColor getColor() const; 00181 00182 /** 00183 * The name of this transferable. This is useful information for the users. 00184 * 00185 * \return the name. 00186 */ 00187 virtual const std::string getName() const; 00188 00189 /** 00190 * 00191 * The description of this transferable. This is useful information for the users. 00192 * 00193 * \return A description 00194 */ 00195 virtual const std::string getDescription() const; 00196 00197 /** 00198 * \param other The other fiber which should be compared 00199 * \return true If both clusters having same fibers IN SAME ORDER! 00200 */ 00201 bool operator==( const WFiberCluster& other ) const; 00202 00203 /** 00204 * The opposite of the operator== 00205 * 00206 * \param other The other fiber which should be compared 00207 * \return false If both clusters having same fibers IN SAME ORDER! 00208 */ 00209 bool operator!=( const WFiberCluster& other ) const; 00210 00211 /** 00212 * Copy assignment operator which does NOT copy the mutex's!!! 00213 * 00214 * \param other The instance to copy. 00215 * 00216 * \return itself 00217 */ 00218 WFiberCluster& operator=( const WFiberCluster& other ) 00219 { 00220 WTransferable::operator=( other ); 00221 m_memberIndices = other.m_memberIndices; 00222 m_fibs = other.m_fibs; 00223 m_color = other.m_color; 00224 m_centerLineCreationLock = new boost::shared_mutex(); 00225 m_longestLineCreationLock = new boost::shared_mutex(); 00226 // copy them only if they exist 00227 if( other.m_centerLine ) 00228 { 00229 m_centerLine = boost::shared_ptr< WFiber >( new WFiber( *other.m_centerLine.get() ) ); 00230 } 00231 if( other.m_longestLine ) 00232 { 00233 m_longestLine = boost::shared_ptr< WFiber >( new WFiber( *other.m_longestLine.get() ) ); 00234 } 00235 return *this; 00236 } 00237 00238 // TODO(math): The only reason why we store here a Reference to the fiber 00239 // dataset is, we need it in the WMVoxelizer module as well as the clustering 00240 // information. Since we don't have the possibility of multiple 00241 // InputConnectors we must agglomerate those into one object. Please remove this. 00242 // \cond Suppress_Doxygen 00243 void setDataSetReference( boost::shared_ptr< const WDataSetFiberVector > fibs ); 00244 boost::shared_ptr< const WDataSetFiberVector > getDataSetReference() const; 00245 // \endcond 00246 00247 /** 00248 * Returns a prototype instantiated with the true type of the deriving class. 00249 * 00250 * \return the prototype. 00251 */ 00252 static boost::shared_ptr< WPrototyped > getPrototype(); 00253 00254 /** 00255 * Returns the center line of this cluster. The centerline gets calculated during the first call of this method. 00256 * 00257 * \return Reference to the center line 00258 */ 00259 boost::shared_ptr< WFiber > getCenterLine() const; 00260 00261 /** 00262 * Returns the center line of this cluster. The longest line gets calculated during the first call if this method. 00263 * 00264 * \return Reference to the longest line 00265 */ 00266 boost::shared_ptr< WFiber > getLongestLine() const; 00267 00268 /** 00269 * Makes the hard work to compute the center line. 00270 */ 00271 void generateCenterLine() const; 00272 00273 /** 00274 * Makes the hard work to find the longest line. 00275 */ 00276 void generateLongestLine() const; 00277 00278 /** 00279 * Recomputes on every call the axis aligned bounding box incorporating all tracts in this cluster. 00280 * 00281 * \return AABB as WBoundingBox. 00282 */ 00283 WBoundingBox getBoundingBox() const; 00284 00285 protected: 00286 /** 00287 * Prototype for this dataset 00288 */ 00289 static boost::shared_ptr< WPrototyped > m_prototype; 00290 00291 /** 00292 * Alings all fibers within the given dataset to be in one main direction. But Alignment only may swap the ordering of the fibers 00293 * but not the positions or something similar. We need this only for the centerline generation. 00294 * 00295 * \param fibs The dataset 00296 */ 00297 void unifyDirection( boost::shared_ptr< WDataSetFiberVector > fibs ) const; 00298 00299 private: 00300 /** 00301 * The centerline may be shortened due to the averaging of outliers. To 00302 * nevertheless color almost the whole bundle surface we need a surface 00303 * parameterization (given via the centerline) upto the endings of the 00304 * bundle. Therefore the centerline is stepwise elongated with the last 00305 * known direction, until no perpendicular plane intersects any of the 00306 * tracts inside of the bundle. 00307 */ 00308 void elongateCenterLine() const; 00309 00310 /** 00311 * All indices in this set are members of this cluster 00312 */ 00313 IndexList m_memberIndices; 00314 00315 // TODO(math): The only reason why we store here a Reference to the fiber 00316 // dataset is, we need it in the WMVoxelizer module as well as the clustering 00317 // information. Since we don't have the possibility of multiple 00318 // InputConnectors we must agglomerate those into one object. Please remove this. 00319 /** 00320 * Reference to the real fibers of the brain this cluster belongs to. 00321 */ 00322 boost::shared_ptr< const WDataSetFiberVector > m_fibs; 00323 00324 /** 00325 * Color which is used to paint the members of this cluster. 00326 */ 00327 WColor m_color; 00328 00329 /** 00330 * Lock the modification in the m_centerLine mutable. The lock is stored as pointer to avoid copy construction problems. 00331 */ 00332 boost::shared_mutex* m_centerLineCreationLock; 00333 00334 /** 00335 * Lock the modification in the m_longestLine mutable. The lock is stored as pointer to avoid copy construction problems. 00336 */ 00337 boost::shared_mutex* m_longestLineCreationLock; 00338 00339 /** 00340 * Average fiber for this cluster representing the main direction and curvature of this cluster. 00341 * 00342 * \note This member is mutable as it needs to be modified during a const getter. 00343 */ 00344 mutable boost::shared_ptr< WFiber > m_centerLine; 00345 00346 /** 00347 * The longest fiber in the dataset. 00348 * 00349 * \note This member is mutable as it needs to be modified during a const getter. 00350 */ 00351 mutable boost::shared_ptr< WFiber > m_longestLine; 00352 }; 00353 00354 inline bool WFiberCluster::empty() const 00355 { 00356 return m_memberIndices.empty(); 00357 } 00358 00359 inline void WFiberCluster::sort() 00360 { 00361 m_memberIndices.sort(); 00362 } 00363 00364 inline size_t WFiberCluster::size() const 00365 { 00366 return m_memberIndices.size(); 00367 } 00368 00369 inline void WFiberCluster::clear() 00370 { 00371 m_memberIndices.clear(); 00372 } 00373 00374 inline void WFiberCluster::setColor( WColor color ) 00375 { 00376 m_color = color; 00377 } 00378 00379 inline WColor WFiberCluster::getColor() const 00380 { 00381 return m_color; 00382 } 00383 00384 inline const std::string WFiberCluster::getName() const 00385 { 00386 return "FiberCluster"; 00387 } 00388 00389 inline const std::string WFiberCluster::getDescription() const 00390 { 00391 return "A collection of indices for fibers representing a fiber cluster"; 00392 } 00393 00394 inline bool WFiberCluster::operator==( const WFiberCluster& other ) const 00395 { 00396 return m_memberIndices == other.m_memberIndices; 00397 } 00398 00399 inline bool WFiberCluster::operator!=( const WFiberCluster& other ) const 00400 { 00401 return m_memberIndices != other.m_memberIndices; 00402 } 00403 00404 inline const WFiberCluster::IndexList& WFiberCluster::getIndices() const 00405 { 00406 return m_memberIndices; 00407 } 00408 00409 inline void WFiberCluster::setIndices( const WFiberCluster::IndexList& indices ) 00410 { 00411 m_memberIndices = indices; 00412 } 00413 00414 inline std::ostream& operator<<( std::ostream& os, const WFiberCluster& c ) 00415 { 00416 using string_utils::operator<<; 00417 return os << c.getIndices(); 00418 } 00419 00420 #endif // WFIBERCLUSTER_H