From c9e46f986eca3322605b036710b3b1d6742d375b Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Mon, 7 Jul 2014 15:17:45 +1000 Subject: [PATCH] matrix: parameterise on element type --- matrix.cpp | 111 ++++++++++++++++++++++++++++++++--------------------- matrix.hpp | 22 ++++++----- 2 files changed, 80 insertions(+), 53 deletions(-) diff --git a/matrix.cpp b/matrix.cpp index 7f81a9a5..4a168202 100644 --- a/matrix.cpp +++ b/matrix.cpp @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with libgim. If not, see . * - * Copyright 2011-2012 Danny Robson + * Copyright 2011-2014 Danny Robson */ #include "matrix.hpp" @@ -26,8 +26,10 @@ using namespace util; +//----------------------------------------------------------------------------- +template void -matrix::scale (double x, double y, double z) { +matrix::scale (T x, T y, T z) { CHECK_HARD (is_affine ()); values[0][0] *= x; values[1][1] *= y; @@ -35,8 +37,10 @@ matrix::scale (double x, double y, double z) { } +//----------------------------------------------------------------------------- +template void -matrix::translate (double x, double y, double z) { +matrix::translate (T x, T y, T z) { CHECK_HARD (is_affine ()); values[0][3] += x; values[1][3] += y; @@ -44,33 +48,37 @@ matrix::translate (double x, double y, double z) { } -matrix -matrix::inverse (void) const { - return matrix(*this).invert (); +//----------------------------------------------------------------------------- +template +matrix +matrix::inverse (void) const { + return matrix(*this).invert (); } -matrix& -matrix::invert (void) { +//----------------------------------------------------------------------------- +template +matrix& +matrix::invert (void) { CHECK_HARD (is_affine ()); // inv ([ M b ] == [ inv(M) -inv(M).b ] // [ 0 1 ]) [ 0 1 // Invert the 3x3 M - double A = (values[1][1] * values[2][2] - values[1][2] * values[2][1]); - double B = (values[1][2] * values[2][0] - values[1][0] * values[2][2]); - double C = (values[1][0] * values[2][1] - values[1][1] * values[2][0]); + T A = (values[1][1] * values[2][2] - values[1][2] * values[2][1]); + T B = (values[1][2] * values[2][0] - values[1][0] * values[2][2]); + T C = (values[1][0] * values[2][1] - values[1][1] * values[2][0]); - double D = (values[0][2] * values[2][1] - values[0][1] * values[2][2]); - double E = (values[0][0] * values[2][2] - values[0][2] * values[2][0]); - double F = (values[2][0] * values[0][1] - values[0][0] * values[2][1]); + T D = (values[0][2] * values[2][1] - values[0][1] * values[2][2]); + T E = (values[0][0] * values[2][2] - values[0][2] * values[2][0]); + T F = (values[2][0] * values[0][1] - values[0][0] * values[2][1]); - double G = (values[0][1] * values[1][2] - values[0][2] * values[1][1]); - double H = (values[0][2] * values[1][0] - values[0][0] * values[1][2]); - double K = (values[0][0] * values[1][1] - values[0][1] * values[1][0]); + T G = (values[0][1] * values[1][2] - values[0][2] * values[1][1]); + T H = (values[0][2] * values[1][0] - values[0][0] * values[1][2]); + T K = (values[0][0] * values[1][1] - values[0][1] * values[1][0]); - double det = values[0][0] * A + values[0][1] * B + values[0][2] * C; + T det = values[0][0] * A + values[0][1] * B + values[0][2] * C; CHECK_NEQ (det, 0.0); values[0][0] = A / det; @@ -84,9 +92,9 @@ matrix::invert (void) { values[2][2] = K / det; // Multiply the b - double b0 = - values[0][0] * values[0][3] - values[0][1] * values[1][3] - values[0][2] * values[2][3]; - double b1 = - values[1][0] * values[0][3] - values[1][1] * values[1][3] - values[1][2] * values[2][3]; - double b2 = - values[2][0] * values[0][3] - values[2][1] * values[1][3] - values[2][2] * values[2][3]; + T b0 = - values[0][0] * values[0][3] - values[0][1] * values[1][3] - values[0][2] * values[2][3]; + T b1 = - values[1][0] * values[0][3] - values[1][1] * values[1][3] - values[1][2] * values[2][3]; + T b2 = - values[2][0] * values[0][3] - values[2][1] * values[1][3] - values[2][2] * values[2][3]; values[0][3] = b0; values[1][3] = b1; @@ -96,9 +104,11 @@ matrix::invert (void) { } -matrix -matrix::operator* (const matrix &rhs) const { - matrix m; +//----------------------------------------------------------------------------- +template +matrix +matrix::operator* (const matrix &rhs) const { + matrix m; memset (m.values, 0, sizeof (m.values)); for (unsigned i = 0; i < 4; ++i) @@ -110,8 +120,10 @@ matrix::operator* (const matrix &rhs) const { } +//----------------------------------------------------------------------------- +template util::point<3> -matrix::to_local (const util::point<3> &p) const { +matrix::to_local (const util::point<3> &p) const { CHECK_SOFT (is_affine ()); return { p.x * values[0][0] + @@ -126,38 +138,51 @@ matrix::to_local (const util::point<3> &p) const { } +//----------------------------------------------------------------------------- +template util::point<3> -matrix::to_global (const util::point<3> &p) const { +matrix::to_global (const util::point<3> &p) const { return inverse ().to_local (p); } - +//----------------------------------------------------------------------------- +template bool -matrix::is_affine (void) const { - return exactly_equal (values[3][0], 0.0) && - exactly_equal (values[3][1], 0.0) && - exactly_equal (values[3][2], 0.0) && - exactly_equal (values[3][3], 1.0); +matrix::is_affine (void) const { + return exactly_equal (values[3][0], static_cast (0)) && + exactly_equal (values[3][1], static_cast (0)) && + exactly_equal (values[3][2], static_cast (0)) && + exactly_equal (values[3][3], static_cast (1)); } -const matrix -matrix::IDENTITY = { { { 1.0, 0.0, 0.0, 0.0 }, - { 0.0, 1.0, 0.0, 0.0 }, - { 0.0, 0.0, 1.0, 0.0 }, - { 0.0, 0.0, 0.0, 1.0 } } }; +//----------------------------------------------------------------------------- +template +const matrix +matrix::IDENTITY = { { { 1, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 0, 1, 0 }, + { 0, 0, 0, 1 } } }; -const matrix -matrix::ZEROES = { { { 0.0, 0.0, 0.0, 0.0 }, - { 0.0, 0.0, 0.0, 0.0 }, - { 0.0, 0.0, 0.0, 0.0 }, - { 0.0, 0.0, 0.0, 0.0 } } }; +template +const matrix +matrix::ZEROES = { { { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 } } }; +//----------------------------------------------------------------------------- +template struct matrix; +template struct matrix; + + +//----------------------------------------------------------------------------- +template std::ostream& -operator<< (std::ostream &os, const matrix &m) { +operator<< (std::ostream &os, const matrix &m) { os << "{ {" << m.values[0][0] << ", " << m.values[0][1] << ", " << m.values[0][2] << ", " diff --git a/matrix.hpp b/matrix.hpp index f14a79ec..0a5b2eeb 100644 --- a/matrix.hpp +++ b/matrix.hpp @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with libgim. If not, see . * - * Copyright 2011-2012 Danny Robson + * Copyright 2011-2014 Danny Robson */ #ifndef __UTIL_MATRIX_HPP @@ -25,27 +25,29 @@ #include namespace util { + template struct matrix { - double values[4][4]; + T values[4][4]; - void scale (double x, double y, double z); - void translate (double x, double y, double z); + void scale (T x, T y, T z); + void translate (T x, T y, T z); - matrix inverse (void) const; - matrix& invert (void); + matrix inverse (void) const; + matrix& invert (void); - matrix operator* (const matrix&) const; + matrix operator* (const matrix&) const; point<3> to_local (const point<3> &p) const; point<3> to_global (const point<3> &p) const; bool is_affine (void) const; - static const matrix IDENTITY; - static const matrix ZEROES; + static const matrix IDENTITY; + static const matrix ZEROES; }; } -std::ostream& operator<< (std::ostream&, const util::matrix&); +template +std::ostream& operator<< (std::ostream&, const util::matrix&); #endif