extract explicit mesh with topology information from implicit surfaces with boolean operations, and do surface/volume integrating on them.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

87 lines
3.1 KiB

#pragma once
#include <functional>
#include <math/eigen_alias.hpp>
#include <xxhash.h>
namespace detail
{
template <typename T>
struct float_to_int_type {
static_assert(std::is_floating_point_v<T>, "T must be a floating point type");
using type = std::conditional_t<sizeof(T) == 4, uint32_t, uint64_t>;
};
static constexpr float float_hash_epsilon = 1e-6f;
} // namespace detail
static inline void hash_combine(size_t &seed, uint32_t value)
{
seed = seed ^ (std::hash<uint32_t>()(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
}
static inline void hash_combine(uint64_t &seed, uint64_t value)
{
seed = seed ^ (std::hash<uint64_t>()(value) + 0x9e3779b97f4a7c15ULL + (seed << 12) + (seed >> 4));
}
template <typename... InputTypes>
static inline size_t hash_combine(size_t seed, InputTypes... values)
{
(hash_combine(seed, values), ...);
return seed;
}
struct hash_funcs_fn {
template <typename T, int M, int N>
size_t operator()(const Eigen::Matrix<T, M, N> &mat, double epsilon = detail::float_hash_epsilon) const
{
static_assert(M != Eigen::Dynamic && N != Eigen::Dynamic, "only fixed size matrix is supported");
if constexpr (std::is_integral_v<T>)
return XXH3_64bits(mat.data(), sizeof(T) * M * N);
else if constexpr (std::is_floating_point_v<T>) {
using integral_type = typename detail::float_to_int_type<T>::type;
Eigen::Matrix<integral_type, M, N> int_mat = (mat.array() / static_cast<T>(epsilon)).template cast<integral_type>();
return XXH3_64bits(int_mat.data(), sizeof(integral_type) * M * N);
} else
static_assert(false, "unsupported type in hash<Eigen::Matrix>");
}
template <typename T, int N>
size_t operator()(const Eigen::Transform<T, N, Eigen::AffineCompact> &trans,
double epsilon = detail::float_hash_epsilon) const
{
if constexpr (std::is_integral_v<T>)
return XXH3_64bits(trans.data(), sizeof(T) * N * (N + 1));
else if constexpr (std::is_floating_point_v<T>) {
using integral_type = typename detail::float_to_int_type<T>::type;
Eigen::Matrix<integral_type, N, N + 1> int_mat =
(trans.affine().array() / static_cast<T>(epsilon)).template cast<integral_type>();
return XXH3_64bits(int_mat.data(), sizeof(integral_type) * N * (N + 1));
} else
static_assert(false, "unsupported type in hash<Eigen::Matrix>");
}
template <typename T>
size_t operator()(std::reference_wrapper<T> ref) const
{
return size_t(std::addressof(ref.get()));
}
template <typename T>
size_t operator()(std::reference_wrapper<const T> ref) const
{
return size_t(std::addressof(ref.get()));
}
template <typename InputIt>
size_t operator()(InputIt first, InputIt last) const
{
using T = std::decay<InputIt>;
return XXH3_64bits(&*first, std::distance(first, last) * sizeof(T));
}
};
static constexpr hash_funcs_fn hash_funcs{};