/** * Generic 3d transformation. \c m must be a 3x3 matrix. */ RVector RVector::transform(const RMatrix& m) { RMatrix input; input = RMatrix::create3x1(x, y, z); RMatrix res = m * input; x = res.get(0, 0); y = res.get(1, 0); z = res.get(2, 0); return *this; }
RMatrix RMatrix::operator *(double s) const { RMatrix ret = *this; for (int rc = 0; rc < ret.getRows(); ++rc) { for (int cc = 0; cc < ret.getCols(); ++cc) { ret.set(rc, cc, ret.get(rc, cc) * s); } } return ret; }
/** * Stream operator for QDebug */ QDebug operator<<(QDebug dbg, const RMatrix& m) { dbg.nospace() << "RMatrix("; for (int rc = 0; rc < m.getRows(); ++rc) { for (int cc = 0; cc < m.getCols(); ++cc) { dbg.nospace() << m.get(rc, cc); if (rc!=m.getRows()-1 || cc!=m.getCols()-1) { dbg.nospace() << ","; } } } dbg.nospace() << ")"; return dbg; }
/** * \return \f$A \cdot W\f$ * This matrix is not affected. */ RMatrix RMatrix::multiplyWith(const RMatrix& w) const { RMatrix r(rows, w.cols); for (int cc = 0; cc < r.cols; ++cc) { for (int rc = 0; rc < r.rows; ++rc) { for (int i = 0; i < cols; ++i) { r.set(rc, cc, r.get(rc, cc) + get(rc, i) * w.get(i, cc)); } } } return r; }
/** * Appends matrix \c v to the right side of this matrix * and returns the new matrix. This matrix is not affected. * * \param v the matrix to append to this matrix * */ RMatrix RMatrix::getAppended(const RMatrix& v) const { if (rows != v.rows) { return RMatrix(); } RMatrix r(rows, cols + v.cols); for (int rc = 0; rc < rows; ++rc) { for (int cc = 0; cc < cols; ++cc) { r.set(rc, cc, get(rc, cc)); } for (int cc = cols; cc < cols + v.cols; ++cc) { r.set(rc, cc, v.get(rc, cc - cols)); } } return r; }
/** * Changes this vector into its isometric projection. * \todo refactor */ RVector RVector::isoProject(RS::IsoProjectionType type, bool trueScale) { static RMatrix iso = RMatrix::create3x3( sqrt(3.0), 0.0, -sqrt(3.0), 1.0, 2.0, 1.0, sqrt(2.0), -sqrt(2.0), sqrt(2.0) ) * (1.0 / sqrt(6.0)); RMatrix input; switch (type) { case RS::IsoRight: input = RMatrix::create3x1(x, y, -z); break; case RS::IsoRightBack: input = RMatrix::create3x1(-x, y, z); break; case RS::IsoTop: input = RMatrix::create3x1(y, z, -x); break; case RS::IsoBottom: input = RMatrix::create3x1(y, z, x); break; case RS::IsoLeft: input = RMatrix::create3x1(z, y, -x); break; case RS::IsoLeftBack: input = RMatrix::create3x1(z, y, x); break; } RMatrix res = iso * input; x = res.get(0, 0); y = res.get(1, 0); z = 0.0; if (trueScale) { double f = 1.0 / cos(RMath::deg2rad(35.0 + 16.0/60.0)); x *= f; y *= f; } return *this; }
/** * \return The inverse matrix of this matrix \f$A^{-1}\f$ or * an empty matrix if this matrix is not invertible. */ RMatrix RMatrix::getInverse() const { if (cols != rows) { return RMatrix(); } RMatrix a = getAppended(createIdentity(cols)); if (!a.rref()) { return RMatrix(); } RMatrix ret(rows, cols); for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { ret.set(r, c, a.get(r, c + cols)); } } return ret; }