#ifndef TRANSFORMATIONH #define TRANSFORMATIONH #include #include #include "xyz.h" using namespace std; #define K 1 #if !K class transformation { public: //slow start, slow end, fastest in middle. static double f(double x) {return x * x * (3 - 2 * x);} protected: /* Smooth interpolation. Returns begin when frameno == 0, end when frameno == nframes - 1. */ static double interpolate(double begin, double end, unsigned frameno, unsigned nframes) { if (nframes > 0 && frameno >= nframes) { cerr << "transformation::interpolate(" << frameno << ", " << nframes << ")\n"; exit(EXIT_FAILURE); } #if 0 const unsigned nf = nframes - 1; return (begin * (nf - frameno) + end * frameno) / nf; #endif const double x = static_cast(frameno) / (nframes - 1); return begin * f(1 - x) + end * f(x); } public: virtual ~transformation() {} virtual transformation *clone() const = 0; virtual xyz operator()(const xyz& point, unsigned frameno, unsigned nframes) const = 0; }; class scale: public transformation { const xyz begin; const xyz end; public: scale(double d): begin(xyz(d, d, d)), end(xyz(d, d, d)) {} scale(double d1, double d2) : begin(xyz(d1, d1, d1)), end(xyz(d2, d2, d2)) {} scale(const xyz& p): begin(p), end(p) {} scale(const xyz& p1, const xyz& p2): begin(p1), end(p2) {} scale *clone() const {return new scale(*this);} xyz operator()(const xyz& p, unsigned frameno, unsigned nframes) const { return xyz( p.x * interpolate(begin.x, end.x, frameno, nframes), p.y * interpolate(begin.y, end.y, frameno, nframes), p.z * interpolate(begin.z, end.z, frameno, nframes) ); } }; class translate: public transformation { const xyz begin; const xyz end; public: translate(const xyz& p): begin(p), end(p) {} translate(const xyz& p1, const xyz& p2): begin(p1), end(p2) {} translate *clone() const {return new translate(*this);} xyz operator()(const xyz& p, unsigned frameno, unsigned nframes) const { return p + xyz( interpolate(begin.x, end.x, frameno, nframes), interpolate(begin.y, end.y, frameno, nframes), interpolate(begin.z, end.z, frameno, nframes) ); } }; template class axis_rotate: public transformation { const double begin; const double end; public: axis_rotate(double d): begin(d), end(d) {} axis_rotate(double d1, double d2): begin(d1), end(d2) {} axis_rotate *clone() const {return new axis_rotate(*this);} xyz operator()(const xyz& p, unsigned frameno, unsigned nframes) const { xyz point = p; return (point.*AXIS)(interpolate(begin, end, frameno, nframes)); } }; typedef axis_rotate<&xyz::xrot> xrot; typedef axis_rotate<&xyz::yrot> yrot; typedef axis_rotate<&xyz::zrot> zrot; //Rotate the point around the line connecting the direction and viewpoint. class rot: public transformation { const xyz direction; const xyz viewpoint; const double begin; const double end; public: rot(const xyz& initial_direction, const xyz& initial_viewpoint, double d) : direction(initial_direction), viewpoint(initial_viewpoint), begin(d), end(d) {} rot(const xyz& initial_direction, const xyz& initial_viewpoint, double d1, double d2) : direction(initial_direction), viewpoint(initial_viewpoint), begin(d1), end(d2) {} rot *clone() const {return new rot(*this);} xyz operator()(const xyz& p, unsigned frameno, unsigned nframes) const { xyz point = p; return point.rot(direction, viewpoint, interpolate(begin, end, frameno, nframes)); } }; #endif #endif