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.

245 lines
8.2 KiB

// BITSET2
//
// Copyright Claas Bontus
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ClaasBontus/bitset2
//
#pragma once
#include "bit_chars.hpp"
#include "reverse_bits.hpp"
namespace detail
{
template <size_t N, class T>
struct array_ops {
using base_t = T;
using this_t = array_ops<N, T>;
using b_chars = bit_chars<N, T>;
enum : size_t {
base_t_n_bits = b_chars::base_t_n_bits,
n_words = b_chars::n_words,
n_array = b_chars::n_array,
mod_val = b_chars::mod_val,
n_m_mod = mod_val == 0 ? 0 : base_t_n_bits - mod_val
};
enum : base_t { hgh_bit_pattern = b_chars::hgh_bit_pattern, all_one = b_chars::all_one };
using array_t = typename h_types<T>::template array_t<n_array>;
using zero_array_t = typename h_types<T>::template array_t<0>;
constexpr array_ops(size_t n_shift) noexcept
: m_n_shift(n_shift),
m_n_shift_mod(n_shift % N),
m_shft_div(n_shift / base_t_n_bits),
m_shft_mod(n_shift % base_t_n_bits),
m_rot_div(m_n_shift_mod / base_t_n_bits),
m_rot_mod(m_n_shift_mod % base_t_n_bits),
m_shft_leftright_shift(base_t_n_bits - m_shft_mod),
m_shft_left_pattern(ce_left_shift(T(~T(0)), m_shft_leftright_shift)),
m_shft_right_pattern(ce_right_shift(T(~T(0)), m_shft_leftright_shift))
{
}
constexpr array_t shift_left(array_t arr) const noexcept
{
shift_left_assgn(arr);
return arr;
}
constexpr array_t shift_right(array_t arr) const noexcept
{
shift_right_assgn(arr);
return arr;
}
/// Used for <<= operator.
constexpr void shift_left_assgn(array_t &arr) const noexcept
{
if (m_n_shift == 0) return;
for (size_t c = n_words; c > 0;) {
--c;
if (c >= m_shft_div) {
auto const c2 = c - m_shft_div;
base_t const v1 = arr[c2] << m_shft_mod;
base_t const v2 =
c2 == 0 ? base_t(0) : ce_right_shift(base_t(arr[c2 - 1] & m_shft_left_pattern), m_shft_leftright_shift);
arr[c] = base_t(v1 | v2);
} else
arr[c] = base_t(0);
} // for c
arr[n_array - 1] &= hgh_bit_pattern;
} // shift_left_assgn
/// Used for >>= operator.
constexpr void shift_right_assgn(array_t &arr) const noexcept
{
if (m_n_shift == 0) return;
for (size_t c = 0; c < n_words; ++c) {
auto const c2 = c + m_shft_div;
if (c2 < n_words) {
base_t const v1 = arr[c2] >> m_shft_mod;
base_t const v2 = (c2 + 1 >= n_words)
? base_t(0)
: ce_left_shift(base_t(arr[c2 + 1] & m_shft_right_pattern), m_shft_leftright_shift);
arr[c] = v1 | v2;
} else
arr[c] = base_t(0);
} // for c
arr[n_array - 1] &= hgh_bit_pattern;
} // shift_right_assgn
constexpr array_t rotate_left(array_t const &arr) const noexcept
{
if (m_n_shift_mod == 0) return arr;
return (n_array == 1) ? array_t{{base_t((base_t(arr[0] << m_n_shift_mod) | (ce_right_shift(arr[0], N - m_n_shift_mod)))
& hgh_bit_pattern)}}
: rotate_left_impl(arr);
} // rotate_left
constexpr array_t flip(array_t const &arr) const noexcept { return flip_impl(arr, std::make_index_sequence<n_array>()); }
constexpr bool all(array_t const &arr) const noexcept { return (N > 0) && all_impl(n_words - 1, arr); }
/// Used for ++ operator.
constexpr void increment(array_t &arr) const noexcept
{
if (N == 0) return;
size_t c = 0;
for (; c + 1 < n_words; ++c) {
if ((++arr[c]) != base_t(0)) return;
}
++arr[c];
arr[c] &= hgh_bit_pattern;
} // increment
/// Used for -- operator.
constexpr void decrement(array_t &arr) const noexcept
{
if (N == 0) return;
size_t c = 0;
for (; c + 1 < n_words; ++c) {
if ((arr[c]--) != base_t(0)) return;
}
--arr[c];
arr[c] &= hgh_bit_pattern;
} // decrement
/// Reverse bits
constexpr array_t reverse(array_t const &arr) const noexcept
{
return n_array == 1 ? array_t{{base_t(reverse_bits<base_t>()(arr[0]) >> n_m_mod)}}
: reverse_impl(arr, std::make_index_sequence<n_array>());
} // reverse
//****************************************************
constexpr bool all_impl(size_t idx, array_t const &arr) const noexcept
{
return h_all(idx, arr) && ((idx == 0) ? true : all_impl(idx - 1, arr));
}
constexpr bool h_all(size_t idx, array_t const &arr) const noexcept
{
return (idx + 1 == n_words) ? (arr[idx] == hgh_bit_pattern) : (arr[idx] == all_one);
}
constexpr array_t rotate_left_impl(array_t const &arr) const noexcept
{
size_t const rot_r_div = (N - m_n_shift_mod) / base_t_n_bits;
size_t const rot_r_mod = (N - m_n_shift_mod) % base_t_n_bits;
size_t const bits_last = (mod_val == 0) ? base_t_n_bits : mod_val;
array_t arr_r{};
size_t c = 0;
size_t const h1 = (bits_last < rot_r_mod) ? 2 : 1;
for (; c + h1 + rot_r_div < n_words; ++c) {
size_t i1 = c + rot_r_div;
size_t i2 = i1 + 1;
base_t v1 = ce_right_shift(arr[i1], rot_r_mod);
base_t v2 = ce_left_shift(arr[i2], base_t_n_bits - rot_r_mod);
arr_r[c] = base_t(v1 | v2);
} // for c
if (c < n_words && bits_last < rot_r_mod) {
base_t v1 = ce_right_shift(arr[n_words - 2], rot_r_mod);
base_t v2 = ce_left_shift(arr[n_words - 1], base_t_n_bits - rot_r_mod);
base_t v3 = ce_left_shift(arr[0], base_t_n_bits - rot_r_mod + bits_last);
arr_r[c++] = base_t(v1 | v2 | v3);
}
if (c < n_words && bits_last > rot_r_mod) {
base_t v1 = ce_right_shift(arr[n_words - 1], rot_r_mod);
base_t v2 = ce_left_shift(arr[0], bits_last - rot_r_mod);
arr_r[c++] = base_t(v1 | v2);
}
for (; c < n_words; ++c) {
size_t i1 = c - m_rot_div;
size_t i2 = i1 - 1;
base_t v1 = ce_left_shift(arr[i1], m_rot_mod);
base_t v2 = ce_right_shift(arr[i2], base_t_n_bits - m_rot_mod);
arr_r[c] = base_t(v1 | v2);
} // for c
arr_r[n_array - 1] &= hgh_bit_pattern;
return arr_r;
} // rotate_left_impl
template <size_t... S>
constexpr array_t flip_impl(array_t const &arr, std::index_sequence<S...>) const noexcept
{
return {{h_flip(S, arr)...}};
}
constexpr base_t h_flip(size_t idx, array_t const &arr) const noexcept
{
return (idx >= n_words) ? base_t(0) : (~arr[idx]) & ((idx + 1 == n_words) ? hgh_bit_pattern : all_one);
}
template <size_t... S>
constexpr array_t reverse_impl(array_t const &arr, std::index_sequence<S...>) const noexcept
{
return {{h_reverse(S, arr)...}};
}
constexpr base_t h_reverse(size_t idx, array_t const &arr) const noexcept
{
return idx + 1 == n_words ? base_t(reverse_bits<base_t>()(arr[0]) >> n_m_mod)
: reverse_bits<base_t>()(h2_reverse(idx, arr));
}
constexpr base_t h2_reverse(size_t idx, array_t const &arr) const noexcept
{
return mod_val == 0 ? arr[n_words - idx - 1]
: base_t((arr[n_words - idx - 1] << n_m_mod) | (arr[n_words - idx - 2] >> mod_val));
}
size_t const m_n_shift;
size_t const m_n_shift_mod;
size_t const m_shft_div;
size_t const m_shft_mod;
size_t const m_rot_div;
size_t const m_rot_mod;
size_t const m_shft_leftright_shift;
base_t const m_shft_left_pattern;
base_t const m_shft_right_pattern;
}; // struct array_ops
} // namespace detail