MorphologicalAttributeFilters
Public API documentation
Loading...
Searching...
No Matches
ValuedMorphologicalTreeView.hpp
1#pragma once
2
3#include "MorphologicalTree.hpp"
4#include "../utils/Altitude.hpp"
5#include "../utils/Contract.hpp"
6
7#include <cstddef>
8#include <span>
9#include <stdexcept>
10
11namespace mmcfilters {
12
24template <AltitudeValue T> class ValuedMorphologicalTreeView {
25 private:
27 const MorphologicalTree* topology_ = nullptr;
29 NodeAltitudeSpan<T> nodeAltitudes_;
31 std::size_t topologyMutationVersion_ = 0;
32
36 void validateNodeAltitudeBufferShape() const {
37 MMCFILTERS_CONTRACT_REQUIRE(nodeAltitudes_.size() == static_cast<std::size_t>(topology_->numInternalNodeSlots()),
38 throw std::runtime_error("ValuedMorphologicalTreeView altitude size must match the dense internal-node domain."));
39 }
40
41 public:
43 using AltitudeType = T;
44
55 : topology_(&topology), nodeAltitudes_(altitude), topologyMutationVersion_(topology.getMutationVersion()) {
56 validateNodeAltitudeBufferShape();
57 }
58
69 : topology_(&topology), nodeAltitudes_(std::span<const T>(altitude)), topologyMutationVersion_(topology.getMutationVersion()) {
70 validateNodeAltitudeBufferShape();
71 }
72
77
83 [[nodiscard]] const MorphologicalTree& topology() const noexcept { return *topology_; }
84
90 [[nodiscard]] NodeAltitudeSpan<T> nodeAltitudes() const noexcept { return nodeAltitudes_; }
91
97 void requireTopologyUnchanged(const char* context) const { topology().requireMutationVersion(topologyMutationVersion_, context); }
98
106 MMCFILTERS_CONTRACT_REQUIRE(nodeId >= 0 && static_cast<std::size_t>(nodeId) < nodeAltitudes_.size(),
107 throw std::invalid_argument("ValuedMorphologicalTreeView::nodeAltitude requires a valid internal NodeId."));
108 return nodeAltitudes_[static_cast<std::size_t>(nodeId)];
109 }
110
122 const MorphologicalTree& tree = topology();
123 MMCFILTERS_CONTRACT_REQUIRE(tree.isAlive(nodeId), throw std::invalid_argument("ValuedMorphologicalTreeView::nodeResidue requires a live internal NodeId."));
124 const NodeId parentNodeId = tree.parent(nodeId);
126 return static_cast<AltitudeDifference<T>>(nodeAltitude(nodeId));
127 }
129 }
130};
131
132} // namespace mmcfilters
constexpr NodeId InvalidNode
Sentinel value used to denote an invalid node identifier.
Definition Common.hpp:34
#define MMCFILTERS_CONTRACT_REQUIRE(condition,...)
Evaluates a caller precondition and its failure action only in checked builds.
Definition Contract.hpp:53
Mutable connected-subset tree on a finite pixel domain.
int numInternalNodeSlots() const
Returns the size of the dense internal-node id domain.
bool isAlive(NodeId nodeId) const
Tests whether a node slot currently represents a live node.
NodeId parent(NodeId nodeId) const
Returns the direct parent of nodeId.
Non-owning view pairing a topology with an external altitude span.
AltitudeDifference< T > nodeResidue(NodeId nodeId) const
Returns the altitude difference between a live node and its parent.
const MorphologicalTree & topology() const noexcept
Returns the borrowed tree topology.
T nodeAltitude(NodeId nodeId) const
Returns the altitude associated with an internal node id.
ValuedMorphologicalTreeView(const MorphologicalTree &topology, const NodeAltitudeBuffer< T > &altitude)
Builds a view over a caller-owned altitude buffer.
NodeAltitudeSpan< T > nodeAltitudes() const noexcept
Returns the borrowed altitude span indexed by internal NodeId.
T AltitudeType
Altitude scalar type borrowed by this view.
ValuedMorphologicalTreeView(const MorphologicalTree &, NodeAltitudeBuffer< T > &&)=delete
Rejects temporary altitude buffers that would leave a dangling span.
void requireTopologyUnchanged(const char *context) const
Throws if the borrowed topology changed since view construction.
ValuedMorphologicalTreeView(const MorphologicalTree &topology, NodeAltitudeSpan< T > altitude)
Builds a view over caller-owned topology and altitude storage.
Owning result for one computed scalar attribute layout and buffer.