OpenWalnut  1.4.0
WGridRegular3D_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 WGRIDREGULAR3D_TEST_H
00026 #define WGRIDREGULAR3D_TEST_H
00027 
00028 #include <cstdio>
00029 #include <sstream>
00030 #include <string>
00031 #include <vector>
00032 
00033 #include <boost/shared_ptr.hpp>
00034 
00035 #include <cxxtest/TestSuite.h>
00036 
00037 #include "../../common/exceptions/WOutOfBounds.h"
00038 #include "../../common/math/test/WVector3dTraits.h"
00039 #include "../../common/WLimits.h"
00040 #include "../WGridRegular3D.h"
00041 
00042 
00043 /**
00044  * Tests the WGridRegular3D class.
00045  */
00046 class WGridRegular3DTest : public CxxTest::TestSuite
00047 {
00048 public:
00049     /**
00050      * Called before every test.
00051      */
00052     void setUp( void )
00053     {
00054         m_delta = 1e-14;
00055     }
00056 
00057     /**
00058      * Ensure that nothing is thrown when an instance is created.
00059      */
00060     void testInstantiation( void )
00061     {
00062         TS_ASSERT_THROWS_NOTHING( WGridRegular3D grid( 3, 3, 3 ) );
00063     }
00064 
00065     /**
00066      * After instantiation there should be the requested number of positions.
00067      */
00068     void testSize( void )
00069     {
00070         WGridTransformOrtho t( WMatrix< double >( 4, 4 ).makeIdentity() );
00071         WGridRegular3D grid( 3, 3, 3, t );
00072         TS_ASSERT_EQUALS( grid.size(), 27 );
00073     }
00074 
00075     /**
00076      * Each convinience function just assembles the three values into an boost array.
00077      */
00078     void testConvinienceFunctions( void )
00079     {
00080         boost::shared_ptr< WGridRegular3D > grid( new WGridRegular3D( 3, 3, 3 ) );
00081         boost::array< unsigned int, 3 > expectedNbCoords = { { 3, 3, 3 } }; // NOLINT curly braces
00082         TS_ASSERT_EQUALS( expectedNbCoords, getNbCoords< double >( grid ) );
00083         boost::array< double, 3 > expectedOffsets = { { 1.0, 1.0, 1.0 } }; // NOLINT curly braces
00084         TS_ASSERT_EQUALS( expectedOffsets, getOffsets< double >( grid ) );
00085         boost::array< WVector3d, 3 > expectedDirections = { { WVector3d( 1.0, 0.0, 0.0 ), WVector3d( 0.0, 1.0, 0.0 ), WVector3d( 0.0, 0.0, 1.0 ) } }; // NOLINT curly braces line length
00086         TS_ASSERT_EQUALS( expectedDirections, getDirections< double >( grid ) );
00087         TS_ASSERT_EQUALS( expectedDirections, getUnitDirections< double >( grid ) );
00088     }
00089 
00090     /**
00091      * After instantiation there should be the right vectors, matrix and origin.
00092      */
00093     void testOrientation( void )
00094     {
00095         WMatrix< double > mat( 4, 4 );
00096         mat.makeIdentity();
00097         mat( 0, 0 ) = 2.2;
00098         mat( 1, 1 ) = 3.3;
00099         mat( 2, 2 ) = 4.4;
00100 
00101         WGridTransformOrtho t( mat );
00102         WGridRegular3D grid( 3, 3, 3, t );
00103         TS_ASSERT_EQUALS( grid.size(), 27 );
00104         TS_ASSERT_EQUALS( grid.getOrigin(), WPosition( 0., 0., 0. ) );
00105         TS_ASSERT_EQUALS( grid.getDirectionX(), WVector3d( 2.2, 0., 0. ) );
00106         TS_ASSERT_EQUALS( grid.getDirectionY(), WVector3d( 0., 3.3, 0. ) );
00107         TS_ASSERT_EQUALS( grid.getDirectionZ(), WVector3d( 0., 0., 4.4 ) );
00108     }
00109 
00110     /**
00111      * getNbCoords should return the samples prescribed by the use of the constructor
00112      */
00113     void testGetNbCoords( void )
00114     {
00115         size_t x = 3;
00116         size_t y = 4;
00117         size_t z = 5;
00118         WGridRegular3D grid( x, y, z );
00119         TS_ASSERT_EQUALS( grid.getNbCoordsX(), x );
00120         TS_ASSERT_EQUALS( grid.getNbCoordsY(), y );
00121         TS_ASSERT_EQUALS( grid.getNbCoordsZ(), z );
00122     }
00123 
00124     /**
00125      * getOffset should return the vector offsets prescribed by the use of the
00126      * constructor
00127      */
00128     void testGetVectorOffset( void )
00129     {
00130         WVector3d x( 3., 1., 2. );
00131         WVector3d y( 2., -6., 0. );
00132         WVector3d z( 12., 4., -20 );
00133 
00134         WMatrix< double > mat( 4, 4 );
00135         mat.makeIdentity();
00136         mat( 0, 0 ) = x[ 0 ];
00137         mat( 1, 0 ) = x[ 1 ];
00138         mat( 2, 0 ) = x[ 2 ];
00139         mat( 0, 1 ) = y[ 0 ];
00140         mat( 1, 1 ) = y[ 1 ];
00141         mat( 2, 1 ) = y[ 2 ];
00142         mat( 0, 2 ) = z[ 0 ];
00143         mat( 1, 2 ) = z[ 1 ];
00144         mat( 2, 2 ) = z[ 2 ];
00145 
00146         WGridTransformOrtho t( mat );
00147         WGridRegular3D grid( 3, 3, 3, t );
00148 
00149         TS_ASSERT_DELTA( grid.getOffsetX(), length( x ), m_delta );
00150         TS_ASSERT_DELTA( grid.getOffsetY(), length( y ), m_delta );
00151         TS_ASSERT_DELTA( grid.getOffsetZ(), length( z ), m_delta );
00152     }
00153 
00154     /**
00155      * getPosition should return the correct position for scalar offsets
00156      */
00157     void testGetPositionScalarOffset( void )
00158     {
00159         unsigned int nX = 10, nY = 11, nZ = 12;
00160         unsigned int iX = 8, iY = 9, iZ = 5;
00161         unsigned int i = iX + iY * nX + iZ * nX * nY;
00162 
00163         double orX = 1.2;
00164         double orY = 3.4;
00165         double orZ = 5.6;
00166 
00167         double ofX = 1.1;
00168         double ofY = 2.2;
00169         double ofZ = 3.3;
00170 
00171         double x = orX + iX * ofX;
00172         double y = orY + iY * ofY;
00173         double z = orZ + iZ * ofZ;
00174 
00175         WMatrix< double > mat( 4, 4 );
00176         mat.makeIdentity();
00177         mat( 0, 0 ) = ofX;
00178         mat( 1, 1 ) = ofY;
00179         mat( 2, 2 ) = ofZ;
00180         mat( 0, 3 ) = orX;
00181         mat( 1, 3 ) = orY;
00182         mat( 2, 3 ) = orZ;
00183 
00184         WPosition expected( x, y, z );
00185         WGridTransformOrtho t( mat );
00186         WGridRegular3D grid( nX, nY, nZ, t );
00187 
00188         TS_ASSERT_DELTA( grid.getPosition( iX, iY, iZ )[0], expected[0], m_delta );
00189         TS_ASSERT_DELTA( grid.getPosition( iX, iY, iZ )[1], expected[1], m_delta );
00190         TS_ASSERT_DELTA( grid.getPosition( iX, iY, iZ )[2], expected[2], m_delta );
00191         TS_ASSERT_DELTA( grid.getPosition( i )[0], expected[0], m_delta );
00192         TS_ASSERT_DELTA( grid.getPosition( i )[1], expected[1], m_delta );
00193         TS_ASSERT_DELTA( grid.getPosition( i )[2], expected[2], m_delta );
00194     }
00195 
00196     /**
00197      * The cell number of a Position is defined as follows:
00198      *
00199        \verbatim
00200         y-axis
00201           |_____ _____ ___   _
00202         3 |     |     |       |
00203           |     |     | ...   + dy
00204           |_____|_____|___   _|
00205         2 |     | . Line
00206           |     |/    | ...
00207           |_____/___ _|___
00208         1 |    /|     |
00209           |   ' |     | ...
00210           |_____|_____|______ x-axis
00211          /0     1     2
00212         / `--.--´
00213        /    dx
00214        origin e.g. ( 3.1, 3.2, -6 ) and dx == dy == 1.0 ( the z-axis is ignored in this example )
00215        \endverbatim
00216      *
00217      * Hence the line starts at approx. ( 3.85, 3.7, -6 ) and ends at
00218      * approx. ( 4.35, 5.0 , -6 ). The Cell number e.g. of the start point
00219      * is then: 4 and of the end point: 7.
00220      */
00221     void testGetVoxelNumberOfGeneralPosition( void )
00222     {
00223         using boost::shared_ptr;
00224 
00225         WMatrix< double > mat( 4, 4 );
00226         mat.makeIdentity();
00227         mat( 0, 3 ) = 3.1;
00228         mat( 1, 3 ) = 3.2;
00229         mat( 2, 3 ) = -6.;
00230 
00231         WGridTransformOrtho t( mat );
00232         shared_ptr< WGridRegular3D > g = shared_ptr< WGridRegular3D >( new WGridRegular3D( 3, 3, 3, t ) );
00233         TS_ASSERT_EQUALS( g->getVoxelNum( WPosition( 4.35, 5.0, -6 ) ), 7 );
00234     }
00235 
00236     /**
00237      * If a grid point is outside of the grid then -1 should be returned.
00238      */
00239     void testGetVoxelNumberOfPositionOutsideOfGrid( void )
00240     {
00241         using boost::shared_ptr;
00242 
00243         shared_ptr< WGridRegular3D > g = shared_ptr< WGridRegular3D >( new WGridRegular3D( 3, 3, 3 ) );
00244         TS_ASSERT_EQUALS( g->getVoxelNum( WPosition( 0 - m_delta, 0, 0 ) ), -1 );
00245         TS_ASSERT_EQUALS( g->getVoxelNum( WPosition( 0, 2 + m_delta, 0 ) ), -1 );
00246     }
00247 
00248     /**
00249      * All points of the surfaces belonging to the lower,left,front corner of a
00250      * voxel belong to this voxel. Instead all points located on the three
00251      * surfaces belonging to the upper right back corner are considered not to
00252      * belong to this voxel.
00253      */
00254     void testGetVoxelNumberOfPositionExactlyBetweenVoxels( void )
00255     {
00256         // A voxel is defined as this ( a cuboid with a center which is a grid point ):
00257         //             ______________ ____ (0.5, 0.5, 0.5)
00258         //            /:            /|
00259         //           / :           / |
00260         //          /  :          /  |
00261         //         /   :         /   |
00262         //       _/____:_ ___ __/    |
00263         //        |    :        |    |
00264         //        |    :    *<--|--------- grid point (0, 0, 0)
00265         //        |    :........|....|__
00266         // dz == 1|   ´         |   /
00267         //        |  ´          |  / dy == 1
00268         //        | ´           | /
00269         //       _|´____________|/__
00270         //        |<- dx == 1 ->|
00271         // -0.5,-0.5,-0.5
00272         //
00273         // the grid is as follows
00274         //         ______________ ____ 2,2,2
00275         //        /:     /      /|
00276         //       / :    /:     / |
00277         //      /------+------/| |
00278         //     /   :……/……:………/…|…|
00279         //    /____:_/___:__/  | |---- 2,2,1
00280         //    |    : |   :  |  |/|
00281         //    |    : |   :  |  | |
00282         //    |    :.|...:..| /| |____ 2,2,0
00283         //    +------+------+´ |/
00284         //    |  '   |      |  /---- 2,1,0
00285         //    | '    |      | /
00286         //    |'_____|______|/____
00287         //    |      |      |
00288         // 0,0,0   1,0,0  2,0,0
00289 
00290         WGridRegular3D  g( 3, 3, 3 );
00291 
00292         // center point of the grid
00293         TS_ASSERT_EQUALS( g.getVoxelNum( WPosition( 1, 1, 1 ) ), 13 );
00294 
00295         // front lower left corner of the last cell
00296         TS_ASSERT_EQUALS( g.getVoxelNum( WPosition( 1.5, 1.5, 1.5 ) ), 26 );
00297 
00298         TS_ASSERT_EQUALS( g.getVoxelNum( WPosition( 1, 1, 0.5 ) ), 13 );
00299         TS_ASSERT_EQUALS( g.getVoxelNum( WPosition( 0 , 1.5 , 1 ) ), 15 );
00300         TS_ASSERT_EQUALS( g.getVoxelNum( WPosition( 0.5, 1, 0 ) ), 4 );
00301 
00302         // origin
00303         TS_ASSERT_EQUALS( g.getVoxelNum( WPosition( 0, 0, 0 ) ), 0 );
00304     }
00305 
00306     /**
00307      * A voxel inside a grid (not located on a border) has 6 neighbours.
00308      */
00309     void testNeighboursInsideAGrid( void )
00310     {
00311         WGridRegular3D g( 3, 3, 3 );
00312         size_t data[] = { 12, 14, 10, 16, 4, 22 };
00313         std::vector< size_t > expected( data, data + 6 );
00314         TS_ASSERT_EQUALS( expected, g.getNeighbours( 13 ) );
00315     }
00316 
00317     /**
00318      * The correct voxel numbers should be returned in a rotated grid.
00319      */
00320     void testRotatedVoxelNum()
00321     {
00322         WVector3d x( 0.707, 0.707, 0.0 );
00323         WVector3d y( -0.707, 0.707, 0.0 );
00324         WVector3d z( 0.0, 0.0, 1.0 );
00325         x = normalize( x );
00326         y = normalize( y );
00327         y *= 2.0;
00328         z *= 1.5;
00329 
00330         WMatrix< double > mat( 4, 4 );
00331         mat.makeIdentity();
00332         mat( 0, 0 ) = x[ 0 ];
00333         mat( 1, 0 ) = x[ 1 ];
00334         mat( 2, 0 ) = x[ 2 ];
00335         mat( 0, 1 ) = y[ 0 ];
00336         mat( 1, 1 ) = y[ 1 ];
00337         mat( 2, 1 ) = y[ 2 ];
00338         mat( 0, 2 ) = z[ 0 ];
00339         mat( 1, 2 ) = z[ 1 ];
00340         mat( 2, 2 ) = z[ 2 ];
00341         mat( 0, 3 ) = 1.0;
00342 
00343         WGridTransformOrtho t( mat );
00344         WGridRegular3D g( 5, 5, 5, t );
00345 
00346         WVector3d v = WVector3d( 1.0, 0.0, 0.0 ) + 0.3 * z + 2.4 * y + 2.9 * x;
00347 
00348         TS_ASSERT_EQUALS( g.getXVoxelCoord( v ), 3 );
00349         TS_ASSERT_EQUALS( g.getYVoxelCoord( v ), 2 );
00350         TS_ASSERT_EQUALS( g.getZVoxelCoord( v ), 0 );
00351     }
00352 
00353     /**
00354      * Positions outside of a rotated grid should return voxel positions of -1.
00355      */
00356     void testRotatedVoxelOutOfGrid()
00357     {
00358         WVector3d x( 0.707, 0.707, 0.0 );
00359         WVector3d y( -0.707, 0.707, 0.0 );
00360         WVector3d z( 0.0, 0.0, 1.0 );
00361         x = normalize( x );
00362         y = normalize( y );
00363         y *= 2.0;
00364         z *= 1.5;
00365 
00366         WMatrix< double > mat( 4, 4 );
00367         mat.makeIdentity();
00368         mat( 0, 0 ) = x[ 0 ];
00369         mat( 1, 0 ) = x[ 1 ];
00370         mat( 2, 0 ) = x[ 2 ];
00371         mat( 0, 1 ) = y[ 0 ];
00372         mat( 1, 1 ) = y[ 1 ];
00373         mat( 2, 1 ) = y[ 2 ];
00374         mat( 0, 2 ) = z[ 0 ];
00375         mat( 1, 2 ) = z[ 1 ];
00376         mat( 2, 2 ) = z[ 2 ];
00377         mat( 0, 3 ) = 1.0;
00378 
00379         WGridTransformOrtho t( mat );
00380         WGridRegular3D g( 5, 5, 5, t );
00381 
00382         WVector3d v( 1.0, 0.0, 0.0 );
00383         v -= wlimits::FLT_EPS * x;
00384 
00385         TS_ASSERT_EQUALS( g.getXVoxelCoord( v ), -1 );
00386         TS_ASSERT_DIFFERS( g.getYVoxelCoord( v ), -1 );
00387         TS_ASSERT_DIFFERS( g.getZVoxelCoord( v ), -1 );
00388 
00389         v -= wlimits::FLT_EPS * z;
00390 
00391         TS_ASSERT_EQUALS( g.getXVoxelCoord( v ), -1 );
00392         TS_ASSERT_DIFFERS( g.getYVoxelCoord( v ), -1 );
00393         TS_ASSERT_EQUALS( g.getZVoxelCoord( v ), -1 );
00394 
00395         v = WVector3d( 1.0, 0.0, 0.0 ) + ( 4.0 + wlimits::FLT_EPS ) * y;
00396 
00397         TS_ASSERT_DIFFERS( g.getXVoxelCoord( v ), -1 );
00398         TS_ASSERT_EQUALS( g.getYVoxelCoord( v ), -1 );
00399         TS_ASSERT_DIFFERS( g.getZVoxelCoord( v ), -1 );
00400     }
00401 
00402     /**
00403      * A voxel with voxel-coordinates 0,0,0 has only three neighbours: 1,0,0; 0,1,0 and 0,0,1.
00404      */
00405     void testNeighboursOnFrontLowerLeft( void )
00406     {
00407         WGridRegular3D g( 3, 3, 3 );
00408         size_t data[] = { 1, 3, 9 };
00409         std::vector< size_t > expected( data, data + 3 );
00410         TS_ASSERT_EQUALS( expected, g.getNeighbours( 0 ) );
00411     }
00412 
00413     /**
00414      * A voxel in the back upper right corner should also have only 3 neighbours.
00415      */
00416     void testNeighbourOnBackUpperRight( void )
00417     {
00418         WGridRegular3D g( 3, 3, 3 );
00419         size_t data[] = { 25, 23, 17 };
00420         std::vector< size_t > expected( data, data + 3 );
00421         TS_ASSERT_EQUALS( expected, g.getNeighbours( 26 ) );
00422     }
00423 
00424     /**
00425      * A Voxel on a border plane should have neighbours on the plane but not
00426      * out side the grid.
00427      */
00428     void testNeighbourOnLeftBorderPlane( void )
00429     {
00430         WGridRegular3D g( 3, 3, 3 );
00431         size_t data[] = { 13, 9, 15, 3, 21 };
00432         std::vector< size_t > expected( data, data + 5 );
00433         TS_ASSERT_EQUALS( expected, g.getNeighbours( 12 ) );
00434     }
00435 
00436     /**
00437      * If the neighbours of a voxel not inside this grid are requested an Exception
00438      * WOutOfBounds should be thrown.
00439      */
00440     void testNeighbourOfVoxelNotInsideThisGrid( void )
00441     {
00442         WGridRegular3D g( 3, 3, 3 );
00443         TS_ASSERT_THROWS_EQUALS( g.getNeighbours( 27 ), const WOutOfBounds &e, std::string( e.what() ),
00444                 "This point: 27 is not part of this grid:  nbPosX: 3 nbPosY: 3 nbPosZ: 3" );
00445     }
00446 
00447     /**
00448      * Check whether we get the right Ids.
00449      */
00450     void testGetCellVertexIds( void )
00451     {
00452         WGridRegular3D g( 5, 3, 3 );
00453         WGridRegular3D::CellVertexArray expected = { { 23, 24, 28, 29, 38, 39, 43, 44 } };
00454         TS_ASSERT_EQUALS( g.getCellVertexIds( 15 ), expected );
00455     }
00456 
00457     /**
00458      * Check whether we get the right cellId.
00459      */
00460     void testGetCellId( void )
00461     {
00462         WGridRegular3D g( 5, 3, 3 );
00463         bool isInside = true;
00464 
00465         // Test some value
00466         size_t cellId = g.getCellId( WPosition( 3.3, 1.75, 0.78 ), &isInside );
00467         TS_ASSERT_EQUALS( cellId, 7 );
00468         TS_ASSERT_EQUALS( isInside, true );
00469 
00470         // Test bounds for X direction
00471         cellId = g.getCellId( WPosition( 4.0, 1.75, 0.3 ), &isInside );
00472         TS_ASSERT_EQUALS( isInside, false );
00473 
00474         cellId = g.getCellId( WPosition( 4.0 - wlimits::FLT_EPS, 1.75, 0.3 ), &isInside );
00475         TS_ASSERT_EQUALS( isInside, true );
00476 
00477         cellId = g.getCellId( WPosition( 0.0, 1.75, 0.3 ), &isInside );
00478         TS_ASSERT_EQUALS( isInside, true );
00479 
00480         cellId = g.getCellId( WPosition( 0.0 - wlimits::FLT_EPS, 1.75, 0.3 ), &isInside );
00481         TS_ASSERT_EQUALS( isInside, false );
00482 
00483         // Test bounds for Y direction
00484         cellId = g.getCellId( WPosition( 3.3, 2.0, 0.3 ), &isInside );
00485         TS_ASSERT_EQUALS( isInside, false );
00486 
00487         cellId = g.getCellId( WPosition( 3.3, 2.0 - wlimits::FLT_EPS, 0.3 ), &isInside );
00488         TS_ASSERT_EQUALS( isInside, true );
00489 
00490         cellId = g.getCellId( WPosition( 3.3, 0.0, 0.3 ), &isInside );
00491         TS_ASSERT_EQUALS( isInside, true );
00492 
00493         cellId = g.getCellId( WPosition( 3.3, 0.0 - wlimits::FLT_EPS, 0.3 ), &isInside );
00494         TS_ASSERT_EQUALS( isInside, false );
00495 
00496         // Test bounds for Z direction
00497         cellId = g.getCellId( WPosition( 3.3, 1.75, 2.0 ), &isInside );
00498         TS_ASSERT_EQUALS( isInside, false );
00499 
00500         cellId = g.getCellId( WPosition( 3.3, 1.75, 2.0 - wlimits::FLT_EPS ), &isInside );
00501         TS_ASSERT_EQUALS( isInside, true );
00502 
00503         cellId = g.getCellId( WPosition( 3.3, 1.75, 0.0 ), &isInside );
00504         TS_ASSERT_EQUALS( isInside, true );
00505 
00506         cellId = g.getCellId( WPosition( 3.3, 1.75, 0.0 - wlimits::FLT_EPS ), &isInside );
00507         TS_ASSERT_EQUALS( isInside, false );
00508     }
00509 
00510     /**
00511      * If a point is inside of the boundary of a grid encloses should return true, otherwise false.
00512      */
00513     void testEnclosesQuery( void )
00514     {
00515         WGridRegular3D g( 2, 2, 2 );
00516 
00517         // Test bounds for X direction
00518         TS_ASSERT( !g.encloses( WPosition( 0 - wlimits::FLT_EPS, 0, 0 ) ) );
00519         TS_ASSERT( g.encloses( WPosition( 0, 0, 0 ) ) );
00520         TS_ASSERT( g.encloses( WPosition( 1.0 - wlimits::FLT_EPS, 0.5, 0.5 ) ) );
00521         TS_ASSERT( !g.encloses( WPosition( 1, 0.5, 0.5 ) ) );
00522 
00523         // Test bounds for Y direction
00524         TS_ASSERT( !g.encloses( WPosition( 0, 0 - wlimits::FLT_EPS, 0 ) ) );
00525         TS_ASSERT( g.encloses( WPosition( 0, 0, 0 ) ) );
00526         TS_ASSERT( g.encloses( WPosition( 0.5, 1.0 - wlimits::FLT_EPS, 0.5 ) ) );
00527         TS_ASSERT( !g.encloses( WPosition( 0.5, 1.0, 0.5 ) ) );
00528 
00529         // Test bounds for Z direction
00530         TS_ASSERT( !g.encloses( WPosition( 0, 0, 0 - wlimits::FLT_EPS ) ) );
00531         TS_ASSERT( g.encloses( WPosition( 0, 0, 0 ) ) );
00532         TS_ASSERT( g.encloses( WPosition( 0.5, 0.5, 1.0 - wlimits::FLT_EPS ) ) );
00533         TS_ASSERT( !g.encloses( WPosition( 0.5, 0.5, 1 ) ) );
00534     }
00535 
00536     /**
00537      * If a point is inside of the boundary of a grid encloses should return true, otherwise false.
00538      */
00539     void testEnclosesRotated()
00540     {
00541         WVector3d x( 0.707, 0.707, 0.0 );
00542         WVector3d y( -0.707, 0.707, 0.0 );
00543         WVector3d z( 0.0, 0.0, 1.0 );
00544         x = normalize( x );
00545         y = normalize( y );
00546         y *= 2.0;
00547         z *= 1.5;
00548 
00549         WMatrix< double > mat( 4, 4 );
00550         mat.makeIdentity();
00551         mat( 0, 0 ) = x[ 0 ];
00552         mat( 1, 0 ) = x[ 1 ];
00553         mat( 2, 0 ) = x[ 2 ];
00554         mat( 0, 1 ) = y[ 0 ];
00555         mat( 1, 1 ) = y[ 1 ];
00556         mat( 2, 1 ) = y[ 2 ];
00557         mat( 0, 2 ) = z[ 0 ];
00558         mat( 1, 2 ) = z[ 1 ];
00559         mat( 2, 2 ) = z[ 2 ];
00560         mat( 0, 3 ) = 1.0;
00561 
00562         WGridTransformOrtho t( mat );
00563         WGridRegular3D g( 5, 5, 5, t );
00564 
00565         WVector3d o = WVector3d( 1.0, 0.0, 0.0 ) + ( x + y + z ) * 2.0 * wlimits::FLT_EPS;
00566         WVector3d v = o - 4.0 * wlimits::FLT_EPS * x;
00567         TS_ASSERT( !g.encloses( v ) );
00568         v = o;
00569         TS_ASSERT( g.encloses( v ) );
00570         v = o + ( 4.0 - 4.0 * wlimits::FLT_EPS ) * x;
00571         TS_ASSERT( g.encloses( v ) );
00572         v += 4.0 *  wlimits::FLT_EPS * x;
00573         TS_ASSERT( !g.encloses( v ) );
00574 
00575         v = o - 4.0 * wlimits::FLT_EPS * y;
00576         TS_ASSERT( !g.encloses( v ) );
00577         v = o + ( 4.0 - 4.0 * wlimits::FLT_EPS ) * y;
00578         TS_ASSERT( g.encloses( v ) );
00579         v += 4.0 * wlimits::FLT_EPS * y;
00580         TS_ASSERT( !g.encloses( v ) );
00581 
00582         v = o - 4.0 * wlimits::FLT_EPS * z;
00583         TS_ASSERT( !g.encloses( v ) );
00584         v = o + ( 4.0 - 4.0 * wlimits::FLT_EPS ) * z;
00585         TS_ASSERT( g.encloses( v ) );
00586         v += 4.0 * wlimits::FLT_EPS * z;
00587         TS_ASSERT( !g.encloses( v ) );
00588     }
00589 
00590 private:
00591     double m_delta; //!< Maximum amount to values are allowed to differ.
00592 };
00593 
00594 #endif  // WGRIDREGULAR3D_TEST_H