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.
 
 
 

214 lines
8.9 KiB

#pragma once
#include "detail/flat_multimap_base.hpp"
#include "small_vector.hpp"
template <template <typename> class Vector, typename Key, typename T, typename Compare = std::less<Key>>
class flat_map : public detail::flat_multimap_base<flat_map<Vector, Key, Compare>, false, Vector, Key, T, Compare>
{
using base_t = detail::flat_multimap_base<flat_map<Vector, Key, Compare>, false, Vector, Key, T, Compare>;
public:
using base_t::base_t;
using typename base_t::key_type;
using typename base_t::mapped_type;
using typename base_t::value_type;
using typename base_t::const_iterator;
using typename base_t::iterator;
flat_map(std::initializer_list<value_type> ilist, const Compare& comp = Compare()) : base_t(ilist, comp) {}
mapped_type& at(const key_type& key)
{
auto target = base_t::find(key);
if (target == base_t::end()) ATOM_fatal("Invalid flat_map<K, V> subscript: Referring index is out of range!");
return target->second;
}
const mapped_type& at(const key_type& key) const { return const_cast<flat_map*>(this)->at(key); }
mapped_type& operator[](const key_type& key) { return try_emplace(key).first->second; }
mapped_type& operator[](key_type&& key) { return try_emplace(std::move(key)).first->second; }
template <typename M>
std::pair<iterator, bool> insert_or_assign(const key_type& k, M&& m)
{
return insert_or_assign_impl(k, std::forward<M>(m));
}
template <typename M>
std::pair<iterator, bool> insert_or_assign(key_type&& k, M&& m)
{
return insert_or_assign_impl(std::move(k), std::forward<M>(m));
}
template <typename M>
iterator insert_or_assign(const_iterator hint, const key_type& k, M&& m)
{
return insert_or_assign_hint_impl(hint, k, std::forward<M>(m));
}
template <typename M>
iterator insert_or_assign(const_iterator hint, key_type&& k, M&& m)
{
return insert_or_assign_hint_impl(hint, std::move(k), std::forward<M>(m));
}
template <typename... Args>
std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args)
{
return try_emplace_impl(k, std::forward<Args>(args)...);
}
template <typename... Args>
std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args)
{
return try_emplace_impl(std::move(k), std::forward<Args>(args)...);
}
template <typename... Args>
iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args)
{
return try_emplace_hint_impl(hint, k, std::forward<Args>(args)...);
}
template <typename... Args>
iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args)
{
return try_emplace_hint_impl(hint, std::move(k), std::forward<Args>(args)...);
}
private:
template <typename K, typename... Args>
void storage_emplace_back(K&& k, Args&&... args)
{
if constexpr (std::is_constructible_v<value_type, std::piecewise_construct_t, std::tuple<K&&>, std::tuple<Args&&...>>) {
base_t::storage.emplace_back(std::piecewise_construct_t{},
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<Args>(args)...));
} else
base_t::storage.emplace_back(std::forward<K>(k), mapped_type(std::forward<Args>(args)...));
}
template <typename K, typename... Args>
iterator storage_emplace(const_iterator hint, K&& k, Args&&... args)
{
if constexpr (std::is_constructible_v<value_type, std::piecewise_construct_t, std::tuple<K&&>, std::tuple<Args&&...>>) {
return base_t::cast_iterator(base_t::storage.emplace(base_t::cast_iterator(hint),
std::piecewise_construct_t{},
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<Args>(args)...)));
} else {
return base_t::cast_iterator(base_t::storage.emplace(base_t::cast_iterator(hint),
std::forward<K>(k),
mapped_type(std::forward<Args>(args)...)));
}
}
template <typename K, typename M>
std::pair<iterator, bool> insert_or_assign_impl(K&& k, M&& m)
{
auto lb = base_t::lower_bound(k); // k <= lb
if (lb == base_t::end() || base_t::key_comp()(k, *lb)) // k < lb
return {base_t::cast_iterator(
base_t::storage.insert(base_t::cast_iterator(lb), value_type(std::forward<K>(k), std::forward<M>(m)))),
true};
else { // k == lb
lb->second = std::forward<M>(m);
return {lb, false};
}
}
template <typename K, typename M>
iterator insert_or_assign_hint_impl(const_iterator hint, K&& k, M&& m)
{
assert(base_t::begin() <= hint && hint <= base_t::end());
const_iterator first;
const_iterator last;
if (hint == base_t::begin() || base_t::key_comp()(*std::prev(hint), k)) { // k > hint - 1
if (hint < base_t::end()) {
if (base_t::key_comp()(k, *hint)) // k < hint
return storage_emplace(hint, std::forward<K>(k), mapped_type(std::forward<M>(m)));
else { // k >= hint
first = hint;
last = base_t::cend();
}
} else { // hint == end()
storage_emplace_back(std::forward<K>(k), mapped_type(std::forward<M>(m)));
return std::prev(base_t::end());
}
} else { // k <= hint - 1
first = base_t::cbegin();
last = hint;
}
auto lb = std::lower_bound(first, last, k, base_t::key_comp()); // value <= lb
if (lb == base_t::end() || base_t::key_comp()(k, *lb)) // value < lb
return storage_emplace(lb, std::forward<K>(k), mapped_type(std::forward<M>(m)));
else { // value == lb
auto iter = base_t::begin() + std::distance(base_t::cbegin(), lb);
iter->second = std::forward<M>(m);
return iter;
}
}
template <typename K, typename... Args>
std::pair<iterator, bool> try_emplace_impl(K&& k, Args&&... args)
{
auto lb = base_t::lower_bound(k); // key <= lb
if (lb == base_t::end() || base_t::key_comp()(k, *lb)) // key < lb
return {storage_emplace(lb, std::forward<K>(k), mapped_type(std::forward<Args>(args)...)), true};
else
return {lb, false}; // key == lb
}
template <typename K, typename... Args>
iterator try_emplace_hint_impl(const_iterator hint, K&& k, Args&&... args)
{
assert(base_t::begin() <= hint && hint <= base_t::end());
const_iterator first;
const_iterator last;
if (hint == base_t::begin() || base_t::key_comp()(*std::prev(hint), k)) { // k > hint - 1
if (hint < base_t::end()) {
if (base_t::key_comp()(k, *hint)) // k < hint
return storage_emplace(hint, std::forward<K>(k), mapped_type(std::forward<Args>(args)...));
else { // k >= hint
first = hint;
last = base_t::cend();
}
} else { // hint == end()
storage_emplace_back(std::forward<K>(k), mapped_type(std::forward<Args>(args)...));
return std::prev(base_t::end());
}
} else { // k <= hint - 1
first = base_t::cbegin();
last = hint;
}
auto lb = std::lower_bound(first, last, k, base_t::key_comp()); // value <= lb
if (lb == base_t::end() || base_t::key_comp()(k, *lb)) // value < lb
return storage_emplace(lb, std::forward<K>(k), mapped_type(std::forward<Args>(args)...));
else
return base_t::begin() + std::distance(base_t::cbegin(), lb); // value == lb
}
};
template <typename Key, typename T, typename Compare = std::less<Key>>
using stl_flat_map = flat_map<detail::stl_vector_allocator_bind, Key, T, Compare>;
template <typename Key, typename T, size_t N = 16, typename Compare = std::less<Key>>
using static_flat_map = flat_map<detail::static_vector_bind<N>::template type, Key, T, Compare>;
template <typename Key, typename T, size_t N = 16, typename Compare = std::less<Key>>
using small_flat_map = flat_map<detail::small_vector_bind<N>::template type, Key, T, Compare>;