OpenWalnut 1.2.5

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 #include "../WExportDataHandler.h"
00039 
00040 /**
00041  * Represents a cluster of indices of a WDataSetFiberVector.
00042  */
00043 class OWDATAHANDLER_EXPORT WFiberCluster : public WTransferable // NOLINT
00044 {
00045 friend class WFiberClusterTest;
00046 public:
00047     /**
00048      * Constructs an cluster with one fiber and a reference to the fiber dataset
00049      * to compute the intercluster distance.
00050      *
00051      * \param index The index of the first fiber belonging to this cluster
00052      */
00053     explicit WFiberCluster( size_t index );
00054 
00055     /**
00056      * Copies the specified \ref WFiberCluster Instance. The copy does not contain a valid centerline or longest line.
00057      *
00058      * \param other the other instance to clone.
00059      */
00060     WFiberCluster( const WFiberCluster& other );
00061 
00062     /**
00063      * Constructs an empty cluster.
00064      */
00065     WFiberCluster();
00066 
00067     /**
00068      * Destructs. Frees used locks/mutex.
00069      */
00070     virtual ~WFiberCluster();
00071 
00072     /**
00073      * Returns true if there are no fibers in that cluster, false otherwise.
00074      *
00075      * \return true if empty
00076      */
00077     bool empty() const;
00078 
00079     /**
00080      * Merge the fibers of the other cluster with the fibers of this cluster.
00081      * Afterwards the other cluster is empty.
00082      *
00083      * \param other The other WFiberCluster which should merged into this one
00084      */
00085     void merge( WFiberCluster &other ); // NOLINT
00086 
00087     /**
00088      * Returns a const reference of all indices inside this cluster
00089      *
00090      * \return the index list
00091      */
00092     const std::list< size_t >& getIndices() const;
00093 
00094     /**
00095      * Reset the indices belonging to that cluster
00096      *
00097      * \param indices list of indices
00098      */
00099     void setIndices( const std::list< size_t >& indices );
00100 
00101     /**
00102      * Sort the indices of fibers associated with this cluster in ascending
00103      * order.
00104      */
00105     void sort();
00106 
00107     /**
00108      * \return Number of fibers associated with this cluster.
00109      */
00110     size_t size() const;
00111 
00112     /**
00113      * Make this cluster empty. Note: The real fibers from fiber dataset are
00114      * not deleted.
00115      */
00116     void clear();
00117 
00118     /**
00119      * Sets the color of which all fibers of this clusters should be painted
00120      * with.
00121      *
00122      * \param color The color for all fibers of this cluster.
00123      */
00124     void setColor( WColor color );
00125 
00126     /**
00127      * Gets the color of which all fibers of this clusters should be painted
00128      * with.
00129      *
00130      * \return cluster color.
00131      */
00132     WColor getColor() const;
00133 
00134     /**
00135      * The only reason for implementing is here, to prevent this class from
00136      * beeing abstract.
00137      *
00138      * \return A name.
00139      */
00140     virtual const std::string getName() const;
00141 
00142     /**
00143      * The only reason for implementing is here, to prevent this class from
00144      * beeing abstract.
00145      *
00146      * \return A name.
00147      */
00148     virtual const std::string getDescription() const;
00149 
00150     /**
00151      * \param other The other fiber which should be compared
00152      * \return true If both clusters having same fibers IN SAME ORDER!
00153      */
00154     bool operator==( const WFiberCluster& other ) const;
00155 
00156     /**
00157      * The opposite of the operator==
00158      *
00159      * \param other The other fiber which should be compared
00160      * \return false If both clusters having same fibers IN SAME ORDER!
00161      */
00162     bool operator!=( const WFiberCluster& other ) const;
00163 
00164     /**
00165      * Copy assignment operator which does NOT copy the mutex's!!!
00166      *
00167      * \param other The instance to copy.
00168      *
00169      * \return itself
00170      */
00171     WFiberCluster& operator=( const WFiberCluster& other )
00172     {
00173         WTransferable::operator=( other );
00174         m_memberIndices = other.m_memberIndices;
00175         m_fibs = other.m_fibs;
00176         m_color = other.m_color;
00177         m_centerLineCreationLock = new boost::shared_mutex();
00178         m_longestLineCreationLock = new boost::shared_mutex();
00179         // copy them only if they exist
00180         if( other.m_centerLine )
00181         {
00182             m_centerLine = boost::shared_ptr< WFiber >( new WFiber( *other.m_centerLine.get() ) );
00183         }
00184         if( other.m_longestLine )
00185         {
00186             m_longestLine = boost::shared_ptr< WFiber >( new WFiber( *other.m_longestLine.get() ) );
00187         }
00188         return *this;
00189     }
00190 
00191     // TODO(math): The only reason why we store here a Reference to the fiber
00192     // dataset is, we need it in the WMVoxelizer module as well as the clustering
00193     // information. Since we don't have the possibility of multiple
00194     // InputConnectors we must agglomerate those into one object. Please remove this.
00195     // \cond Suppress_Doxygen
00196     void setDataSetReference( boost::shared_ptr< const WDataSetFiberVector > fibs );
00197     boost::shared_ptr< const WDataSetFiberVector > getDataSetReference() const;
00198     static boost::shared_ptr< WPrototyped > getPrototype();
00199     // \endcond
00200 
00201     /**
00202      * Returns the center line of this cluster. The centerline gets calculated during the first call of this method.
00203      *
00204      * \return Reference to the center line
00205      */
00206     boost::shared_ptr< WFiber > getCenterLine() const;
00207 
00208     /**
00209      * Returns the center line of this cluster. The longest line gets calculated during the first call if this method.
00210      *
00211      * \return Reference to the longest line
00212      */
00213     boost::shared_ptr< WFiber > getLongestLine() const;
00214 
00215     /**
00216      * Makes the hard work to compute the center line.
00217      */
00218     void generateCenterLine() const;
00219 
00220     /**
00221      * Makes the hard work to find the longest line.
00222      */
00223     void generateLongestLine() const;
00224 
00225     /**
00226      * Recomputes on every call the axis aligned bounding box incorporating all tracts in this cluster.
00227      *
00228      * \return AABB as WBoundingBox.
00229      */
00230     WBoundingBox getBoundingBox() const;
00231 
00232 protected:
00233     // TODO(math): The only reason why we store here a Reference to the fiber
00234     // dataset is, we need it in the WMVoxelizer module as well as the clustering
00235     // information. Since we don't have the possibility of multiple
00236     // InputConnectors we must agglomerate those into one object. Please remove this.
00237     // \cond Suppress_Doxygen
00238     static boost::shared_ptr< WPrototyped > m_prototype;
00239     // \endcond
00240 
00241     /**
00242      * Alings all fibers within the given dataset to be in one main direction. But Alignment only may swap the ordering of the fibers
00243      * but not the positions or something similar. We need this only for the centerline generation.
00244      *
00245      * \param fibs The dataset
00246      */
00247     void unifyDirection( boost::shared_ptr< WDataSetFiberVector > fibs ) const;
00248 
00249 private:
00250     /**
00251      * The centerline may be shortened due to the averaging of outliers. To
00252      * nevertheless color almost the whole bundle surface we need a surface
00253      * parameterization (given via the centerline) upto the endings of the
00254      * bundle. Therefore the centerline is stepwise elongated with the last
00255      * known direction, until no perpendicular plane intersects any of the
00256      * tracts inside of the bundle.
00257      */
00258     void elongateCenterLine() const;
00259 
00260     /**
00261      * All indices in this set are members of this cluster
00262      */
00263     std::list< size_t > m_memberIndices;
00264 
00265     // TODO(math): The only reason why we store here a Reference to the fiber
00266     // dataset is, we need it in the WMVoxelizer module as well as the clustering
00267     // information. Since we don't have the possibility of multiple
00268     // InputConnectors we must agglomerate those into one object. Please remove this.
00269     /**
00270      * Reference to the real fibers of the brain this cluster belongs to.
00271      */
00272     boost::shared_ptr< const WDataSetFiberVector > m_fibs;
00273 
00274     /**
00275      * Color which is used to paint the members of this cluster.
00276      */
00277     WColor m_color;
00278 
00279     /**
00280      * Lock the modification in the m_centerLine mutable. The lock is stored as pointer to avoid copy construction problems.
00281      */
00282     boost::shared_mutex* m_centerLineCreationLock;
00283 
00284     /**
00285      * Lock the modification in the m_longestLine mutable. The lock is stored as pointer to avoid copy construction problems.
00286      */
00287     boost::shared_mutex* m_longestLineCreationLock;
00288 
00289     /**
00290      * Average fiber for this cluster representing the main direction and curvature of this cluster.
00291      *
00292      * \note This member is mutable as it needs to be modified during a const getter.
00293      */
00294     mutable boost::shared_ptr< WFiber > m_centerLine;
00295 
00296     /**
00297      * The longest fiber in the dataset.
00298      *
00299      * \note This member is mutable as it needs to be modified during a const getter.
00300      */
00301     mutable boost::shared_ptr< WFiber > m_longestLine;
00302 };
00303 
00304 inline bool WFiberCluster::empty() const
00305 {
00306     return m_memberIndices.empty();
00307 }
00308 
00309 inline void WFiberCluster::sort()
00310 {
00311     m_memberIndices.sort();
00312 }
00313 
00314 inline size_t WFiberCluster::size() const
00315 {
00316     return m_memberIndices.size();
00317 }
00318 
00319 inline void WFiberCluster::clear()
00320 {
00321     m_memberIndices.clear();
00322 }
00323 
00324 inline void WFiberCluster::setColor( WColor color )
00325 {
00326     m_color = color;
00327 }
00328 
00329 inline WColor WFiberCluster::getColor() const
00330 {
00331     return m_color;
00332 }
00333 
00334 inline const std::string WFiberCluster::getName() const
00335 {
00336     return "FiberCluster";
00337 }
00338 
00339 inline const std::string WFiberCluster::getDescription() const
00340 {
00341     return "A collection of indices for fibers representing a fiber cluster";
00342 }
00343 
00344 inline bool WFiberCluster::operator==( const WFiberCluster& other ) const
00345 {
00346     return m_memberIndices == other.m_memberIndices;
00347 }
00348 
00349 inline bool WFiberCluster::operator!=( const WFiberCluster& other ) const
00350 {
00351     return m_memberIndices != other.m_memberIndices;
00352 }
00353 
00354 inline const std::list< size_t >& WFiberCluster::getIndices() const
00355 {
00356     return m_memberIndices;
00357 }
00358 
00359 inline void WFiberCluster::setIndices( const std::list< size_t >& indices )
00360 {
00361     m_memberIndices = indices;
00362 }
00363 
00364 inline std::ostream& operator<<( std::ostream& os, const WFiberCluster& c )
00365 {
00366     using string_utils::operator<<;
00367     return os << c.getIndices();
00368 }
00369 
00370 #endif  // WFIBERCLUSTER_H
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends