3#include "../trees/MorphologicalTree.hpp"
4#include "../trees/detail/CommittedTreeAccess.hpp"
5#include "../utils/Common.hpp"
11namespace mmcfilters::local_attributes {
22namespace detail::kernel {
40inline NodeId anchoredEntry(
const MorphologicalTree& tree, PixelId anchorPixel, PixelId samplePixel) {
41 const NodeId anchorSmallestNode = ::mmcfilters::detail::CommittedTreeAccess::smallestNodeMap(tree, anchorPixel);
42 const NodeId sampleSmallestNode = ::mmcfilters::detail::CommittedTreeAccess::smallestNodeMap(tree, samplePixel);
43 return connectedSubsetJoin(tree, anchorSmallestNode, sampleSmallestNode);
47inline NodeId anchoredEntry(
const MorphologicalTree& tree, PixelId anchorPixel, WindowOffset offset) {
48 const GridDomain2D& domain = ::mmcfilters::detail::CommittedTreeAccess::gridDomain2D(tree);
49 const int anchorRow = anchorPixel / domain.columns;
50 const int anchorColumn = anchorPixel % domain.columns;
51 const int sampleRow = anchorRow + offset.rowOffset;
52 const int sampleColumn = anchorColumn + offset.columnOffset;
53 if (sampleRow < 0 || sampleRow >= domain.rows || sampleColumn < 0 || sampleColumn >= domain.columns) {
56 return anchoredEntry(tree, anchorPixel,
static_cast<PixelId>(sampleRow * domain.columns + sampleColumn));
73 tree_.requireNotEditing(
"ConnectedSubsetTreeLocalizer");
79 if (!tree_.isPixel(pixel)) {
80 throw std::out_of_range(
"ConnectedSubsetTreeLocalizer::smallestNode received an invalid pixel.");
82 const NodeId value = tree_.smallestNode(pixel);
83 if (!tree_.isAlive(value)) {
84 throw std::logic_error(
"ConnectedSubsetTreeLocalizer::smallestNode found a pixel without a live smallest node.");
98 throw std::invalid_argument(
"ConnectedSubsetTreeLocalizer::join requires two live nodes.");
111 if (!tree_.isPixel(anchorPixel) || !tree_.isPixel(
samplePixel)) {
114 return detail::kernel::anchoredEntry(tree_, anchorPixel,
samplePixel);
125 const GridDomain2D& domain = tree_.requireGridDomain2D(
"ConnectedSubsetTreeLocalizer::anchoredEntry");
129 const NodeId entry = detail::kernel::anchoredEntry(tree_, anchorPixel, offset);
135 void requireStableTree()
const { tree_.requireMutationVersion(mutationVersion_,
"ConnectedSubsetTreeLocalizer"); }
138 std::size_t mutationVersion_ = 0;
int PixelId
Pixel identifier type used by source and active construction domains.
int NodeId
Node identifier type used throughout the project.
constexpr NodeId InvalidNode
Sentinel value used to denote an invalid node identifier.
Mutable connected-subset tree on a finite pixel domain.
Validated public view of connected-subset-tree localization.
NodeId smallestNode(PixelId pixel) const
Returns the smallest node of one valid pixel.
std::optional< NodeId > anchoredEntry(PixelId anchorPixel, PixelId samplePixel) const
Returns the first node on the anchor branch containing an absolute sample.
NodeId join(NodeId lhsSmallestNode, NodeId rhsSmallestNode) const
Returns the inclusion join, equivalently the LCA, of two live smallest nodes.
ConnectedSubsetTreeLocalizer(const MorphologicalTree &tree)
Captures one established tree without building another index.
std::optional< NodeId > anchoredEntry(PixelId anchorPixel, WindowOffset offset) const
Returns the first node containing a translated sample.
Owning result for one computed scalar attribute layout and buffer.
Shape metadata optionally attached to the pixel domain.
int columns
Number of grid columns.
int rows
Number of grid rows.
Relative row-column offset of one translated local sample.
int columnOffset
Positive values move right.
int rowOffset
Positive values move down.
friend bool operator==(const WindowOffset &lhs, const WindowOffset &rhs)=default
Compares both coordinate displacements.