3#include "../trees/ValuedMorphologicalTreeView.hpp"
4#include "detail/ContourTraversal.hpp"
32 struct SharedIndexes {
36 std::size_t mutationVersion;
38 contours::detail::NodeSupportIndex supportIndex;
40 contours::detail::ContourLifetimeIndex contourLifetimes;
47 : tree(source), mutationVersion(source.
getMutationVersion()), supportIndex(source), contourLifetimes(source) {}
54 struct TraversalState {
56 std::shared_ptr<const SharedIndexes> indexes;
58 contours::detail::ContourTraversal traversal;
60 bool hasCurrentContour;
66 explicit TraversalState(std::shared_ptr<const SharedIndexes> source)
67 : indexes(std::move(source)), traversal(indexes->tree, indexes->supportIndex, indexes->contourLifetimes),
68 hasCurrentContour(traversal.advance()) {}
86 using value_type = std::pair<NodeId, std::span<const PixelId>>;
97 if (!state_ || !state_->hasCurrentContour) {
98 throw std::out_of_range(
"Contour iterator is exhausted.");
100 return state_->traversal.current();
108 if (!state_ || !state_->hasCurrentContour) {
109 throw std::out_of_range(
"Contour iterator is exhausted.");
111 state_->hasCurrentContour = state_->traversal.advance();
120 return !
it.state_ || !
it.state_->hasCurrentContour;
130 explicit iterator(std::shared_ptr<const SharedIndexes> indexes) : state_(std::
make_shared<TraversalState>(std::
move(indexes))) {}
132 std::shared_ptr<TraversalState> state_;
145 template <AltitudeValue T>
154 const auto support = indexes_->supportIndex.support(node);
156 for (
PixelId pixel : support) {
157 if (indexes_->contourLifetimes.establishedIsContourPixel(pixel, node)) {
169 indexes_->requireStableTree();
187 for (
auto [node, pixels] : *
this) {
189 indexes_->requireStableTree();
201 return view.topology();
205 std::shared_ptr<const SharedIndexes> indexes_;
#define MMCFILTERS_CONTRACT_CHECKED_ONLY(...)
Executes validation statements only when defensive checks are enabled.
Single-pass iterator yielding (node, borrowed pixel span).
std::pair< NodeId, std::span< const PixelId > > value_type
Node identifier and borrowed contour span yielded by dereference.
std::input_iterator_tag iterator_concept
C++20 iterator concept for this single-pass traversal.
void operator++(int)
Advances without retaining the previous borrowed contour.
std::input_iterator_tag iterator_category
Iterator category used by standard algorithms.
friend bool operator==(const iterator &it, std::default_sentinel_t) noexcept
Tests exhaustion against the range's sentinel.
iterator & operator++()
Advances the shared single-pass position.
value_type operator*() const
Borrows the current node contour.
std::ptrdiff_t difference_type
Signed type used to represent iterator distances.
Incremental foreground A4 contours on the image domain.
std::default_sentinel_t end() const noexcept
Returns the exhaustion sentinel.
void forEachContour(Consumer &&consumer) const
Calls consumer(node, pixels) once for every live node.
ContourComputation(const ValuedMorphologicalTreeView< T > &view)
Builds contours from the topology of a current valued view.
ContourComputation(const MorphologicalTree &tree)
Builds the compact indexes for a stable tree with a 2D domain.
iterator begin() const
Starts an independent incremental post-order traversal.
std::vector< PixelId > contour(NodeId node) const
Returns an owned contour of one live node, without caching it.
Mutable connected-subset tree on a finite pixel domain.
void requireMutationVersion(std::size_t expectedVersion, const char *context) const
Rejects stale read-only views that captured an older mutation version.
std::size_t getMutationVersion() const noexcept
Returns the monotonic mutation counter used by read-only views.
Owning result for one computed scalar attribute layout and buffer.