OpenWalnut  1.4.0
WDataSetVector_test.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 WDATASETVECTOR_TEST_H
00026 #define WDATASETVECTOR_TEST_H
00027 
00028 #include <vector>
00029 #include <cmath>
00030 
00031 #include <boost/array.hpp>
00032 
00033 #include <cxxtest/TestSuite.h>
00034 
00035 #include "../../common/WLogger.h"
00036 #include "../WDataSetVector.h"
00037 
00038 /**
00039  * Test basic functionality of WDataSetVector.
00040  */
00041 class WDataSetVectorTest : public CxxTest::TestSuite
00042 {
00043 public:
00044     /**
00045      * Constructs unit test environment.
00046      */
00047     void setUp( void )
00048     {
00049         WLogger::startup();
00050     }
00051 
00052     /**
00053      * An interpolate of an vector is as if every components were interpolated
00054      */
00055     void testInterpolate( void )
00056     {
00057         boost::shared_ptr< WGridRegular3D > grid( new WGridRegular3D( 2, 2, 2 ) );
00058         boost::array< WPosition, 8 > d = { { WPosition(  0, 1, 2 ), WPosition(  3, 4, 5 ), WPosition(  6, 7, 8 ), // NOLINT braces
00059             WPosition(  9,10,11 ), WPosition( 12,13,14 ), WPosition( 15,16,17 ), WPosition( 18,19,20 ), WPosition( 21,22,23 ) } }; // NOLINT braces
00060 
00061         boost::shared_ptr< std::vector< double > > data( new std::vector< double > );
00062         for( size_t i = 0; i < grid->size() * 3; ++i )
00063         {
00064             data->push_back( i );
00065         }
00066 
00067         double almost1 = 1 - wlimits::DBL_EPS;
00068         boost::array< WPosition, 8 > gridPos = { { WPosition( 0, 0, 0 ), WPosition( almost1, 0, 0 ), WPosition( 0, almost1, 0 ), // NOLINT braces
00069             WPosition( almost1, almost1, 0 ), WPosition( 0, 0, almost1 ), WPosition(  almost1, 0, almost1 ),
00070             WPosition( 0, almost1, almost1 ), WPosition(  almost1, almost1, almost1 ) } }; // NOLINT braces
00071 
00072         boost::shared_ptr< WValueSet< double > > valueSet( new WValueSet< double >( 1, 3, data, W_DT_DOUBLE ) );
00073         WDataSetVector ds( valueSet, grid );
00074 
00075         bool success = false;
00076         for( size_t i = 0; i < 8; ++i )
00077         {
00078             if( !delta( ds.interpolate( gridPos[i], &success ), d[i], 1e-9 ) )
00079             {
00080                 std::stringstream ss;
00081                 ss << "i:" << i << " gridPos(i):" << gridPos[i] << " d(i):" << d[i] << " interpol:" << ds.interpolate( gridPos[i], &success ) << "\n";
00082                 TS_FAIL( ss.str() );
00083             }
00084             TS_ASSERT( success );
00085         }
00086 
00087         TS_ASSERT( delta( ds.interpolate( WPosition( 0.3, 0.4, 0.5 ), &success ), WPosition( 9.3, 10.3, 11.3 ), 1e-9 ) );
00088         TS_ASSERT( success );
00089         TS_ASSERT( delta( ds.interpolate( WPosition( 0.5, 0.5, 0.5 ), &success ), WPosition( 10.5, 11.5, 12.5 ), 1e-9 ) );
00090         TS_ASSERT( success );
00091     }
00092 
00093     /**
00094      * Checks if the reorientation of the vectors is applied in eigenVectorInterpolate().
00095      \verbatim
00096                          v_6( 1, 0, 0 )               v_7( 1, 0, 0 )
00097                        /----------------------------/
00098                  z A  /|                           /|
00099                    | / |                          / |
00100                    |/  |                         /  |
00101                    /---+------------------------/   |
00102             v_4( 1, 0, 0 )               v_5( 1, 0, 0 )
00103                    |   |                        |   |
00104                    |   |                        |   |
00105                    |   |                        |   |
00106                    |   |    y                   |   |
00107                    |   |   /                    |   |
00108                    |   |  /                     |   |
00109                    |   | /                      |   |
00110                    |   | v_2( 1, 0, 0 )         |   | v_3( 1, 0, 0 )
00111                    |   /------------------------+---/
00112                    |  /                         |  /
00113                    | /                          | /
00114                    |/                           |/
00115                    /----------------------------/------------------> x
00116             v_0( -1, 0, 0)                v_1( 1, 0, 0 )
00117 
00118      \endverbatim
00119      */
00120     void testEigenVectorInterpolate( void )
00121     {
00122         boost::shared_ptr< WGrid > grid( new WGridRegular3D( 2, 2, 2 ) );
00123         boost::shared_ptr< std::vector< double > > data( new std::vector< double > );
00124         boost::array< WPosition, 8 > d = { { WPosition( -1, 0, 0 ), // NOLINT braces
00125                                              WPosition(  1, 0, 0 ),
00126                                              WPosition(  1, 0, 0 ),
00127                                              WPosition(  1, 0, 0 ),
00128                                              WPosition(  1, 0, 0 ),
00129                                              WPosition(  1, 0, 0 ),
00130                                              WPosition(  1, 0, 0 ),
00131                                              WPosition(  1, 0, 0 ) } }; // NOLINT braces
00132 
00133         for( size_t i = 0; i < grid->size(); ++i )
00134         {
00135             data->push_back( d[i][0] );
00136             data->push_back( d[i][1] );
00137             data->push_back( d[i][2] );
00138         }
00139         boost::shared_ptr< WValueSet< double > > valueSet( new WValueSet< double >( 1, 3, data, W_DT_DOUBLE ) );
00140         WDataSetVector ds( valueSet, grid );
00141 
00142         bool success = false;
00143         TS_ASSERT_EQUALS( ds.interpolate( WPosition( 0.0, 0.0, 0.0 ), &success ), d[0] );
00144         TS_ASSERT( success );
00145         TS_ASSERT( delta( ds.interpolate( WPosition( 0.9999, 0.9999, 0.9999 ), &success ), d[7], 1e-9 ) );
00146         TS_ASSERT( success );
00147         TS_ASSERT_EQUALS( ds.interpolate( WPosition( 0.5, 0.5, 0.5 ), &success ), WPosition( 0.75, 0.0, 0.0 ) );
00148         TS_ASSERT( success );
00149         TS_ASSERT_EQUALS( ds.eigenVectorInterpolate( WPosition( 0.0, 0.0, 0.0 ), &success ), d[0] );
00150         TS_ASSERT( success );
00151         TS_ASSERT( delta( ds.eigenVectorInterpolate( WPosition( 0.9999, 0.9999, 0.9999 ), &success ), WPosition( -1.0, 0.0, 0.0 ), 1e-9 ) );
00152         TS_ASSERT( success );
00153         TS_ASSERT_EQUALS( ds.eigenVectorInterpolate( WPosition( 0.5, 0.5, 0.5 ), &success ), WPosition( -1.0, 0.0, 0.0 ) );
00154         TS_ASSERT( success );
00155     }
00156 
00157     /**
00158      * Using interpolate on Positions on the boundary of the grid the success flag is true but there should not be any segfaults.
00159      * See ticket #313 for more informations.
00160      */
00161     void testBoundary_ticket313( void )
00162     {
00163         boost::shared_ptr< WGridRegular3D > grid( new WGridRegular3D( 3, 4, 5 ) );
00164         bool success = false;
00165         boost::shared_ptr< std::vector< double > > data( new std::vector< double >( grid->size() * 3 ) );
00166         for( size_t i = 0; i < grid->size() * 3; ++i )
00167         {
00168             ( *data )[i] = i;
00169         }
00170         boost::shared_ptr< WValueSet< double > > valueSet( new WValueSet< double >( 1, 3, data, W_DT_DOUBLE ) );
00171         WDataSetVector ds( valueSet, grid );
00172         ds.interpolate( WPosition( 2.0, 3.0, 4.0 ), &success );
00173         TS_ASSERT( !success );
00174     }
00175 
00176     /**
00177      * When the grid for this dataset was rotated the interpolation should still work.
00178      */
00179     void testRotatedGridInterpolate( void )
00180     {
00181         // rotation around z with 45 degrees
00182         WMatrix< double > mat( 4, 4 );
00183         mat.makeIdentity();
00184         mat( 0, 0 ) =  1.0 / sqrt( 2.0 );
00185         mat( 0, 1 ) =  1.0 / sqrt( 2.0 );
00186         mat( 1, 0 ) = -1.0 / sqrt( 2.0 );
00187         mat( 1, 1 ) =  1.0 / sqrt( 2.0 );
00188 
00189         WGridTransformOrtho v( mat );
00190 
00191         boost::shared_ptr< WGridRegular3D > grid( new WGridRegular3D( 2, 2, 2, v ) );
00192         boost::shared_ptr< std::vector< double > > data( new std::vector< double > );
00193         boost::array< WPosition, 8 > d = { { WPosition( -1, 0, 0 ), // NOLINT braces
00194                                              WPosition(  1, 0, 0 ),
00195                                              WPosition(  1, 0, 0 ),
00196                                              WPosition(  1, 0, 0 ),
00197                                              WPosition(  1, 0, 0 ),
00198                                              WPosition(  1, 0, 0 ),
00199                                              WPosition(  1, 0, 0 ),
00200                                              WPosition(  1, 0, 0 ) } }; // NOLINT braces
00201 
00202         for( size_t i = 0; i < grid->size(); ++i )
00203         {
00204             data->push_back( d[i][0] );
00205             data->push_back( d[i][1] );
00206             data->push_back( d[i][2] );
00207         }
00208         boost::shared_ptr< WValueSet< double > > valueSet( new WValueSet< double >( 1, 3, data, W_DT_DOUBLE ) );
00209         WDataSetVector ds( valueSet, grid );
00210 
00211         bool success = false;
00212         WPosition pos = grid->getTransform().positionToWorldSpace( WPosition( 0.0, 0.0, 0.0 ) );
00213         TS_ASSERT_EQUALS( ds.interpolate( pos, &success ), d[0] );
00214         TS_ASSERT( success );
00215         pos = grid->getTransform().positionToWorldSpace( WPosition( 0.9999, 0.9999, 0.9999 ) );
00216         TS_ASSERT( delta( ds.interpolate( pos, &success ), d[7], 1e-9 ) );
00217         TS_ASSERT( success );
00218         pos = grid->getTransform().positionToWorldSpace( WPosition( 0.5, 0.5, 0.5 ) );
00219         TS_ASSERT_EQUALS( ds.interpolate( pos, &success ), WPosition( 0.75, 0.0, 0.0 ) );
00220         TS_ASSERT( success );
00221         pos = grid->getTransform().positionToWorldSpace( WPosition( 0.0, 0.0, 0.0 ) );
00222         TS_ASSERT_EQUALS( ds.eigenVectorInterpolate( pos, &success ), d[0] );
00223         TS_ASSERT( success );
00224         pos = grid->getTransform().positionToWorldSpace( WPosition( 0.9999, 0.9999, 0.9999 ) );
00225         TS_ASSERT( delta( ds.eigenVectorInterpolate( pos, &success ), WPosition( -1.0, 0.0, 0.0 ), 1e-9 ) );
00226         TS_ASSERT( success );
00227         pos = grid->getTransform().positionToWorldSpace( WPosition( 0.5, 0.5, 0.5 ) );
00228         TS_ASSERT_EQUALS( ds.eigenVectorInterpolate( pos, &success ), WPosition( -1.0, 0.0, 0.0 ) );
00229         TS_ASSERT( success );
00230     }
00231 
00232 private:
00233     /**
00234      * Computes if both vectors are almost similar and their components do not differ from a certain given delta.
00235      *
00236      * \param lhs First vector
00237      * \param rhs Second vector
00238      * \param d The given delta
00239      *
00240      * \return True if and only if all components differing at most by the given delta.
00241      */
00242     bool delta( WVector3d lhs, WVector3d rhs, double d )
00243     {
00244         bool result = true;
00245         for( int i = 0; result && ( i < 3 ); ++i )
00246         {
00247             result = result && ( std::abs( lhs[i] - rhs[i] ) <= d );
00248             if( !result )
00249             {
00250                 std::cout.precision( 10 );
00251                 std::cout.setf( std::ios::fixed, std::ios::floatfield );
00252                 std::cout << "delta failed! => lhs:" << lhs << " rhs:" << rhs << " failed: abs(lhs[" << i << "] - rhs["
00253                     << i << "])=" << std::abs( lhs[i] - rhs[i] ) << ", but should be: " << d << "\n";
00254             }
00255         }
00256         return result;
00257     }
00258 };
00259 
00260 #endif  // WDATASETVECTOR_TEST_H