Add group -> matrix converter

This commit is contained in:
Nikita Lisitsa 2023-01-15 22:42:24 +03:00
parent 4c5d8777d6
commit f6d9b14f38
2 changed files with 156 additions and 1 deletions

View file

@ -10,7 +10,7 @@ file(GLOB_RECURSE PSEMEK_GEOM_SOURCES "source/*.cpp")
psemek_add_library(psemek-geom ${PSEMEK_GEOM_HEADERS} ${PSEMEK_GEOM_SOURCES})
target_include_directories(psemek-geom PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(psemek-geom PUBLIC psemek-util Boost::boost)
target_link_libraries(psemek-geom PUBLIC psemek-util psemek-group Boost::boost)
if(PSEMEK_ROBUST_PREDICATES)
target_link_libraries(psemek-geom PUBLIC gmp)
endif()

View file

@ -0,0 +1,155 @@
#pragma once
#include <psemek/group/cyclic.hpp>
#include <psemek/group/dihedral.hpp>
#include <psemek/geom/affine_transform.hpp>
#include <psemek/geom/quaternion.hpp>
#include <psemek/util/assert.hpp>
namespace psemek::geom
{
template <typename T, std::size_t N>
struct symmetry
{
matrix<T, N, N> m;
symmetry();
symmetry(symmetry const &) = default;
template <std::size_t D, typename Repr>
symmetry(group::cyclic<D, Repr> const & g);
template <std::size_t D, typename Repr>
symmetry(group::cyclic<D, Repr> const & g, std::size_t i, std::size_t j);
template <std::size_t D, typename Repr>
symmetry(group::dihedral<D, Repr> const & g);
template <std::size_t D, typename Repr>
symmetry(group::dihedral<D, Repr> const & g, std::size_t i, std::size_t j);
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> const & v) const;
point<T, N> operator()(point<T, N> const & p) const;
};
template <typename T, std::size_t N>
symmetry<T, N>::symmetry()
{
m = m.identity();
}
template <typename T, std::size_t N>
template <std::size_t D, typename Repr>
symmetry<T, N>::symmetry(group::cyclic<D, Repr> const & g)
: symmetry(g, 0, 1)
{}
template <typename T, std::size_t N>
template <std::size_t D, typename Repr>
symmetry<T, N>::symmetry(group::cyclic<D, Repr> const & g, std::size_t i, std::size_t j)
{
m = m.identity();
T angle = (T{2} * geom::pi * static_cast<T>(g.value())) / static_cast<T>(D);
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>
template <std::size_t D, typename Repr>
symmetry<T, N>::symmetry(group::dihedral<D, Repr> const & g)
: symmetry(g, 0, 1)
{}
template <typename T, std::size_t N>
template <std::size_t D, typename Repr>
symmetry<T, N>::symmetry(group::dihedral<D, Repr> const & g, std::size_t i, std::size_t j)
{
m = m.identity();
T angle = (T{2} * geom::pi * static_cast<T>(g.value())) / static_cast<T>(D);
// See https://en.wikipedia.org/wiki/Dihedral_group#Matrix_representation
if (g.is_rotation())
{
m[i][i] = std::cos(angle);
m[i][j] = -std::sin(angle);
m[j][i] = std::sin(angle);
m[j][j] = std::cos(angle);
}
else
{
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>
matrix<T, N, N + 1> symmetry<T, N>::affine_matrix() const
{
matrix<T, N, N + 1> result;
for (std::size_t i = 0; i < N; ++i)
for (std::size_t j = 0; j < N; ++j)
result[i][j] = m[i][j];
for (std::size_t i = 0; i < N; ++i)
result[i][N] = T{0};
return result;
}
template <typename T, std::size_t N>
matrix<T, N, N> symmetry<T, N>::linear_matrix() const
{
return m;
}
template <typename T, std::size_t N>
vector<T, N> symmetry<T, N>::translation_vector() const
{
return vector<T, N>::zero();
}
template <typename T, std::size_t N>
matrix<T, N + 1, N + 1> symmetry<T, N>::homogeneous_matrix() const
{
auto result = matrix<T, N + 1, N + 1>::identity();
for (std::size_t i = 0; i < N; ++i)
for (std::size_t j = 0; j < N; ++j)
result[i][j] = m[i][j];
return result;
}
template <typename T, std::size_t N>
affine_transform<T, N, N> symmetry<T, N>::transform() const
{
return {m, geom::vector<T, N>::zero()};
}
template <typename T, std::size_t N>
vector<T, N> symmetry<T, N>::operator()(vector<T, N> const & v) const
{
return m * v;
}
template <typename T, std::size_t N>
point<T, N> symmetry<T, N>::operator()(point<T, N> const & p) const
{
return p.zero() + m * (p - p.zero());
}
}