OpenWalnut  1.4.0
WMath_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 WMATH_TEST_H
00026 #define WMATH_TEST_H
00027 
00028 #include <iomanip>
00029 
00030 #include <cxxtest/TestSuite.h>
00031 
00032 #include "../WMath.h"
00033 #include "../../WLimits.h"
00034 #include "WPositionTraits.h"
00035 
00036 
00037 /**
00038  * Unit tests wmath's helper functions.
00039  */
00040 class WMathTest : public CxxTest::TestSuite
00041 {
00042 public:
00043     /**
00044      * If some points are inside the plane the triangle is considered to intersect with that plane.
00045      */
00046     void testTrianglePlaneIntersectionWithPointsInPlane( void )
00047     {
00048         WPlane p( WVector3d( 0, 0, 1 ), WPosition( 0, 0, 0 ) );
00049         TS_ASSERT( testIntersectTriangle( WPosition( 0, 0, 0 ), WPosition( 0, 0, 1 ), WPosition( 1, 0, 1 ), p ) );
00050         TS_ASSERT( testIntersectTriangle( WPosition( 0, 0, 0 ), WPosition( 0, 1, 0 ), WPosition( 1, 0, 1 ), p ) );
00051         TS_ASSERT( testIntersectTriangle( WPosition( 0, 0, 0 ), WPosition( 0, 1, 0 ), WPosition( 1, 0, 0 ), p ) );
00052     }
00053 
00054     /**
00055      * If no point is in plane but at not all are on one side the trinagle intersects.
00056      */
00057     void testTrianglePlaneIntersectionWithNoPointInPlane( void )
00058     {
00059         WPlane p( WVector3d( 0, 0, 1 ), WPosition( 0, 0, 0 ) );
00060         TS_ASSERT( testIntersectTriangle( WPosition( 0, 0, -1 ), WPosition( 0, 0, 1 ), WPosition( 1, 0, 1 ), p ) );
00061     }
00062 
00063     /**
00064      * If all point are on one side of the plane no intersection can take place.
00065      */
00066     void testTrianglePlaneIntersectionWithAllPointsOnOneSide( void )
00067     {
00068         WPlane p( WVector3d( 0, 0, 1 ), WPosition( 0, 0, 0 ) );
00069         TS_ASSERT( !testIntersectTriangle( WPosition( 0, 0, -1 ), WPosition( 0, 1, -1 ), WPosition( 1, 0, -3 ), p ) );
00070     }
00071 
00072 
00073     /**
00074      * The intersection of a plane plane with a segment, having a starting and
00075      * an endpoint. It should be a commutative operation in terms of staring
00076      * and ending points.
00077      */
00078     void testIntersectionOfPlaneWithSegment( void )
00079     {
00080         WPlane p( WVector3d( 0, 0, 1 ), WPosition( 0, 0, 0 ) );
00081         boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
00082         bool actual = intersectPlaneSegment( p, WPosition( 3, 0, 1 ), WPosition( 1, 0, -1 ), cutPoint );
00083         TS_ASSERT_EQUALS( actual, true );
00084         TS_ASSERT_EQUALS( *cutPoint, WPosition( 2, 0, 0 ) );
00085         actual = intersectPlaneSegment( p, WPosition( 1, 0, -1 ), WPosition( 3, 0, 1 ), cutPoint );
00086         TS_ASSERT_EQUALS( actual, true );
00087         TS_ASSERT_EQUALS( *cutPoint, WPosition( 2, 0, 0 ) );
00088     }
00089 
00090     /**
00091      * If there is no intersection at all the position 0,0,0 should be written
00092      * into the point of intersection and false should be returned.
00093      */
00094     void testNoIntersectionOfPlaneWithSegment( void )
00095     {
00096         WPlane p( WVector3d( 0, 0, 1 ), WPosition( 0, 0, 0 ) );
00097         boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
00098         bool actual = intersectPlaneSegment( p,
00099                                                     WPosition( 3, 0, 10 * wlimits::DBL_EPS ),
00100                                                     WPosition( 10 * wlimits::DBL_EPS, 0, 10 * wlimits::DBL_EPS ), cutPoint );
00101         TS_ASSERT_EQUALS( actual, false );
00102         TS_ASSERT_EQUALS( *cutPoint, WPosition( 0, 0, 0 ) );
00103     }
00104 
00105     /**
00106      * If an endpoint is inside of the plane then a point of intersection
00107      * must exists and true must be returned.
00108      */
00109     void testIntersectionOfPlaneWithSegmentHavingOnePointInPlane( void )
00110     {
00111         WPlane p( WVector3d( 0, 0, 1 ), WPosition( 0, 0, 0 ) );
00112         boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
00113         bool actual = intersectPlaneSegment( p, WPosition( 3, 0, wlimits::DBL_EPS ), WPosition( 1, 0, 1 ), cutPoint );
00114         TS_ASSERT_EQUALS( actual, true );
00115         TS_ASSERT( std::abs( ( *cutPoint )[0] - 3.0 ) <= 2*wlimits::DBL_EPS );
00116         TS_ASSERT( std::abs( ( *cutPoint )[1] - 0 ) <= 2*wlimits::DBL_EPS );
00117         TS_ASSERT( std::abs( ( *cutPoint )[2] - 0 ) <= 2*wlimits::DBL_EPS );
00118         actual = intersectPlaneSegment( p, WPosition( 1, 0, 1 ), WPosition( 3, 0, wlimits::DBL_EPS ), cutPoint );
00119         TS_ASSERT_EQUALS( actual, true );
00120         TS_ASSERT( std::abs( ( *cutPoint )[0] - 3.0 ) <= 2*wlimits::DBL_EPS );
00121         TS_ASSERT( std::abs( ( *cutPoint )[1] - 0 ) <= 2*wlimits::DBL_EPS );
00122         TS_ASSERT( std::abs( ( *cutPoint )[2] - 0 ) <= 2*wlimits::DBL_EPS );
00123     }
00124 
00125     /**
00126      * If the segment is totally inside of the plane, the first point must be
00127      * returned which is actually one (of many intersecting points)
00128      * intersecting point and true must be returned.
00129      */
00130     void testIntersectionOfPlaneWithSegmentInPlane( void )
00131     {
00132         WPlane p( WVector3d( 0, 0, 1 ), WPosition( 0, 0, 0 ) );
00133         boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
00134         bool actual = intersectPlaneSegment( p, WPosition( 3, 0, 0 ), WPosition( 1, 0, 0 ), cutPoint );
00135         TS_ASSERT_EQUALS( actual, true );
00136         TS_ASSERT_EQUALS( *cutPoint, WPosition( 3, 0, 0 ) );
00137         actual = intersectPlaneSegment( p, WPosition( 1, 0, 0 ), WPosition( 3, 0, 0 ), cutPoint );
00138         TS_ASSERT_EQUALS( actual, true );
00139         TS_ASSERT_EQUALS( *cutPoint, WPosition( 1, 0, 0 ) );
00140     }
00141 
00142     /**
00143      * If a set of consecutive segements (aka line) is tested again
00144      * intersection with that plane, each segment should be tested.
00145      */
00146     void testIntersectionOfPlaneWithLine( void )
00147     {
00148         WLine l;
00149         l.push_back( WPosition( -1, 0, 0 ) );
00150         l.push_back( WPosition( 1, 0, 0 ) );
00151         l.push_back( WPosition( 2, 0, 0 ) );
00152         l.push_back( WPosition( 5, 0, 0 ) );
00153         l.push_back( WPosition( 5, 4, 0 ) );
00154         WPlane p( WVector3d( 1, 0, 0 ), WPosition( 3.5, 13, 23 ) );
00155         boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
00156         bool actual = intersectPlaneLineNearCP( p, l, cutPoint );
00157         TS_ASSERT( actual );
00158         TS_ASSERT( std::abs( ( *cutPoint )[0] - 3.5 ) <= 2*wlimits::DBL_EPS );
00159         TS_ASSERT( std::abs( ( *cutPoint )[1] - 0 ) <= 2*wlimits::DBL_EPS );
00160         TS_ASSERT( std::abs( ( *cutPoint )[2] - 0 ) <= 2*wlimits::DBL_EPS );
00161     }
00162 
00163     /**
00164      * If none of the segments of the line intersects with the plane, false and
00165      * 0,0,0 should be returned.
00166      */
00167     void testNoIntersectionOfPlaneWithLine( void )
00168     {
00169         WLine l;
00170         l.push_back( WPosition( -1, 0, 0 ) );
00171         l.push_back( WPosition( 1, 0, 0 ) );
00172         l.push_back( WPosition( 2, 0, 0 ) );
00173         l.push_back( WPosition( 5, 0, 0 ) );
00174         l.push_back( WPosition( 5, 4, 0 ) );
00175         WPlane p( WVector3d( 1, 0, 0 ), WPosition( 5.0001, 13, 23 ) );
00176         boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
00177         bool actual = intersectPlaneLineNearCP( p, l, cutPoint );
00178         TS_ASSERT( !actual );
00179         WPlane q( WVector3d( -1.1, 0, 0 ), WPosition( 5.0001, 13, 23 ) );
00180         actual = intersectPlaneLineNearCP( q, l, cutPoint );
00181         TS_ASSERT( !actual );
00182     }
00183 
00184     /**
00185      * If an endpoint of a line intersects with the plane, this point should be
00186      * returned and ofcourse true.
00187      */
00188     void testIntersectionPlaneLineWithJustOnePoint( void )
00189     {
00190         WLine l;
00191         l.push_back( WPosition( -1, 0, 0 ) );
00192         l.push_back( WPosition( 1, 0, 0 ) );
00193         l.push_back( WPosition( 2, 0, 0 ) );
00194         l.push_back( WPosition( 5, 0, 0 ) );
00195         l.push_back( WPosition( 5, 4, 0 ) );
00196         WPlane p( WVector3d( 1, 0, 0 ), WPosition( -1, 13, 23 ) );
00197         boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
00198         bool actual = intersectPlaneLineNearCP( p, l, cutPoint );
00199         TS_ASSERT( actual );
00200         TS_ASSERT( std::abs( ( *cutPoint )[0] - ( -1 ) ) <= 2*wlimits::DBL_EPS );
00201         TS_ASSERT( std::abs( ( *cutPoint )[1] - 0 ) <= 2*wlimits::DBL_EPS );
00202         TS_ASSERT( std::abs( ( *cutPoint )[2] - 0 ) <= 2*wlimits::DBL_EPS );
00203     }
00204 
00205     /**
00206      * If a whole segment of the line is insisde that plane the first point
00207      * should be returned along with true as return code.
00208      */
00209     void testIntersectionPlaneLineWithSegmentInPlane( void )
00210     {
00211         WLine l;
00212         l.push_back( WPosition( -1, 0, 0 ) );
00213         l.push_back( WPosition( 1, 0, 0 ) );
00214         l.push_back( WPosition( 2, 0, 0 ) );
00215         l.push_back( WPosition( 5, 0, 0 ) );
00216         l.push_back( WPosition( 5, 4, 0 ) );
00217         WPlane p( WVector3d( 1, 0, 0 ), WPosition( 5, 13, 23 ) );
00218         boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
00219         bool actual = intersectPlaneLineNearCP( p, l, cutPoint );
00220         TS_ASSERT( actual );
00221         TS_ASSERT( std::abs( ( *cutPoint )[0] - 5 ) <= 2*wlimits::DBL_EPS );
00222         TS_ASSERT( std::abs( ( *cutPoint )[1] - 0 ) <= 2*wlimits::DBL_EPS );
00223         TS_ASSERT( std::abs( ( *cutPoint )[2] - 0 ) <= 2*wlimits::DBL_EPS );
00224     }
00225 
00226     /**
00227      * If many points of intersection occurs the closest to the base point
00228      * should be selected and return true.
00229      */
00230     void testMultipleIntersectionPlaneLine( void )
00231     {
00232         WLine l;
00233         l.push_back( WPosition( -1, 0, 0 ) );
00234         l.push_back( WPosition( 1, 0, 0 ) );
00235         l.push_back( WPosition( 2, 1, 0 ) );
00236         l.push_back( WPosition( -1, 1, 0 ) );
00237         WPlane p( WVector3d( 1, 0, 0 ), WPosition( 0, 0, 0 ) );
00238         boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
00239         bool actual = intersectPlaneLineNearCP( p, l, cutPoint );
00240         TS_ASSERT( actual );
00241         TS_ASSERT( std::abs( ( *cutPoint )[0] - 0 ) <= 2*wlimits::DBL_EPS );
00242         TS_ASSERT( std::abs( ( *cutPoint )[1] - 0 ) <= 2*wlimits::DBL_EPS );
00243         TS_ASSERT( std::abs( ( *cutPoint )[2] - 0 ) <= 2*wlimits::DBL_EPS );
00244         WPlane q( WVector3d( -1, 0, 0 ), WPosition( 0, 0.6, 0 ) );
00245         actual = intersectPlaneLineNearCP( q, l, cutPoint );
00246         TS_ASSERT( actual );
00247         TS_ASSERT( std::abs( ( *cutPoint )[0] - 0 ) <= 2*wlimits::DBL_EPS );
00248         TS_ASSERT( std::abs( ( *cutPoint )[1] - 1 ) <= 2*wlimits::DBL_EPS );
00249         TS_ASSERT( std::abs( ( *cutPoint )[2] - 0 ) <= 2*wlimits::DBL_EPS );
00250     }
00251 
00252     /**
00253      * Test the factorial calculation.
00254      */
00255     void testFactorials( void )
00256     {
00257         // TODO(philips): add even and odd factorials
00258         TS_ASSERT_EQUALS( factorial( 0 ), 1 );
00259         TS_ASSERT_EQUALS( factorial( 1 ), 1 );
00260         TS_ASSERT_EQUALS( factorial( 2 ), 2 );
00261         TS_ASSERT_EQUALS( factorial( 3 ), 6 );
00262         TS_ASSERT_EQUALS( factorial( 4 ), 24 );
00263         TS_ASSERT_EQUALS( factorial( 5 ), 120 );
00264         TS_ASSERT_EQUALS( factorial( 6 ), 720 );
00265         TS_ASSERT_EQUALS( factorial( 7 ), 5040 );
00266         TS_ASSERT_EQUALS( factorial( 8 ), 40320 );
00267     }
00268 
00269     /**
00270      * Test the areEqual function.
00271      */
00272     void testAreEqual( void )
00273     {
00274         TS_ASSERT_EQUALS( areEqual( 1.0, 1.0 ), true );
00275         TS_ASSERT_EQUALS( areEqual( 1.0, 1.0, 1e-3 ), true );
00276         TS_ASSERT_EQUALS( areEqual( 1.0, 1.0+1e-3, 1e-3 ), true );
00277         TS_ASSERT_EQUALS( areEqual( 1.0, 1.0+2e-3, 1e-3 ), false );
00278         TS_ASSERT_EQUALS( areEqual( 1.0, 1.0+1e-3 ), false );
00279     }
00280 };
00281 
00282 #endif  // WMATH_TEST_H