OpenWalnut
1.4.0
|
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