Skip to content

Instantly share code, notes, and snippets.

@loliGothicK
Created October 10, 2019 21:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save loliGothicK/a7c924f49f6fe5a4e3a55311978ce34b to your computer and use it in GitHub Desktop.
Save loliGothicK/a7c924f49f6fe5a4e3a55311978ce34b to your computer and use it in GitHub Desktop.
range wrapper for TopExp_Explorer
#ifndef CADDi_OCC_EXTENSIONS_EXPLORER_HPP
#define CADDi_OCC_EXTENSIONS_EXPLORER_HPP
#include <iterator>
#include <type_traits>
#include <utility>
#include <functional>
#include <memory>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Shape.hxx>
#include <boost/container/flat_map.hpp>
#include <mitama/container/entry.hpp>
namespace caddi::occ_ex {
struct explorer_sentinel {};
namespace _detail {
class control_block_t {
boost::container::flat_map<std::size_t, TopoDS_Shape> table_;
public:
std::size_t upper_bound = std::numeric_limits<std::size_t>::max();
auto entry(std::size_t index) {
return mitama::entry_t(table_, index);
}
};
}
class explorer_iterator {
TopExp_Explorer* exp_;
std::shared_ptr<_detail::control_block_t> storage_;
std::size_t index_;
public:
using difference_type = std::ptrdiff_t;
using value_type = TopoDS_Shape;
using reference = TopoDS_Shape&;
using pointer = TopoDS_Shape*;
using iterator_category = std::bidirectional_iterator_tag;
explorer_iterator(TopExp_Explorer* exp, std::shared_ptr<_detail::control_block_t> storage)
: exp_(exp)
, storage_(storage)
{}
explorer_iterator() = default;
explorer_iterator(explorer_iterator const&) = default;
explorer_iterator(explorer_iterator&&) = default;
explorer_iterator& operator=(explorer_iterator const&) = default;
explorer_iterator& operator=(explorer_iterator&&) = default;
~explorer_iterator() = default;
explorer_iterator& operator++() & {
index_++;
exp_->Next();
if (!exp_->More()) storage_->upper_bound = index_;
else storage_->entry(index_).or_emplace(exp_->Current());
return *this;
}
explorer_iterator operator++(int) & {
auto iter = *this;
index_++;
exp_->Next();
if (!exp_->More()) storage_->upper_bound = index_;
else storage_->entry(index_).or_emplace(exp_->Current());
return iter;
}
explorer_iterator& operator--() & {
index_--;
return *this;
}
explorer_iterator operator--(int) & {
auto iter = *this;
index_--;
return iter;
}
TopoDS_Shape& operator*() const {
return storage_->entry(index_).or_emplace(exp_->Current());
}
friend bool operator==(explorer_iterator const& lhs, explorer_iterator const& rhs)
{ return lhs.exp_ == rhs.exp_ && lhs.index_ == rhs.index_; }
friend bool operator!=(explorer_iterator const& lhs, explorer_iterator const& rhs)
{ return !(lhs == rhs); }
friend bool operator==(explorer_sentinel const&, explorer_iterator const& iter)
{ return !iter.exp_->More() && iter.index_ >= iter.storage_->upper_bound; }
friend bool operator==(explorer_iterator const& iter, explorer_sentinel const& sentinel)
{ return sentinel == iter; }
friend bool operator!=(explorer_sentinel const& sentinel, explorer_iterator const& iter)
{ return !(sentinel == iter); }
friend bool operator!=(explorer_iterator const& iter, explorer_sentinel const& sentinel)
{ return !(sentinel == iter); }
};
bool operator==(explorer_sentinel, explorer_sentinel) { return true; }
bool operator!=(explorer_sentinel, explorer_sentinel) { return false; }
class explorer {
std::reference_wrapper<TopExp_Explorer> exp_;
std::shared_ptr<_detail::control_block_t> storage_;
public:
explicit explorer(TopExp_Explorer& exp): exp_(exp), storage_( std::make_shared<_detail::control_block_t>() ) {}
explorer() = delete;
explorer(explorer const&) = default;
explorer(explorer&&) = default;
explorer& operator=(explorer const&) = default;
explorer& operator=(explorer&&) = default;
explorer_iterator begin() const { return explorer_iterator{&exp_.get(), storage_}; }
explorer_sentinel end() const { return {}; }
};
explorer_iterator begin(explorer const& exp)
{ return exp.begin(); }
explorer_sentinel end(explorer const&)
{ return {}; }
}
namespace std {
template <>
class iterator_traits<caddi::occ_ex::explorer_iterator> {
public:
using difference_type = std::ptrdiff_t;
using value_type = TopoDS_Shape;
using reference = TopoDS_Shape&;
using pointer = TopoDS_Shape*;
using iterator_category = std::bidirectional_iterator_tag;
};
}
#endif
@loliGothicK
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment