mmcfilters
Public API documentation
Loading...
Searching...
No Matches
AreaComputer.hpp
1#pragma once
2
3#include "AttributeComputerDomain.hpp"
4#include "AttributeComputerFamily.hpp"
5#include "../detail/AttributeKernelSupport.hpp"
6#include "../../trees/detail/TreeTraversalDetail.hpp"
7#include "../../trees/detail/CommittedTreeAccess.hpp"
8#include "../../utils/Contract.hpp"
9#include "../../trees/MorphologicalTree.hpp"
10
11#include <array>
12#include <concepts>
13#include <stdexcept>
14#include <string_view>
15
16namespace mmcfilters::attributes::computers {
17
18namespace detail {
19
20template <std::floating_point Real> inline void validateAreaContext(const AttributeComputeContext<Real>& context) {
21 requireAttributeBufferShape(context.tree, context.buffer, context.attrNames);
22 if (!context.attrNames.contains(Area)) {
23 throw std::invalid_argument("AREA computation requires an AREA column in the output layout.");
24 }
25}
26
27namespace kernel {
28
30template <std::floating_point Real> inline void computeArea(const AttributeComputeContext<Real>& context) {
31 const int stride = context.attrNames.NUM_ATTRIBUTES;
32 const int offset = context.attrNames.indexMap.find(Area)->second;
33 auto indexOfArea = [&](NodeId node) { return static_cast<std::size_t>(node * stride + offset); };
34 ::mmcfilters::detail::kernel::traversePostOrder(
35 context.tree, context.tree.root(),
36 [&](NodeId node) {
37 context.buffer[indexOfArea(node)] = static_cast<Real>(::mmcfilters::detail::CommittedTreeAccess::properPartCardinality(context.tree, node));
38 },
39 [&](NodeId parent, NodeId child) { context.buffer[indexOfArea(parent)] += context.buffer[indexOfArea(child)]; }, [](NodeId) {});
40}
41
42} // namespace kernel
43} // namespace detail
44
65 public:
67 static constexpr std::string_view familyName = "area";
68
70 static constexpr AttributeComputerFamily family = AttributeComputerFamily::Area;
71
73 static constexpr AttributeComputerDomain domain = AttributeComputerDomain::Topology;
74
78 inline static constexpr std::array<Attribute, 1> producedAttributes{Area};
79
91 template <std::floating_point Real> static void compute(const AttributeComputeContext<Real>& context) {
92 MMCFILTERS_CONTRACT_CHECKED_ONLY(detail::validateAreaContext(context));
93 detail::kernel::computeArea(context);
94 }
95
96 public:
104 template <std::floating_point Real> static void computeUnitRows(const UnitAttributeComputeContext<Real>& context) {
105 requireUnitAttributeBufferShape(context.tree, context.unitPixels, context.buffer, context.attrNames);
106 if (!requestsAttribute(context.requestedAttributes, Area)) {
107 return;
108 }
109 for (NodeId leafIndex = 0; leafIndex < static_cast<NodeId>(context.unitPixels.size()); ++leafIndex) {
110 context.buffer[context.attrNames.linearIndex(leafIndex, Area)] = Real{1};
111 }
112 }
113};
114
115} // namespace mmcfilters::attributes::computers
int NodeId
Node identifier type used throughout the project.
Definition Common.hpp:17
#define MMCFILTERS_CONTRACT_CHECKED_ONLY(...)
Executes validation statements only when defensive checks are enabled.
Definition Contract.hpp:67
Computes the canonical subtree area attribute.
static constexpr std::array< Attribute, 1 > producedAttributes
Canonical list of attributes produced by this computer.
static void computeUnitRows(const UnitAttributeComputeContext< Real > &context)
Materializes AREA for one-pixel unit supports.
static constexpr AttributeComputerDomain domain
Execution domain required by the computer.
static constexpr std::string_view familyName
Family name used in dependency-plan diagnostics.
static constexpr AttributeComputerFamily family
Stable family id used by the scheduler.
static void compute(const AttributeComputeContext< Real > &context)
Computes area by summing direct proper-part counts bottom-up.
Owning result for one computed scalar attribute layout and buffer.
std::vector< Real > second
Flat per-node attribute buffer indexed through first.