3#include "../utils/Image.hpp"
4#include "../utils/Contract.hpp"
5#include "../attributes/AttributeResultTypes.hpp"
6#include "../trees/MorphologicalTree.hpp"
7#include "../trees/ValuedMorphologicalTree.hpp"
8#include "../trees/ValuedMorphologicalTreeView.hpp"
64 template <std::
floating_po
int Real =
float>
66 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
79 template <std::
floating_po
int Real =
float>
81 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
92 template <std::
floating_po
int Real =
float, AltitudeValue T>
94 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
107 template <std::
floating_po
int Real =
float, AltitudeValue T>
109 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
120 template <std::
floating_po
int Real =
float, AltitudeValue T>
122 const std::vector<AttributeOrGroup>& attributes,
123 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
136 template <std::
floating_po
int Real =
float, AltitudeValue T>
138 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
152 template <std::
floating_po
int Real =
float, AltitudeValue T>
154 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
167 template <std::
floating_po
int Real =
float, AltitudeValue T>
169 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
184 template <std::
floating_po
int Real =
float, AltitudeValue T>
187 NodeAttributeSamplingPolicy samplingPolicy = NodeAttributeSamplingPolicy::LargestSupportDescendant,
188 MissingNodeAttributeSamplePolicy missingSamplePolicy = MissingNodeAttributeSamplePolicy::RepeatNearest,
189 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
206 template <std::
floating_po
int Real =
float, AltitudeValue T>
209 NodeAttributeSamplingPolicy samplingPolicy = NodeAttributeSamplingPolicy::LargestSupportDescendant,
210 MissingNodeAttributeSamplePolicy missingSamplePolicy = MissingNodeAttributeSamplePolicy::RepeatNearest,
211 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
228 template <std::
floating_po
int Real =
float, AltitudeValue T>
230 const std::vector<AttributeOrGroup>& attributes,
231 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
244 template <std::
floating_po
int Real =
float, AltitudeValue T>
246 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
263 template <std::
floating_po
int Real =
float, AltitudeValue T>
265 const std::vector<AttributeOrGroup>& attributes,
266 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
286 template <std::
floating_po
int Real =
float, AltitudeValue T>
288 std::span<const Real> nodeValues);
299 template <std::
floating_po
int Real =
float, AltitudeValue T>
301 const std::vector<Real>& nodeValues);
312 template <std::
floating_po
int Real =
float, AltitudeValue T>
314 std::span<const Real> nodeValues);
325 template <std::
floating_po
int Real =
float, AltitudeValue T>
327 const std::vector<Real>& nodeValues);
337 template <std::
floating_po
int Real =
float, AltitudeValue T>
348 template <std::
floating_po
int Real =
float, AltitudeValue T>
354#include "../attributes/detail/NodeAttributeSampleMaterialization.hpp"
355#include "../attributes/detail/AttributePipeline.hpp"
356#include "../attributes/detail/AttributeProjection.hpp"
358namespace mmcfilters {
368template <std::
floating_po
int OutputReal, std::
floating_po
int InternalReal>
369[[nodiscard]]
inline ComputedAttributeData<OutputReal> castComputedAttributeData(ComputedAttributeData<InternalReal> computed) {
370 if constexpr (std::is_same_v<OutputReal, InternalReal>) {
373 std::vector<OutputReal> output;
374 output.reserve(computed.second.size());
375 for (
const InternalReal value : computed.second) {
376 output.push_back(
static_cast<OutputReal
>(value));
378 return ComputedAttributeData<OutputReal>{std::move(computed.first), std::move(output), computed.
nodeIdSpace};
388template <std::
floating_po
int OutputReal, std::
floating_po
int InternalReal>
389[[nodiscard]]
inline SampledNodeAttributeData<OutputReal> castSampledNodeAttributeData(SampledNodeAttributeData<InternalReal> computed) {
390 if constexpr (std::is_same_v<OutputReal, InternalReal>) {
393 std::vector<OutputReal> output;
394 output.reserve(computed.second.size());
395 for (
const InternalReal value : computed.second) {
396 output.push_back(
static_cast<OutputReal
>(value));
398 return SampledNodeAttributeData<OutputReal>{std::move(computed.first), std::move(output), computed.
nodeIdSpace};
408template <std::
floating_po
int OutputReal, std::
floating_po
int InternalReal>
409[[nodiscard]]
inline std::vector<OutputReal> castAttributeValues(std::vector<InternalReal> values) {
410 if constexpr (std::is_same_v<OutputReal, InternalReal>) {
413 std::vector<OutputReal> output;
414 output.reserve(values.size());
415 for (
const InternalReal value : values) {
416 output.push_back(
static_cast<OutputReal
>(value));
431template <std::
floating_po
int OutputReal, std::
floating_po
int InternalReal>
432[[nodiscard]]
inline ImagePtr<OutputReal> mapNodeAttributeToImageCast(
const MorphologicalTree& tree,
const AttributeNames& attrNames,
433 std::span<const InternalReal> nodeValues, Attribute attribute) {
435 OutputReal* img = imgPtr->rawData();
436 for (
int p = 0; p < imgPtr->getSize(); ++p) {
437 const NodeId nodeId = tree.smallestNode(p);
438 img[p] =
static_cast<OutputReal
>(nodeValues[attrNames.linearIndex(nodeId, attribute)]);
445template <std::
floating_po
int Real>
448 return detail::castComputedAttributeData<Real>(detail::materializeAttributesWithoutAltitude<double>(tree, {
attrOrGroup},
outputSpace));
451template <std::
floating_po
int Real>
453 const std::vector<AttributeOrGroup>& attributes, NodeIdSpace
outputSpace) {
454 return detail::castComputedAttributeData<Real>(detail::materializeAttributesWithoutAltitude<double>(tree, attributes,
outputSpace));
457template <std::
floating_po
int Real, AltitudeValue T>
463template <std::
floating_po
int Real, AltitudeValue T>
466 tree.requireTopologyUnchanged(
"AttributeComputation::computeSingleTopologyAttribute");
467 return detail::castComputedAttributeData<Real>(
468 detail::materializeTopologyAttributeRequest<double>(tree.topology(), tree.nodeAltitudes(), {attrOrGroup}, detail::DependencyMapT<double>{},
outputSpace));
471template <std::
floating_po
int Real, AltitudeValue T>
473 const std::vector<AttributeOrGroup>& attributes, NodeIdSpace
outputSpace) {
477template <std::
floating_po
int Real, AltitudeValue T>
479 const std::vector<AttributeOrGroup>& attributes, NodeIdSpace
outputSpace) {
480 tree.requireTopologyUnchanged(
"AttributeComputation::computeTopologyAttributes");
481 return detail::castComputedAttributeData<Real>(
482 detail::materializeTopologyAttributeRequest<double>(tree.topology(), tree.nodeAltitudes(), attributes, detail::DependencyMapT<double>{},
outputSpace));
485template <std::
floating_po
int Real, AltitudeValue T>
488 return detail::castComputedAttributeData<Real>(detail::materializeAttributes<double>(tree.topology(), tree.nodeAltitudeSpan(), {attrOrGroup},
outputSpace));
491template <std::
floating_po
int Real, AltitudeValue T>
495 return detail::castComputedAttributeData<Real>(detail::materializeAttributes<double>(tree.topology(), tree.nodeAltitudes(), {attrOrGroup},
outputSpace));
498template <std::
floating_po
int Real, AltitudeValue T>
507template <std::
floating_po
int Real, AltitudeValue T>
513 tree.requireTopologyUnchanged(
"AttributeComputation::computeSampledNodeAttribute");
516 return detail::castSampledNodeAttributeData<Real>(detail::materializeNodeAttributeSamples<double>(
520template <std::
floating_po
int Real, AltitudeValue T>
522 const std::vector<AttributeOrGroup>& attributes, NodeIdSpace
outputSpace) {
523 return detail::castComputedAttributeData<Real>(detail::materializeAttributes<double>(tree.topology(), tree.nodeAltitudeSpan(), attributes,
outputSpace));
526template <std::
floating_po
int Real, AltitudeValue T>
530 return detail::castComputedAttributeData<Real>(detail::materializeAttributes<double>(tree.topology(), tree.nodeAltitudes(), attributes,
outputSpace));
533template <std::
floating_po
int Real, AltitudeValue T>
535 const std::vector<AttributeOrGroup>& attributes,
538 return detail::castComputedAttributeData<Real>(detail::materializeAttributes<double>(
valuedTree.topology(),
valuedTree.nodeAltitudes(), attributes,
outputSpace));
541template <std::
floating_po
int Real, AltitudeValue T>
547template <std::
floating_po
int Real, AltitudeValue T>
553template <std::
floating_po
int Real, AltitudeValue T>
556 tree.topology().requireNotEditing(
"AttributeComputation::projectNodeValuesToExportedHigra");
557 tree.requireTopologyUnchanged(
"AttributeComputation::projectNodeValuesToExportedHigra");
558 if constexpr (std::is_same_v<Real, double>) {
559 return detail::projectNodeValuesToExportedHigraTyped<double>(tree.topology(), tree.nodeAltitudes(),
attrNames,
nodeValues);
566 return detail::castAttributeValues<Real>(
567 detail::projectNodeValuesToExportedHigraTyped<double>(tree.topology(), tree.nodeAltitudes(),
attrNames, std::span<const double>(
internalValues)));
571template <std::
floating_po
int Real, AltitudeValue T>
577template <std::
floating_po
int Real, AltitudeValue T>
579 auto [
attrNames,
buffer] = AttributeComputation::computeSingleAttribute<double>(tree, attribute, NodeIdSpace::MorphologicalTree);
580 return detail::mapNodeAttributeToImageCast<Real>(tree.topology(),
attrNames, std::span<const double>(
buffer), attribute);
583template <std::
floating_po
int Real, AltitudeValue T>
585 tree.requireTopologyUnchanged(
"AttributeComputation::computeAttributeMapping");
586 auto [
attrNames,
buffer] = AttributeComputation::computeSingleAttribute<double>(tree, attribute, NodeIdSpace::MorphologicalTree);
587 return detail::mapNodeAttributeToImageCast<Real>(tree.topology(),
attrNames, std::span<const double>(
buffer), attribute);
typename detail::AltitudeDifferenceSelector< T >::type AltitudeDifference
Arithmetic result type for altitude differences.
int NodeId
Node identifier type used throughout the project.
#define MMCFILTERS_CONTRACT_CHECKED_ONLY(...)
Executes validation statements only when defensive checks are enabled.
std::shared_ptr< Image< PixelType > > ImagePtr
Shared pointer alias for an image with arbitrary pixel type.
Public facade for attribute computation.
static ImagePtr< Real > computeAttributeMapping(const ValuedMorphologicalTree< T > &tree, Attribute attribute)
Projects a node attribute to a pixel image in the original domain.
static ComputedAttributeData< Real > computeAttributes(const ValuedMorphologicalTree< T > &tree, const std::vector< AttributeOrGroup > &attributes, NodeIdSpace outputSpace=NodeIdSpace::MorphologicalTree)
Computes a heterogeneous set of scalar attributes and attribute groups in one coordinated run.
static ComputedAttributeData< Real > computeSingleTopologyAttribute(const MorphologicalTree &tree, AttributeOrGroup attr, NodeIdSpace outputSpace=NodeIdSpace::MorphologicalTree)
Computes one topology/support-only scalar attribute or group.
static std::vector< Real > projectNodeValuesToExportedHigra(const ValuedMorphologicalTree< T > &tree, const AttributeNames &attrNames, std::span< const Real > nodeValues)
Projects an already computed internal-node attribute buffer to the compact Higra layout produced by T...
static SampledNodeAttributeData< Real > computeSampledNodeAttribute(const ValuedMorphologicalTree< T > &tree, Attribute attribute, AltitudeDifference< T > altitudeStep, int samplingRadius, NodeAttributeSamplingPolicy samplingPolicy=NodeAttributeSamplingPolicy::LargestSupportDescendant, MissingNodeAttributeSamplePolicy missingSamplePolicy=MissingNodeAttributeSamplePolicy::RepeatNearest, NodeIdSpace outputSpace=NodeIdSpace::MorphologicalTree)
Samples one scalar node attribute at altitude-based positions.
static ComputedAttributeData< Real > computeAttributesFromAltitudeSpan(const ValuedMorphologicalTreeView< T > &valuedTree, const std::vector< AttributeOrGroup > &attributes, NodeIdSpace outputSpace=NodeIdSpace::MorphologicalTree)
Computes attributes over an external altitude span.
static ComputedAttributeData< Real > computeTopologyAttributes(const MorphologicalTree &tree, const std::vector< AttributeOrGroup > &attributes, NodeIdSpace outputSpace=NodeIdSpace::MorphologicalTree)
Computes several topology/support-only attributes or groups.
static ComputedAttributeData< Real > computeSingleAttribute(const ValuedMorphologicalTree< T > &tree, AttributeOrGroup attr, NodeIdSpace outputSpace=NodeIdSpace::MorphologicalTree)
Computes a single scalar attribute or a full attribute group.
Layout object that maps scalar attributes to flat-buffer offsets.
static Ptr create(int rows, int columns)
Creates an owned image with uninitialised pixel values.
Mutable connected-subset tree on a finite pixel domain.
Non-owning view pairing a topology with an external altitude span.
Wrapper pairing MorphologicalTree topology with an external altitude buffer.
Owning result for one computed scalar attribute layout and buffer.
NodeIdSpace nodeIdSpace
Node-id domain used by the rows of second.
Owning result for one sampled node-attribute layout and buffer.