diff options
author | Manoj Rajagopalan <manoj@nanorex.com> | 2008-04-23 22:02:26 +0000 |
---|---|---|
committer | Manoj Rajagopalan <manoj@nanorex.com> | 2008-04-23 22:02:26 +0000 |
commit | b9c1699510519ee541b8a93481002d51a778c12d (patch) | |
tree | c6f89067e3e3a079f44d7d41445f111d3b5df949 | |
parent | 13d5aeb9ec1d2404e3384b1f05fff1120af901ec (diff) | |
download | nanoengineer-theirix-b9c1699510519ee541b8a93481002d51a778c12d.tar.gz nanoengineer-theirix-b9c1699510519ee541b8a93481002d51a778c12d.zip |
Adding files to repo to correct breakage of revision 12636
8 files changed, 1656 insertions, 6 deletions
diff --git a/cad/plugins/NanoVision-1/include/Nanorex/Interface/NXNamedView.h b/cad/plugins/NanoVision-1/include/Nanorex/Interface/NXNamedView.h new file mode 100644 index 000000000..1983f575b --- /dev/null +++ b/cad/plugins/NanoVision-1/include/Nanorex/Interface/NXNamedView.h @@ -0,0 +1,74 @@ +// Copyright 2008 Nanorex, Inc. See LICENSE file for details. + +#ifndef NX_NAMEDVIEW_H +#define NX_NAMEDVIEW_H + +#include <Nanorex/Utility/NXVector.h> +#include <Nanorex/Utility/NXQuaternion.h> + +#include <iostream> +#include <string> + +namespace Nanorex { + +/* CLASS: NXNamedView */ +class NXNamedView { +public: + NXNamedView() {} + NXNamedView(std::string const& theName, + NXQuaternion<double> const& theRotationQuat, + double const& theScale, + NXVector3d const& thePOV, + double const& theZoomFactor) + : name(theName), rotationQuat(theRotationQuat), scale(theScale), + POV(thePOV), zoomFactor(theZoomFactor), vdist(6.0*scale) + { + } + ~NXNamedView() {} + + std::string const& getName(void) const { return name; } + void setName(std::string const& theName) { name = theName; } + + NXQuaternion<double> const& getQuat(void) const { return rotationQuat; } + void setQuat(NXQuaternion<double> const& quat) { rotationQuat = quat; } + + double const& getScale(void) const { return scale; } + void setScale(double const& theScale) { scale = theScale; vdist = 6.0*scale; } + + NXVectorRef3d getPOV(void) { return NXVectorRef3d(POV); } + void setPOV(NXVector3d const& thePOV) { POV = thePOV; } + + double const& getZoomFactor(void) const { return zoomFactor; } + void setZoomFactor(double const& theZoomFactor) {zoomFactor = theZoomFactor;} + + static double GetNear(void) { return 0.25; } + static double GetFar(void) { return 12.0; } + + double const& getPOVDistanceFromEye(void) const { return vdist; } + double getNearPlaneDistanceFromEye(void) const { return GetNear() * vdist; } + double getFarPlaneDistanceFromEye(void) const { return GetFar() * vdist; } + +private: + std::string name; + NXQuaternion<double> rotationQuat; + double scale; + NXVector3d POV; + double zoomFactor; + + double vdist; +}; + + +inline +std::ostream& operator << (std::ostream& o, Nanorex::NXNamedView& view) +{ + o << "csys (" << view.getName() << ") " << view.getQuat() + << " (" << view.getScale() << ") " << view.getPOV() + << " (" << view.getZoomFactor() << ')'; + return o; +} + + +} // namespace Nanorex + +#endif // NX_NAMEDVIEW_H diff --git a/cad/plugins/NanoVision-1/include/Nanorex/Utility/NXMatrix.h b/cad/plugins/NanoVision-1/include/Nanorex/Utility/NXMatrix.h new file mode 100644 index 000000000..f37104482 --- /dev/null +++ b/cad/plugins/NanoVision-1/include/Nanorex/Utility/NXMatrix.h @@ -0,0 +1,170 @@ +// Copyright 2008 Nanorex, Inc. See LICENSE file for details. + +#ifndef NX_MATRIX_H +#define NX_MATRIX_H + +#include <Nanorex/Utility/NXVector.h> + +namespace Nanorex { + +/* CLASS: NXMatrix */ +/** + * Column-major matrix of dimensions M x N + * + */ +template<typename T, int M, int N> + class NXMatrix { + public: + NXMatrix() throw() {} + ~NXMatrix() throw() {} + + T const *const data(void) const throw() { return elems; } + T *const data(void) throw() { return elems; } + + /// Access value at m-th row, n-th column + T const& operator () (int const& m, int const& n) const throw(); + + /// Access value at m-th row, n-th column + T& operator () (int const& m, int const& n) throw(); + + /// Access n-th column + NXVectorRef<T,N> col(int const& n) throw(); + + template<typename T1> + NXMatrix<T,M,N>& operator += (NXMatrix<T1,M,N> const& A) throw(); + + template<typename T1> + NXMatrix<T,M,N>& operator -= (NXMatrix<T1,M,N> const& A) throw(); + + template<typename T1> + NXMatrix<T,M,N>& operator *= (T1 const& c) throw(); + + template<typename T1> + NXMatrix<T,M,N>& operator /= (T1 const& c) throw(); + + + private: + T elems[M*N]; + }; + + +typedef NXMatrix<double,3,3> NXMatrix33d; +typedef NXMatrix<float,3,3> NXMatrix33f; +typedef NXMatrix<double,4,4> NXMatrix44d; +typedef NXMatrix<float,4,4> NXMatrix44f; + +// Access value at m-th row, n-th column +template<typename T, int M, int N> + inline + T const& NXMatrix<T,M,N>::operator () (int const& m, int const& n) const throw() +{ + return elems[n*M + m]; +} + +// Access value at m-th row, n-th column +template<typename T, int M, int N> + inline + T& NXMatrix<T,M,N>::operator () (int const& m, int const& n) throw() +{ + return elems[n*M + m]; +} + +// Access n-th column +template<typename T, int M, int N> + inline + NXVectorRef<T,N> NXMatrix<T,M,N>::col(int const& n) throw() +{ + return NXVectorRef<T,N>(elems + n*M); +} + + +template<typename T, int M, int N> + template<typename T1> + inline + NXMatrix<T,M,N>& + NXMatrix<T,M,N>::operator += (NXMatrix<T1,M,N> const& A) throw() +{ + // Exploit isomorphism with M*N-dimensional vectors + NXVectorRef<T,M*N> selfRef(elems); + NXVectorRef<T1,M*N> ARef(A.data()); + selfRef += ARef; + return *this; +} + + +template<typename T, int M, int N> + template<typename T1> + inline + NXMatrix<T,M,N>& + NXMatrix<T,M,N>::operator -= (NXMatrix<T1,M,N> const& A) throw() +{ + // Exploit isomorphism with M*N-dimensional vectors + NXVectorRef<T,M*N> selfRef(elems); + NXVectorRef<T1,M*N> ARef(A.data()); + selfRef -= ARef; + return *this; +} + + +template<typename T, int M, int N> + template<typename T1> + inline + NXMatrix<T,M,N>& NXMatrix<T,M,N>::operator *= (T1 const& c) throw() +{ + // Exploit isomorphism with M*N-dimensional vectors + NXVectorRef<T,M*N> selfRef(elems); + selfRef *= c; + return *this; +} + + +template<typename T, int M, int N> + template<typename T1> + inline + NXMatrix<T,M,N>& NXMatrix<T,M,N>::operator /= (T1 const& c) throw() +{ + // Exploit isomorphism with M*N-dimensional vectors + NXVectorRef<T,M*N> selfRef(elems); + T const one_by_c = T(1) / c; + selfRef *= one_by_c; + return *this; +} + + + +/// Matrix-matrix multiplication (inefficient) +template<typename T, int M, int N, int K> + NXMatrix<T,M,N> operator * (NXMatrix<T,M,K> const& A, + NXMatrix<T,K,N> const& B) +{ + NXMatrix<T,M,N> C; // result + for(int m=0; m<M; ++m) { + for(int n=0; n<N; ++n) { + T sum_mn(0); + for(int k=0; k<K; ++k) { + sum_mn += A(m,k) * B(k,n); + } + C(m,n) = sum_mn; + } + } +} + + +/// Matrix-vector multiplication (inefficient) +template<typename T, int M, int N> + NXVector<T,M> operator * (NXMatrix<T,M,N> const& A, + NXVector<T,N> const& x) +{ + NXVector<T,M> y; // result + y.zero(); + for(int n=0; n<N; ++n) { + for(int m=0; m<M; ++m) { + y[m] += A(m,n) * x[n]; + } + } +} + + +} // namespace Nanorex + +#endif // NX_MATRIX_H diff --git a/cad/plugins/NanoVision-1/include/Nanorex/Utility/NXQuaternion.h b/cad/plugins/NanoVision-1/include/Nanorex/Utility/NXQuaternion.h new file mode 100644 index 000000000..781476f00 --- /dev/null +++ b/cad/plugins/NanoVision-1/include/Nanorex/Utility/NXQuaternion.h @@ -0,0 +1,407 @@ +// Copyright 2008 Nanorex, Inc. See LICENSE file for details. + +#ifndef NX_QUATERNION_H +#define NX_QUATERNION_H + +#include <Nanorex/Utility/NXVector.h> +#include <Nanorex/Utility/NXMatrix.h> + +#include <cmath> + + +#ifdef _GNU_SOURCE +inline void sincos(float x, float *sinx, float *cosx) {sincosf(x, sinx, cosx);} +inline void sincos(long double x, long double *sinx, long double *cosx) { + sincosl(x, sinx, cosx); +} +#endif + + +namespace Nanorex { + +/// Quaternion class stored as cos(theta/2) + sin(theta/2)*(x,y,z) +template<typename T> +class NXQuaternion { +public: + + NXQuaternion(); + + /// w = cos(theta)/2 where theta is rotation angle, (x,y,z) specify axis vector + /// NXQuaternion(1,0,0,0) => no rotation + NXQuaternion(T const& _w, // cos(theta)/2 + T const& _x, T const& _y, T const& _z); + + /// Quaternion that rotates the standard axes into the right-handed coordinate + /// frame described by orthonormal vectors _x, _y and _z + NXQuaternion(NXVectorRef<T,3> x, NXVectorRef<T,3> y, NXVectorRef<T,3> z); + + /// Rotation quaternion + NXQuaternion(NXVectorRef<T,3> rotAxis, T const& theta); + + /// Quaternion that rotates from vec1 to vec2 + NXQuaternion(NXVectorRef<T,3> vec1, NXVectorRef<T,3> vec2); + + ~NXQuaternion() {} + + /// Vector along the rotation axis + NXVector<T,3> getAxisDirection(void); + + /// Rotation angle in radians + T getAngle(void) const; + void setAngle(T const& theta); + + /// Set to (*this + q) which is the result of applying *this followed by q + NXQuaternion<T>& operator += (NXQuaternion<T> const& q); + + /// Result of (*this + q2) + NXQuaternion<T> operator + (NXQuaternion<T> const& q2) const; + + /// Unary minus + NXQuaternion<T> operator - (void) const; + + NXQuaternion<T>& operator *= (T const& n); + + /// Build rotation matrix. + void buildMatrix(NXMatrix<T,4,4>& R); + + NXVector<T,3> rot(NXVectorRef<T,3> v); + NXVector<T,3> unrot(NXVectorRef<T,3> v); + + NXQuaternion<T>& normalizeSelf(void); + +private: + T w; ///< cos(theta/2) + NXVector<T,3> axis; ///< sin(theta/2) * rotation-axis-vector + + int incrementCounter; + + template<typename S> + friend std::ostream& operator << (std::ostream& o, NXQuaternion<S> const& q); +}; + + +template<typename T> + inline + NXQuaternion<T>::NXQuaternion() + : w(1.0), axis(0.0, 0.0, 1.0) +{ +} + + +template<typename T> + inline + NXQuaternion<T>::NXQuaternion(T const& _w, + T const& _x, T const& _y, T const& _z) + : w(_w), axis(), incrementCounter(0) +{ + /// @fixme check domain of _w + T const sin_half_theta = sqrt(1.0 - _w*_w); + axis[0] = sin_half_theta * _x; + axis[1] = sin_half_theta * _y; + axis[2] = sin_half_theta * _z; + normalizeSelf(); +} + + +// Rotation quaternion +template<typename T> + inline + NXQuaternion<T>::NXQuaternion(NXVectorRef<T,3> rotAxis, T const& theta) + : w(0), axis(rotAxis), incrementCounter(0) +{ + setAngle(theta); +} + + +// Quaternion that rotates from vec1 to vec2 +template<typename T> + inline + NXQuaternion<T>::NXQuaternion(NXVectorRef<T,3> vec1, NXVectorRef<T,3> vec2) + : w(0), axis(), incrementCounter(0) +{ + NXVector<T,3> x = vec1; + NXVector<T,3> y = vec2; + x.normalizeSelf(); + y.normalizeSelf(); + T const dotxy = dot(x,y); + NXVector<T,3> v = cross(x,y); + T const vLen = length(v); + + if(vLen < 0.000001) { + // x, y are very close, or very close to opposite, or one of them is zero + if(dotxy < 0.0) { + // close to opposite; treat as actually opposite + w = 0.0; + NXVector<T,3> X_AXIS(1,0,0), Y_AXIS(0,1,0); + NXVector<T,3> ax1 = cross(x, X_AXIS); + NXVector<T,3> ax2 = cross(x, Y_AXIS); + if(length(ax1) > length(ax2)) + axis = ax1; + else + axis = ax2; + } + else { + // very close, or one is zero -- we could pretend they're equal, but let's be a little + // more accurate than that -- vl is sin of desired theta, so vl/2 is approximately sin(theta/2) + // (##e could improve this further by using a better formula to relate sin(theta/2) to sin(theta)), + // so formula for xyz part is v/vl * vl/2 == v/2 [bruce 050730] + NXVector<T,3> const xyz = v / 2.0; + double const sin_half_theta = vLen / 2.0; + double const cos_half_theta = sqrt(1 - sin_half_theta * sin_half_theta); + w = cos_half_theta; + axis = xyz; + } + } + + else { + /// @todo check for possible instability when dotxy ~ 1 + T const maxval = T(-1.0) > dotxy ? T(-1.0) : dotxy; + T const minval = T(1.0) < maxval ? T(1.0) : maxval; + T theta = acos(minval); + NXVector<T,3> crossxv = cross(x,v); + T const doty_crossxv = dot(y, crossxv); + if (doty_crossxv > 0.0) + theta = 2.0 * M_PI - theta; + w = cos(theta * 0.5); + double const s = sqrt(1 - w*w) / vLen; + axis = s * v; + } +} + +template<typename T> + NXVector<T,3> NXQuaternion<T>::getAxisDirection(void) +{ + if(axis[0] == 0.0 && axis[1] == 0.0 && axis[2] == 0.0) + // no rotation => return arbitrary axis + return NXVector<T,3>(0.0, 0.0, 1.0); + else + return axis; +} + + +template<typename T> + inline + T twistor_angle(NXVectorRef<T,3> axis, + NXVectorRef<T,3> pt1, + NXVectorRef<T,3> pt2) +{ + NXQuaternion<T> q(axis, NXVector<T,3>(0,0,1)); + pt1 = q.rot(pt1); + pt2 = q.rot(pt2); + T const a1 = atan2(pt1[1], pt1[0]); + T const a2 = atan2(pt2[1], pt2[0]); + T const theta = a2 - a1; + return theta; +} + + +template<typename T> + inline + NXQuaternion<T> twistor(NXVectorRef<T,3> axis, + NXVectorRef<T,3> pt1, + NXVectorRef<T,3> pt2) +{ + T const theta = twistor_angle(axis, pt1, pt2); + return NXQuaternion<T>(axis, theta); +} + + +/* CONSTRUCTOR */ +// Placed here because of dependence on twistor() which in turn depends on other constructors +// Quaternion that rotates the standard axes into the right-handed coordinate +// frame described by orthonormal vectors _x, _y and _z +template<typename T> + inline + NXQuaternion<T>::NXQuaternion(NXVectorRef<T,3> x, + NXVectorRef<T,3> y, + NXVectorRef<T,3> z) + : w(0), axis(), incrementCounter(0) +{ + NXVector<T,3> const X_AXIS(1.0, 0.0, 0.0); + NXVector<T,3> const Y_AXIS(1.0, 0.0, 0.0); + + NXQuaternion<T> xfixer(X_AXIS, x); + NXVector<T,3> yAxis2 = xfixer.rot(Y_AXIS); + NXQuaternion<T> yfixer = twistor(x, yAxis2, y); /// @todo implement twistor + NXQuaternion<T> res = xfixer + yfixer; + + *this = res; +} + + + + +template<typename T> +inline T NXQuaternion<T>::getAngle(void) const +{ + if(w > -1.0 && w < 1.0) { + T const retval = 2.0 * acos(w); + return retval; + } + else + return 0.0; +} + + +template<typename T> +inline void NXQuaternion<T>::setAngle(T const& theta) +{ + T const half_theta = 0.5 * theta; +#ifdef _GNU_SOURCE + T sin_half_theta = 0.0, cos_half_theta = 0.0; + sincos(half_theta, &sin_half_theta, &cos_half_theta); +#else + T const sin_half_theta = sin(half_theta); + T const cos_half_theta = cos(half_theta); +#endif + w = cos_half_theta; + axis *= sin_half_theta; + normalizeSelf(); +} + + +template<typename T> + inline + NXQuaternion<T> NXQuaternion<T>::operator + (NXQuaternion<T> const& q2) const +{ + NXQuaternion<T> q; + q.w = q2.w*w - q2.axis[0]*axis[0] - q2.axis[1]*axis[1] - q2.axis[2]*axis[2]; + q.axis[0] = q2.w*axis[0] + q2.axis[0]*w + q2.axis[1]*axis[2] - q2.axis[2]*axis[1]; + q.axis[1] = q2.w*axis[1] - q2.axis[0]*axis[2] + q2.axis[1]*w + q2.axis[2]*axis[0]; + q.axis[2] = q2.w*axis[2] + q2.axis[0]*axis[1] - q2.axis[1]*axis[0] + q2.axis[2]*w; + return q; +} + + +template<typename T> + inline NXQuaternion<T>& NXQuaternion<T>::operator += (NXQuaternion<T> const& q) +{ + *this = *this + q; + ++incrementCounter; + if(incrementCounter == 50) + normalizeSelf(); + return *this; +} + +/// multiplication by a scalar, i.e. Q1 * 1.3, defined so that +/// e.g. Q1 * 2 == Q1 + Q1, or Q1 = Q1 * 0.5 + Q1 * 0.5 +template<typename T> + inline NXQuaternion<T> operator * (NXQuaternion<T> const& q, T const& n) +{ + NXQuaternion<T> qResult(q); + qResult.setAngle(n * q.getAngle()); + return qResult; +} + +template<typename T> + inline NXQuaternion<T>& NXQuaternion<T>::operator *= (T const& n) +{ + *this = *this * n; + return *this; +} + + +template<typename T> + inline NXQuaternion<T> NXQuaternion<T>::operator - (void) const +{ + NXQuaternion<T> q; + q.w = w; // cos is even + q.axis = -axis; + return q; +} + + +template<typename T> + inline NXQuaternion<T> conj(NXQuaternion<T> const& q) +{ + return -q; +} + + +template<typename T> + inline NXQuaternion<T>& NXQuaternion<T>::normalizeSelf(void) +{ + T const len = length(axis); + if(len != 0.0) { + T const s = sqrt(1.0 - w*w) / len; + axis *= s; + } + else { + w = 1.0; + axis.zero(); + } + return *this; +} + + +/// Build rotation matrix +template<typename T> + inline void NXQuaternion<T>::buildMatrix(NXMatrix<T,4,4>& R) +{ + normalizeSelf(); + R(0,0) = T(1.0) - T(2.0) * (axis[1] * axis[1] + axis[2] * axis[2]); + R(0,1) = T(2.0) * (axis[0] * axis[1] - axis[2] * w); + R(0,2) = T(2.0) * (axis[2] * axis[0] + axis[1] * w); + R(0,3) = T(0.0); + + R(1,0) = T(2.0) * (axis[0] * axis[1] + axis[2] * w); + R(1,1) = T(1.0) - T(2.0) * (axis[2] * axis[2] + axis[0] * axis[0]); + R(1,2) = T(2.0) * (axis[1] * axis[2] - axis[0] * w); + R(1,3) = T(0.0); + + R(2,0) = T(2.0) * (axis[2] * axis[0] - axis[1] * w); + R(2,1) = T(2.0) * (axis[1] * axis[2] + axis[0] * w); + R(2,2) = T(1.0) - T(2.0) * (axis[1] * axis[1] + axis[0] * axis[0]); + R(2,3) = T(0.0); + + R(3,0) = T(0.0); + R(3,1) = T(0.0); + R(3,2) = T(0.0); + R(3,3) = T(1.0); + +} + + +template<typename T> + inline + NXVector<T,3> NXQuaternion<T>::rot(NXVectorRef<T,3> v) +{ + NXMatrix<T,4,4> R; + buildMatrix(R); + NXVector<T,4> v4; + NXVectorRef<T,3>(v4.data()).copy(v); + v4[3] = T(0); + NXVector<T,4> result4 = R * v4; + NXVector<T,3> result; + result.copy(NXVectorRef<T,3>(result4.data())); + return result; +} + + +template<typename T> + inline + NXVector<T,3> unrot(NXVectorRef<T,3> v) +{ + NXMatrix<T,4,4> R; + NXVector<T,3> result; + + // compute R^T v + buildMatrix(R); + for(int m=0; m<3; ++m) + result[m] = dot(R.col(m), v); + + return result; +} + + +template<typename T> + std::ostream& operator << (std::ostream& o, NXQuaternion<T> const& q) +{ + o << '(' << q.w << ',' << q.axis[0] << ',' << q.axis[1] << ',' << q.axis[2] << ')'; + return o; +} + + +} // namespace Nanorex + +#endif // NX_QUATERNION_H diff --git a/cad/plugins/NanoVision-1/include/Nanorex/Utility/NXTrackball.h b/cad/plugins/NanoVision-1/include/Nanorex/Utility/NXTrackball.h new file mode 100644 index 000000000..d05b658c3 --- /dev/null +++ b/cad/plugins/NanoVision-1/include/Nanorex/Utility/NXTrackball.h @@ -0,0 +1,90 @@ +// Copyright 2008 Nanorex, Inc. See LICENSE file for details. + +#ifndef NX_TRACKBALL_H +#define NX_TRACKBALL_H + +#include <Nanorex/Utility/NXQuaternion.h> +#include <cmath> + +namespace Nanorex { + +class NXTrackball { +public: + NXTrackball() + : w2(0.0), h2(0.0), scale(0.0), mouseSpeedDuringRotation(1.0) {} + + NXTrackball(int const& w, int const& h) { + resize(w, h); + mouseSpeedDuringRotation = 1.0; + } + + ~NXTrackball() {} + + // accessors + double getWidth(void) const { return (w2+w2); } + + double getHeight(void) const { return (h2+h2); } + + void resize(int const& w, int const& h) { + w2 = 0.5*((double)w); + h2 = 0.5*((double)h); + scale = 1.1 / ((w2 < h2) ? w2 : h2); + } + + // double const *const getOldMouse(void) const { return oldMouse; } + // double const *const getNewMouse(void) const { return newMouse; } + + double const& getMouseSpeedDuringRotation(void) const { + return mouseSpeedDuringRotation; + } + void setMouseSpeedDuringRotation(double const& speed) { + mouseSpeedDuringRotation = speed; + } + + void start(int const& x, int const& y) { + proj2sphere( oldMouse, + (double(x) - w2) * scale * mouseSpeedDuringRotation, + (h2 - double(y)) * scale * mouseSpeedDuringRotation ); + } + + void update(int const& x, int const& y) { + proj2sphere( newMouse, + (double(x) - w2) * scale * mouseSpeedDuringRotation, + (h2 - double(y)) * scale * mouseSpeedDuringRotation ); + } + + NXQuaternion<double> getRotationQuat(void) { + return NXQuaternion<double>(NXVectorRef<double,3>(oldMouse), + NXVectorRef<double,3>(newMouse)); + } + +private: + double w2; // half-screen-width + double h2; // half-screen-height + double scale; + double mouseSpeedDuringRotation; + double oldMouse[3]; + double newMouse[3]; + + /// Project screen coords (x,y) in [-1,1]^2 to unit-sphere and store in wpt + static void proj2sphere(double *wpt, double const& x, double const& y) { + double const d = sqrt(x*x+y*y); + double const theta = M_PI * 0.5 * d; + if(d > 0.0001) { +#ifdef _GNU_SOURCE + double sinTheta = 0.0, cosTheta = 0.0; + sincos(theta, &sinTheta, &cosTheta); +#else + double const sinTheta = sin(theta); + double const cosTheta = cos(theta); +#endif + wpt[0] = sinTheta * x / d; + wpt[1] = sinTheta * y / d; + wpt[2] = cosTheta; + } + } +}; + +} // Nanorex + +#endif // NX_TRACKBALL_H diff --git a/cad/plugins/NanoVision-1/include/Nanorex/Utility/NXVector.h b/cad/plugins/NanoVision-1/include/Nanorex/Utility/NXVector.h new file mode 100644 index 000000000..e66881e66 --- /dev/null +++ b/cad/plugins/NanoVision-1/include/Nanorex/Utility/NXVector.h @@ -0,0 +1,583 @@ + +/** \file NXVector.h + * \brief Implements point-vector classes using expression templates + */ +#ifndef NX_VECTOR_H +#define NX_VECTOR_H + +#include "Nanorex/Utility/NXUtility.h" +#include <cmath> +#include <cstring> +#include <iostream> + +namespace Nanorex { + + +// forward declarations for usable types +template<typename T, int N> class NXVectorRef; +template<typename T, int N> class NXVector; + +static double const NX_DEFAULTTOL = 1.0e-6; + +template<typename T1, typename T2> + struct promotion_traits; + +template<typename T> struct promotion_traits<T,T> { typedef T type; }; +template<> struct promotion_traits<float,double> { typedef double type; }; +template<> struct promotion_traits<double,float> { typedef double type; }; +template<> struct promotion_traits<double,long double> { typedef long double type; }; +template<> struct promotion_traits<long double,double> { typedef long double type; }; +template<> struct promotion_traits<float,long double> { typedef long double type; }; +template<> struct promotion_traits<long double,float> { typedef long double type; }; + + +/* CLASS: NXVectorBase */ +template <typename T, int N, template <typename,int> class NXVectorDerived> + class NXVectorBase { + public: + typedef T value_type; + typedef NXVectorBase<T,N,NXVectorDerived> baseclass_type; + typedef NXVectorDerived<T,N> subclass_type; + + private: + typedef NXVectorBase<T,N,NXVectorDerived> self_type; + + + public: + NXVectorBase() {} + ~NXVectorBase() {} + + // shallow or deep copy as per the implementation + template<template <typename, int> class NXVectorDerived2> + self_type& + operator = (NXVectorBase<T,N,NXVectorDerived2> const& v) throw() + { + asLeaf() = v.asLeaf(); + return *this; + } + + // force deep copy between identical value_types + template<template <typename, int> class NXVectorDerived2> + self_type& copy(NXVectorBase<T,N,NXVectorDerived2> const& v) throw() + { + NXVectorBase<T,N,NXVectorDerived2>& v_non_const = + const_cast<NXVectorBase<T,N,NXVectorDerived2>&>(v); + memcpy((void*) data(), + (void*) v_non_const.data(), + N * sizeof(T)); + return *this; + } + + // force deep copy between static_cast-able value_types + template<typename T1, template <typename, int> class NXVectorDerived2> + self_type& copy(NXVectorBase<T1,N,NXVectorDerived2> const& v) throw() + { + for(int n=0; n<N; ++n) + data()[n] = static_cast<T const>(v.data()[n]); + return *this; + } + + subclass_type& asLeaf(void) throw() { + return static_cast<subclass_type&>(*this); + } + + subclass_type const& asLeaf(void) const throw() { + return static_cast<subclass_type const&>(*this); + } + + // derived classes must implement the data array m_coords + T *const data(void) throw() { return asLeaf().data(); } + T const *const data(void) const throw() { return asLeaf().data(); } + + T const& operator [] (int const& n) const throw() { return data()[n]; } + T& operator [] (int const& n) throw() { return data()[n]; } + + int size(void) const throw() { return N; } + + self_type& zero(void) throw(); + + /// Unary minus + NXVector<T,N> operator - (void) const throw(); + + /// self-increment + template<typename T1, template <typename, int> class NXVectorDerived2> + self_type& operator += (NXVectorBase<T1,N,NXVectorDerived2> const& b) + throw(); + + /// self-decrement + template<typename T1, template <typename, int> class NXVectorDerived2> + self_type& operator -= (NXVectorBase<T1,N,NXVectorDerived2> const& b) + throw(); + + /// self-scaling + template<typename T1> + self_type& operator *= (T1 const& c) throw(); + + /// self-scaling + template<typename T1> + self_type& operator /= (T1 const& c) throw(); + + self_type& normalizeSelf(double const& TOL=NX_DEFAULTTOL) throw(); + + /// normalized copy of self + NXVector<T,N> normalized(double const& TOL=NX_DEFAULTTOL) const throw(); + + protected: + static inline T s_sqr(T const& x) throw() { return x*x; } + static inline T s_div(T const& a, T const& b) throw() + { return static_cast<T>(static_cast<double>(a)/static_cast<double>(b)); } + + }; + + +/* CLASS: NXVectorRef */ +/** + * N-dimensional vector view of an array with shallow copy semantics + */ +template<typename T, int N> + class NXVectorRef : public NXVectorBase<T,N,NXVectorRef> { + public: + + NXVectorRef() : m_coords(NULL) {} + NXVectorRef(T *const v) : m_coords(v) {} + NXVectorRef(NXVector<T,N>& v) : m_coords(v.data()) {} + + // shallow copy constructor + template<template <typename, int> class NXVectorDerived> + NXVectorRef<T,N>& operator = (NXVectorBase<T,N,NXVectorDerived>& v) { + m_coords = v.data(); + return *this; + } + ~NXVectorRef() {} + + T *const data(void) throw() { return m_coords; } + T const *const data(void) const throw() { return m_coords; } + + protected: + T *m_coords; + }; + +// typedefs for common instantiations +typedef NXVectorRef<float, 2> NXVectorRef2f; +typedef NXVectorRef<double,2> NXVectorRef2d; +typedef NXVectorRef<float, 3> NXVectorRef3f; +typedef NXVectorRef<double,3> NXVectorRef3d; +typedef NXVectorRef<float, 4> NXVectorRef4f; +typedef NXVectorRef<double,4> NXVectorRef4d; + + +// ----------------------------------------------------------------------------- +/* CLASS: NXVector */ +/** + * N-dimensional point + * Allocates private data store and inherits functionality from NXVectorBase + */ +template<typename T, int N> + class NXVector : public NXVectorBase<T,N,NXVector> { + public: + NXVector() throw () {} + NXVector(T const& x) throw (NXException); + NXVector(T const& y, T const& y) throw (NXException); + NXVector(T const& x, T const& y, T const& z) throw (NXException); + NXVector(T const v[]) throw (); ///< initialize from array + + // copy assignment with deep copy semantics + template<typename T1, template <typename, int> class NXVectorDerived> + NXVector<T,N>& + operator = (NXVectorBase<T1,N,NXVectorDerived> const& v) throw(); + + // copy constructor with deep copy semantics + template<typename T1, template <typename, int> class NXVectorDerived> + NXVector(NXVectorBase<T1,N,NXVectorDerived> const& v) throw (); + + ~NXVector() {} + + T *const data(void) throw() { return m_coords; } + T const *const data(void) const throw() { return m_coords; } + + private: + T m_coords[N]; + }; + +// typedefs for common instantiations +typedef NXVector<float, 2> NXVector2f; +typedef NXVector<double,2> NXVector2d; +typedef NXVector<float, 3> NXVector3f; +typedef NXVector<double,3> NXVector3d; +typedef NXVector<float, 4> NXVector4f; +typedef NXVector<double,4> NXVector4d; + + +/* CONSTRUCTOR */ +template<typename T, int N> + inline + NXVector<T,N>::NXVector(T const& x) throw (NXException) + : NXVector<T,N>::baseclass_type() + // : NXVectorRef<T,N>(m_coord_data) +{ + if(N != 1) + throw NXException("Initialization with different dimensionality"); + m_coords[0] = x; +} + +/* CONSTRUCTOR */ +template<typename T, int N> + inline + NXVector<T,N>::NXVector(T const& x, T const& y) throw (NXException) + : NXVector<T,N>::baseclass_type() + // : NXVectorRef<T,N>(m_coord_data) +{ + if(N != 2) + throw NXException("Initialization with different dimensionality"); + m_coords[0] = x; + m_coords[1] = y; +} + +/* CONSTRUCTOR */ +template<typename T, int N> + inline + NXVector<T,N>::NXVector(T const& x, T const& y, T const& z) throw (NXException) + : NXVector<T,N>::baseclass_type() + // : NXVectorRef<T,N>(m_coord_data) +{ + if(N != 3) + throw NXException("Initialization with different dimensionality"); + m_coords[0] = x; + m_coords[1] = y; + m_coords[2] = z; +} + +/* CONSTRUCTOR */ +template<typename T, int N> + inline + NXVector<T,N>::NXVector(T const v[]) throw () + : NXVector<T,N>::baseclass_type() + // : NXVectorRef<T,N>(m_coord_data) +{ + // for(int n=0; n<N; ++n) m_coords[n] = v[n]; + std::memcpy((void*) m_coords, + (void*) const_cast<T*>(v), + N * sizeof(T)); +} + +/* COPY-ASSIGNMENT */ +/// Deep copy semantics +template<typename T, int N> + template<typename T1, template <typename, int> class NXVectorDerived> + inline + NXVector<T,N>& + NXVector<T,N>::operator = (NXVectorBase<T1,N,NXVectorDerived> const& v) throw() +{ + for(int n=0; n<N; ++n) m_coords[n] = static_cast<T const>(v[n]); + return *this; +} + +/* CONSTRUCTOR */ +// copy constructor with deep copy semantics +template<typename T, int N> + template<typename T1, template <typename, int> class NXVectorDerived> + inline + NXVector<T,N>::NXVector(NXVectorBase<T1,N,NXVectorDerived> const& v) throw () + : NXVector<T,N>::baseclass_type() +{ + (void) (*this = v); // use copy assignment +} + + +// ------------------------------------------------------------------------ +/* Global functions */ + +template<typename T, template<typename,int> class NXVectorDerived> + inline + T dot(NXVectorBase<T,1,NXVectorDerived>& a, + NXVectorBase<T,1,NXVectorDerived>& b) +{ + return a[0]*b[0]; +} + +template<typename T, int N, template<typename,int> class NXVectorDerived> + inline + T dot(NXVectorBase<T,N,NXVectorDerived>& a, + NXVectorBase<T,N,NXVectorDerived>& b) +{ + NXVectorRef<T,N-1> a1(a.data()), b1(b.data()); + T const s = dot(a1, b1); + T const result = s + a[N-1]*b[N-1]; + return result; +} + +template<typename T, int N, template<typename,int> class NXVectorDerived> + inline + T squared_norm(NXVectorBase<T,N,NXVectorDerived>& v) { return dot(v,v); } + +template<typename T, int N, template<typename,int> class NXVectorDerived> + inline + T norm(NXVectorBase<T,N,NXVectorDerived>& v) +{ + double const sqr_nrm = static_cast<double>(squared_norm(v)); + double const nrm = sqrt(sqr_nrm); + return static_cast<T>(nrm); +} + +template<typename T, int N, template<typename,int> class NXVectorDerived> + inline + T length(NXVectorBase<T,N,NXVectorDerived>& v) +{ + return norm(v); +} + +template<typename T, + template<typename,int> class NXVectorDerived1, + template<typename,int> class NXVectorDerived2 + > + inline + NXVector<T,3> cross(NXVectorBase<T,3,NXVectorDerived1>& a, + NXVectorBase<T,3,NXVectorDerived2>& b) +{ + NXVector<T,3> c; + c[0] = a[1] * b[2] - a[2] * b[1]; + c[1] = a[2] * b[0] - a[0] * b[2]; + c[2] = a[0] * b[1] - a[1] * b[0]; + return c; +} + +// ------------------------------------------------------------------------ +/* NXVectorBase member functions - common operations */ + +// template<typename T> +// inline +// NXVectorRef<T,1>& NXVectorRef<T,1>::zero(void) +// { m_coords[0] = T(0); return *this; } + +template<typename T, int N, template<typename,int> class NXVectorDerived> + inline + NXVectorBase<T,N, NXVectorDerived>& + NXVectorBase<T,N,NXVectorDerived>::zero(void) throw() +{ + for(int n=0; n<N; ++n) data()[n] = T(0); +/* if(N==1) m_coords[0] = T(0); + else { + NXVectorRef<T,N-1>(m_coords).zero(); + m_coords[N-1]=T(0); + }*/ + return *this; +} + +// increment base-case +// template<typename T> +// inline +// NXVectorRef<T,1>& NXVectorRef<T,1>::operator += (NXVectorRef<T,1> const& v) +// { m_coords[0] += v.m_coords[0]; return *this; } + +// increment common-case +template<typename T, int N, template<typename,int> class NXVectorDerived> + template<typename T1, template<typename, int> class NXVectorDerived2> + inline + NXVectorBase<T,N,NXVectorDerived>& + NXVectorBase<T,N,NXVectorDerived>:: + operator += (NXVectorBase<T1,N,NXVectorDerived2> const& v) + throw() +{ + for(int n=0; n<N; ++n) data()[n] += static_cast<T const>(v.data()[n]); +/* NXVectorRef<T,N-1>(m_coords) += NXVectorRef<T,N-1>(v.m_coords); + m_coords[N-1] += v.m_coords[N-1];*/ + return *this; +} + +// decrement base-case +// template<typename T> +// inline +// NXVectorRef<T,1>& NXVectorRef<T,1>::operator -= (NXVectorRef<T,1> const& v) +// { m_coords[0] -= v.m_coords[0]; return *this; } + +// decrement common-case +template<typename T, int N, template<typename,int> class NXVectorDerived> + template<typename T1, template<typename, int> class NXVectorDerived2> + inline + NXVectorBase<T,N,NXVectorDerived>& + NXVectorBase<T,N,NXVectorDerived>:: + operator -= (NXVectorBase<T1,N,NXVectorDerived2> const& v) + throw() +{ + for(int n=0; n<N; ++n) data()[n] -= static_cast<T const>(v.data()[n]); +/* NXVectorRef<T,N-1>(m_coords) -= NXVectorRef<T,N-1>(v.m_coords); + m_coords[N-1] -= v.m_coords[N-1];*/ + return *this; +} + +// scaling base-case +// template<typename T> +// inline +// NXVectorRef<T,1>& NXVectorRef<T,1>::operator *= (T const& c) +// { +// m_coords[0] *= c; +// return *this; +// } + +// scaling common-case +template<typename T, int N, template<typename,int> class NXVectorDerived> + template<typename T1> + inline + NXVectorBase<T,N,NXVectorDerived>& + NXVectorBase<T,N,NXVectorDerived>::operator *= (T1 const& c) throw() +{ + for(int n=0; n<N; ++n) data()[n] *= static_cast<T const>(c); +/* NXVectorRef<T,N-1>(m_coords) *= c; + m_coords[N-1] *= c;*/ + return *this; +} + +// scaling base-case +// template<typename T> +// inline +// NXVectorRef<T,1>& NXVectorRef<T,1>::operator /= (T const& c) +// { +// m_coords[0] /= c; +// return *this; +// } + +// scaling common-case +template<typename T, int N, template<typename,int> class NXVectorDerived> + template<typename T1> + inline + NXVectorBase<T,N,NXVectorDerived>& + NXVectorBase<T,N,NXVectorDerived>::operator /= (T1 const& c) throw() +{ + for(int n=0; n<N; ++n) data()[n] /= static_cast<T1 const>(c); +/* NXVectorRef<T,N-1>(m_coords) /= c; + m_coords[N-1] /= c;*/ + return *this; +} + + +template<typename T, int N, template<typename,int> class NXVectorDerived> + inline + NXVectorBase<T,N,NXVectorDerived>& + NXVectorBase<T,N,NXVectorDerived>::normalizeSelf(double const& TOL) throw() +{ + /// @fixme possible loss of precision through repeated interconversion + T const len = norm(*this); + if(double(len) < TOL) zero(); + else this->operator /= (len); + return *this; +} + +/// Return normalized copy without modifying self +template<typename T, int N, template<typename,int> class NXVectorDerived> + inline + NXVector<T,N> + NXVectorBase<T,N,NXVectorDerived>::normalized(double const& TOL) const throw() +{ + NXVector<T,N> v(data()); + v.normalizeSelf(TOL); + return v; +} + +/// Unary minus +template<typename T, int N, template<typename,int> class NXVectorDerived> + inline + NXVector<T,N> + NXVectorBase<T,N,NXVectorDerived>::operator - (void) const throw() +{ + NXVector<T,N> result; + for(int n=0; n<N; ++n) + result[n] = -data()[n]; + return result; +} + +// Binary operators + +/// Addition +template<typename T1, typename T2, int N, + template<typename,int> class NXVectorDerived1, + template<typename,int> class NXVectorDerived2 + > + inline + NXVector<typename promotion_traits<T1,T2>::type, N> + operator + (NXVectorBase<T1,N,NXVectorDerived1>& v1, + NXVectorBase<T2,N,NXVectorDerived2>& v2) +{ + typedef typename promotion_traits<T1,T2>::type T; + NXVector<T,N> result; + for(int n=0; n<N; ++n) + result[n] = v1[n] + v2[n]; + return result; +} + + +/// Subtraction +template<typename T1, typename T2, int N, + template<typename,int> class NXVectorDerived1, + template<typename,int> class NXVectorDerived2 + > + inline + NXVector<typename promotion_traits<T1,T2>::type, N> + operator - (NXVectorBase<T1,N,NXVectorDerived1>& v1, + NXVectorBase<T2,N,NXVectorDerived2>& v2) +{ + typedef typename promotion_traits<T1,T2>::type T; + NXVector<T,N> result; + for(int n=0; n<N; ++n) + result[n] = v1[n] - v2[n]; + return result; +} + + +/// Scaling +template<typename T1, typename T2, int N, template<typename,int> class NXVectorDerived> + inline + NXVector<typename promotion_traits<T1,T2>::type, N> + operator * (T1 const& c, NXVectorBase<T2,N,NXVectorDerived>& v) +{ + typedef typename promotion_traits<T1,T2>::type T; + NXVector<T,N> result; + for(int n=0; n<N; ++n) + result[n] = static_cast<T>(c) * static_cast<T>(v[n]); + return result; +} + + +/// Scaling - post-multiplication by scalar +template<typename T1, typename T2, int N, template<typename,int> class NXVectorDerived> + inline + NXVector<typename promotion_traits<T1,T2>::type, N> + operator * (NXVectorBase<T2,N,NXVectorDerived>& v, T1 const& c) +{ + typedef typename promotion_traits<T1,T2>::type T; + NXVector<T,N> result; + for(int n=0; n<N; ++n) + result[n] = static_cast<T>(c) * static_cast<T>(v[n]); + return result; +} + + +/// Scaling - division by +template<typename T1, typename T2, int N, template<typename,int> class NXVectorDerived> + inline + NXVector<typename promotion_traits<T1,T2>::type, N> + operator / (NXVectorBase<T2,N,NXVectorDerived>& v, T1 const& c) +{ + typedef typename promotion_traits<T1,T2>::type T; + NXVector<T,N> result; + for(int n=0; n<N; ++n) + result[n] = static_cast<T>(v[n]) / static_cast<T>(c); + return result; +} + + +template <typename T, int N, template <typename,int> class NXVectorDerived> + inline + std::ostream& operator << (std::ostream& o, + NXVectorBase<T,N,NXVectorDerived> const& v) +{ + o << '('; + for(int n=0; n<N-1; ++n) + o << v[n] << ','; + o << v[N-1] << ')'; + return o; +} + +} // Nanorex + +#endif // NX_VECTOR_H + diff --git a/cad/plugins/NanoVision-1/src/KDevelop/nv1.kdevelop b/cad/plugins/NanoVision-1/src/KDevelop/nv1.kdevelop index 2feb5387d..148201ebc 100644 --- a/cad/plugins/NanoVision-1/src/KDevelop/nv1.kdevelop +++ b/cad/plugins/NanoVision-1/src/KDevelop/nv1.kdevelop @@ -142,39 +142,46 @@ </kdevdebugger> <kdevtrollproject> <run> - <mainprogram>/home/rmanoj/Nanorex/SVN/trunk/cad/plugins/NanoVision-1/bin/nv1</mainprogram> + <mainprogram>/home/rmanoj/Nanorex/SVN/trunk/cad/plugins/NanoVision-1/src/KDevelop</mainprogram> <programargs/> <directoryradio>executable</directoryradio> <globaldebugarguments/> <globalcwd>/home/rmanoj/Nanorex/SVN/trunk/cad/plugins/NanoVision-1/bin/</globalcwd> - <useglobalprogram>true</useglobalprogram> + <useglobalprogram>false</useglobalprogram> <terminal>false</terminal> <autocompile>false</autocompile> <autoinstall>false</autoinstall> <autokdesu>false</autokdesu> <envvars> <envvar value="/home/rmanoj/Nanorex/SVN/trunk/cad/plugins/NanoVision-1/lib:/usr/local/lib" name="LD_LIBRARY_PATH" /> - <envvar value="/home/rmanoj/Nanorex/SVN/trunk/cad/plugins/NanoVision-1/src/KDevelop/count1" name="QMAKEFEATURES" /> </envvars> <runarguments> <HDF5_SimResultsImportExport/> <GLT/> - <CppUnit/> + <CppUnit>NXSceneGraphTestSuite</CppUnit> <NXOpenGLRenderingEngineTest/> <HDF5_Consumer/> <nv1/> <NXBallAndStickOpenGLRendererTest/> <count1/> + <QTestLib/> + <QtTests/> + <MMPOpenGLRendererTest/> + <TrajectoryGraphicsWindowTest/> </runarguments> <cwd> <HDF5_SimResultsImportExport>/home/rmanoj/Nanorex/SVN/trunk/cad/plugins/NanoVision-1/src/KDevelop</HDF5_SimResultsImportExport> <GLT>/home/rmanoj/Nanorex/SVN/trunk/cad/plugins/NanoVision-1/src/KDevelop</GLT> - <CppUnit>/home/bh/11Nano/SVN-D/cad/plugins/NanoVision-1/src/KDevelop/../../../..</CppUnit> + <CppUnit>/home/rmanoj/Nanorex/SVN/trunk/cad/plugins/NanoVision-1/src/KDevelop/../../../../</CppUnit> <HDF5_Consumer>/home/bh/11Nano/SVN-D/cad/plugins/NanoVision-1/src/KDevelop</HDF5_Consumer> <nv1>/home/rmanoj/Nanorex/SVN/trunk/cad/plugins/NanoVision-1/src/KDevelop</nv1> <NXBallAndStickOpenGLRendererTest>/home/rmanoj/Nanorex/SVN/trunk/cad/plugins/NanoVision-1/src/KDevelop</NXBallAndStickOpenGLRendererTest> <count1>/home/rmanoj/Nanorex/SVN/trunk/cad/plugins/NanoVision-1/src/KDevelop</count1> <NXOpenGLRenderingEngineTest>/home/rmanoj/Nanorex/SVN/trunk/cad/plugins/NanoVision-1/src/KDevelop</NXOpenGLRenderingEngineTest> + <QTestLib>/home/rmanoj/Nanorex/SVN/trunk/cad/plugins/NanoVision-1/bin/</QTestLib> + <QtTests>/home/rmanoj/Nanorex/SVN/trunk/cad/plugins/NanoVision-1/src/KDevelop/../../../..</QtTests> + <MMPOpenGLRendererTest>../../../../../bin/</MMPOpenGLRendererTest> + <TrajectoryGraphicsWindowTest>../../../../../../../bin/</TrajectoryGraphicsWindowTest> </cwd> <debugarguments> <HDF5_SimResultsImportExport/> @@ -185,10 +192,14 @@ <nv1/> <NXBallAndStickOpenGLRendererTest/> <count1/> + <QTestLib/> + <QtTests/> + <MMPOpenGLRendererTest/> + <TrajectoryGraphicsWindowTest/> </debugarguments> </run> <general> - <activedir>nv1</activedir> + <activedir>Testing/Plugins/RenderingEngines/OpenGL/TrajectoryGraphicsWindowTest</activedir> </general> <make> <abortonerror>false</abortonerror> @@ -204,6 +215,8 @@ <replacePaths>false</replacePaths> <disableDefaultOpts>true</disableDefaultOpts> <enableFilenamesOnly>false</enableFilenamesOnly> + <showVariablesInTree>true</showVariablesInTree> + <showParseErrors>true</showParseErrors> </qmake> <subclassing/> </kdevtrollproject> diff --git a/cad/plugins/NanoVision-1/src/Utility/NXVectorTest.cpp b/cad/plugins/NanoVision-1/src/Utility/NXVectorTest.cpp new file mode 100644 index 000000000..96abcc1d8 --- /dev/null +++ b/cad/plugins/NanoVision-1/src/Utility/NXVectorTest.cpp @@ -0,0 +1,262 @@ +// Copyright 2008 Nanorex, Inc. See LICENSE file for details. + +#include "NXVectorTest.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(NXVectorTest); +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(NXVectorTest, + "NXVectorTestSuite"); + +// --------------------------------------------------------------------- +/* Helper comparison functions */ + + +template<typename T, int N, template<typename,int> class NXVectorDerived> +void cppunit_assert_vectors_equal(NXVectorBase<T,N,NXVectorDerived> const& pRef, + T answer[N], + T const& delta = 1.0e-8) +{ + for(int n=0; n<N; ++n) { + CPPUNIT_ASSERT_DOUBLES_EQUAL(double(pRef[n]), + double(answer[n]), + double(delta)); + } +} + +template<typename T, int N, template<typename,int> class NXVectorDerived> +void cppunit_assert_points_unequal(NXVectorBase<T,N,NXVectorDerived> const& pRef, + T answer[N], + T const& delta = 1.0e-8) +{ + for(int n=0; n<N; ++n) { + CPPUNIT_ASSERT(fabs(double(pRef[n])-double(answer[n])) > double(delta)); + } +} + +template<typename T, int N, +template<typename,int> class NXVectorDerived, +template<typename,int> class NXVectorDerived2 +> +void cppunit_assert_vectors_equal(NXVectorBase<T,N,NXVectorDerived> const& p1Ref, + NXVectorBase<T,N,NXVectorDerived2> const& p2Ref, + T const& delta = 1.0e-8) +{ + for(int n=0; n<N; ++n) { + CPPUNIT_ASSERT_DOUBLES_EQUAL(double(p1Ref[n]), + double(p2Ref[n]), + double(delta)); + } +} + + +// --------------------------------------------------------------------- +/* Test-suite */ + +void NXVectorTest::accessTest(void) +{ + NXVector4d p; + double answer[4] = { 0.0, 1.0, 2.0, 3.0 }; + p[0] = answer[0]; p[1] = answer[1]; p[2] = answer[2]; p[3] = answer[3]; + double const *const ptr = p.data(); + CPPUNIT_ASSERT(ptr[0] == 0.0); + CPPUNIT_ASSERT(ptr[1] == 1.0); + CPPUNIT_ASSERT(ptr[2] == 2.0); + CPPUNIT_ASSERT(ptr[3] == 3.0); + cppunit_assert_vectors_equal(p, answer, 0.0); +} + +void NXVectorTest::dataTest(void) +{ + NXVector4d p; + NXVectorRef4d pRef; + pRef = p; + CPPUNIT_ASSERT(p.data() == pRef.data()); + + // test copy constructor for deep-copy semantics + double init[4] = { 2.0, 3.0, -1.0, 6.0 }; + NXVectorRef4d initRef(init); + NXVector4d initCopy(initRef); + CPPUNIT_ASSERT(initRef.data() != initCopy.data()); + cppunit_assert_vectors_equal(initRef, initCopy); + // test copy assignment for deep-copy + initCopy.zero(); + initCopy = initRef; + CPPUNIT_ASSERT(initRef.data() != initCopy.data()); + cppunit_assert_vectors_equal(initRef, initCopy); +} + +void NXVectorTest::sizeTest(void) +{ + NXVector4d p; + CPPUNIT_ASSERT(p.size() == 4); + NXVectorRef3f pRef; + CPPUNIT_ASSERT(pRef.size() == 3); +} + +void NXVectorTest::zeroTest(void) +{ + NXVector4d p; + p.zero(); + CPPUNIT_ASSERT(p[0] == 0.0); + CPPUNIT_ASSERT(p[1] == 0.0); + CPPUNIT_ASSERT(p[2] == 0.0); + CPPUNIT_ASSERT(p[3] == 0.0); + + NXVector<char,2> cp; + cp.zero(); + CPPUNIT_ASSERT(cp[0] == '\0'); + CPPUNIT_ASSERT(cp[1] == '\0'); +} + +void NXVectorTest::incrementTest(void) +{ + NXVector4d p; + double init[4] = { 0.0, 1.0, 2.0, 3.0 }; + p[0] = init[0]; p[1] = init[1]; p[2] = init[2]; p[3] = init[3]; + NXVector4d p2; + p2.zero(); + p2 += p; + cppunit_assert_vectors_equal(p2, init); + double twice[4] = { 0.0, 2.0, 4.0, 6.0 }; + p2 += p2; + cppunit_assert_vectors_equal(p2, twice, 0.0); + +} + +void NXVectorTest::decrementTest(void) +{ + double zeros[4] = { 0.0, 0.0, 0.0, 0.0 }; + NXVector4d p1; + p1.zero(); + NXVector4d p2; + p2.zero(); + p1 -= p2; + cppunit_assert_vectors_equal(p1, zeros, 0.0); + + double init[4] = { 1.0, -2.0, 13.0, -27.0 }; + double answer[4] = { -1.0, 2.0, -13.0, 27.0 }; + NXVectorRef4d initRef(init); + NXVector4d initCopy = initRef; + cppunit_assert_vectors_equal(initRef, initCopy); + initCopy -= initRef; + cppunit_assert_vectors_equal(initCopy, zeros, 0.0); + initCopy -= initRef; + cppunit_assert_vectors_equal(initCopy, answer, 0.0); +} + +void NXVectorTest::scalingTest(void) +{ + double init[4] = { 5.0, 8.0, -2.0, 3.0 }; + double const factor = -2.0; + double answer[4] = { -10.0, -16.0, 4.0, -6.0 }; + NXVectorRef4d p(init); + p *= factor; + cppunit_assert_vectors_equal(p, answer, 0.0); + // check to see if the reference updated the actual array + for(int n=0; n<4; ++n) + CPPUNIT_ASSERT(init[n] == answer[n]); +} + +void NXVectorTest::invScalingTest(void) +{ + double init[4] = { -10.0, -16.0, 4.0, -6.0 }; + double answer[4] = { 5.0, 8.0, -2.0, 3.0 }; + double const factor = -2.0; + NXVectorRef4d p(init); + p /= factor; + cppunit_assert_vectors_equal(p, answer, 0.0); + // check to see if the reference updated the actual array + for(int n=0; n<4; ++n) + CPPUNIT_ASSERT(init[n] == answer[n]); +} + +void NXVectorTest::dotTest(void) +{ + double p1Data[4] = { 5.0, 6.0, 7.0, 8.0 }; + double p2Data[4] = { 8.0, 7.0, 6.0, 5.0 }; + NXVectorRef4d p1(p1Data); + NXVectorRef4d p2(p2Data); + double const p1_dot_p2 = dot(p1, p2); + double const answer = (p1Data[0] * p2Data[0] + + p1Data[1] * p2Data[1] + + p1Data[2] * p2Data[2] + + p1Data[3] * p2Data[3]); + CPPUNIT_ASSERT(p1_dot_p2 == answer); +} + +void NXVectorTest::squared_normTest(void) +{ + double pData[4] = { 5.0, 6.0, 7.0, 8.0 }; + NXVectorRef4d p(pData); + double const pSquaredNorm = squared_norm(p); + double const answer = (pData[0] * pData[0] + + pData[1] * pData[1] + + pData[2] * pData[2] + + pData[3] * pData[3]); + CPPUNIT_ASSERT(pSquaredNorm == answer); +} + +void NXVectorTest::normTest(void) +{ + double pData[5] = { 3.0, 4.0, 5.0, 5.0, 5.0 }; + NXVectorRef<double,5> p(pData); + double const pNorm = norm(p); + double const answer = 10.0; + CPPUNIT_ASSERT_DOUBLES_EQUAL(pNorm, answer, 1.0e-8); +} + +void NXVectorTest::normalizeSelfTest(void) +{ + double init[4] = { 1.0, 1.0, 1.0, 1.0 }; + NXVector4d initCopy(init); + initCopy.normalizeSelf(); + double answer[4] = { 0.5, 0.5, 0.5, 0.5 }; + cppunit_assert_vectors_equal(initCopy, answer, 1.0e-8); + + NXVector<float,2> pythagoreanPair; + pythagoreanPair[0] = 3.0f; + pythagoreanPair[1] = 4.0f; + pythagoreanPair.normalizeSelf(); + float pythagoreanPairNormalizedValues[2] = { 0.6f, 0.8f }; + NXVectorRef2f pythagoreanPairNormalized(pythagoreanPairNormalizedValues); + cppunit_assert_vectors_equal(pythagoreanPair, + pythagoreanPairNormalized, + 1.0e-8f); +} + +void NXVectorTest::normalizedTest(void) +{ + double init[4] = { 1.0, 1.0, 1.0, 1.0 }; + NXVector4d initCopy(init); + NXVector4d initNormalized = initCopy.normalized(); + double answer[4] = { 0.5, 0.5, 0.5, 0.5 }; + cppunit_assert_vectors_equal(initNormalized, answer, 1.0e-8); + cppunit_assert_points_unequal(initNormalized, init, 1.0e-8); +} + +void NXVectorTest::crossTest(void) +{ + double iData[3] = { 1.0, 0.0, 0.0 }; + double jData[3] = { 0.0, 1.0, 0.0 }; + double kData[3] = { 0.0, 0.0, 1.0 }; + NXVectorRef3d iUnit(iData), jUnit(jData), kUnit(kData); + NXVector3d iCross = cross(jUnit, kUnit); + cppunit_assert_vectors_equal(iCross, iUnit); + NXVector3d jCross = cross(kUnit, iUnit); + cppunit_assert_vectors_equal(jCross, jUnit); + NXVector3d kCross = cross(iUnit, jUnit); + cppunit_assert_vectors_equal(kCross, kUnit); + + double pData[3] = { 2.0, 1.0, -1.0 }; + double qData[3] = { -3.0, 4.0, 1.0 }; + double pcrossqData [3] = { 5.0, 1.0, 11.0 }; + NXVectorRef3d p(pData), q(qData); + NXVector3d r = cross(p,q); + cppunit_assert_vectors_equal(NXVectorRef3d(pcrossqData), r.data()); + + int lData[3] = { 0, 1, 1 }; + int mData[3] = { 1, -1, 3 }; + int minus_lcrossm_data[3] = { -4, -1, 1 }; + NXVectorRef<int,3> l(lData), m(mData); + NXVector<int,3> n = cross(m,l); + cppunit_assert_vectors_equal(n, minus_lcrossm_data, 0); +} diff --git a/cad/plugins/NanoVision-1/src/Utility/NXVectorTest.h b/cad/plugins/NanoVision-1/src/Utility/NXVectorTest.h new file mode 100644 index 000000000..10a5298b1 --- /dev/null +++ b/cad/plugins/NanoVision-1/src/Utility/NXVectorTest.h @@ -0,0 +1,51 @@ +// Copyright 2008 Nanorex, Inc. See LICENSE file for details. + +#ifndef NX_POINTTEST_H +#define NX_POINTTEST_H + +#include <cppunit/extensions/HelperMacros.h> + +#include "Nanorex/Utility/NXVector.h" + +using namespace Nanorex; + +class NXVectorTest : public CPPUNIT_NS::TestFixture { + + CPPUNIT_TEST_SUITE(NXVectorTest); + CPPUNIT_TEST(accessTest); + CPPUNIT_TEST(dataTest); + CPPUNIT_TEST(sizeTest); + CPPUNIT_TEST(zeroTest); + CPPUNIT_TEST(incrementTest); + CPPUNIT_TEST(decrementTest); + CPPUNIT_TEST(scalingTest); + CPPUNIT_TEST(invScalingTest); + CPPUNIT_TEST(dotTest); + CPPUNIT_TEST(squared_normTest); + CPPUNIT_TEST(normTest); + CPPUNIT_TEST(normalizeSelfTest); + CPPUNIT_TEST(normalizedTest); + CPPUNIT_TEST(crossTest); + CPPUNIT_TEST_SUITE_END(); + +public: + void setUp(void) {} + void tearDown(void) {} + + void accessTest(void); + void dataTest(void); + void sizeTest(void); + void zeroTest(void); + void incrementTest(void); + void decrementTest(void); + void scalingTest(void); + void invScalingTest(void); + void dotTest(void); + void squared_normTest(void); + void normTest(void); + void normalizeSelfTest(void); + void normalizedTest(void); + void crossTest(void); +}; + +#endif // NX_POINTTEST_H |