OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
WFiberCluster.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WFIBERCLUSTER_H
26 #define WFIBERCLUSTER_H
27 
28 #include <list>
29 #include <string>
30 #include <vector>
31 
32 #include <boost/shared_ptr.hpp>
33 #include <boost/thread.hpp>
34 
35 #include "../../common/WColor.h"
36 #include "../../common/WTransferable.h"
37 #include "../WDataSetFiberVector.h"
38 #include "../WExportDataHandler.h"
39 
40 /**
41  * Represents a cluster of indices of a WDataSetFiberVector.
42  */
44 {
45 friend class WFiberClusterTest;
46 public:
47  /**
48  * Constructs an cluster with one fiber and a reference to the fiber dataset
49  * to compute the intercluster distance.
50  *
51  * \param index The index of the first fiber belonging to this cluster
52  */
53  explicit WFiberCluster( size_t index );
54 
55  /**
56  * Copies the specified \ref WFiberCluster Instance. The copy does not contain a valid centerline or longest line.
57  *
58  * \param other the other instance to clone.
59  */
60  WFiberCluster( const WFiberCluster& other );
61 
62  /**
63  * Constructs an empty cluster.
64  */
65  WFiberCluster();
66 
67  /**
68  * Destructs. Frees used locks/mutex.
69  */
70  virtual ~WFiberCluster();
71 
72  /**
73  * Returns true if there are no fibers in that cluster, false otherwise.
74  *
75  * \return true if empty
76  */
77  bool empty() const;
78 
79  /**
80  * Merge the fibers of the other cluster with the fibers of this cluster.
81  * Afterwards the other cluster is empty.
82  *
83  * \param other The other WFiberCluster which should merged into this one
84  */
85  void merge( WFiberCluster &other ); // NOLINT
86 
87  /**
88  * Returns a const reference of all indices inside this cluster
89  *
90  * \return the index list
91  */
92  const std::list< size_t >& getIndices() const;
93 
94  /**
95  * Reset the indices belonging to that cluster
96  *
97  * \param indices list of indices
98  */
99  void setIndices( const std::list< size_t >& indices );
100 
101  /**
102  * Sort the indices of fibers associated with this cluster in ascending
103  * order.
104  */
105  void sort();
106 
107  /**
108  * \return Number of fibers associated with this cluster.
109  */
110  size_t size() const;
111 
112  /**
113  * Make this cluster empty. Note: The real fibers from fiber dataset are
114  * not deleted.
115  */
116  void clear();
117 
118  /**
119  * Sets the color of which all fibers of this clusters should be painted
120  * with.
121  *
122  * \param color The color for all fibers of this cluster.
123  */
124  void setColor( WColor color );
125 
126  /**
127  * Gets the color of which all fibers of this clusters should be painted
128  * with.
129  *
130  * \return cluster color.
131  */
132  WColor getColor() const;
133 
134  /**
135  * The only reason for implementing is here, to prevent this class from
136  * beeing abstract.
137  *
138  * \return A name.
139  */
140  virtual const std::string getName() const;
141 
142  /**
143  * The only reason for implementing is here, to prevent this class from
144  * beeing abstract.
145  *
146  * \return A name.
147  */
148  virtual const std::string getDescription() const;
149 
150  /**
151  * \param other The other fiber which should be compared
152  * \return true If both clusters having same fibers IN SAME ORDER!
153  */
154  bool operator==( const WFiberCluster& other ) const;
155 
156  /**
157  * The opposite of the operator==
158  *
159  * \param other The other fiber which should be compared
160  * \return false If both clusters having same fibers IN SAME ORDER!
161  */
162  bool operator!=( const WFiberCluster& other ) const;
163 
164  /**
165  * Copy assignment operator which does NOT copy the mutex's!!!
166  *
167  * \param other The instance to copy.
168  *
169  * \return itself
170  */
171  WFiberCluster& operator=( const WFiberCluster& other )
172  {
173  WTransferable::operator=( other );
174  m_memberIndices = other.m_memberIndices;
175  m_fibs = other.m_fibs;
176  m_color = other.m_color;
177  m_centerLineCreationLock = new boost::shared_mutex();
178  m_longestLineCreationLock = new boost::shared_mutex();
179  // copy them only if they exist
180  if( other.m_centerLine )
181  {
182  m_centerLine = boost::shared_ptr< WFiber >( new WFiber( *other.m_centerLine.get() ) );
183  }
184  if( other.m_longestLine )
185  {
186  m_longestLine = boost::shared_ptr< WFiber >( new WFiber( *other.m_longestLine.get() ) );
187  }
188  return *this;
189  }
190 
191  // TODO(math): The only reason why we store here a Reference to the fiber
192  // dataset is, we need it in the WMVoxelizer module as well as the clustering
193  // information. Since we don't have the possibility of multiple
194  // InputConnectors we must agglomerate those into one object. Please remove this.
195  // \cond Suppress_Doxygen
196  void setDataSetReference( boost::shared_ptr< const WDataSetFiberVector > fibs );
197  boost::shared_ptr< const WDataSetFiberVector > getDataSetReference() const;
198  static boost::shared_ptr< WPrototyped > getPrototype();
199  // \endcond
200 
201  /**
202  * Returns the center line of this cluster. The centerline gets calculated during the first call of this method.
203  *
204  * \return Reference to the center line
205  */
206  boost::shared_ptr< WFiber > getCenterLine() const;
207 
208  /**
209  * Returns the center line of this cluster. The longest line gets calculated during the first call if this method.
210  *
211  * \return Reference to the longest line
212  */
213  boost::shared_ptr< WFiber > getLongestLine() const;
214 
215  /**
216  * Makes the hard work to compute the center line.
217  */
218  void generateCenterLine() const;
219 
220  /**
221  * Makes the hard work to find the longest line.
222  */
223  void generateLongestLine() const;
224 
225  /**
226  * Recomputes on every call the axis aligned bounding box incorporating all tracts in this cluster.
227  *
228  * \return AABB as WBoundingBox.
229  */
230  WBoundingBox getBoundingBox() const;
231 
232 protected:
233  // TODO(math): The only reason why we store here a Reference to the fiber
234  // dataset is, we need it in the WMVoxelizer module as well as the clustering
235  // information. Since we don't have the possibility of multiple
236  // InputConnectors we must agglomerate those into one object. Please remove this.
237  // \cond Suppress_Doxygen
238  static boost::shared_ptr< WPrototyped > m_prototype;
239  // \endcond
240 
241  /**
242  * Alings all fibers within the given dataset to be in one main direction. But Alignment only may swap the ordering of the fibers
243  * but not the positions or something similar. We need this only for the centerline generation.
244  *
245  * \param fibs The dataset
246  */
247  void unifyDirection( boost::shared_ptr< WDataSetFiberVector > fibs ) const;
248 
249 private:
250  /**
251  * The centerline may be shortened due to the averaging of outliers. To
252  * nevertheless color almost the whole bundle surface we need a surface
253  * parameterization (given via the centerline) upto the endings of the
254  * bundle. Therefore the centerline is stepwise elongated with the last
255  * known direction, until no perpendicular plane intersects any of the
256  * tracts inside of the bundle.
257  */
258  void elongateCenterLine() const;
259 
260  /**
261  * All indices in this set are members of this cluster
262  */
263  std::list< size_t > m_memberIndices;
264 
265  // TODO(math): The only reason why we store here a Reference to the fiber
266  // dataset is, we need it in the WMVoxelizer module as well as the clustering
267  // information. Since we don't have the possibility of multiple
268  // InputConnectors we must agglomerate those into one object. Please remove this.
269  /**
270  * Reference to the real fibers of the brain this cluster belongs to.
271  */
272  boost::shared_ptr< const WDataSetFiberVector > m_fibs;
273 
274  /**
275  * Color which is used to paint the members of this cluster.
276  */
277  WColor m_color;
278 
279  /**
280  * Lock the modification in the m_centerLine mutable. The lock is stored as pointer to avoid copy construction problems.
281  */
282  boost::shared_mutex* m_centerLineCreationLock;
283 
284  /**
285  * Lock the modification in the m_longestLine mutable. The lock is stored as pointer to avoid copy construction problems.
286  */
287  boost::shared_mutex* m_longestLineCreationLock;
288 
289  /**
290  * Average fiber for this cluster representing the main direction and curvature of this cluster.
291  *
292  * \note This member is mutable as it needs to be modified during a const getter.
293  */
294  mutable boost::shared_ptr< WFiber > m_centerLine;
295 
296  /**
297  * The longest fiber in the dataset.
298  *
299  * \note This member is mutable as it needs to be modified during a const getter.
300  */
301  mutable boost::shared_ptr< WFiber > m_longestLine;
302 };
303 
304 inline bool WFiberCluster::empty() const
305 {
306  return m_memberIndices.empty();
307 }
308 
309 inline void WFiberCluster::sort()
310 {
311  m_memberIndices.sort();
312 }
313 
314 inline size_t WFiberCluster::size() const
315 {
316  return m_memberIndices.size();
317 }
318 
319 inline void WFiberCluster::clear()
320 {
321  m_memberIndices.clear();
322 }
323 
324 inline void WFiberCluster::setColor( WColor color )
325 {
326  m_color = color;
327 }
328 
329 inline WColor WFiberCluster::getColor() const
330 {
331  return m_color;
332 }
333 
334 inline const std::string WFiberCluster::getName() const
335 {
336  return "FiberCluster";
337 }
338 
339 inline const std::string WFiberCluster::getDescription() const
340 {
341  return "A collection of indices for fibers representing a fiber cluster";
342 }
343 
344 inline bool WFiberCluster::operator==( const WFiberCluster& other ) const
345 {
346  return m_memberIndices == other.m_memberIndices;
347 }
348 
349 inline bool WFiberCluster::operator!=( const WFiberCluster& other ) const
350 {
351  return m_memberIndices != other.m_memberIndices;
352 }
353 
354 inline const std::list< size_t >& WFiberCluster::getIndices() const
355 {
356  return m_memberIndices;
357 }
358 
359 inline void WFiberCluster::setIndices( const std::list< size_t >& indices )
360 {
361  m_memberIndices = indices;
362 }
363 
364 inline std::ostream& operator<<( std::ostream& os, const WFiberCluster& c )
365 {
366  using string_utils::operator<<;
367  return os << c.getIndices();
368 }
369 
370 #endif // WFIBERCLUSTER_H