blob: c2e8c63a14a5434903f442db387800a4b6df0005 [file] [log] [blame]
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COBALT_MATH_MATRIX3_F_H_
#define COBALT_MATH_MATRIX3_F_H_
#include "base/logging.h"
#include "cobalt/math/point_f.h"
#include "cobalt/math/rect_f.h"
#include "cobalt/math/vector3d_f.h"
namespace cobalt {
namespace math {
class Matrix3F {
public:
~Matrix3F();
static Matrix3F Zeros();
static Matrix3F Ones();
static Matrix3F Identity();
static Matrix3F FromOuterProduct(const Vector3dF& a, const Vector3dF& bt);
static Matrix3F FromArray(const float data[9]);
static Matrix3F FromValues(float m00, float m01, float m02, float m10,
float m11, float m12, float m20, float m21,
float m22);
void SetMatrix(float m00, float m01, float m02, float m10, float m11,
float m12, float m20, float m21, float m22) {
data_[0] = m00;
data_[1] = m01;
data_[2] = m02;
data_[3] = m10;
data_[4] = m11;
data_[5] = m12;
data_[6] = m20;
data_[7] = m21;
data_[8] = m22;
}
bool IsZeros() const;
bool IsIdentity() const;
bool IsEqual(const Matrix3F& rhs) const;
// Element-wise comparison with given precision.
bool IsNear(const Matrix3F& rhs, float precision) const;
// Access data by row (i) and column (j).
float Get(int i, int j) const { return (*this)(i, j); }
void Set(int i, int j, float v) { (*this)(i, j) = v; }
float operator()(int i, int j) const {
return data_[MatrixToArrayCoords(i, j)];
}
float& operator()(int i, int j) { return data_[MatrixToArrayCoords(i, j)]; }
Matrix3F operator*(const Matrix3F& other) const;
// Returns the result of multiplying the given homogeneous 2D point by this
// matrix.
PointF operator*(const PointF& rhs) const;
Vector3dF column(int i) const {
return Vector3dF(data_[MatrixToArrayCoords(0, i)],
data_[MatrixToArrayCoords(1, i)],
data_[MatrixToArrayCoords(2, i)]);
}
void set_column(int i, const Vector3dF& c) {
data_[MatrixToArrayCoords(0, i)] = c.x();
data_[MatrixToArrayCoords(1, i)] = c.y();
data_[MatrixToArrayCoords(2, i)] = c.z();
}
// Returns an inverse of this if the matrix is non-singular, zero (== Zero())
// otherwise.
Matrix3F Inverse() const;
// Value of the determinant of the matrix.
float Determinant() const;
// Trace (sum of diagonal elements) of the matrix.
float Trace() const {
return data_[MatrixToArrayCoords(0, 0)] + data_[MatrixToArrayCoords(1, 1)] +
data_[MatrixToArrayCoords(2, 2)];
}
// Compute eigenvalues and (optionally) normalized eigenvectors of
// a positive defnite matrix *this. Eigenvectors are computed only if
// non-null |eigenvectors| matrix is passed. If it is NULL, the routine
// will not attempt to compute eigenvectors but will still return eigenvalues
// if they can be computed.
// If eigenvalues cannot be computed (the matrix does not meet constraints)
// the 0-vector is returned. Note that to retrieve eigenvalues, the matrix
// only needs to be symmetric while eigenvectors require it to be
// positive-definite. Passing a non-positive definite matrix will result in
// NaNs in vectors which cannot be computed.
// Eigenvectors are placed as column in |eigenvectors| in order corresponding
// to eigenvalues.
Vector3dF SolveEigenproblem(Matrix3F* eigenvectors) const;
// Applies operator*(const PointF&) to each of the 4 points on the rectangle
// and then returns a RectF that is the tightest axis-aligned bounding box
// around those points.
RectF MapRect(const RectF& rect);
private:
Matrix3F(); // Uninitialized default.
static int MatrixToArrayCoords(int i, int j) {
DCHECK(i >= 0 && i < 3);
DCHECK(j >= 0 && j < 3);
return i * 3 + j;
}
float data_[9];
};
inline bool operator==(const Matrix3F& lhs, const Matrix3F& rhs) {
return lhs.IsEqual(rhs);
}
inline std::ostream& operator<<(std::ostream& stream, const Matrix3F& matrix) {
stream << "[";
stream << "[" << matrix(0, 0) << ", " << matrix(0, 1) << ", " << matrix(0, 2)
<< "], ";
stream << "[" << matrix(1, 0) << ", " << matrix(1, 1) << ", " << matrix(1, 2)
<< "], ";
stream << "[" << matrix(2, 0) << ", " << matrix(2, 1) << ", " << matrix(2, 2)
<< "]";
stream << "]";
return stream;
}
} // namespace math
} // namespace cobalt
#endif // COBALT_MATH_MATRIX3_F_H_