/* * Copyright 2007-2008 Ben Boeckel * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ /** * \file sigcore/Matrix.h */ #ifndef SIGCORE_MATRIX #define SIGCORE_MATRIX // Sigcore includes #include "Global.h" // Qt includes #include #include namespace Sigcore { /** * \class Sigcore::Matrix Matrix.h sigcore/Matrix.h * \brief Class for a two dimensional vector. */ template class SIGCORE_EXPORT Matrix { public: /** * Default constructor. */ Matrix(); /** * Constructor. * * \param height The height of the matrix. * \param width The width of the matrix. * \param value The value to set all values to. */ Matrix(const int height, const int width, const T& value = T()); /** * Copy constructor. * * \param rhs The matrix to copy. */ Matrix(const Matrix& rhs); /** * Add a row to the matrix. * * \param value The value to set the row to. */ void addRow(const T& value = T()); /** * Add a column to the matrix. * * \param value The value to set the column to. */ void addColumn(const T& value = T()); /** * Inserts a row into the matrix. * * \param row Where the new row will be placed. * \param value The value to set the row to. */ void insertRow(const int row, const T& value = T()); /** * Inserts a column into the matrix. * * \param column Where the new column will be placed. * \param value The value to set the column to. */ void insertColumn(const int column, const T& value = T()); /** * Removes a row from the matrix. * * \param row The row to remove from the matrix. */ void deleteRow(const int row); /** * Removes a column from the matrix. * * \param column The column to remove from the matrix. */ void deleteColumn(const int column); /** * Clears the matrix. */ void clear(); /** * Resizes the matrix to a new size. Rows and columns are removed from the end to shrink and added to the * end to grow. * * \param newHeight The target height. * \param newWidth The target width. * \param value Value to set any additional rows and columns to. */ void resize(const int newHeight, const int newWidth, const T& value = T()); /** * Get a row from the matrix. * * \param row The row to retrieve. * \return A row of the matrix. */ QVector row(const int row) const; /** * Get a column from the matrix. * * \param column The column to retrieve. * \return A column of the matrix. */ QVector column(const int column) const; /** * Add a masked matrix to the matrix. * * \param top The top-most part of the matrix. * \param left The left-most part of the matrix. * \param mask The mask to add. */ void addMask(const int top, const int left, const Matrix& mask); /** * \return The height of the matrix. */ int height() const; /** * \return The width of the matrix. */ int width() const; /** * Method for accessing values in the matrix. * * \param row The row of the cell. * \param column The column of te cell. * \return The value of the cell in the matrix. */ T& operator()(const int row, const int column); /** * Convenience method. * * \param row The row of the cell. * \param column The column of te cell. * \return The value of the cell in the matrix. */ T operator()(const int row, const int column) const; Matrix& operator=(const Matrix& rhs); bool operator==(const Matrix& rhs) const; bool operator!=(const Matrix& rhs) const; private: QVector< QVector > m_matrix; }; template Matrix::Matrix() { } template Matrix::Matrix(const int height, const int width, const T& value) { resize(height, width, value); } template Matrix::Matrix(const Matrix& rhs) { *this = rhs; } template void Matrix::addRow(const T& value) { insertRow(height(), value); } template void Matrix::addColumn(const T& value) { insertColumn(width(), value); } template void Matrix::insertRow(const int row, const T& value) { Q_ASSERT(0 <= row); Q_ASSERT(row <= height()); if (!height() || !width()) m_matrix.append(QVector(1, value)); else m_matrix.insert(row, QVector(width(), value)); } template void Matrix::insertColumn(const int column, const T& value) { Q_ASSERT(0 <= column); Q_ASSERT(column <= width()); if (!height() || !width()) m_matrix.append(QVector(1, value)); else { for (int i = 0; i < height(); ++i) m_matrix[i].insert(column, value); } } template void Matrix::deleteRow(const int row) { Q_ASSERT(0 <= row); Q_ASSERT(row < height()); if (height() == 1) m_matrix.clear(); else m_matrix.remove(row); } template void Matrix::deleteColumn(const int column) { Q_ASSERT(0 <= column); Q_ASSERT(column < width()); if (width() == 1) m_matrix.clear(); else { for (int i = 0; i < height(); ++i) m_matrix[i].remove(column); } } template void Matrix::clear() { m_matrix.clear(); } template void Matrix::resize(const int newHeight, const int newWidth, const T& value) { while (height() < newHeight) addRow(value); while (newHeight < height()) deleteRow(newHeight); while (width() < newWidth) addColumn(value); while (newWidth < width()) deleteColumn(newWidth); } template QVector Matrix::row(const int row) const { Q_ASSERT(0 <= row); Q_ASSERT(row < height()); return m_matrix.at(row); } template QVector Matrix::column(const int column) const { Q_ASSERT(0 <= column); Q_ASSERT(column < width()); QVector col; foreach (QVector row, m_matrix) col.append(row.at(column)); return col; } template void Matrix::addMask(const int top, const int left, const Matrix& mask) { Q_ASSERT(0 <= top); Q_ASSERT(top < height()); Q_ASSERT(0 <= left); Q_ASSERT(left < width()); Q_ASSERT(0 <= mask.height()); Q_ASSERT(top + mask.height() <= height()); Q_ASSERT(0 <= mask.width()); Q_ASSERT(left + mask.width() <= width()); for (int i = 0; i < mask.height(); ++i) { for (int j = 0; j < mask.width(); ++j) { if (operator()(top + i, left + j) || mask(i, j)) operator()(top + i, left + j) = 1; } } } template int Matrix::height() const { return m_matrix.size(); } template int Matrix::width() const { if (m_matrix.size()) return m_matrix[0].size(); return 0; } template T& Matrix::operator()(const int row, const int column) { Q_ASSERT(row < height()); Q_ASSERT(column < width()); return m_matrix[row][column]; } template T Matrix::operator()(const int row, const int column) const { Q_ASSERT(row < height()); Q_ASSERT(column < width()); return m_matrix.at(row).at(column); } template Matrix& Matrix::operator=(const Matrix& rhs) { if (this == &rhs) return *this; resize(rhs.height(), rhs.width()); for (int i = 0; i < height(); ++i) { for (int j = 0; j < width(); ++j) m_matrix[i][j] = rhs.m_matrix[i][j]; } return *this; } template bool Matrix::operator==(const Matrix& rhs) const { if (this == &rhs) return true; return m_matrix == rhs.m_matrix; } template bool Matrix::operator!=(const Matrix& rhs) const { return !(*this == rhs); } } #endif