OpenWalnut 1.3.1
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      * 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