Add generic affine transform class & unify transform interfaces

This commit is contained in:
Nikita Lisitsa 2020-09-29 19:15:53 +03:00
parent 325f90d7c8
commit 2b57e3e696
6 changed files with 522 additions and 231 deletions

View file

@ -0,0 +1,147 @@
#pragma once
#include <psemek/geom/vector.hpp>
#include <psemek/geom/point.hpp>
#include <psemek/geom/matrix.hpp>
#include <psemek/geom/gauss.hpp>
namespace psemek::geom
{
// Affine transformation from M-dimensional to N-dimensional affine space
template <typename T, std::size_t N, std::size_t M>
struct affine_transform
{
matrix<T, N, M + 1> m;
static affine_transform zero();
affine_transform();
affine_transform(matrix<T, N, M + 1> const & matrix);
affine_transform(matrix<T, N, M> const & linear, vector<T, N> const & translation);
affine_transform(affine_transform const &) = default;
matrix<T, N, M + 1> affine_matrix() const;
matrix<T, N, M> linear_matrix() const;
vector<T, N> translation_vector() const;
matrix<T, N + 1, M + 1> homogeneous_matrix() const;
vector<T, N> operator()(vector<T, M> const & v) const;
point<T, N> operator()(point<T, M> const & p) const;
};
template <typename T, std::size_t N, std::size_t M>
affine_transform<T, N, M> affine_transform<T, N, M>::zero()
{
return affine_transform<T, N, M>{matrix<T, N, M + 1>::zero()};
}
template <typename T, std::size_t N, std::size_t M>
affine_transform<T, N, M>::affine_transform()
: m{m.zero()}
{
for (std::size_t i = 0; i < std::min(N, M); ++i)
m[i][i] = T{1};
}
template <typename T, std::size_t N, std::size_t M>
affine_transform<T, N, M>::affine_transform(matrix<T, N, M + 1> const & matrix)
: m{matrix}
{}
template <typename T, std::size_t N, std::size_t M>
affine_transform<T, N, M>::affine_transform(matrix<T, N, M> const & linear, vector<T, N> const & translation)
{
for (std::size_t r = 0; r < N; ++r)
{
for (std::size_t c = 0; c < M; ++c)
m[r][c] = linear[r][c];
m[r][M] = translation[r];
}
}
template <typename T, std::size_t N, std::size_t M>
matrix<T, N, M + 1> affine_transform<T, N, M>::affine_matrix() const
{
return m;
}
template <typename T, std::size_t N, std::size_t M>
matrix<T, N, M> affine_transform<T, N, M>::linear_matrix() const
{
matrix<T, N, M> result;
for (std::size_t r = 0; r < N; ++r)
{
for (std::size_t c = 0; c < M; ++c)
result[r][c] = m[r][c];
}
return result;
}
template <typename T, std::size_t N, std::size_t M>
vector<T, N> affine_transform<T, N, M>::translation_vector() const
{
vector<T, N> result;
for (std::size_t r = 0; r < N; ++r)
result[r] = m[r][M];
return result;
}
template <typename T, std::size_t N, std::size_t M>
matrix<T, N + 1, M + 1> affine_transform<T, N, M>::homogeneous_matrix() const
{
matrix<T, N + 1, M + 1> result;
for (std::size_t r = 0; r < N; ++r)
{
for (std::size_t c = 0; c <= M; ++c)
result[r][c] = m[r][c];
}
for (std::size_t c = 0; c < M; ++c)
result[N][c] = T{0};
result[N][M] = T{1};
return result;
}
template <typename T, std::size_t N, std::size_t M>
vector<T, N> affine_transform<T, N, M>::operator()(vector<T, M> const & v) const
{
vector<T, N> result = vector<T, N>::zero();
for (std::size_t r = 0; r < N; ++r)
{
for (std::size_t c = 0; c < M; ++c)
result[r] += m[r][c] * v[c];
}
return result;
}
template <typename T, std::size_t N, std::size_t M>
point<T, N> affine_transform<T, N, M>::operator()(point<T, M> const & p) const
{
point<T, N> result = point<T, N>::zero();
for (std::size_t r = 0; r < N; ++r)
{
for (std::size_t c = 0; c < M; ++c)
result[r] += m[r][c] * p[c];
result[r] += m[r][M];
}
return result;
}
template <typename T, std::size_t N, std::size_t M, std::size_t K>
affine_transform<T, N, K> operator * (affine_transform<T, N, M> const & t1, affine_transform<T, M, K> const & t2)
{
auto const t1_lin = t1.linear_matrix();
return {t1_lin * t2.linear_matrix(), t1_lin * t2.translation_vector() + t1.translation_vector()};
}
template <typename T, std::size_t N>
std::optional<affine_transform<T, N, N>> inverse(affine_transform<T, N, N> const & t)
{
auto lin_inv = inverse(t.linear_matrix());
if (!lin_inv)
return std::nullopt;
return affine_transform<T, N, N>{lin_inv, - lin_inv * t.translation()};
}
}

View file

@ -1,59 +1,108 @@
#pragma once
#include <psemek/geom/vector.hpp>
#include <psemek/geom/point.hpp>
#include <psemek/geom/matrix.hpp>
#include <psemek/geom/affine_transform.hpp>
#include <psemek/util/assert.hpp>
namespace psemek::geom
{
template <typename T, std::size_t D>
template <typename T, std::size_t N>
struct swap
{
using vector_type = geom::vector<T, D>;
using point_type = geom::point<T, D>;
using matrix_type = geom::matrix<T, D, D>;
std::size_t i, j;
swap(std::size_t i, std::size_t j);
swap(swap const &) = default;
vector_type operator()(vector_type v) const;
matrix<T, N, N + 1> affine_matrix() const;
matrix<T, N, N> linear_matrix() const;
vector<T, N> translation_vector() const;
matrix<T, N + 1, N + 1> homogeneous_matrix() const;
matrix_type matrix() const;
affine_transform<T, N, N> transform() const;
swap inverse() const;
vector<T, N> operator()(vector<T, N> v) const;
point<T, N> operator()(point<T, N> p) const;
private:
std::size_t i_, j_;
template <typename Matrix>
void fill_matrix(Matrix & m) const;
};
template <typename T, std::size_t D>
swap<T, D>::swap(std::size_t i, std::size_t j)
: i_(i)
, j_(j)
{}
template <typename T, std::size_t D>
vector<T, D> swap<T, D>::operator()(vector_type v) const
template <typename T, std::size_t N>
swap<T, N>::swap(std::size_t i, std::size_t j)
: i{i}
, j{j}
{
std::swap(v[i_], v[j_]);
assert(i < N);
assert(j < N);
}
template <typename T, std::size_t N>
vector<T, N> swap<T, N>::operator()(vector<T, N> v) const
{
std::swap(v[i], v[j]);
return v;
}
template <typename T, std::size_t D>
matrix<T, D, D> swap<T, D>::matrix() const
template <typename T, std::size_t N>
point<T, N> swap<T, N>::operator()(point<T, N> p) const
{
matrix_type m = matrix_type::identity();
m[i_][i_] = 0;
m[j_][j_] = 0;
m[i_][j_] = 1;
m[j_][i_] = 1;
return m;
std::swap(p[i], p[j]);
return p;
}
template <typename T, std::size_t D>
swap<T, D> swap<T, D>::inverse() const
template <typename T, std::size_t N>
matrix<T, N, N + 1> swap<T, N>::affine_matrix() const
{
return *this;
auto result = matrix<T, N, N + 1>::identity();
fill_matrix(result);
return result;
}
template <typename T, std::size_t N>
matrix<T, N, N> swap<T, N>::linear_matrix() const
{
auto result = matrix<T, N, N>::identity();
fill_matrix(result);
return result;
}
template <typename T, std::size_t N>
vector<T, N> swap<T, N>::translation_vector() const
{
return vector<T, N>::zero();
}
template <typename T, std::size_t N>
matrix<T, N + 1, N + 1> swap<T, N>::homogeneous_matrix() const
{
auto result = matrix<T, N + 1, N + 1>::identity();
fill_matrix(result);
return result;
}
template <typename T, std::size_t N>
affine_transform<T, N, N> swap<T, N>::transform() const
{
return {affine_matrix()};
}
template <typename T, std::size_t N>
template <typename Matrix>
void swap<T, N>::fill_matrix(Matrix & m) const
{
m[i][i] = T{0};
m[j][j] = T{0};
m[i][j] = T{1};
m[j][i] = T{1};
}
template <typename T, std::size_t N>
swap<T, N> inverse(swap<T, N> const & s)
{
return s;
}
}

View file

@ -1,168 +1,224 @@
#pragma once
#include <psemek/geom/vector.hpp>
#include <psemek/geom/point.hpp>
#include <psemek/geom/matrix.hpp>
#include <psemek/geom/homogeneous.hpp>
#include <psemek/geom/affine_transform.hpp>
#include <psemek/util/assert.hpp>
namespace psemek::geom
{
// Rotation in oriented plane (i,j)
template <typename T, std::size_t D>
template <typename T, std::size_t N>
struct plane_rotation
{
using scalar_type = T;
using vector_type = geom::vector<T, D>;
using point_type = geom::point<T, D>;
using matrix_type = geom::matrix<T, D, D>;
std::size_t i, j;
T angle;
plane_rotation(std::size_t i, std::size_t j, T angle = T(0));
plane_rotation();
plane_rotation(std::size_t i, std::size_t j, T angle);
plane_rotation(plane_rotation const &) = default;
scalar_type angle() const;
scalar_type angle(scalar_type a);
matrix<T, N, N + 1> affine_matrix() const;
matrix<T, N, N> linear_matrix() const;
vector<T, N> translation_vector() const;
matrix<T, N + 1, N + 1> homogeneous_matrix() const;
vector_type operator()(vector_type v) const;
affine_transform<T, N, N> transform() const;
matrix_type matrix() const;
plane_rotation inverse() const;
vector<T, N> operator()(vector<T, N> const & v) const;
point<T, N> operator()(point<T, N> const & p) const;
private:
std::size_t const i_;
std::size_t const j_;
T angle_;
template <typename Matrix>
void fill_matrix(Matrix & m) const;
};
// 3D-rotation around an axis
// 3N-rotation around an axis
template <typename T>
struct axis_rotation
{
using scalar_type = T;
using vector_type = geom::vector<T, 3>;
using point_type = geom::point<T, 3>;
using matrix_type = geom::matrix<T, 3, 3>;
vector<T, 3> axis;
T angle;
axis_rotation();
axis_rotation(vector_type axis, scalar_type angle);
axis_rotation(vector<T, 3> const & axis, T angle);
axis_rotation(axis_rotation const &) = default;
vector_type axis() const;
vector_type axis(vector_type a);
matrix<T, 3, 4> affine_matrix() const;
matrix<T, 3, 3> linear_matrix() const;
vector<T, 3> translation_vector() const;
matrix<T, 4, 4> homogeneous_matrix() const;
scalar_type angle() const;
scalar_type angle(scalar_type a);
affine_transform<T, 3, 3> transform() const;
vector_type operator()(vector_type v) const;
matrix_type matrix() const;
axis_rotation inverse() const;
vector<T, 3> operator()(vector<T, 3> const & v) const;
point<T, 3> operator()(point<T, 3> const & p) const;
private:
vector_type axis_;
scalar_type angle_;
template <typename Matrix>
void fill_matrix(Matrix & m) const;
};
template <typename T, std::size_t D>
plane_rotation<T, D>::plane_rotation(std::size_t i, std::size_t j, T angle)
: i_(i), j_(j), angle_(angle)
{}
template <typename T, std::size_t D>
T plane_rotation<T, D>::angle() const
template <typename T, std::size_t N>
plane_rotation<T, N>::plane_rotation()
: i{0}
, j{1}
, angle{0}
{
return angle_;
assert(i < N);
assert(j < N);
}
template <typename T, std::size_t D>
T plane_rotation<T, D>::angle(T a)
template <typename T, std::size_t N>
plane_rotation<T, N>::plane_rotation(std::size_t i, std::size_t j, T angle)
: i{i}
, j{j}
, angle{angle}
{
T t = angle_;
angle_ = a;
return t;
assert(i < N);
assert(j < N);
}
template <typename T, std::size_t D>
vector<T, D> plane_rotation<T, D>::operator()(vector_type v) const
template <typename T, std::size_t N>
matrix<T, N, N + 1> plane_rotation<T, N>::affine_matrix() const
{
T vi = v[i_] * std::cos(angle_) - v[j_] * std::sin(angle_);
T vj = v[i_] * std::sin(angle_) + v[j_] * std::cos(angle_);
v[i_] = vi;
v[j_] = vj;
return v;
auto result = matrix<T, N, N + 1>::identity();
fill_matrix(result);
return result;
}
template <typename T, std::size_t D>
matrix<T, D, D> plane_rotation<T, D>::matrix() const
template <typename T, std::size_t N>
matrix<T, N, N> plane_rotation<T, N>::linear_matrix() const
{
matrix_type m = matrix_type::identity();
m[i_][i_] = std::cos(angle_);
m[i_][j_] = -std::sin(angle_);
m[j_][i_] = std::sin(angle_);
m[j_][j_] = std::cos(angle_);
return m;
auto result = matrix<T, N, N>::identity();
fill_matrix(result);
return result;
}
template <typename T, std::size_t D>
plane_rotation<T, D> plane_rotation<T, D>::inverse() const
template <typename T, std::size_t N>
vector<T, N> plane_rotation<T, N>::translation_vector() const
{
return {i_, j_, -angle_};
return vector<T, N>::zero();
}
template <typename T, std::size_t N>
matrix<T, N + 1, N + 1> plane_rotation<T, N>::homogeneous_matrix() const
{
auto result = matrix<T, N + 1, N + 1>::identity();
fill_matrix(result);
return result;
}
template <typename T, std::size_t N>
affine_transform<T, N, N> plane_rotation<T, N>::transform() const
{
return {affine_matrix()};
}
template <typename T, std::size_t N>
vector<T, N> plane_rotation<T, N>::operator()(vector<T, N> const & v) const
{
auto result = v;
result[i] = v[i] * std::cos(angle) - v[j] * std::sin(angle);
result[j] = v[i] * std::sin(angle) + v[j] * std::cos(angle);
return result;
}
template <typename T, std::size_t N>
point<T, N> plane_rotation<T, N>::operator()(point<T, N> const & p) const
{
auto result = p;
result[i] = p[i] * std::cos(angle) - p[j] * std::sin(angle);
result[j] = p[i] * std::sin(angle) + p[j] * std::cos(angle);
return result;
}
template <typename T, std::size_t N>
template <typename Matrix>
void plane_rotation<T, N>::fill_matrix(Matrix & m) const
{
m[i][i] = std::cos(angle);
m[i][j] = -std::sin(angle);
m[j][i] = std::sin(angle);
m[j][j] = std::cos(angle);
}
template <typename T, std::size_t N>
plane_rotation<T, N> inverse(plane_rotation<T, N> const & r)
{
return {r.j, r.i, r.angle};
}
template <typename T>
axis_rotation<T>::axis_rotation()
: axis_rotation(vector_type{T(0), T(0), T(1)}, T(0))
: axis{T{0}, T{0}, T{1}}
, angle{T{0}}
{}
template <typename T>
axis_rotation<T>::axis_rotation(vector_type axis, scalar_type angle)
: axis_(axis)
, angle_(angle)
axis_rotation<T>::axis_rotation(vector<T, 3> const & axis, T angle)
: axis{axis}
, angle{angle}
{}
template <typename T>
vector<T, 3> axis_rotation<T>::axis() const
matrix<T, 3, 4> axis_rotation<T>::affine_matrix() const
{
return axis_;
auto result = matrix<T, 3, 4>::identity();
fill_matrix(result);
return result;
}
template <typename T>
vector<T, 3> axis_rotation<T>::axis(vector_type a)
matrix<T, 3, 3> axis_rotation<T>::linear_matrix() const
{
auto t = axis_;
axis_ = a;
return t;
auto result = matrix<T, 3, 3>::identity();
fill_matrix(result);
return result;
}
template <typename T>
T axis_rotation<T>::angle() const
vector<T, 3> axis_rotation<T>::translation_vector() const
{
return angle_;
return vector<T, 3>::zero();
}
template <typename T>
T axis_rotation<T>::angle(scalar_type a)
matrix<T, 4, 4> axis_rotation<T>::homogeneous_matrix() const
{
auto t = angle_;
angle_ = a;
return t;
auto result = matrix<T, 4, 4>::identity();
fill_matrix(result);
return result;
}
template <typename T>
vector<T, 3> axis_rotation<T>::operator()(vector_type v) const
affine_transform<T, 3, 3> axis_rotation<T>::transform() const
{
return matrix() * v;
return {affine_matrix()};
}
template <typename T>
matrix<T, 3, 3> axis_rotation<T>::matrix() const
vector<T, 3> axis_rotation<T>::operator()(vector<T, 3> const & v) const
{
matrix_type m = matrix_type::identity();
T c = std::cos(angle_);
T s = std::sin(angle_);
T x = axis_[0];
T y = axis_[1];
T z = axis_[2];
return linear_matrix() * v;
}
template <typename T>
point<T, 3> axis_rotation<T>::operator()(point<T, 3> const & p) const
{
auto const o = geom::point<T, 3>::zero();
return linear_matrix() * (p - o) + o;
}
template <typename T>
template <typename Matrix>
void axis_rotation<T>::fill_matrix(Matrix & m) const
{
T const c = std::cos(angle);
T const s = std::sin(angle);
T const x = axis[0];
T const y = axis[1];
T const z = axis[2];
m[0][0] = c + x * x * (1 - c);
m[0][1] = x * y * (1 - c) - z * s;
m[0][2] = x * z * (1 - c) + y * s;
@ -172,13 +228,12 @@ namespace psemek::geom
m[2][0] = z * x * (1 - c) - y * s;
m[2][1] = z * y * (1 - c) + x * s;
m[2][2] = c + z * z * (1 - c);
return m;
}
template <typename T>
axis_rotation<T> axis_rotation<T>::inverse() const
axis_rotation<T> inverse(axis_rotation<T> const & r)
{
return {axis_, -angle_};
return {r.axis, -r.angle};
}
}

View file

@ -1,93 +1,125 @@
#pragma once
#include <psemek/geom/vector.hpp>
#include <psemek/geom/point.hpp>
#include <psemek/geom/matrix.hpp>
#include <psemek/geom/affine_transform.hpp>
namespace psemek::geom
{
template <typename T, std::size_t D>
template <typename T, std::size_t N>
struct scale
{
using vector_type = geom::vector<T, D>;
using point_type = geom::point<T, D>;
using matrix_type = geom::matrix<T, D, D>;
vector<T, N> s;
scale();
scale(T v);
scale(vector_type v);
scale(T s);
scale(vector<T, N> const & s);
scale(scale const &) = default;
vector_type vector() const;
vector_type vector(vector_type v);
matrix<T, N, N + 1> affine_matrix() const;
matrix<T, N, N> linear_matrix() const;
vector<T, N> translation_vector() const;
matrix<T, N + 1, N + 1> homogeneous_matrix() const;
vector_type operator()(vector_type v) const;
affine_transform<T, N, N> transform() const;
matrix_type matrix() const;
scale inverse() const;
vector<T, N> operator()(vector<T, N> v) const;
point<T, N> operator()(point<T, N> p) const;
private:
vector_type v_;
template <typename Matrix>
void fill_matrix(Matrix & m) const;
};
template <typename T, std::size_t D>
scale<T, D>::scale()
template <typename T, std::size_t N>
scale<T, N>::scale()
{
for (std::size_t i = 0; i < D; ++i)
v_[i] = T(1);
for (std::size_t i = 0; i < N; ++i)
s[i] = T{1};
}
template <typename T, std::size_t D>
scale<T, D>::scale(T v)
template <typename T, std::size_t N>
scale<T, N>::scale(T s)
{
for (std::size_t i = 0; i < D; ++i)
v_[i] = v;
for (std::size_t i = 0; i < N; ++i)
this->s[i] = s;
}
template <typename T, std::size_t D>
scale<T, D>::scale(vector_type v)
: v_(v)
template <typename T, std::size_t N>
scale<T, N>::scale(vector<T, N> const & s)
: s{s}
{}
template <typename T, std::size_t D>
vector<T, D> scale<T, D>::vector() const
template <typename T, std::size_t N>
matrix<T, N, N + 1> scale<T, N>::affine_matrix() const
{
return v_;
auto result = matrix<T, N, N + 1>::zero();
fill_matrix(result);
return result;
}
template <typename T, std::size_t D>
vector<T, D> scale<T, D>::vector(vector_type v)
template <typename T, std::size_t N>
matrix<T, N, N> scale<T, N>::linear_matrix() const
{
auto t = v_;
v_ = v;
return t;
auto result = matrix<T, N, N>::zero();
fill_matrix(result);
return result;
}
template <typename T, std::size_t D>
vector<T, D> scale<T, D>::operator()(vector_type v) const
template <typename T, std::size_t N>
vector<T, N> scale<T, N>::translation_vector() const
{
for (std::size_t i = 0; i < D; ++i)
v[i] *= v_[i];
return vector<T, N>::zero();
}
template <typename T, std::size_t N>
matrix<T, N + 1, N + 1> scale<T, N>::homogeneous_matrix() const
{
auto result = matrix<T, N + 1, N + 1>::zero();
fill_matrix(result);
return result;
}
template <typename T, std::size_t N>
affine_transform<T, N, N> scale<T, N>::transform() const
{
return {affine_matrix()};
}
template <typename T, std::size_t N>
vector<T, N> scale<T, N>::operator()(vector<T, N> v) const
{
for (std::size_t i = 0; i < N; ++i)
v[i] *= s[i];
return v;
}
template <typename T, std::size_t D>
matrix<T, D, D> scale<T, D>::matrix() const
template <typename T, std::size_t N>
point<T, N> scale<T, N>::operator()(point<T, N> p) const
{
matrix_type m = matrix_type::identity();
for (std::size_t i = 0; i < D; ++i)
m[i][i] = v_[i];
return m;
for (std::size_t i = 0; i < N; ++i)
p[i] *= s[i];
return p;
}
template <typename T, std::size_t D>
scale<T, D> scale<T, D>::inverse() const
template <typename T, std::size_t N>
template <typename Matrix>
void scale<T, N>::fill_matrix(Matrix & m) const
{
vector_type v;
for (std::size_t i = 0; i < D; ++i)
v[i] = T(1) / v_[i];
return {v};
for (std::size_t i = 0; i < N; ++i)
m[i][i] = s[i];
}
template <typename T, std::size_t N>
std::optional<scale<T, N>> inverse(scale<T, N> const & s)
{
vector<T, N> result;
for (std::size_t i = 0; i < N; ++i)
{
if (s.s[i] == T{0})
return std::nullopt;
result[i] = T{1} / s.s[i];
}
return scale<T, N>{result};
}
}

View file

@ -1,85 +1,92 @@
#pragma once
#include <psemek/geom/vector.hpp>
#include <psemek/geom/point.hpp>
#include <psemek/geom/matrix.hpp>
#include <psemek/geom/affine_transform.hpp>
namespace psemek::geom
{
template <typename T, std::size_t D>
template <typename T, std::size_t N>
struct translation
{
using vector_type = geom::vector<T, D>;
using point_type = geom::point<T, D>;
using homogeneous_matrix_type = geom::matrix<T, D + 1, D + 1>;
vector<T, N> v;
translation();
translation(vector_type v);
translation(vector<T, N> const & v);
translation(translation const &) = default;
vector_type vector() const;
vector_type vector(vector_type v);
matrix<T, N, N + 1> affine_matrix() const;
matrix<T, N, N> linear_matrix() const;
vector<T, N> translation_vector() const;
matrix<T, N + 1, N + 1> homogeneous_matrix() const;
vector_type operator()(vector_type v) const;
point_type operator()(point_type p) const;
affine_transform<T, N, N> transform() const;
homogeneous_matrix_type homogeneous_matrix() const;
translation inverse() const;
private:
vector_type v_;
vector<T, N> operator()(vector<T, N> const & v) const;
point<T, N> operator()(point<T, N> const & p) const;
};
template <typename T, std::size_t D>
translation<T, D>::translation()
: translation(vector_type::zero())
template <typename T, std::size_t N>
translation<T, N>::translation()
: v{vector<T, N>::zero()}
{}
template <typename T, std::size_t D>
translation<T, D>::translation(vector_type v)
: v_(v)
template <typename T, std::size_t N>
translation<T, N>::translation(vector<T, N> const & v)
: v{v}
{}
template <typename T, std::size_t D>
vector<T, D> translation<T, D>::vector() const
template <typename T, std::size_t N>
matrix<T, N, N + 1> translation<T, N>::affine_matrix() const
{
return v_;
auto result = matrix<T, N, N + 1>::identity();
for (std::size_t i = 0; i < N; ++i)
result[i][N] = v[i];
return result;
}
template <typename T, std::size_t D>
vector<T, D> translation<T, D>::vector(vector_type v)
template <typename T, std::size_t N>
matrix<T, N, N> translation<T, N>::linear_matrix() const
{
auto t = v_;
v_ = v;
return t;
return matrix<T, N, N>::identity();
}
template <typename T, std::size_t D>
vector<T, D> translation<T, D>::operator()(vector_type v) const
template <typename T, std::size_t N>
vector<T, N> translation<T, N>::translation_vector() const
{
return v;
}
template <typename T, std::size_t D>
point<T, D> translation<T, D>::operator()(point_type p) const
template <typename T, std::size_t N>
matrix<T, N + 1, N + 1> translation<T, N>::homogeneous_matrix() const
{
return p + v_;
auto result = matrix<T, N + 1, N + 1>::identity();
for (std::size_t i = 0; i < N; ++i)
result[i][N] = v[i];
return result;
}
template <typename T, std::size_t D>
matrix<T, D + 1, D + 1> translation<T, D>::homogeneous_matrix() const
template <typename T, std::size_t N>
affine_transform<T, N, N> translation<T, N>::transform() const
{
homogeneous_matrix_type m = homogeneous_matrix_type::identity();
for (std::size_t i = 0; i < D; ++i)
m[i][D] = v_[i];
return m;
return {affine_matrix()};
}
template <typename T, std::size_t D>
translation<T, D> translation<T, D>::inverse() const
template <typename T, std::size_t N>
vector<T, N> translation<T, N>::operator()(vector<T, N> const & v) const
{
return {-v_};
return v;
}
template <typename T, std::size_t N>
point<T, N> translation<T, N>::operator()(point<T, N> const & p) const
{
return p + v;
}
template <typename T, std::size_t N>
translation<T, N> inverse(translation<T, N> const & t)
{
return {-t.v};
}
}

View file

@ -6,7 +6,6 @@
#include <psemek/geom/rotation.hpp>
#include <psemek/geom/permutation.hpp>
#include <psemek/geom/scale.hpp>
#include <psemek/geom/homogeneous.hpp>
#include <cmath>
@ -109,14 +108,16 @@ namespace psemek::geom
matrix<float, 4, 4> spherical_camera::view() const
{
return
translation<float, 3>({0.f, 0.f, -distance}).homogeneous_matrix()
* homogeneous(swap<float, 3>(1, 2).matrix())
* homogeneous(scale<float, 3>({1.f, -1.f, 1.f}).matrix())
* homogeneous(plane_rotation<float, 3>(1, 2, elevation_angle).matrix())
* homogeneous(plane_rotation<float, 3>(1, 0, azimuthal_angle).matrix())
* translation<float, 3>({ -target[0], -target[1], -target[2] }).homogeneous_matrix()
auto tr =
translation<float, 3>({0.f, 0.f, -distance}).transform()
* swap<float, 3>(1, 2).transform()
* scale<float, 3>({1.f, -1.f, 1.f}).transform()
* plane_rotation<float, 3>(1, 2, elevation_angle).transform()
* plane_rotation<float, 3>(1, 0, azimuthal_angle).transform()
* translation<float, 3>({ -target[0], -target[1], -target[2] }).transform()
;
return tr.homogeneous_matrix();
}
}