00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifdef HAVE_CONFIG_H
00019 # include <simgear_config.h>
00020 #endif
00021
00022 #include <cstdlib>
00023 #include <iostream>
00024
00025 #include <plib/sg.h>
00026
00027 #include "SGMath.hxx"
00028
00029 template<typename T>
00030 bool
00031 Vec3Test(void)
00032 {
00033 SGVec3<T> v1, v2, v3;
00034
00035
00036 v1 = SGVec3<T>(1, 2, 3);
00037 v2 = SGVec3<T>(3, 2, 1);
00038 if (equivalent(v1, v2))
00039 return false;
00040
00041
00042 v3 = SGVec3<T>(-1, -2, -3);
00043 if (!equivalent(-v1, v3))
00044 return false;
00045
00046
00047 v3 = SGVec3<T>(1, 2, 3);
00048 if (!equivalent(+v1, v3))
00049 return false;
00050
00051
00052 v3 = SGVec3<T>(4, 4, 4);
00053 if (!equivalent(v1 + v2, v3))
00054 return false;
00055
00056
00057 v3 = SGVec3<T>(-2, 0, 2);
00058 if (!equivalent(v1 - v2, v3))
00059 return false;
00060
00061
00062 v3 = SGVec3<T>(2, 4, 6);
00063 if (!equivalent(2*v1, v3))
00064 return false;
00065
00066
00067 if (fabs(dot(v1, v2) - 10) > 10*SGLimits<T>::epsilon())
00068 return false;
00069
00070
00071 v3 = SGVec3<T>(-4, 8, -4);
00072 if (!equivalent(cross(v1, v2), v3))
00073 return false;
00074
00075
00076 if (fabs(14 - length(v1)*length(v1)) > 14*SGLimits<T>::epsilon())
00077 return false;
00078
00079 return true;
00080 }
00081
00082 template<typename T>
00083 bool
00084 QuatTest(void)
00085 {
00086 const SGVec3<T> e1(1, 0, 0);
00087 const SGVec3<T> e2(0, 1, 0);
00088 const SGVec3<T> e3(0, 0, 1);
00089 SGVec3<T> v1, v2;
00090 SGQuat<T> q1, q2, q3, q4;
00091
00092 q1 = SGQuat<T>::fromAngleAxis(SGMisc<T>::pi(), e1);
00093 v1 = SGVec3<T>(1, 2, 3);
00094 v2 = SGVec3<T>(1, -2, -3);
00095 if (!equivalent(q1.transform(v1), v2))
00096 return false;
00097
00098
00099 q1 = SGQuat<T>::fromAngleAxis(0.5*SGMisc<T>::pi(), e1);
00100 v2 = SGVec3<T>(1, 3, -2);
00101 if (!equivalent(q1.transform(v1), v2))
00102 return false;
00103
00104
00105 q1 = SGQuat<T>::fromAngleAxis(SGMisc<T>::pi(), e2);
00106 v2 = SGVec3<T>(-1, 2, -3);
00107 if (!equivalent(q1.transform(v1), v2))
00108 return false;
00109
00110
00111 q1 = SGQuat<T>::fromAngleAxis(0.5*SGMisc<T>::pi(), e2);
00112 v2 = SGVec3<T>(-3, 2, 1);
00113 if (!equivalent(q1.transform(v1), v2))
00114 return false;
00115
00116
00117 q1 = SGQuat<T>::fromAngleAxis(SGMisc<T>::pi(), e3);
00118 v2 = SGVec3<T>(-1, -2, 3);
00119 if (!equivalent(q1.transform(v1), v2))
00120 return false;
00121
00122
00123 q1 = SGQuat<T>::fromAngleAxis(0.5*SGMisc<T>::pi(), e3);
00124 v2 = SGVec3<T>(2, -1, 3);
00125 if (!equivalent(q1.transform(v1), v2))
00126 return false;
00127
00128
00129
00130 q1 = SGQuat<T>::fromAngleAxis(0.5*SGMisc<T>::pi(), e1);
00131 q2 = SGQuat<T>::fromAngleAxis(0.5*SGMisc<T>::pi(), e2);
00132 q3 = q1*q2;
00133 v2 = q2.transform(q1.transform(v1));
00134 if (!equivalent(q3.transform(v1), v2))
00135 return false;
00136
00138 float x = 0.2*SGMisc<T>::pi();
00139 float y = 0.3*SGMisc<T>::pi();
00140 float z = 0.4*SGMisc<T>::pi();
00141 q1 = SGQuat<T>::fromAngleAxis(z, e3);
00142 q2 = SGQuat<T>::fromAngleAxis(y, e2);
00143 q3 = SGQuat<T>::fromAngleAxis(x, e1);
00144 v2 = q3.transform(q2.transform(q1.transform(v1)));
00145 q4 = SGQuat<T>::fromEulerRad(z, y, x);
00146 if (!equivalent(q4.transform(v1), v2))
00147 return false;
00148
00150 q1 = SGQuat<T>::fromAngleAxis(0.2*SGMisc<T>::pi(), e1);
00151 q2 = SGQuat<T>::fromAngleAxis(0.7*SGMisc<T>::pi(), e2);
00152 q3 = q1*q2;
00153 SGVec3<T> angleAxis;
00154 q1.getAngleAxis(angleAxis);
00155 q4 = SGQuat<T>::fromAngleAxis(angleAxis);
00156 if (!equivalent(q1, q4))
00157 return false;
00158 q2.getAngleAxis(angleAxis);
00159 q4 = SGQuat<T>::fromAngleAxis(angleAxis);
00160 if (!equivalent(q2, q4))
00161 return false;
00162 q3.getAngleAxis(angleAxis);
00163 q4 = SGQuat<T>::fromAngleAxis(angleAxis);
00164 if (!equivalent(q3, q4))
00165 return false;
00166
00167 return true;
00168 }
00169
00170 template<typename T>
00171 bool
00172 MatrixTest(void)
00173 {
00174
00175 SGVec3<T> v0(2, 7, 17);
00176 SGQuat<T> q0 = SGQuat<T>::fromAngleAxis(SGMisc<T>::pi(), normalize(v0));
00177 SGMatrix<T> m0 = SGMatrix<T>::unit();
00178 m0.postMultTranslate(v0);
00179 m0.postMultRotate(q0);
00180
00181
00182 SGMatrix<T> m1 = SGMatrix<T>::unit();
00183 m1.preMultTranslate(-v0);
00184 m1.preMultRotate(inverse(q0));
00185
00186 SGMatrix<T> m2, m3;
00187 invert(m2, m0);
00188 m3 = transNeg(m0);
00189 if (!equivalent(m1, m2))
00190 return false;
00191 if (!equivalent(m2, m3))
00192 return false;
00193
00194
00195 if (!equivalent(m0*m1, SGMatrix<T>::unit()))
00196 return false;
00197 if (!equivalent(m1*m0, SGMatrix<T>::unit()))
00198 return false;
00199 if (!equivalent(m0*m2, SGMatrix<T>::unit()))
00200 return false;
00201 if (!equivalent(m2*m0, SGMatrix<T>::unit()))
00202 return false;
00203 if (!equivalent(m0*m3, SGMatrix<T>::unit()))
00204 return false;
00205 if (!equivalent(m3*m0, SGMatrix<T>::unit()))
00206 return false;
00207
00208 return true;
00209 }
00210
00211 bool
00212 GeodesyTest(void)
00213 {
00214
00215 double epsDeg = 10*360*SGLimits<double>::epsilon();
00216
00217
00218 double epsM = 10*6e6*SGLimits<double>::epsilon();
00219
00220 SGVec3<double> cart0, cart1;
00221 SGGeod geod0, geod1;
00222 SGGeoc geoc0;
00223
00224
00225 geod0 = SGGeod::fromDegM(30, 20, 17);
00226
00227
00228 cart0 = SGVec3<double>::fromGeod(geod0);
00229 geod1 = SGGeod::fromCart(cart0);
00230 if (epsDeg < fabs(geod0.getLongitudeDeg() - geod1.getLongitudeDeg()) ||
00231 epsDeg < fabs(geod0.getLatitudeDeg() - geod1.getLatitudeDeg()) ||
00232 epsM < fabs(geod0.getElevationM() - geod1.getElevationM()))
00233 return false;
00234
00235
00236 geoc0 = SGGeoc::fromCart(cart0);
00237 cart1 = SGVec3<double>::fromGeoc(geoc0);
00238 if (!equivalent(cart0, cart1))
00239 return false;
00240
00241 return true;
00242 }
00243
00244
00245 bool
00246 sgInterfaceTest(void)
00247 {
00248 SGVec3f v3f = SGVec3f::e2();
00249 SGVec4f v4f = SGVec4f::e2();
00250 SGQuatf qf = SGQuatf::fromEulerRad(1.2, 1.3, -0.4);
00251 SGMatrixf mf;
00252 mf.postMultTranslate(v3f);
00253 mf.postMultRotate(qf);
00254
00255
00256
00257 SGVec3f tv3f;
00258 sgVec3 sv3f;
00259 sgCopyVec3(sv3f, v3f.sg());
00260 sgCopyVec3(tv3f.sg(), sv3f);
00261 if (tv3f != v3f)
00262 return false;
00263
00264
00265
00266 SGVec4f tv4f;
00267 sgVec4 sv4f;
00268 sgCopyVec4(sv4f, v4f.sg());
00269 sgCopyVec4(tv4f.sg(), sv4f);
00270 if (tv4f != v4f)
00271 return false;
00272
00273
00274
00275 SGQuatf tqf;
00276 sgQuat sqf;
00277 sgCopyQuat(sqf, qf.sg());
00278 sgCopyQuat(tqf.sg(), sqf);
00279 if (tqf != qf)
00280 return false;
00281
00282
00283
00284 SGMatrixf tmf;
00285 sgMat4 smf;
00286 sgCopyMat4(smf, mf.sg());
00287 sgCopyMat4(tmf.sg(), smf);
00288 if (tmf != mf)
00289 return false;
00290
00291 return true;
00292 }
00293
00294 bool
00295 sgdInterfaceTest(void)
00296 {
00297 SGVec3d v3d = SGVec3d::e2();
00298 SGVec4d v4d = SGVec4d::e2();
00299 SGQuatd qd = SGQuatd::fromEulerRad(1.2, 1.3, -0.4);
00300 SGMatrixd md;
00301 md.postMultTranslate(v3d);
00302 md.postMultRotate(qd);
00303
00304
00305
00306 SGVec3d tv3d;
00307 sgdVec3 sv3d;
00308 sgdCopyVec3(sv3d, v3d.sg());
00309 sgdCopyVec3(tv3d.sg(), sv3d);
00310 if (tv3d != v3d)
00311 return false;
00312
00313
00314
00315 SGVec4d tv4d;
00316 sgdVec4 sv4d;
00317 sgdCopyVec4(sv4d, v4d.sg());
00318 sgdCopyVec4(tv4d.sg(), sv4d);
00319 if (tv4d != v4d)
00320 return false;
00321
00322
00323
00324 SGQuatd tqd;
00325 sgdQuat sqd;
00326 sgdCopyQuat(sqd, qd.sg());
00327 sgdCopyQuat(tqd.sg(), sqd);
00328 if (tqd != qd)
00329 return false;
00330
00331
00332
00333 SGMatrixd tmd;
00334 sgdMat4 smd;
00335 sgdCopyMat4(smd, md.sg());
00336 sgdCopyMat4(tmd.sg(), smd);
00337 if (tmd != md)
00338 return false;
00339
00340 return true;
00341 }
00342
00343 int
00344 main(void)
00345 {
00346
00347 if (!Vec3Test<float>())
00348 return EXIT_FAILURE;
00349 if (!Vec3Test<double>())
00350 return EXIT_FAILURE;
00351
00352
00353 if (!QuatTest<float>())
00354 return EXIT_FAILURE;
00355 if (!QuatTest<double>())
00356 return EXIT_FAILURE;
00357
00358
00359 if (!MatrixTest<float>())
00360 return EXIT_FAILURE;
00361 if (!MatrixTest<double>())
00362 return EXIT_FAILURE;
00363
00364
00365 if (!GeodesyTest())
00366 return EXIT_FAILURE;
00367
00368
00369 if (!sgInterfaceTest())
00370 return EXIT_FAILURE;
00371 if (!sgdInterfaceTest())
00372 return EXIT_FAILURE;
00373
00374 std::cout << "Successfully passed all tests!" << std::endl;
00375 return EXIT_SUCCESS;
00376 }