/*************************************************************************************** ***** CLASS FRAME IMPLEMENTATION ***** **************************************************************************************** ** Author: Peter Stuart ** Date: 3/7/98 ** Description: This class represents a coordinate frame. The frame is made up of three ** orthogonal vectors u, v, w, and origin point o. Methods include finding the ** matrix to trasform coordinates from frame space to cartesian space, changing ** orientation and position in both frame and cartesian coordinates, and the ** standard relational, assignment, and output stream methods. ** ** Note: All of these graphics classes use a right-handed coordinate system. ** ***************************************************************************************/ #include "Frame.hpp" /* Constructor ************ ** Default values for private variables: ** _u: <1.0, 0.0, 0.0> ** _v: <0.0, 1.0, 0.0> ** _w: <0.0, 0.0, 1.0> ** _o: <0.0, 0.0, 0.0> */ Frame::Frame (const Vector& u, const Vector& v, const Vector& w, const Point& o) { _u = u; _v = v; _w = w; _o = o; } // Copy Constructor Frame::Frame (const Frame& fr) { _u = fr._u; _v = fr._v; _w = fr._w; _o = fr._o; } // Destructor Frame::~Frame (void) { ; } // BASIC OPERATIONS /////////////// // Transform Frame using matrix // NOTE: Since the frame's origin is a separate variable, it is necessary to // break the matrix into its rotation and translation parts. The rotation // part is then used on the vectors of the frame, and the translation // part is used on the frame's position. It was done this way so that // the vectors of the frame would stay unit vectors. void Frame::transformFrame (const Matrix4D& mat) { Matrix4D rot, move; Point opt; rot = mat; rot.setElement(3, 0, 0.0); rot.setElement(3, 1, 0.0); rot.setElement(3, 2, 0.0); move = move.identity(); move.setElement(3, 0, mat.getElement(3, 0)); move.setElement(3, 1, mat.getElement(3, 1)); move.setElement(3, 2, mat.getElement(3, 2)); _o = _o*move; _u = (_u*rot).direction(); _v = (_v*rot).direction(); _w = (_w*rot).direction(); } // Translate frame with respect to its own coordinate system void Frame::translateFrame (const double& x, const double& y, const double& z) { Matrix4D move, trans; trans.setElement(0, 0, _u.x()); trans.setElement(0, 1, _v.x()); trans.setElement(0, 2, _w.x()); trans.setElement(1, 0, _u.y()); trans.setElement(1, 1, _v.y()); trans.setElement(1, 2, _w.y()); trans.setElement(2, 0, _u.z()); trans.setElement(2, 1, _v.z()); trans.setElement(2, 2, _w.z()); trans.setElement(3, 3, 1.0); move = translate(x, y, z); move = trans*move*trans.inverse(); _o = _o*move; } // rotate frame with respect to its own coordinate system void Frame::rotateFrame (const double& x, const double& y, const double& z) { Matrix4D trans, rot; trans.setElement(0, 0, _u.x()); trans.setElement(0, 1, _v.x()); trans.setElement(0, 2, _w.x()); trans.setElement(1, 0, _u.y()); trans.setElement(1, 1, _v.y()); trans.setElement(1, 2, _w.y()); trans.setElement(2, 0, _u.z()); trans.setElement(2, 1, _v.z()); trans.setElement(2, 2, _w.z()); trans.setElement(3, 3, 1.0); rot = rotate(x, y, z); rot = trans*rot*trans.inverse(); _u = (_u*rot).direction(); _v = (_v*rot).direction(); _w = (_w*rot).direction(); } // Create frame to cartesian frame coordinate transformation matrix Matrix4D Frame::frameTransform(void) { Matrix4D temp; // returning matrix // set matrix to transform coordinates to the cartesian frame temp.setElement(0, 0, _u.x()); temp.setElement(0, 1, _v.x()); temp.setElement(0, 2, _w.x()); temp.setElement(1, 0, _u.y()); temp.setElement(1, 1, _v.y()); temp.setElement(1, 2, _w.y()); temp.setElement(2, 0, _u.z()); temp.setElement(2, 1, _v.z()); temp.setElement(2, 2, _w.z()); temp.setElement(3, 0, _o.x()); temp.setElement(3, 1, _o.y()); temp.setElement(3, 2, _o.z()); temp.setElement(3, 3, 1.0); return temp; } // Create cartesian frame to frame coordinate transformation matrix Matrix4D Frame::cartTransform(void) { Matrix4D temp; // returning matrix Vector j; // vector from origin to frame position j = zeroPoint - _o; temp.setElement(0, 0, _u.x()); temp.setElement(0, 1, _v.x()); temp.setElement(0, 2, _w.x()); temp.setElement(1, 0, _u.y()); temp.setElement(1, 1, _v.y()); temp.setElement(1, 2, _w.y()); temp.setElement(2, 0, _u.z()); temp.setElement(2, 1, _v.z()); temp.setElement(2, 2, _w.z()); temp.setElement(3, 0, _u.dot(j)); temp.setElement(3, 1, _v.dot(j)); temp.setElement(3, 2, _w.dot(j)); temp.setElement(3, 3, 1.0); return temp; } // ELEMENTARY OPEARTORS ////////////////////////// // Assignment operator Frame& Frame::operator = (const Frame& fr) { if (this == &fr) return (*this); _u = fr._u; _v = fr._v; _w = fr._w; _o = fr._o; return (*this); } // Relational operators int operator == (const Frame& fr1, const Frame& fr2) { if (fr1._u != fr2._u) return FALSE; if (fr1._v != fr2._v) return FALSE; if (fr1._w != fr2._w) return FALSE; if (fr1._o != fr2._o) return FALSE; return TRUE; } int operator != (const Frame& fr1, const Frame& fr2) { if (fr1._u != fr2._u) return TRUE; if (fr1._v != fr2._v) return TRUE; if (fr1._w != fr2._w) return TRUE; if (fr1._o != fr2._o) return TRUE; return FALSE; } // output stream ostream& operator << (ostream& co, const Frame& fr) { co << "\nu: " << fr._u << "\nv: " << fr._v << "\nw: " << fr._w << "\no: " << fr._o; return co; }