128 lines
2.7 KiB
C++
128 lines
2.7 KiB
C++
#pragma once
|
|
|
|
#include <psemek/geom/affine_transform.hpp>
|
|
|
|
namespace psemek::geom
|
|
{
|
|
|
|
template <typename T, std::size_t N>
|
|
struct scale
|
|
{
|
|
vector<T, N> s;
|
|
|
|
scale();
|
|
scale(T s);
|
|
scale(vector<T, N> const & s);
|
|
scale(scale const &) = default;
|
|
|
|
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;
|
|
|
|
affine_transform<T, N, N> transform() const;
|
|
|
|
vector<T, N> operator()(vector<T, N> v) const;
|
|
point<T, N> operator()(point<T, N> p) const;
|
|
|
|
private:
|
|
template <typename Matrix>
|
|
void fill_matrix(Matrix & m) const;
|
|
};
|
|
|
|
template <typename T, std::size_t N>
|
|
scale(vector<T, N>) -> scale<T, N>;
|
|
|
|
template <typename T, std::size_t N>
|
|
scale<T, N>::scale()
|
|
{
|
|
for (std::size_t i = 0; i < N; ++i)
|
|
s[i] = T{1};
|
|
}
|
|
|
|
template <typename T, std::size_t N>
|
|
scale<T, N>::scale(T s)
|
|
{
|
|
for (std::size_t i = 0; i < N; ++i)
|
|
this->s[i] = s;
|
|
}
|
|
|
|
template <typename T, std::size_t N>
|
|
scale<T, N>::scale(vector<T, N> const & s)
|
|
: s{s}
|
|
{}
|
|
|
|
template <typename T, std::size_t N>
|
|
matrix<T, N, N + 1> scale<T, N>::affine_matrix() const
|
|
{
|
|
auto result = matrix<T, N, N + 1>::identity();
|
|
fill_matrix(result);
|
|
return result;
|
|
}
|
|
|
|
template <typename T, std::size_t N>
|
|
matrix<T, N, N> scale<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> scale<T, N>::translation_vector() const
|
|
{
|
|
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>::identity();
|
|
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 N>
|
|
point<T, N> scale<T, N>::operator()(point<T, N> p) const
|
|
{
|
|
for (std::size_t i = 0; i < N; ++i)
|
|
p[i] *= s[i];
|
|
return p;
|
|
}
|
|
|
|
template <typename T, std::size_t N>
|
|
template <typename Matrix>
|
|
void scale<T, N>::fill_matrix(Matrix & m) const
|
|
{
|
|
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};
|
|
}
|
|
|
|
}
|