3#include "AttributeComputerDomain.hpp"
4#include "AttributeComputerFamily.hpp"
5#include "../detail/AttributeKernelSupport.hpp"
6#include "../../trees/detail/TreeTraversalDetail.hpp"
7#include "../../trees/TreeAltitudeAlgorithms.hpp"
8#include "../../utils/Altitude.hpp"
17namespace mmcfilters::attributes::computers {
20inline NodeId volumeSlotOf(
const MorphologicalTree&, NodeId nodeId)
noexcept {
26 bool relative =
false;
28 [[nodiscard]]
bool any() const noexcept {
29 return volume || relative;
32 [[nodiscard]]
bool needsAreaDependency() const noexcept {
36 [[nodiscard]]
static VolumeRequest from(std::span<const Attribute> requestedAttributes) {
38 .volume = containsVolumeAttribute(requestedAttributes, VOLUME),
39 .relative = containsVolumeAttribute(requestedAttributes, RELATIVE_VOLUME)};
43 [[nodiscard]]
static bool containsVolumeAttribute(
44 std::span<const Attribute> requestedAttributes,
47 return std::find(requestedAttributes.begin(), requestedAttributes.end(), attribute) != requestedAttributes.end();
63template<std::
floating_po
int Real, AltitudeValue T>
64void computeVolumeAttributeKernel(
65 const MorphologicalTree& tree,
66 std::span<const T> altitude,
67 std::span<Real> buffer,
68 const AttributeNames& attrNames,
69 std::span<const Attribute> requestedAttributes,
70 std::span<
const DependencySourceT<Real>> dependencySources)
74 const VolumeRequest request = VolumeRequest::from(requestedAttributes);
79 auto indexOfVol = [&](
NodeId idx) {
return attrNames.linearIndex(idx, VOLUME); };
80 auto indexOfRel = [&](
NodeId idx) {
return attrNames.linearIndex(idx, RELATIVE_VOLUME); };
81 const DependencyResolver<Real> dependencies{dependencySources};
82 const DependencySourceT<Real>* dependencyArea = request.needsAreaDependency()
83 ? &dependencies.require(AREA)
85 auto indexOfArea = [&](
NodeId idx) {
return dependencyArea->attrNames->linearIndex(idx, AREA); };
87 ::mmcfilters::detail::traversePostOrder(
91 const NodeId node = detail::volumeSlotOf(tree, nodeId);
92 const T nodeAltitude = TreeAltitudeAlgorithms::getAltitude(altitude, nodeId);
94 buffer[indexOfVol(node)] =
95 static_cast<Real>(tree.getNumProperParts(nodeId)) * static_cast<Real>(nodeAltitude);
97 buffer[indexOfRel(node)] = Real{0};
100 const NodeId parent = detail::volumeSlotOf(tree, parentNodeId);
101 const NodeId child = detail::volumeSlotOf(tree, childNodeId);
103 buffer[indexOfVol(parent)] += buffer[indexOfVol(child)];
104 if (request.relative)
105 buffer[indexOfRel(parent)] +=
106 buffer[indexOfRel(child)] +
108 dependencyArea->buffer[indexOfArea(child)] *
114 const NodeId node = detail::volumeSlotOf(tree, nodeId);
115 if (request.relative)
116 buffer[indexOfRel(node)] += dependencyArea->buffer[indexOfArea(node)];
144 static constexpr std::string_view familyName =
"volume";
147 static constexpr AttributeComputerFamily family = AttributeComputerFamily::Volume;
150 static constexpr AttributeComputerDomain domain = AttributeComputerDomain::Altitude;
155 inline static constexpr std::array<Attribute, 2> producedAttributes{
168 template <std::
floating_po
int Real, AltitudeValue T>
172 detail::computeVolumeAttributeKernel(
188 template <std::
floating_po
int Real, AltitudeValue T>
192 TreeAltitudeAlgorithms::validateAltitudeBufferShape(
context.tree,
context.altitude);
194 const detail::VolumeRequest
request = detail::VolumeRequest::from(
context.requestedAttributes);
int NodeId
Node identifier type used throughout the project.
static T getAltitude(std::span< const T > altitude, NodeId nodeId)
Reads one node altitude from an explicit altitude buffer.
static void validateAltitudeBufferShape(const MorphologicalTree &tree, std::span< const T > altitude)
Validates that an altitude buffer covers the dense internal-node domain.
Computes cumulative grey-level volume descriptors on the hierarchy.
static void compute(const AltitudeAttributeComputeContext< Real, T > &context)
Computes the requested volume descriptors.
static void computeUnitRows(const AltitudeUnitAttributeComputeContext< Real, T > &context)
Materializes volume descriptors for one-pixel unit supports.
Owning result for one computed scalar attribute layout and buffer.