Add group -> matrix converter
This commit is contained in:
parent
4c5d8777d6
commit
f6d9b14f38
2 changed files with 156 additions and 1 deletions
|
|
@ -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()
|
||||
|
|
|
|||
155
libs/geom/include/psemek/geom/symmetry.hpp
Normal file
155
libs/geom/include/psemek/geom/symmetry.hpp
Normal 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());
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue