OpenWalnut  1.3.1
WMath_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 WMATH_TEST_H
26 #define WMATH_TEST_H
27 
28 #include <iomanip>
29 
30 #include <cxxtest/TestSuite.h>
31 
32 #include "../WMath.h"
33 #include "../../WLimits.h"
34 #include "WPositionTraits.h"
35 
36 
37 /**
38  * Unit tests wmath's helper functions.
39  */
40 class WMathTest : public CxxTest::TestSuite
41 {
42 public:
43  /**
44  * If some points are inside the plane the triangle is considered to intersect with that plane.
45  */
47  {
48  WPlane p( WVector3d( 0, 0, 1 ), WPosition( 0, 0, 0 ) );
49  TS_ASSERT( testIntersectTriangle( WPosition( 0, 0, 0 ), WPosition( 0, 0, 1 ), WPosition( 1, 0, 1 ), p ) );
50  TS_ASSERT( testIntersectTriangle( WPosition( 0, 0, 0 ), WPosition( 0, 1, 0 ), WPosition( 1, 0, 1 ), p ) );
51  TS_ASSERT( testIntersectTriangle( WPosition( 0, 0, 0 ), WPosition( 0, 1, 0 ), WPosition( 1, 0, 0 ), p ) );
52  }
53 
54  /**
55  * If no point is in plane but at not all are on one side the trinagle intersects.
56  */
58  {
59  WPlane p( WVector3d( 0, 0, 1 ), WPosition( 0, 0, 0 ) );
60  TS_ASSERT( testIntersectTriangle( WPosition( 0, 0, -1 ), WPosition( 0, 0, 1 ), WPosition( 1, 0, 1 ), p ) );
61  }
62 
63  /**
64  * If all point are on one side of the plane no intersection can take place.
65  */
67  {
68  WPlane p( WVector3d( 0, 0, 1 ), WPosition( 0, 0, 0 ) );
69  TS_ASSERT( !testIntersectTriangle( WPosition( 0, 0, -1 ), WPosition( 0, 1, -1 ), WPosition( 1, 0, -3 ), p ) );
70  }
71 
72 
73  /**
74  * The intersection of a plane plane with a segment, having a starting and
75  * an endpoint. It should be a commutative operation in terms of staring
76  * and ending points.
77  */
79  {
80  WPlane p( WVector3d( 0, 0, 1 ), WPosition( 0, 0, 0 ) );
81  boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
82  bool actual = intersectPlaneSegment( p, WPosition( 3, 0, 1 ), WPosition( 1, 0, -1 ), cutPoint );
83  TS_ASSERT_EQUALS( actual, true );
84  TS_ASSERT_EQUALS( *cutPoint, WPosition( 2, 0, 0 ) );
85  actual = intersectPlaneSegment( p, WPosition( 1, 0, -1 ), WPosition( 3, 0, 1 ), cutPoint );
86  TS_ASSERT_EQUALS( actual, true );
87  TS_ASSERT_EQUALS( *cutPoint, WPosition( 2, 0, 0 ) );
88  }
89 
90  /**
91  * If there is no intersection at all the position 0,0,0 should be written
92  * into the point of intersection and false should be returned.
93  */
95  {
96  WPlane p( WVector3d( 0, 0, 1 ), WPosition( 0, 0, 0 ) );
97  boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
98  bool actual = intersectPlaneSegment( p,
99  WPosition( 3, 0, 10 * wlimits::DBL_EPS ),
100  WPosition( 10 * wlimits::DBL_EPS, 0, 10 * wlimits::DBL_EPS ), cutPoint );
101  TS_ASSERT_EQUALS( actual, false );
102  TS_ASSERT_EQUALS( *cutPoint, WPosition( 0, 0, 0 ) );
103  }
104 
105  /**
106  * If an endpoint is inside of the plane then a point of intersection
107  * must exists and true must be returned.
108  */
110  {
111  WPlane p( WVector3d( 0, 0, 1 ), WPosition( 0, 0, 0 ) );
112  boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
113  bool actual = intersectPlaneSegment( p, WPosition( 3, 0, wlimits::DBL_EPS ), WPosition( 1, 0, 1 ), cutPoint );
114  TS_ASSERT_EQUALS( actual, true );
115  TS_ASSERT( std::abs( ( *cutPoint )[0] - 3.0 ) <= 2*wlimits::DBL_EPS );
116  TS_ASSERT( std::abs( ( *cutPoint )[1] - 0 ) <= 2*wlimits::DBL_EPS );
117  TS_ASSERT( std::abs( ( *cutPoint )[2] - 0 ) <= 2*wlimits::DBL_EPS );
118  actual = intersectPlaneSegment( p, WPosition( 1, 0, 1 ), WPosition( 3, 0, wlimits::DBL_EPS ), cutPoint );
119  TS_ASSERT_EQUALS( actual, true );
120  TS_ASSERT( std::abs( ( *cutPoint )[0] - 3.0 ) <= 2*wlimits::DBL_EPS );
121  TS_ASSERT( std::abs( ( *cutPoint )[1] - 0 ) <= 2*wlimits::DBL_EPS );
122  TS_ASSERT( std::abs( ( *cutPoint )[2] - 0 ) <= 2*wlimits::DBL_EPS );
123  }
124 
125  /**
126  * If the segment is totally inside of the plane, the first point must be
127  * returned which is actually one (of many intersecting points)
128  * intersecting point and true must be returned.
129  */
131  {
132  WPlane p( WVector3d( 0, 0, 1 ), WPosition( 0, 0, 0 ) );
133  boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
134  bool actual = intersectPlaneSegment( p, WPosition( 3, 0, 0 ), WPosition( 1, 0, 0 ), cutPoint );
135  TS_ASSERT_EQUALS( actual, true );
136  TS_ASSERT_EQUALS( *cutPoint, WPosition( 3, 0, 0 ) );
137  actual = intersectPlaneSegment( p, WPosition( 1, 0, 0 ), WPosition( 3, 0, 0 ), cutPoint );
138  TS_ASSERT_EQUALS( actual, true );
139  TS_ASSERT_EQUALS( *cutPoint, WPosition( 1, 0, 0 ) );
140  }
141 
142  /**
143  * If a set of consecutive segements (aka line) is tested again
144  * intersection with that plane, each segment should be tested.
145  */
147  {
148  WLine l;
149  l.push_back( WPosition( -1, 0, 0 ) );
150  l.push_back( WPosition( 1, 0, 0 ) );
151  l.push_back( WPosition( 2, 0, 0 ) );
152  l.push_back( WPosition( 5, 0, 0 ) );
153  l.push_back( WPosition( 5, 4, 0 ) );
154  WPlane p( WVector3d( 1, 0, 0 ), WPosition( 3.5, 13, 23 ) );
155  boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
156  bool actual = intersectPlaneLineNearCP( p, l, cutPoint );
157  TS_ASSERT( actual );
158  TS_ASSERT( std::abs( ( *cutPoint )[0] - 3.5 ) <= 2*wlimits::DBL_EPS );
159  TS_ASSERT( std::abs( ( *cutPoint )[1] - 0 ) <= 2*wlimits::DBL_EPS );
160  TS_ASSERT( std::abs( ( *cutPoint )[2] - 0 ) <= 2*wlimits::DBL_EPS );
161  }
162 
163  /**
164  * If none of the segments of the line intersects with the plane, false and
165  * 0,0,0 should be returned.
166  */
168  {
169  WLine l;
170  l.push_back( WPosition( -1, 0, 0 ) );
171  l.push_back( WPosition( 1, 0, 0 ) );
172  l.push_back( WPosition( 2, 0, 0 ) );
173  l.push_back( WPosition( 5, 0, 0 ) );
174  l.push_back( WPosition( 5, 4, 0 ) );
175  WPlane p( WVector3d( 1, 0, 0 ), WPosition( 5.0001, 13, 23 ) );
176  boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
177  bool actual = intersectPlaneLineNearCP( p, l, cutPoint );
178  TS_ASSERT( !actual );
179  WPlane q( WVector3d( -1.1, 0, 0 ), WPosition( 5.0001, 13, 23 ) );
180  actual = intersectPlaneLineNearCP( q, l, cutPoint );
181  TS_ASSERT( !actual );
182  }
183 
184  /**
185  * If an endpoint of a line intersects with the plane, this point should be
186  * returned and ofcourse true.
187  */
189  {
190  WLine l;
191  l.push_back( WPosition( -1, 0, 0 ) );
192  l.push_back( WPosition( 1, 0, 0 ) );
193  l.push_back( WPosition( 2, 0, 0 ) );
194  l.push_back( WPosition( 5, 0, 0 ) );
195  l.push_back( WPosition( 5, 4, 0 ) );
196  WPlane p( WVector3d( 1, 0, 0 ), WPosition( -1, 13, 23 ) );
197  boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
198  bool actual = intersectPlaneLineNearCP( p, l, cutPoint );
199  TS_ASSERT( actual );
200  TS_ASSERT( std::abs( ( *cutPoint )[0] - ( -1 ) ) <= 2*wlimits::DBL_EPS );
201  TS_ASSERT( std::abs( ( *cutPoint )[1] - 0 ) <= 2*wlimits::DBL_EPS );
202  TS_ASSERT( std::abs( ( *cutPoint )[2] - 0 ) <= 2*wlimits::DBL_EPS );
203  }
204 
205  /**
206  * If a whole segment of the line is insisde that plane the first point
207  * should be returned along with true as return code.
208  */
210  {
211  WLine l;
212  l.push_back( WPosition( -1, 0, 0 ) );
213  l.push_back( WPosition( 1, 0, 0 ) );
214  l.push_back( WPosition( 2, 0, 0 ) );
215  l.push_back( WPosition( 5, 0, 0 ) );
216  l.push_back( WPosition( 5, 4, 0 ) );
217  WPlane p( WVector3d( 1, 0, 0 ), WPosition( 5, 13, 23 ) );
218  boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
219  bool actual = intersectPlaneLineNearCP( p, l, cutPoint );
220  TS_ASSERT( actual );
221  TS_ASSERT( std::abs( ( *cutPoint )[0] - 5 ) <= 2*wlimits::DBL_EPS );
222  TS_ASSERT( std::abs( ( *cutPoint )[1] - 0 ) <= 2*wlimits::DBL_EPS );
223  TS_ASSERT( std::abs( ( *cutPoint )[2] - 0 ) <= 2*wlimits::DBL_EPS );
224  }
225 
226  /**
227  * If many points of intersection occurs the closest to the base point
228  * should be selected and return true.
229  */
231  {
232  WLine l;
233  l.push_back( WPosition( -1, 0, 0 ) );
234  l.push_back( WPosition( 1, 0, 0 ) );
235  l.push_back( WPosition( 2, 1, 0 ) );
236  l.push_back( WPosition( -1, 1, 0 ) );
237  WPlane p( WVector3d( 1, 0, 0 ), WPosition( 0, 0, 0 ) );
238  boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
239  bool actual = intersectPlaneLineNearCP( p, l, cutPoint );
240  TS_ASSERT( actual );
241  TS_ASSERT( std::abs( ( *cutPoint )[0] - 0 ) <= 2*wlimits::DBL_EPS );
242  TS_ASSERT( std::abs( ( *cutPoint )[1] - 0 ) <= 2*wlimits::DBL_EPS );
243  TS_ASSERT( std::abs( ( *cutPoint )[2] - 0 ) <= 2*wlimits::DBL_EPS );
244  WPlane q( WVector3d( -1, 0, 0 ), WPosition( 0, 0.6, 0 ) );
245  actual = intersectPlaneLineNearCP( q, l, cutPoint );
246  TS_ASSERT( actual );
247  TS_ASSERT( std::abs( ( *cutPoint )[0] - 0 ) <= 2*wlimits::DBL_EPS );
248  TS_ASSERT( std::abs( ( *cutPoint )[1] - 1 ) <= 2*wlimits::DBL_EPS );
249  TS_ASSERT( std::abs( ( *cutPoint )[2] - 0 ) <= 2*wlimits::DBL_EPS );
250  }
251 
252  /**
253  * Test the factorial calculation.
254  */
255  void testFactorials( void )
256  {
257  // TODO(philips): add even and odd factorials
258  TS_ASSERT_EQUALS( factorial( 0 ), 1 );
259  TS_ASSERT_EQUALS( factorial( 1 ), 1 );
260  TS_ASSERT_EQUALS( factorial( 2 ), 2 );
261  TS_ASSERT_EQUALS( factorial( 3 ), 6 );
262  TS_ASSERT_EQUALS( factorial( 4 ), 24 );
263  TS_ASSERT_EQUALS( factorial( 5 ), 120 );
264  TS_ASSERT_EQUALS( factorial( 6 ), 720 );
265  TS_ASSERT_EQUALS( factorial( 7 ), 5040 );
266  TS_ASSERT_EQUALS( factorial( 8 ), 40320 );
267  }
268 };
269 
270 #endif // WMATH_TEST_H