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.
 
 
 

246 lines
8.6 KiB

#pragma once
#include <type_traits>
#include <limits>
#include <array>
#include <cstddef>
#include <new>
#include <utility>
#include <memory>
#include <utils/no_unique_address_emulation.hpp>
namespace detail
{
template <std::size_t _Np, typename... _Types>
struct __nth__ {
};
template <typename _Tp0, typename... _Rest>
struct __nth__<0, _Tp0, _Rest...> {
using type = _Tp0;
};
template <typename _Tp0, typename _Tp1, typename... _Rest>
struct __nth__<1, _Tp0, _Tp1, _Rest...> {
using type = _Tp1;
};
template <typename _Tp0, typename _Tp1, typename _Tp2, typename... _Rest>
struct __nth__<2, _Tp0, _Tp1, _Tp2, _Rest...> {
using type = _Tp2;
};
template <const std::size_t _Np, typename _Tp0, typename _Tp1, typename _Tp2, typename... _Rest>
struct __nth__<_Np, _Tp0, _Tp1, _Tp2, _Rest...> : __nth__<_Np - 3, _Rest...> {
};
template <const std::size_t _Idx, typename... _Types>
using _Select_nth_type = typename __nth__<_Idx, _Types...>::type;
template <unsigned long long _Val, typename... _Ints>
struct _Select_int_base;
template <unsigned long long _Val, typename _IntType, typename... _Ints>
struct _Select_int_base<_Val, _IntType, _Ints...> : std::conditional_t<(_Val <= std::numeric_limits<_IntType>::max()),
std::integral_constant<_IntType, (_IntType)_Val>,
_Select_int_base<_Val, _Ints...>> {
};
template <unsigned long long _Val>
struct _Select_int_base<_Val> {
};
template <unsigned long long _Val>
using _Select_int =
typename _Select_int_base<_Val, unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long>::type::
value_type;
} // namespace detail
namespace impl::variadic
{
#pragma packed(push, 1)
template <typename _Index_type>
struct _Index_base {
_Index_type __this_;
_Index_type __next_;
constexpr _Index_base(const _Index_type __i, const _Index_type __j) noexcept : __this_{__i}, __next_{__j} {}
};
#pragma packed(pop)
template <typename _Ty, typename _Index_type>
struct _Element : public _Index_base<_Index_type>,
public no_unique_address_emulation<_Ty> {
template <typename... _Args>
explicit constexpr _Element(const std::size_t __i, _Args&&... __ctors) //
noexcept(std::is_nothrow_constructible_v<_Ty, _Args...>)
: _Index_base<_Index_type>{static_cast<_Index_type>(__i), std::numeric_limits<_Index_type>::max()},
no_unique_address_emulation<_Ty>(std::forward<_Args>(__ctors)...)
{
}
};
template <typename _Visitor>
struct __vtable__ {
template <std::size_t _Idx, typename _Ty = _Select_nth_type<_Idx, _Types...>>
static void _S_invoke(_Visitor&& __visitor, void* __ptr) noexcept(std::is_nothrow_invocable_v<_Visitor, _Ty&>)
{
auto* __box = std::launder(reinterpret_cast<_Box<_Ty>*>(__ptr));
std::forward<_Visitor>(__visitor)(__box->__val_);
}
template <std::size_t... _Indices>
static constexpr auto _S_make_vtab(std::index_sequence<_Indices...>) noexcept
{
return std::array<void (*)(_Visitor&&, void*), sizeof...(_Types)>{&_S_invoke<_Indices>...};
}
static constexpr auto __vtab_ = _S_make_vtab(std::index_sequence_for<_Types...>{});
};
} // namespace impl::variadic
template <const std::size_t __Sp_, typename... _Types>
struct variadic {
using _Index_type = detail::_Select_int<sizeof...(_Types)>;
struct _Idx_base {
_Index_type __this_;
_Index_type __next_;
} __attribute__((__packed__));
template <typename _Ty>
struct _Box : public _Idx_base {
[[__no_unique_address__]] _Ty __val_;
template <typename... _Args>
explicit constexpr _Box(const std::size_t __i,
_Args&&... __ctors) noexcept(std::is_nothrow_constructible_v<_Ty, _Args...>)
: _Idx_base{static_cast<_Index_type>(__i), std::numeric_limits<_Index_type>::max()},
__val_(std::forward<_Args>(__ctors)...)
{
}
};
static constexpr std::size_t __max_align_ = std::max({std::alignment_of_v<_Box<_Types>>...});
template <typename _Visitor>
struct __vtable__ {
template <std::size_t _Idx, typename _Ty = _Select_nth_type<_Idx, _Types...>>
static void _S_invoke(_Visitor&& __visitor, void* __ptr) noexcept(std::is_nothrow_invocable_v<_Visitor, _Ty&>)
{
auto* __box = std::launder(reinterpret_cast<_Box<_Ty>*>(__ptr));
std::forward<_Visitor>(__visitor)(__box->__val_);
}
template <std::size_t... _Indices>
static constexpr auto _S_make_vtab(std::index_sequence<_Indices...>) noexcept
{
return std::array<void (*)(_Visitor&&, void*), sizeof...(_Types)>{&_S_invoke<_Indices>...};
}
static constexpr auto __vtab_ = _S_make_vtab(std::index_sequence_for<_Types...>{});
};
alignas(__max_align_) std::byte __data_[__Sp_];
void* __p_ = &__data_[0];
std::size_t __sz_ = __Sp_;
std::size_t __count_ = 0;
_Index_type* __next_ = nullptr;
template <typename _Ty>
[[__nodiscard__]] //
_Ty* _M_implicit_aligned_alloc(const std::size_t __align = alignof(_Ty)) noexcept
{
if (std::align(__align, sizeof(_Ty), __p_, __sz_)) [[__likely__]] {
_Ty* __result = std::launder(reinterpret_cast<_Ty*>(__p_));
__p_ = static_cast<std::byte*>(__p_) + sizeof(_Ty);
__sz_ -= sizeof(_Ty);
return __result;
}
return nullptr;
}
template <std::size_t _Idx, typename... _Args, typename _Result = _Select_nth_type<_Idx, _Types...>>
_Result& emplace_back(_Args&&... __ctors)
{
if (__next_) { *__next_ = static_cast<_Index_type>(_Idx); }
if (auto* __ptr = _M_implicit_aligned_alloc<_Box<_Result>>()) [[__likely__]] {
::new (__ptr) _Box<_Result>{_Idx, std::forward<_Args>(__ctors)...};
__next_ = &__ptr->__next_;
++__count_;
return __ptr->__val_;
}
throw std::bad_alloc{};
}
template <typename _Visitor>
void loop(_Visitor&& __visitor)
{
if (__count_ == 0) [[__unlikely__]] { return; }
static constexpr auto& __table_ = __vtable__<_Visitor&&>::__vtab_;
void* __current = &__data_[0];
const void* const __end = __p_;
while (__current < __end) [[__likely__]] {
auto* __base = std::launder(reinterpret_cast<_Idx_base*>(__current));
const auto __i = __base->__this_;
const auto __j = __base->__next_;
if (__i < sizeof...(_Types)) [[__likely__]] { __table_[__i](std::forward<_Visitor>(__visitor), __current); }
__current = _S_advance_ptr(__current, __i, __j);
}
}
private:
template <std::size_t... _Indices>
static void* _S_advance_ptr_impl(const void* __ptr,
const std::size_t __i,
const std::size_t __j,
std::index_sequence<_Indices...>) noexcept
{
static constexpr std::array<std::size_t, sizeof...(_Types)> __alignments_ = {std::alignment_of_v<_Box<_Types>>...};
static constexpr std::array<std::size_t, sizeof...(_Types)> __sizes_ = {sizeof(_Box<_Types>)...};
const auto __intptr = reinterpret_cast<std::uintptr_t>(__ptr) + __sizes_[__i];
if (__j == std::numeric_limits<_Index_type>::max()) {
// NOLINTNEXTLINE
return reinterpret_cast<void*>(__intptr);
}
const auto __align = __alignments_[__j];
const auto __result = (__intptr - 1U + __align) & -__align;
// NOLINTNEXTLINE
return reinterpret_cast<void*>(__result);
}
static void* _S_advance_ptr(const void* __ptr, const std::size_t __i, const std::size_t __j)
{
return _S_advance_ptr_impl(__ptr, __i, __j, std::index_sequence_for<_Types...>{});
}
public:
[[__nodiscard__]] std::size_t size() const noexcept { return __count_; }
[[__nodiscard__]] bool empty() const noexcept { return __count_ == 0; }
[[__nodiscard__]] std::size_t capacity() const noexcept { return __Sp_; }
[[__nodiscard__]] std::size_t available() const noexcept { return __sz_; }
void clear() noexcept
{
loop([] [[__gnu__::__always_inline__]] (auto& __obj) noexcept {
using _Type = std::decay_t<decltype(__obj)>;
if constexpr (!std::is_trivially_destructible_v<_Type>) { __obj.~_Type(); }
});
__p_ = &__data_[0];
__sz_ = __Sp_;
__count_ = 0;
}
~variadic() { clear(); }
};