home *** CD-ROM | disk | FTP | other *** search
- #ifndef _HVECTOR_H
- #define _HVECTOR_H
-
- #include "cvector.h"
-
- // This is a template for a homogenous vector class (like a
- // Cartesian vector but with a w scaling coordinate).
- // The usual operators are supplied.
-
- #define HomogenousVectorDeclare(T) \
- class HVec(T) { \
- public: \
- static errorHandler error; \
- static void badvec(int, const char *); \
- static errorHandler setErrorHandler(errorHandler); \
- \
- T &operator[](int i) { return x[i]; } \
- T operator()(int i) const { return x[i]; } \
- operator T*() { return x; } \
- \
- HVec(T)() {} \
- \
- HVec(T)(T xval, T yval, T zval, T wval = 1) { \
- x[0] = xval; x[1] = yval; x[2] = zval; x[3] = wval; \
- } \
- \
- HVec(T)(const HVec(T) &v) { \
- x[0] = v(0); x[1] = v(1); x[2] = v(2); x[3] = v(3); \
- } \
- \
- T magnitude() const { \
- if (x[3] != 0) \
- return sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]) / x[3]; \
- else { \
- (*error)(0, "w=0 in magnitude"); \
- return 0; \
- } \
- } \
- \
- HVec(T) &normalize(); \
- HVec(T) &canonicalize(); \
- \
- HVec(T) &operator+=(const HVec(T) &v); \
- HVec(T) &operator-=(const HVec(T) &v); \
- \
- HVec(T) &operator*=(T s) { \
- x[0] *= s; \
- x[1] *= s; \
- x[2] *= s; \
- return *this; \
- } \
- \
- HVec(T) &operator/=(T s) { \
- T recip = 1.0 / s; \
- x[0] *= recip; \
- x[1] *= recip; \
- x[2] *= recip; \
- return *this; \
- } \
- \
- /* Dehomogenize a homogenous vector */ \
- operator CVec(T)() const; \
- \
- /* Homogenize a cartesian vector */ \
- HVec(T)(const CVec(T) &v) { \
- x[0] = v(0); x[1] = v(1); x[2] = v(2); x[3] = 1; \
- } \
- \
- protected: \
- T x[4]; \
- }; \
- \
- /* -V */ \
- inline HVec(T) operator-(const HVec(T) &v) \
- { \
- return HVec(T)(-v(0), -v(1), -v(2), v(3)); \
- } \
- \
- /* s * V */ \
- inline HVec(T) operator*(T s, const HVec(T) &v) \
- { \
- return HVec(T)(s * v(0), s * v(1), s * v(2), v(3)); \
- } \
- \
- /* V * s */ \
- inline HVec(T) operator*(const HVec(T) &v, T s) { \
- return s * v; \
- } \
- \
- /* V / s */ \
- inline HVec(T) operator/(const HVec(T) &v, T s) \
- { \
- T recip = 1.0 / s; \
- return HVec(T)(v(0)*recip, v(1)*recip, v(2)*recip, v(3)); \
- } \
- \
- /* V + V */ \
- HVec(T) operator+(const HVec(T) &a, const HVec(T) &b); \
- \
- /* V - V */ \
- HVec(T) operator-(const HVec(T) &a, const HVec(T) &b); \
- \
- /* V cross V */ \
- HVec(T) operator^(const HVec(T) &a, const HVec(T) &b); \
- \
- /* V dot V */ \
- inline T operator*(const HVec(T) &a, const HVec(T) &b) \
- { \
- return (a(0) * b(0) + a(1) * b(1) + a(2) * b(2)) / \
- (a(3) * b(3)); \
- } \
- \
- /* V == V (no fuzz for comparison) */ \
- int operator==(const HVec(T) &a, const HVec(T) &b); \
- \
- /* V != V (no fuzz for comparison) */ \
- inline int operator!=(const HVec(T) &a, const HVec(T) &b) { \
- return !(a == b); \
- } \
- \
- ostream &operator<<(ostream &o, const HVec(T) &v);
-
- #define HomogenousVectorImplement(T) \
- \
- errorHandler HVec(T)::error = &HVec(T)::badvec; \
- \
- void HVec(T)::badvec(int code, const char *msg) { \
- cerr << "HVec(T): error " << code << ": " \
- << msg << endl; \
- } \
- \
- errorHandler HVec(T)::setErrorHandler(errorHandler e) { \
- errorHandler old = HVec(T)::error; \
- HVec(T)::error = e; \
- return old; \
- } \
- \
- \
- HVec(T) &HVec(T)::normalize() { \
- T mag = this->magnitude(); \
- \
- if (mag != 0.0) { \
- mag = 1 / (mag * x[3]); \
- x[0] *= mag; \
- x[1] *= mag; \
- x[2] *= mag; \
- x[3] = 1; \
- } \
- \
- return *this; \
- } \
- \
- HVec(T) &HVec(T)::canonicalize() { \
- if (x[3] == 0) \
- (*error)(1, "w=0 in canonicalize"); \
- else if (x[3] != 1) { \
- float recip = 1 / x[3]; \
- x[0] *= recip; \
- x[1] *= recip; \
- x[2] *= recip; \
- x[3] = 1; \
- } \
- return *this; \
- } \
- \
- HVec(T) &HVec(T)::operator+=(const HVec(T) &v) { \
- if (x[3] != v(3)) { \
- HVec(T) tv(v); \
- canonicalize(); \
- tv.canonicalize(); \
- x[0] += tv(0); \
- x[1] += tv(1); \
- x[2] += tv(2); \
- } else { \
- x[0] += v(0); \
- x[1] += v(1); \
- x[2] += v(2); \
- } \
- return *this; \
- } \
- \
- HVec(T) &HVec(T)::operator-=(const HVec(T) &v) { \
- if (x[3] != v(3)) { \
- HVec(T) tv(v); \
- canonicalize(); \
- tv.canonicalize(); \
- x[0] -= tv(0); \
- x[1] -= tv(1); \
- x[2] -= tv(2); \
- } else { \
- x[0] -= v(0); \
- x[1] -= v(1); \
- x[2] -= v(2); \
- } \
- return *this; \
- } \
- \
- HVec(T) operator+(const HVec(T) &a, const HVec(T) &b) \
- { \
- if (a(3) != b(3)) { \
- HVec(T) ta = a; \
- HVec(T) tb = b; \
- ta.canonicalize(); \
- tb.canonicalize(); \
- return HVec(T)(ta(0)+tb(0), ta(1)+tb(1), ta(2)+tb(2)); \
- } else \
- return HVec(T)(a(0)+b(0), a(1)+b(1), a(2)+b(2), a(3)); \
- } \
- \
- HVec(T) operator-(const HVec(T) &a, const HVec(T) &b) \
- { \
- if (a(3) != b(3)) { \
- HVec(T) ta = a; \
- HVec(T) tb = b; \
- ta.canonicalize(); \
- tb.canonicalize(); \
- return HVec(T)(ta(0)-tb(0), ta(1)-tb(1), ta(2)-tb(2)); \
- } else \
- return HVec(T)(a(0)-b(0), a(1)-b(1), a(2)-b(2), a(3)); \
- } \
- \
- HVec(T) operator^(const HVec(T) &a, const HVec(T) &b) \
- { \
- HVec(T) ta(a); \
- HVec(T) tb(b); \
- ta.canonicalize(); \
- tb.canonicalize(); \
- return HVec(T)(ta(1) * tb(2) - ta(2) * tb(1), \
- ta(2) * tb(0) - ta(0) * tb(2), \
- ta(0) * tb(1) - ta(1) * tb(0)); \
- } \
- \
- int operator==(const HVec(T) &a, const HVec(T) &b) \
- { \
- if (a(3) != b(3)) { \
- HVec(T) ta(a); \
- HVec(T) tb(b); \
- ta.canonicalize(); \
- tb.canonicalize(); \
- return (ta(0) == tb(0)) && \
- (ta(1) == tb(1)) && \
- (ta(2) == tb(2)); \
- } else \
- return (a(0) == b(0)) && \
- (a(1) == b(1)) && \
- (a(2) == b(2)); \
- } \
- \
- HVec(T)::operator CVec(T)() const { \
- HVec(T) a(*this); \
- a.canonicalize(); \
- return CVec(T)(a(0), a(1), a(2)); \
- } \
- \
- ostream &operator<<(ostream &o, const HVec(T) &v) { \
- return o << "( " << v(0) << ' ' << v(1) << ' ' \
- << v(2) << ' ' << v(3) << " )"; \
- }
-
- HomogenousVectorDeclare(float);
-
- typedef HVec(float) HVector;
-
- #endif /*_HVECTOR_H*/
-