Расширение MatrixBase
В этом разделе мы увидим, как добавить пользовательские методы к MatrixBase. Поскольку все выражения и типы матриц наследуют MatrixBase, добавление метода к MatrixBase делает его немедленно доступным для всех выражений! Типичный случай использования, например, сделать Eigen совместимым с другим API.
Вы наверняка знаете, что в C++ невозможно добавить методы к существующему классу. Так как же это возможно? Здесь трюк заключается в том, чтобы включить в объявление MatrixBase файл, определенный препроцессорным токеном EIGEN_MATRIXBASE_PLUGIN:.
class MatrixBase { // ... #ifdef EIGEN_MATRIXBASE_PLUGIN #include EIGEN_MATRIXBASE_PLUGIN #endif };
Таким образом, чтобы расширить MatrixBase своими методами, вам просто нужно создать файл с объявлением вашего метода и определить EIGEN_MATRIXBASE_PLUGIN перед включением любого заголовочного файла Eigen.
Вы можете расширить многие другие классы, используемые в Eigen, определив аналогичные препроцессорные символы. Например, определите EIGEN_ARRAYBASE_PLUGIN, если вы хотите расширить класс ArrayBase. Полный список классов, которые можно расширить таким образом, и соответствующие препроцессорные символы можно найти на нашей странице Директивы препроцессора.
Вот пример файла расширения для добавления методов к MatrixBase:
MatrixBaseAddons.h
inline Scalar at(uint i, uint j) const { return this->operator()(i,j); } inline Scalar& at(uint i, uint j) { return this->operator()(i,j); } inline Scalar at(uint i) const { return this->operator[](i); } inline Scalar& at(uint i) { return this->operator[](i); } inline RealScalar squaredLength() const { return squaredNorm(); } inline RealScalar length() const { return norm(); } inline RealScalar invLength(void) const { return fast_inv_sqrt(squaredNorm()); } template<typename OtherDerived> inline Scalar squaredDistanceTo(const MatrixBase<OtherDerived>& other) const { return (derived() - other.derived()).squaredNorm(); } template<typename OtherDerived> inline RealScalar distanceTo(const MatrixBase<OtherDerived>& other) const { return internal::sqrt(derived().squaredDistanceTo(other)); } inline void scaleTo(RealScalar l) { RealScalar vl = norm(); if (vl>1e-9) derived() *= (l/vl); } inline Transpose<Derived> transposed() {return this->transpose();} inline const Transpose<Derived> transposed() const {return this->transpose();} inline uint minComponentId(void) const { int i; this->minCoeff(&i); return i; } inline uint maxComponentId(void) const { int i; this->maxCoeff(&i); return i; } template<typename OtherDerived> void makeFloor(const MatrixBase<OtherDerived>& other) { derived() = derived().cwiseMin(other.derived()); } template<typename OtherDerived> void makeCeil(const MatrixBase<OtherDerived>& other) { derived() = derived().cwiseMax(other.derived()); } const CwiseBinaryOp<internal::scalar_sum_op<Scalar>, const Derived, const ConstantReturnType> operator+(const Scalar& scalar) const { return CwiseBinaryOp<internal::scalar_sum_op<Scalar>, const Derived, const ConstantReturnType>(derived(), Constant(rows(),cols(),scalar)); } friend const CwiseBinaryOp<internal::scalar_sum_op<Scalar>, const ConstantReturnType, Derived> operator+(const Scalar& scalar, const MatrixBase<Derived>& mat) { return CwiseBinaryOp<internal::scalar_sum_op<Scalar>, const ConstantReturnType, Derived>(Constant(rows(),cols(),scalar), mat.derived()); }
Затем можно ввести следующее объявление в файл config.h или любой другой предварительный заголовочный файл своего проекта:
#define EIGEN_MATRIXBASE_PLUGIN "MatrixBaseAddons.h"
© Eigen.
Licensed under the MPL2 License.
https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html