OpenWalnut  1.3.1
WFiberCluster_test.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_TEST_H
26 #define WFIBERCLUSTER_TEST_H
27 
28 #include <list>
29 
30 #include <cxxtest/TestSuite.h>
31 
32 #include "../../../common/WLimits.h"
33 #include "../../../common/WLogger.h"
34 #include "../../test/WDataSetFiberVectorTraits.h"
35 #include "../WFiberCluster.h"
36 
37 /**
38  * Unit test the WFiberCluster class
39  */
40 class WFiberClusterTest : public CxxTest::TestSuite
41 {
42 public:
43  /**
44  * When merging two clusters the indices are merged and the second cluster
45  * becomes empty.
46  */
47  void testMerge( void )
48  {
49  WFiberCluster a( 1 );
50  WFiberCluster b;
51  size_t mydata[] = { 16, 2, 77, 29 }; // NOLINT
52  std::list< size_t > data( mydata, mydata + sizeof( mydata ) / sizeof( size_t ) );
53  b.m_memberIndices = data;
54  a.merge( b );
55  TS_ASSERT( b.empty() );
56  size_t mxdata[] = { 1, 16, 2, 77, 29 }; // NOLINT
57  std::list< size_t > xdata( mxdata, mxdata + sizeof( mxdata ) / sizeof( size_t ) );
58  WFiberCluster expected;
59  expected.m_memberIndices = xdata;
60  TS_ASSERT_EQUALS( expected, a );
61  }
62 
63  /**
64  * Generates a dataset for some unit tests.
65  \verbatim
66  Fiber B had initially 3 points: [0;2],[2;2],[4;2] after resampling there are 5 points:
67  [0;2],[1;2],[2;2],[3;2],[4;2]
68  Fiber A had initially 7 points: [0;0],[1;1],[2;1],[3;1],[4;1],[5;1],[6;1] after resampling there are 5 points:
69  [0;0],[1.5;1],[3;1],[4.5;1],[6;1]
70 
71  |
72  2 -B----B-----B------B-----B
73  |
74  |
75  | ,.m------m---------m-------m (center line)
76  | /
77  | /
78  1 -m aA----a--A--a---A-a----Aa-----A
79  | /
80  | /
81  | /
82  | /
83  |/
84  A-----+-----+-----+-----+-----+-----+---
85  0 1 2 3 4 5 6
86 
87  \endverbatim
88  */
89  void testCenterLine( void )
90  {
91  WFiber expected;
92  expected.push_back( WPosition( 0, 1, 0 ) );
93  expected.push_back( WPosition( ( ( 9.0 - 3 * std::sqrt( 2.0 ) ) / 4.0 - 1.0 ) / 2.0 + 1, 1.5, 0 ) );
94  expected.push_back( WPosition( ( ( 9.0 - 3 * std::sqrt( 2.0 ) ) / 4.0 + ( 5 + std::sqrt( 2.0 ) ) / 4.0 - 2.0 ) / 2.0 + 2, 1.5, 0 ) );
95  expected.push_back( WPosition( ( ( 9.0 - 3 * std::sqrt( 2.0 ) ) / 4.0 + 2 * ( 5 + std::sqrt( 2.0 ) ) / 4.0 - 3.0 ) / 2.0 + 3, 1.5, 0 ) );
96  expected.push_back( WPosition( 5, 1.5, 0 ) );
97  m_cluster->generateCenterLine();
98  assert_equals_delta( *m_cluster->getCenterLine(), expected, wlimits::FLT_EPS );
99  std::cout << *m_cluster->getDataSetReference() << std::endl;
100  }
101 
102  /**
103  * If there are two fibers which are nearly parallel changing ones direction
104  * will have huge effect
105  */
107  {
108  WDataSetFiberVector expected( *m_cluster->getDataSetReference() ); // make a copy
109 
110  boost::shared_ptr< WDataSetFiberVector > fibs( new WDataSetFiberVector( expected ) );
111  fibs->at( 1 ).reverseOrder(); // simulate wrong direction of the second fiber
112 
113  m_cluster->unifyDirection( fibs );
114  using string_utils::operator<<;
115  TS_ASSERT_EQUALS( *fibs, expected );
116  }
117 
118  /**
119  * Check determination of the direction of a pair of fibers which are in the following shape (all points having the same Y and Z coordinate).
120  \verbatim
121  AS--------------------------->AE BS------------------------->BE
122  \endverbatim
123  */
125  {
126  WFiber a;
127  a.push_back( WPosition( 0, 0, 0 ) );
128  a.push_back( WPosition( 1, 0, 0 ) );
129  a.push_back( WPosition( 2, 0, 0 ) );
130  a.push_back( WPosition( 3, 0, 0 ) );
131  a.push_back( WPosition( 4, 0, 0 ) );
132  a.push_back( WPosition( 5, 0, 0 ) );
133  a.push_back( WPosition( 6, 0, 0 ) );
134  WFiber b;
135  b.push_back( WPosition( 10, 0, 0 ) );
136  b.push_back( WPosition( 11, 0, 0 ) );
137  b.push_back( WPosition( 12, 0, 0 ) );
138  b.push_back( WPosition( 13, 0, 0 ) );
139  b.push_back( WPosition( 14, 0, 0 ) );
140  b.push_back( WPosition( 15, 0, 0 ) );
141  b.push_back( WPosition( 16, 0, 0 ) );
142  WDataSetFiberVector expected;
143  expected.push_back( a );
144  expected.push_back( b );
145 
146  boost::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector( expected ) );
147  ds->at( 1 ).reverseOrder();
148  m_cluster->unifyDirection( ds );
149  TS_ASSERT_EQUALS( *ds, expected ); // second tract should flip over
150  m_cluster->unifyDirection( ds );
151  TS_ASSERT_EQUALS( *ds, expected ); // no tract should flip over
152  }
153 
154  /**
155  * Check determination of the direction of a pair of fibers which are in the following shape.
156  *
157  \verbatim
158  AS. _BS
159  `. ,-'
160  `. /
161  \ /
162  \ |
163  `. .'
164  | |
165  | |
166  | |
167  | |
168  | |
169  | |
170  AE BE
171  \endverbatim
172  */
174  {
175  WFiber a;
176  a.push_back( WPosition( 0, 0, 0 ) );
177  a.push_back( WPosition( 5, 1, 0 ) );
178  a.push_back( WPosition( 8, 3, 0 ) );
179  a.push_back( WPosition( 11, 7, 0 ) );
180  a.push_back( WPosition( 11, 10, 0 ) );
181  a.push_back( WPosition( 11, 12, 0 ) );
182  WFiber b;
183  b.push_back( WPosition( 23, 0, 0 ) );
184  b.push_back( WPosition( 19, 2, 0 ) );
185  b.push_back( WPosition( 17, 5, 0 ) );
186  b.push_back( WPosition( 15, 7, 0 ) );
187  b.push_back( WPosition( 16, 10, 0 ) );
188  b.push_back( WPosition( 16, 12, 0 ) );
189  WDataSetFiberVector expected;
190  expected.push_back( a );
191  expected.push_back( b );
192 
193  boost::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector( expected ) );
194  ds->at( 1 ).reverseOrder();
195  m_cluster->unifyDirection( ds );
196  TS_ASSERT_EQUALS( *ds, expected ); // second tract should flip over
197  m_cluster->unifyDirection( ds );
198  TS_ASSERT_EQUALS( *ds, expected ); // no tract should flip over
199  }
200 
201  /**
202  * Check determination of the direction of a pair of fibers which are in the following shape.
203  *
204  \verbatim
205  _.-----AS
206  ,'
207  / ,-'BS
208  | ,'
209  | / AE
210  | / BE |
211  | | | |
212  | | | |
213  \ \ ,| |
214  \ `. ,Y' _,'
215  `\_ `'''''' _.'
216  '`--------''
217  \endverbatim
218  */
220  {
221  WFiber a;
222  a.push_back( WPosition( 14, 0, 0 ) );
223  a.push_back( WPosition( 5, 1, 0 ) );
224  a.push_back( WPosition( 2, 4, 0 ) );
225  a.push_back( WPosition( 3, 9, 0 ) );
226  a.push_back( WPosition( 11, 11, 0 ) );
227  a.push_back( WPosition( 19, 10, 0 ) );
228  a.push_back( WPosition( 24, 8, 0 ) );
229  a.push_back( WPosition( 23, 4, 0 ) );
230  WFiber b;
231  b.push_back( WPosition( 13, 2, 0 ) );
232  b.push_back( WPosition( 7, 4, 0 ) );
233  b.push_back( WPosition( 6, 8, 0 ) );
234  b.push_back( WPosition( 10, 10, 0 ) );
235  b.push_back( WPosition( 17, 9, 0 ) );
236  b.push_back( WPosition( 19, 7, 0 ) );
237  b.push_back( WPosition( 19, 5, 0 ) );
238  WDataSetFiberVector expected;
239  expected.push_back( a );
240  expected.push_back( b );
241 
242  boost::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector( expected ) );
243  ds->at( 1 ).reverseOrder();
244  m_cluster->unifyDirection( ds );
245  TS_ASSERT_EQUALS( *ds, expected ); // second tract should flip over
246  m_cluster->unifyDirection( ds );
247  TS_ASSERT_EQUALS( *ds, expected ); // no tract should flip over
248  }
249 
250  /**
251  * Check determination of the direction of a pair of fibers which are in the following shape.
252  *
253  \verbatim
254  ,,---._
255  ,' \
256  / \
257  | |
258  \ ,'
259  \ ,'
260  `-AS AE
261  BS BE
262  ,' `.
263  / \
264  | |
265  | |
266  | |
267  \ /
268  `-._ _,-'
269  `''
270  \endverbatim
271  */
273  {
274  WFiber a;
275  a.push_back( WPosition( 6, 6, 0 ) );
276  a.push_back( WPosition( 3, 5, 0 ) );
277  a.push_back( WPosition( 2, 3, 0 ) );
278  a.push_back( WPosition( 4, 1, 0 ) );
279  a.push_back( WPosition( 7, 0, 0 ) );
280  a.push_back( WPosition( 11, 0, 0 ) );
281  a.push_back( WPosition( 14, 2, 0 ) );
282  a.push_back( WPosition( 13, 4, 0 ) );
283  a.push_back( WPosition( 11, 6, 0 ) );
284  WFiber b;
285  b.push_back( WPosition( 6, 7, 0 ) );
286  b.push_back( WPosition( 3, 9, 0 ) );
287  b.push_back( WPosition( 1, 11, 0 ) );
288  b.push_back( WPosition( 3, 14, 0 ) );
289  b.push_back( WPosition( 8, 15, 0 ) );
290  b.push_back( WPosition( 13, 14, 0 ) );
291  b.push_back( WPosition( 15, 12, 0 ) );
292  b.push_back( WPosition( 14, 9, 0 ) );
293  b.push_back( WPosition( 11, 7, 0 ) );
294  WDataSetFiberVector expected;
295  expected.push_back( a );
296  expected.push_back( b );
297 
298  boost::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector( expected ) );
299  ds->at( 1 ).reverseOrder();
300  m_cluster->unifyDirection( ds );
301  TS_ASSERT_EQUALS( *ds, expected ); // second tract should flip over
302  m_cluster->unifyDirection( ds );
303  TS_ASSERT_EQUALS( *ds, expected ); // no tract should flip over
304  }
305 
306  /**
307  * Check determination of the direction of a pair of fibers which are in the following shape.
308  *
309  \verbatim
310  ,,-'-AE BS''`-._
311  ,' `.
312  / \
313  / `.
314  / `.
315  / |
316  | |
317  | |
318  | |
319  | |
320  | |
321  | |
322  AS BE
323  \endverbatim
324  */
326  {
327  WFiber a;
328  a.push_back( WPosition( 1, 12, 0 ) );
329  a.push_back( WPosition( 1, 9, 0 ) );
330  a.push_back( WPosition( 2, 5, 0 ) );
331  a.push_back( WPosition( 5, 1, 0 ) );
332  a.push_back( WPosition( 9, 0, 0 ) );
333  a.push_back( WPosition( 14, 0, 0 ) );
334  WFiber b;
335  b.push_back( WPosition( 19, 0, 0 ) );
336  b.push_back( WPosition( 24, 0, 0 ) );
337  b.push_back( WPosition( 29, 2, 0 ) );
338  b.push_back( WPosition( 32, 5, 0 ) );
339  b.push_back( WPosition( 33, 8, 0 ) );
340  b.push_back( WPosition( 33, 12, 0 ) );
341  WDataSetFiberVector expected;
342  expected.push_back( a );
343  expected.push_back( b );
344 
345  boost::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector( expected ) );
346  ds->at( 1 ).reverseOrder();
347  m_cluster->unifyDirection( ds );
348  TS_ASSERT_EQUALS( *ds, expected ); // second tract should flip over
349  m_cluster->unifyDirection( ds );
350  TS_ASSERT_EQUALS( *ds, expected ); // no tract should flip over
351  }
352 
353 private:
354  /**
355  * Compares to point sequences (aka lines) with a given delta.
356  *
357  * \param first First line to compare with
358  * \param second Second line to compare with
359  * \param delta The delta within two points are considered as equally
360  */
361  void assert_equals_delta( const WLine& first, const WLine& second, double delta = wlimits::DBL_EPS ) const
362  {
363  int diffPos = 0;
364  if( ( diffPos = equalsDelta( first, second, delta ) ) != -1 )
365  {
366  using string_utils::operator<<;
367  std::stringstream msg;
368  msg << "Lines are different in at least point: " << diffPos;
369  TS_FAIL( msg.str() );
370  std::cout << "first line at: " << diffPos << std::endl << first[diffPos] << std::endl;
371  std::cout << "second line at: " << diffPos << std::endl << second[diffPos] << std::endl;
372  std::cout << "first line: " << std::endl << first << std::endl;
373  std::cout << "second line: " << std::endl << second << std::endl;
374  }
375  }
376 
377  /**
378  * Generates a dataset for some unit tests.
379  \verbatim
380  Fiber B has 3 points: [0;2],[2;2],[4;2]
381  Fiber A has 7 points: [0;0],[1;1],[2;1],[3;1],[4;1],[5;1],[6;1]
382 
383  |
384  2 -b----------b------------b
385  |
386  |
387  |
388  |
389  |
390  1 -| a-----a-----a-----a-----a-----a
391  | /
392  | /
393  | /
394  | /
395  |/
396  a-----+-----+-----+-----+-----+-----+---
397  0 1 2 3 4 5 6
398 
399  \endverbatim
400  */
401  void setUp( void )
402  {
403  // generate fiber dataset to operate on
404  WFiber fib_a;
405  fib_a.push_back( WPosition( 0, 0, 0 ) );
406  fib_a.push_back( WPosition( 1, 1, 0 ) );
407  fib_a.push_back( WPosition( 2, 1, 0 ) );
408  fib_a.push_back( WPosition( 3, 1, 0 ) );
409  fib_a.push_back( WPosition( 4, 1, 0 ) );
410  fib_a.push_back( WPosition( 5, 1, 0 ) );
411  fib_a.push_back( WPosition( 6, 1, 0 ) );
412  WFiber fib_b;
413  fib_b.push_back( WPosition( 0, 2, 0 ) );
414  fib_b.push_back( WPosition( 2, 2, 0 ) );
415  fib_b.push_back( WPosition( 4, 2, 0 ) );
416  boost::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector() );
417  ds->push_back( fib_a );
418  ds->push_back( fib_b );
419  generateFiberCluster( ds );
420  }
421 
422  /**
423  * Generates out of the given dataset a WFiberCluster containing all fibers.
424  *
425  * \param ds The fiber dataset
426  */
427  void generateFiberCluster( const boost::shared_ptr< WDataSetFiberVector > ds )
428  {
429  m_cluster.reset();
430  m_cluster = boost::shared_ptr< WFiberCluster >( new WFiberCluster() );
431  m_cluster->setDataSetReference( ds );
432  std::list< size_t > idx;
433  for( size_t i = 0; i < ds->size(); ++i )
434  {
435  idx.push_back( i );
436  }
437  m_cluster->setIndices( idx );
438  }
439 
440  /**
441  * Tidyups the dataset used in some unit tests
442  */
443  void tearDown( void )
444  {
445  m_cluster.reset();
446  }
447 
448  boost::shared_ptr< WFiberCluster > m_cluster; //!< pre generated cluster for some unit tests
449 };
450 
451 #endif // WFIBERCLUSTER_TEST_H