OpenWalnut  1.5.0dev
WDataSetVector_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 WDATASETVECTOR_TEST_H
26 #define WDATASETVECTOR_TEST_H
27 
28 #include <cmath>
29 #include <memory>
30 #include <vector>
31 
32 #include <boost/array.hpp>
33 #include <boost/random.hpp>
34 #include <cxxtest/TestSuite.h>
35 
36 #include "../../common/WLogger.h"
37 #include "../WDataSetVector.h"
38 
39 /**
40  * Test basic functionality of WDataSetVector.
41  */
42 class WDataSetVectorTest : public CxxTest::TestSuite
43 {
44 public:
45  /**
46  * Constructs unit test environment.
47  */
48  void setUp( void )
49  {
51  }
52 
53  /**
54  * An interpolate of an vector is as if every components were interpolated
55  */
56  void testInterpolate( void )
57  {
58  std::shared_ptr< WGridRegular3D > grid( new WGridRegular3D( 2, 2, 2 ) );
59  boost::array< WPosition, 8 > d = { { WPosition( 0, 1, 2 ), WPosition( 3, 4, 5 ), WPosition( 6, 7, 8 ), // NOLINT braces
60  WPosition( 9,10,11 ), WPosition( 12,13,14 ), WPosition( 15,16,17 ), WPosition( 18,19,20 ), WPosition( 21,22,23 ) } }; // NOLINT braces
61 
62  std::shared_ptr< std::vector< double > > data( new std::vector< double > );
63  for( size_t i = 0; i < grid->size() * 3; ++i )
64  {
65  data->push_back( i );
66  }
67 
68  double almost1 = 1 - wlimits::DBL_EPS;
69  boost::array< WPosition, 8 > gridPos = { { WPosition( 0, 0, 0 ), WPosition( almost1, 0, 0 ), WPosition( 0, almost1, 0 ), // NOLINT braces
70  WPosition( almost1, almost1, 0 ), WPosition( 0, 0, almost1 ), WPosition( almost1, 0, almost1 ),
71  WPosition( 0, almost1, almost1 ), WPosition( almost1, almost1, almost1 ) } }; // NOLINT braces
72 
73  std::shared_ptr< WValueSet< double > > valueSet( new WValueSet< double >( 1, 3, data, W_DT_DOUBLE ) );
74  WDataSetVector ds( valueSet, grid );
75 
76  bool success = false;
77  for( size_t i = 0; i < 8; ++i )
78  {
79  if( !delta( ds.interpolate( gridPos[i], &success ), d[i], 1e-9 ) )
80  {
81  std::stringstream ss;
82  ss << "i:" << i << " gridPos(i):" << gridPos[i] << " d(i):" << d[i] << " interpol:" << ds.interpolate( gridPos[i], &success ) << "\n";
83  TS_FAIL( ss.str() );
84  }
85  TS_ASSERT( success );
86  }
87 
88  TS_ASSERT( delta( ds.interpolate( WPosition( 0.3, 0.4, 0.5 ), &success ), WPosition( 9.3, 10.3, 11.3 ), 1e-9 ) );
89  TS_ASSERT( success );
90  TS_ASSERT( delta( ds.interpolate( WPosition( 0.5, 0.5, 0.5 ), &success ), WPosition( 10.5, 11.5, 12.5 ), 1e-9 ) );
91  TS_ASSERT( success );
92  }
93 
94  /**
95  * Checks if the reorientation of the vectors is applied in eigenVectorInterpolate().
96  \verbatim
97  v_6( 1, 0, 0 ) v_7( 1, 0, 0 )
98  /----------------------------/
99  z A /| /|
100  | / | / |
101  |/ | / |
102  /---+------------------------/ |
103  v_4( 1, 0, 0 ) v_5( 1, 0, 0 )
104  | | | |
105  | | | |
106  | | | |
107  | | y | |
108  | | / | |
109  | | / | |
110  | | / | |
111  | | v_2( 1, 0, 0 ) | | v_3( 1, 0, 0 )
112  | /------------------------+---/
113  | / | /
114  | / | /
115  |/ |/
116  /----------------------------/------------------> x
117  v_0( -1, 0, 0) v_1( 1, 0, 0 )
118 
119  \endverbatim
120  */
122  {
123  std::shared_ptr< WGrid > grid( new WGridRegular3D( 2, 2, 2 ) );
124  std::shared_ptr< std::vector< double > > data( new std::vector< double > );
125  boost::array< WPosition, 8 > d = { { WPosition( -1, 0, 0 ), // NOLINT braces
126  WPosition( 1, 0, 0 ),
127  WPosition( 1, 0, 0 ),
128  WPosition( 1, 0, 0 ),
129  WPosition( 1, 0, 0 ),
130  WPosition( 1, 0, 0 ),
131  WPosition( 1, 0, 0 ),
132  WPosition( 1, 0, 0 ) } }; // NOLINT braces
133 
134  for( size_t i = 0; i < grid->size(); ++i )
135  {
136  data->push_back( d[i][0] );
137  data->push_back( d[i][1] );
138  data->push_back( d[i][2] );
139  }
140  std::shared_ptr< WValueSet< double > > valueSet( new WValueSet< double >( 1, 3, data, W_DT_DOUBLE ) );
141  WDataSetVector ds( valueSet, grid );
142 
143  bool success = false;
144  TS_ASSERT_EQUALS( ds.interpolate( WPosition( 0.0, 0.0, 0.0 ), &success ), d[0] );
145  TS_ASSERT( success );
146  TS_ASSERT( delta( ds.interpolate( WPosition( 0.9999, 0.9999, 0.9999 ), &success ), d[7], 1e-9 ) );
147  TS_ASSERT( success );
148  TS_ASSERT_EQUALS( ds.interpolate( WPosition( 0.5, 0.5, 0.5 ), &success ), WPosition( 0.75, 0.0, 0.0 ) );
149  TS_ASSERT( success );
150  TS_ASSERT_EQUALS( ds.eigenVectorInterpolate( WPosition( 0.0, 0.0, 0.0 ), &success ), d[0] );
151  TS_ASSERT( success );
152  TS_ASSERT( delta( ds.eigenVectorInterpolate( WPosition( 0.9999, 0.9999, 0.9999 ), &success ), WPosition( -1.0, 0.0, 0.0 ), 1e-9 ) );
153  TS_ASSERT( success );
154  TS_ASSERT_EQUALS( ds.eigenVectorInterpolate( WPosition( 0.5, 0.5, 0.5 ), &success ), WPosition( -1.0, 0.0, 0.0 ) );
155  TS_ASSERT( success );
156  }
157 
158  /**
159  * Using interpolate on Positions on the boundary of the grid the success flag is true but there should not be any segfaults.
160  * See ticket #313 for more informations.
161  */
163  {
164  std::shared_ptr< WGridRegular3D > grid( new WGridRegular3D( 3, 4, 5 ) );
165  bool success = false;
166  std::shared_ptr< std::vector< double > > data( new std::vector< double >( grid->size() * 3 ) );
167  for( size_t i = 0; i < grid->size() * 3; ++i )
168  {
169  ( *data )[i] = i;
170  }
171  std::shared_ptr< WValueSet< double > > valueSet( new WValueSet< double >( 1, 3, data, W_DT_DOUBLE ) );
172  WDataSetVector ds( valueSet, grid );
173  ds.interpolate( WPosition( 2.0, 3.0, 4.0 ), &success );
174  TS_ASSERT( !success );
175  }
176 
177  /**
178  * When the grid for this dataset was rotated the interpolation should still work.
179  */
181  {
182  // rotation around z with 45 degrees
183  WMatrix< double > mat( 4, 4 );
184  mat.makeIdentity();
185  mat( 0, 0 ) = 1.0 / sqrt( 2.0 );
186  mat( 0, 1 ) = 1.0 / sqrt( 2.0 );
187  mat( 1, 0 ) = -1.0 / sqrt( 2.0 );
188  mat( 1, 1 ) = 1.0 / sqrt( 2.0 );
189 
190  WGridTransformOrtho v( mat );
191 
192  std::shared_ptr< WGridRegular3D > grid( new WGridRegular3D( 2, 2, 2, v ) );
193  std::shared_ptr< std::vector< double > > data( new std::vector< double > );
194  boost::array< WPosition, 8 > d = { { WPosition( -1, 0, 0 ), // NOLINT braces
195  WPosition( 1, 0, 0 ),
196  WPosition( 1, 0, 0 ),
197  WPosition( 1, 0, 0 ),
198  WPosition( 1, 0, 0 ),
199  WPosition( 1, 0, 0 ),
200  WPosition( 1, 0, 0 ),
201  WPosition( 1, 0, 0 ) } }; // NOLINT braces
202 
203  for( size_t i = 0; i < grid->size(); ++i )
204  {
205  data->push_back( d[i][0] );
206  data->push_back( d[i][1] );
207  data->push_back( d[i][2] );
208  }
209  std::shared_ptr< WValueSet< double > > valueSet( new WValueSet< double >( 1, 3, data, W_DT_DOUBLE ) );
210  WDataSetVector ds( valueSet, grid );
211 
212  bool success = false;
213  WPosition pos = grid->getTransform().positionToWorldSpace( WPosition( 0.0, 0.0, 0.0 ) );
214  TS_ASSERT_EQUALS( ds.interpolate( pos, &success ), d[0] );
215  TS_ASSERT( success );
216  pos = grid->getTransform().positionToWorldSpace( WPosition( 0.9999, 0.9999, 0.9999 ) );
217  TS_ASSERT( delta( ds.interpolate( pos, &success ), d[7], 1e-9 ) );
218  TS_ASSERT( success );
219  pos = grid->getTransform().positionToWorldSpace( WPosition( 0.5, 0.5, 0.5 ) );
220  TS_ASSERT_EQUALS( ds.interpolate( pos, &success ), WPosition( 0.75, 0.0, 0.0 ) );
221  TS_ASSERT( success );
222  pos = grid->getTransform().positionToWorldSpace( WPosition( 0.0, 0.0, 0.0 ) );
223  TS_ASSERT_EQUALS( ds.eigenVectorInterpolate( pos, &success ), d[0] );
224  TS_ASSERT( success );
225  pos = grid->getTransform().positionToWorldSpace( WPosition( 0.9999, 0.9999, 0.9999 ) );
226  TS_ASSERT( delta( ds.eigenVectorInterpolate( pos, &success ), WPosition( -1.0, 0.0, 0.0 ), 1e-9 ) );
227  TS_ASSERT( success );
228  pos = grid->getTransform().positionToWorldSpace( WPosition( 0.5, 0.5, 0.5 ) );
229  TS_ASSERT_EQUALS( ds.eigenVectorInterpolate( pos, &success ), WPosition( -1.0, 0.0, 0.0 ) );
230  TS_ASSERT( success );
231  }
232 
233  /**
234  * Check whether interpolation works for a translated dataset.
235  */
237  {
238  boost::random::mt19937 rng;
239  boost::random::uniform_int_distribution<> urnd( 3, 20 );
240  boost::random::uniform_real_distribution<> drnd( -1000.0, +1000.0 );
241 
242  WMatrix< double > mat( 4, 4 );
243  mat.makeIdentity();
244  mat( 0, 0 ) = 1.7;
245  mat( 1, 1 ) = 1.7;
246  mat( 2, 2 ) = 1.7;
247 
248  std::size_t sx = urnd( rng );
249  std::size_t sy = urnd( rng );
250  std::size_t sz = urnd( rng );
251 
252  boost::random::uniform_real_distribution<> prndx( 0.0, ( sx - 1.000000001 ) * mat( 0, 0 ) );
253  boost::random::uniform_real_distribution<> prndy( 0.0, ( sy - 1.000000001 ) * mat( 1, 1 ) );
254  boost::random::uniform_real_distribution<> prndz( 0.0, ( sz - 1.000000001 ) * mat( 2, 2 ) );
255 
256  WGridTransformOrtho v( mat );
257  std::shared_ptr< WGridRegular3D > grid( new WGridRegular3D( sx, sy, sz, v ) );
258  std::shared_ptr< std::vector< double > > data( new std::vector< double >( grid->size() * 3 ) );
259 
260  for( std::size_t k = 0; k < grid->size(); ++k )
261  {
262  data->at( 3 * k + 0 ) = drnd( rng );
263  data->at( 3 * k + 1 ) = drnd( rng );
264  data->at( 3 * k + 2 ) = drnd( rng );
265  }
266 
267  std::shared_ptr< WValueSet< double > > valueSet( new WValueSet< double >( 1, 3, data, W_DT_DOUBLE ) );
268  WDataSetVector ds( valueSet, grid );
269 
270  for( std::size_t k = 0; k < 1000; ++k )
271  {
272  WMatrix< double > m = mat;
273 
274  m( 0, 3 ) = drnd( rng );
275  m( 1, 3 ) = drnd( rng );
276  m( 2, 3 ) = drnd( rng );
277 
278  WGridTransformOrtho t( m );
279  std::shared_ptr< WGridRegular3D > tGrid( new WGridRegular3D( sx, sy, sz, t ) );
280  std::shared_ptr< WValueSet< double > > tValueSet( new WValueSet< double >( 1, 3, data, W_DT_DOUBLE ) );
281  WDataSetVector tds( tValueSet, tGrid );
282 
283  // test random positions in the dataset
284  for( std::size_t i = 0; i < 100; ++i )
285  {
286  WVector3d p( prndx( rng ), prndy( rng ), prndz( rng ) );
287  WVector3d q( p[ 0 ] + m( 0, 3 ), p[ 1 ] + m( 1, 3 ), p[ 2 ] + m( 2, 3 ) );
288 
289  bool s1, s2;
290  TS_ASSERT( delta( ds.interpolate( p, &s1 ), tds.interpolate( q, &s2 ), 1e-9 ) );
291  TS_ASSERT( s1 );
292  TS_ASSERT( s2 );
293  TS_ASSERT( delta( ds.eigenVectorInterpolate( p, &s1 ), tds.eigenVectorInterpolate( q, &s2 ), 1e-9 ) );
294  TS_ASSERT( s1 );
295  TS_ASSERT( s2 );
296  }
297  }
298  }
299 
300 private:
301  /**
302  * Computes if both vectors are almost similar and their components do not differ from a certain given delta.
303  *
304  * \param lhs First vector
305  * \param rhs Second vector
306  * \param d The given delta
307  *
308  * \return True if and only if all components differing at most by the given delta.
309  */
310  bool delta( WVector3d lhs, WVector3d rhs, double d )
311  {
312  bool result = true;
313  for( int i = 0; result && ( i < 3 ); ++i )
314  {
315  result = result && ( std::abs( lhs[i] - rhs[i] ) <= d );
316  if( !result )
317  {
318  std::cout.precision( 10 );
319  std::cout.setf( std::ios::fixed, std::ios::floatfield );
320  std::cout << "delta failed! => lhs:" << lhs << " rhs:" << rhs << " failed: abs(lhs[" << i << "] - rhs["
321  << i << "])=" << std::abs( lhs[i] - rhs[i] ) << ", but should be: " << d << "\n";
322  }
323  }
324  return result;
325  }
326 };
327 
328 #endif // WDATASETVECTOR_TEST_H
Test basic functionality of WDataSetVector.
void testRotatedGridInterpolate(void)
When the grid for this dataset was rotated the interpolation should still work.
void testInterpolate(void)
An interpolate of an vector is as if every components were interpolated.
void setUp(void)
Constructs unit test environment.
void testEigenVectorInterpolate(void)
Checks if the reorientation of the vectors is applied in eigenVectorInterpolate().
void testTranslatedGridInterpolation()
Check whether interpolation works for a translated dataset.
bool delta(WVector3d lhs, WVector3d rhs, double d)
Computes if both vectors are almost similar and their components do not differ from a certain given d...
void testBoundary_ticket313(void)
Using interpolate on Positions on the boundary of the grid the success flag is true but there should ...
This data set type contains vectors as values.
WVector3d eigenVectorInterpolate(const WPosition &pos, bool *success) const
Interpolates the very same way as interpolate but it assures that all vecs are aligned to point into ...
WVector3d interpolate(const WPosition &pos, bool *success) const
Interpolates the vector field at the given position.
A grid that has parallelepiped cells which all have the same proportion.
Implements an orthogonal grid transformation.
static void startup(std::ostream &output=std::cout, LogLevel level=LL_DEBUG)
Create the first and only instance of the logger as it is a singleton.
Definition: WLogger.cpp:41
WMatrix & makeIdentity()
Makes the matrix contain the identity matrix, i.e.
Definition: WMatrix.h:352
This only is a 3d double vector.
Base Class for all value set types.
Definition: WValueSet.h:47
const double DBL_EPS
Smallest double such: 1.0 + DBL_EPS == 1.0 is still true.
Definition: WLimits.cpp:46