OpenWalnut  1.4.0
WFiberCluster.h
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      * Sets the main direction of the cluster
00184      *
00185      * \param mainDirection the cluster's main direction
00186      */
00187     void setMainDirection( osg::Vec3 mainDirection );
00188 
00189     /**
00190      * Gets the main direction of the cluster ( if set )
00191      *
00192      * \return the cluster's main direction
00193      */
00194     osg::Vec3 getMainDirection() const;
00195 
00196     /**
00197      * The name of this transferable. This is useful information for the users.
00198      *
00199      * \return the name.
00200      */
00201     virtual const std::string getName() const;
00202 
00203     /**
00204      *
00205      * The description of this transferable. This is useful information for the users.
00206      *
00207      * \return A description
00208      */
00209     virtual const std::string getDescription() const;
00210 
00211     /**
00212      * \param other The other fiber which should be compared
00213      * \return true If both clusters having same fibers IN SAME ORDER!
00214      */
00215     bool operator==( const WFiberCluster& other ) const;
00216 
00217     /**
00218      * The opposite of the operator==
00219      *
00220      * \param other The other fiber which should be compared
00221      * \return false If both clusters having same fibers IN SAME ORDER!
00222      */
00223     bool operator!=( const WFiberCluster& other ) const;
00224 
00225     /**
00226      * Copy assignment operator which does NOT copy the mutex's!!!
00227      *
00228      * \param other The instance to copy.
00229      *
00230      * \return itself
00231      */
00232     WFiberCluster& operator=( const WFiberCluster& other )
00233     {
00234         WTransferable::operator=( other );
00235         m_memberIndices = other.m_memberIndices;
00236         m_fibs = other.m_fibs;
00237         m_color = other.m_color;
00238         m_centerLineCreationLock = new boost::shared_mutex();
00239         m_longestLineCreationLock = new boost::shared_mutex();
00240         // copy them only if they exist
00241         if( other.m_centerLine )
00242         {
00243             m_centerLine = boost::shared_ptr< WFiber >( new WFiber( *other.m_centerLine.get() ) );
00244         }
00245         if( other.m_longestLine )
00246         {
00247             m_longestLine = boost::shared_ptr< WFiber >( new WFiber( *other.m_longestLine.get() ) );
00248         }
00249         return *this;
00250     }
00251 
00252     // TODO(math): The only reason why we store here a Reference to the fiber
00253     // dataset is, we need it in the WMVoxelizer module as well as the clustering
00254     // information. Since we don't have the possibility of multiple
00255     // InputConnectors we must agglomerate those into one object. Please remove this.
00256     // \cond Suppress_Doxygen
00257     void setDataSetReference( boost::shared_ptr< const WDataSetFiberVector > fibs );
00258     boost::shared_ptr< const WDataSetFiberVector > getDataSetReference() const;
00259     // \endcond
00260 
00261     /**
00262      * Returns a prototype instantiated with the true type of the deriving class.
00263      *
00264      * \return the prototype.
00265      */
00266     static boost::shared_ptr< WPrototyped > getPrototype();
00267 
00268     /**
00269      * Returns the center line of this cluster. The centerline gets calculated during the first call of this method.
00270      *
00271      * \return Reference to the center line
00272      */
00273     boost::shared_ptr< WFiber > getCenterLine() const;
00274 
00275     /**
00276      * Returns the center line of this cluster. The longest line gets calculated during the first call if this method.
00277      *
00278      * \return Reference to the longest line
00279      */
00280     boost::shared_ptr< WFiber > getLongestLine() const;
00281 
00282     /**
00283      * Makes the hard work to compute the center line.
00284      */
00285     void generateCenterLine() const;
00286 
00287     /**
00288      * Makes the hard work to find the longest line.
00289      */
00290     void generateLongestLine() const;
00291 
00292     /**
00293      * Recomputes on every call the axis aligned bounding box incorporating all tracts in this cluster.
00294      *
00295      * \return AABB as WBoundingBox.
00296      */
00297     WBoundingBox getBoundingBox() const;
00298 
00299 protected:
00300     /**
00301      * Prototype for this dataset
00302      */
00303     static boost::shared_ptr< WPrototyped > m_prototype;
00304 
00305     /**
00306      * Alings all fibers within the given dataset to be in one main direction. But Alignment only may swap the ordering of the fibers
00307      * but not the positions or something similar. We need this only for the centerline generation.
00308      *
00309      * \param fibs The dataset
00310      */
00311     void unifyDirection( boost::shared_ptr< WDataSetFiberVector > fibs ) const;
00312 
00313 private:
00314     /**
00315      * The centerline may be shortened due to the averaging of outliers. To
00316      * nevertheless color almost the whole bundle surface we need a surface
00317      * parameterization (given via the centerline) upto the endings of the
00318      * bundle. Therefore the centerline is stepwise elongated with the last
00319      * known direction, until no perpendicular plane intersects any of the
00320      * tracts inside of the bundle.
00321      */
00322     void elongateCenterLine() const;
00323 
00324     /**
00325      * All indices in this set are members of this cluster
00326      */
00327     IndexList m_memberIndices;
00328 
00329     // TODO(math): The only reason why we store here a Reference to the fiber
00330     // dataset is, we need it in the WMVoxelizer module as well as the clustering
00331     // information. Since we don't have the possibility of multiple
00332     // InputConnectors we must agglomerate those into one object. Please remove this.
00333     /**
00334      * Reference to the real fibers of the brain this cluster belongs to.
00335      */
00336     boost::shared_ptr< const WDataSetFiberVector > m_fibs;
00337 
00338     /**
00339      * Color which is used to paint the members of this cluster.
00340      */
00341     WColor m_color;
00342 
00343     /**
00344      * The cluster's main direction
00345      */
00346     osg::Vec3 m_mainDirection;
00347 
00348     /**
00349      * Lock the modification in the m_centerLine mutable. The lock is stored as pointer to avoid copy construction problems.
00350      */
00351     boost::shared_mutex* m_centerLineCreationLock;
00352 
00353     /**
00354      * Lock the modification in the m_longestLine mutable. The lock is stored as pointer to avoid copy construction problems.
00355      */
00356     boost::shared_mutex* m_longestLineCreationLock;
00357 
00358     /**
00359      * Average fiber for this cluster representing the main direction and curvature of this cluster.
00360      *
00361      * \note This member is mutable as it needs to be modified during a const getter.
00362      */
00363     mutable boost::shared_ptr< WFiber > m_centerLine;
00364 
00365     /**
00366      * The longest fiber in the dataset.
00367      *
00368      * \note This member is mutable as it needs to be modified during a const getter.
00369      */
00370     mutable boost::shared_ptr< WFiber > m_longestLine;
00371 };
00372 
00373 inline bool WFiberCluster::empty() const
00374 {
00375     return m_memberIndices.empty();
00376 }
00377 
00378 inline void WFiberCluster::sort()
00379 {
00380     m_memberIndices.sort();
00381 }
00382 
00383 inline size_t WFiberCluster::size() const
00384 {
00385     return m_memberIndices.size();
00386 }
00387 
00388 inline void WFiberCluster::clear()
00389 {
00390     m_memberIndices.clear();
00391 }
00392 
00393 inline void WFiberCluster::setColor( WColor color )
00394 {
00395     m_color = color;
00396 }
00397 
00398 inline WColor WFiberCluster::getColor() const
00399 {
00400     return m_color;
00401 }
00402 
00403 inline void WFiberCluster::setMainDirection( osg::Vec3 mainDirection )
00404 {
00405     m_mainDirection = mainDirection;
00406 }
00407 
00408 inline osg::Vec3 WFiberCluster::getMainDirection() const
00409 {
00410     return m_mainDirection;
00411 }
00412 
00413 inline const std::string WFiberCluster::getName() const
00414 {
00415     return "FiberCluster";
00416 }
00417 
00418 inline const std::string WFiberCluster::getDescription() const
00419 {
00420     return "A collection of indices for fibers representing a fiber cluster";
00421 }
00422 
00423 inline bool WFiberCluster::operator==( const WFiberCluster& other ) const
00424 {
00425     return m_memberIndices == other.m_memberIndices;
00426 }
00427 
00428 inline bool WFiberCluster::operator!=( const WFiberCluster& other ) const
00429 {
00430     return m_memberIndices != other.m_memberIndices;
00431 }
00432 
00433 inline const WFiberCluster::IndexList& WFiberCluster::getIndices() const
00434 {
00435     return m_memberIndices;
00436 }
00437 
00438 inline void WFiberCluster::setIndices( const WFiberCluster::IndexList& indices )
00439 {
00440     m_memberIndices = indices;
00441 }
00442 
00443 inline std::ostream& operator<<( std::ostream& os, const WFiberCluster& c )
00444 {
00445     using string_utils::operator<<;
00446     return os << c.getIndices();
00447 }
00448 
00449 #endif  // WFIBERCLUSTER_H