mmcfilters
Public API documentation
Loading...
Searching...
No Matches
AttributeComputation.hpp
1#pragma once
2
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"
9
10#include <concepts>
11#include <span>
12#include <string>
13#include <type_traits>
14#include <utility>
15#include <vector>
16
17namespace mmcfilters {
18
52 public:
64 template <std::floating_point Real = float>
65 [[nodiscard]] static ComputedAttributeData<Real> computeSingleTopologyAttribute(const MorphologicalTree& tree, AttributeOrGroup attr,
66 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
67
79 template <std::floating_point Real = float>
80 [[nodiscard]] static ComputedAttributeData<Real> computeTopologyAttributes(const MorphologicalTree& tree, const std::vector<AttributeOrGroup>& attributes,
81 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
82
92 template <std::floating_point Real = float, AltitudeValue T>
93 [[nodiscard]] static ComputedAttributeData<Real> computeSingleTopologyAttribute(const ValuedMorphologicalTree<T>& tree, AttributeOrGroup attr,
94 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
95
107 template <std::floating_point Real = float, AltitudeValue T>
108 [[nodiscard]] static ComputedAttributeData<Real> computeSingleTopologyAttribute(const ValuedMorphologicalTreeView<T>& tree, AttributeOrGroup attr,
109 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
110
120 template <std::floating_point Real = float, AltitudeValue T>
122 const std::vector<AttributeOrGroup>& attributes,
123 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
124
136 template <std::floating_point Real = float, AltitudeValue T>
137 [[nodiscard]] static ComputedAttributeData<Real> computeTopologyAttributes(const ValuedMorphologicalTreeView<T>& tree, const std::vector<AttributeOrGroup>& attributes,
138 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
139
152 template <std::floating_point Real = float, AltitudeValue T>
153 [[nodiscard]] static ComputedAttributeData<Real> computeSingleAttribute(const ValuedMorphologicalTree<T>& tree, AttributeOrGroup attr,
154 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
155
167 template <std::floating_point Real = float, AltitudeValue T>
168 [[nodiscard]] static ComputedAttributeData<Real> computeSingleAttribute(const ValuedMorphologicalTreeView<T>& tree, AttributeOrGroup attr,
169 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
170
184 template <std::floating_point Real = float, AltitudeValue T>
185 [[nodiscard]] static SampledNodeAttributeData<Real>
186 computeSampledNodeAttribute(const ValuedMorphologicalTree<T>& tree, Attribute attribute, AltitudeDifference<T> altitudeStep, int samplingRadius,
187 NodeAttributeSamplingPolicy samplingPolicy = NodeAttributeSamplingPolicy::LargestSupportDescendant,
188 MissingNodeAttributeSamplePolicy missingSamplePolicy = MissingNodeAttributeSamplePolicy::RepeatNearest,
189 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
190
206 template <std::floating_point Real = float, AltitudeValue T>
207 [[nodiscard]] static SampledNodeAttributeData<Real>
208 computeSampledNodeAttribute(const ValuedMorphologicalTreeView<T>& tree, Attribute attribute, AltitudeDifference<T> altitudeStep, int samplingRadius,
209 NodeAttributeSamplingPolicy samplingPolicy = NodeAttributeSamplingPolicy::LargestSupportDescendant,
210 MissingNodeAttributeSamplePolicy missingSamplePolicy = MissingNodeAttributeSamplePolicy::RepeatNearest,
211 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
212
228 template <std::floating_point Real = float, AltitudeValue T>
230 const std::vector<AttributeOrGroup>& attributes,
231 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
232
244 template <std::floating_point Real = float, AltitudeValue T>
245 [[nodiscard]] static ComputedAttributeData<Real> computeAttributes(const ValuedMorphologicalTreeView<T>& tree, const std::vector<AttributeOrGroup>& attributes,
246 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
247
263 template <std::floating_point Real = float, AltitudeValue T>
265 const std::vector<AttributeOrGroup>& attributes,
266 NodeIdSpace outputSpace = NodeIdSpace::MorphologicalTree);
267
286 template <std::floating_point Real = float, AltitudeValue T>
287 [[nodiscard]] static std::vector<Real> projectNodeValuesToExportedHigra(const ValuedMorphologicalTree<T>& tree, const AttributeNames& attrNames,
288 std::span<const Real> nodeValues);
289
299 template <std::floating_point Real = float, AltitudeValue T>
300 [[nodiscard]] static std::vector<Real> projectNodeValuesToExportedHigra(const ValuedMorphologicalTree<T>& tree, const AttributeNames& attrNames,
301 const std::vector<Real>& nodeValues);
302
312 template <std::floating_point Real = float, AltitudeValue T>
313 [[nodiscard]] static std::vector<Real> projectNodeValuesToExportedHigra(const ValuedMorphologicalTreeView<T>& tree, const AttributeNames& attrNames,
314 std::span<const Real> nodeValues);
315
325 template <std::floating_point Real = float, AltitudeValue T>
326 [[nodiscard]] static std::vector<Real> projectNodeValuesToExportedHigra(const ValuedMorphologicalTreeView<T>& tree, const AttributeNames& attrNames,
327 const std::vector<Real>& nodeValues);
328
337 template <std::floating_point Real = float, AltitudeValue T>
338 [[nodiscard]] static ImagePtr<Real> computeAttributeMapping(const ValuedMorphologicalTree<T>& tree, Attribute attribute);
339
348 template <std::floating_point Real = float, AltitudeValue T>
349 [[nodiscard]] static ImagePtr<Real> computeAttributeMapping(const ValuedMorphologicalTreeView<T>& tree, Attribute attribute);
350};
351
352} // namespace mmcfilters
353
354#include "../attributes/detail/NodeAttributeSampleMaterialization.hpp"
355#include "../attributes/detail/AttributePipeline.hpp"
356#include "../attributes/detail/AttributeProjection.hpp"
357
358namespace mmcfilters {
359
360namespace detail {
361
368template <std::floating_point OutputReal, std::floating_point InternalReal>
369[[nodiscard]] inline ComputedAttributeData<OutputReal> castComputedAttributeData(ComputedAttributeData<InternalReal> computed) {
370 if constexpr (std::is_same_v<OutputReal, InternalReal>) {
371 return computed;
372 } else {
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));
377 }
378 return ComputedAttributeData<OutputReal>{std::move(computed.first), std::move(output), computed.nodeIdSpace};
379 }
380}
381
388template <std::floating_point OutputReal, std::floating_point InternalReal>
389[[nodiscard]] inline SampledNodeAttributeData<OutputReal> castSampledNodeAttributeData(SampledNodeAttributeData<InternalReal> computed) {
390 if constexpr (std::is_same_v<OutputReal, InternalReal>) {
391 return computed;
392 } else {
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));
397 }
398 return SampledNodeAttributeData<OutputReal>{std::move(computed.first), std::move(output), computed.nodeIdSpace};
399 }
400}
401
408template <std::floating_point OutputReal, std::floating_point InternalReal>
409[[nodiscard]] inline std::vector<OutputReal> castAttributeValues(std::vector<InternalReal> values) {
410 if constexpr (std::is_same_v<OutputReal, InternalReal>) {
411 return values;
412 } else {
413 std::vector<OutputReal> output;
414 output.reserve(values.size());
415 for (const InternalReal value : values) {
416 output.push_back(static_cast<OutputReal>(value));
417 }
418 return output;
419 }
420}
421
431template <std::floating_point OutputReal, std::floating_point InternalReal>
432[[nodiscard]] inline ImagePtr<OutputReal> mapNodeAttributeToImageCast(const MorphologicalTree& tree, const AttributeNames& attrNames,
433 std::span<const InternalReal> nodeValues, Attribute attribute) {
434 ImagePtr<OutputReal> imgPtr = Image<OutputReal>::create(tree.numRows(), tree.numColumns());
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)]);
439 }
440 return imgPtr;
441}
442
443} // namespace detail
444
445template <std::floating_point Real>
447 NodeIdSpace outputSpace) {
448 return detail::castComputedAttributeData<Real>(detail::materializeAttributesWithoutAltitude<double>(tree, {attrOrGroup}, outputSpace));
449}
450
451template <std::floating_point Real>
453 const std::vector<AttributeOrGroup>& attributes, NodeIdSpace outputSpace) {
454 return detail::castComputedAttributeData<Real>(detail::materializeAttributesWithoutAltitude<double>(tree, attributes, outputSpace));
455}
456
457template <std::floating_point Real, AltitudeValue T>
462
463template <std::floating_point Real, AltitudeValue T>
465 NodeIdSpace outputSpace) {
466 tree.requireTopologyUnchanged("AttributeComputation::computeSingleTopologyAttribute");
467 return detail::castComputedAttributeData<Real>(
468 detail::materializeTopologyAttributeRequest<double>(tree.topology(), tree.nodeAltitudes(), {attrOrGroup}, detail::DependencyMapT<double>{}, outputSpace));
469}
470
471template <std::floating_point Real, AltitudeValue T>
473 const std::vector<AttributeOrGroup>& attributes, NodeIdSpace outputSpace) {
474 return computeTopologyAttributes<Real>(tree.asView(), attributes, outputSpace);
475}
476
477template <std::floating_point 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));
483}
484
485template <std::floating_point Real, AltitudeValue T>
487 NodeIdSpace outputSpace) {
488 return detail::castComputedAttributeData<Real>(detail::materializeAttributes<double>(tree.topology(), tree.nodeAltitudeSpan(), {attrOrGroup}, outputSpace));
489}
490
491template <std::floating_point Real, AltitudeValue T>
493 NodeIdSpace outputSpace) {
494 MMCFILTERS_CONTRACT_CHECKED_ONLY(tree.requireTopologyUnchanged("AttributeComputation::computeSingleAttribute"));
495 return detail::castComputedAttributeData<Real>(detail::materializeAttributes<double>(tree.topology(), tree.nodeAltitudes(), {attrOrGroup}, outputSpace));
496}
497
498template <std::floating_point Real, AltitudeValue T>
501 NodeAttributeSamplingPolicy samplingPolicy,
502 MissingNodeAttributeSamplePolicy missingSamplePolicy,
503 NodeIdSpace outputSpace) {
505}
506
507template <std::floating_point Real, AltitudeValue T>
510 NodeAttributeSamplingPolicy samplingPolicy,
511 MissingNodeAttributeSamplePolicy missingSamplePolicy,
512 NodeIdSpace outputSpace) {
513 tree.requireTopologyUnchanged("AttributeComputation::computeSampledNodeAttribute");
514 auto base = computeSingleAttribute<double>(tree, attribute, NodeIdSpace::MorphologicalTree);
515
516 return detail::castSampledNodeAttributeData<Real>(detail::materializeNodeAttributeSamples<double>(
517 tree.topology(), tree.nodeAltitudes(), std::move(base), attribute, altitudeStep, samplingRadius, samplingPolicy, missingSamplePolicy, outputSpace));
518}
519
520template <std::floating_point 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));
524}
525
526template <std::floating_point Real, AltitudeValue T>
527inline ComputedAttributeData<Real> AttributeComputation::computeAttributes(const ValuedMorphologicalTreeView<T>& tree, const std::vector<AttributeOrGroup>& attributes,
528 NodeIdSpace outputSpace) {
529 MMCFILTERS_CONTRACT_CHECKED_ONLY(tree.requireTopologyUnchanged("AttributeComputation::computeAttributes"));
530 return detail::castComputedAttributeData<Real>(detail::materializeAttributes<double>(tree.topology(), tree.nodeAltitudes(), attributes, outputSpace));
531}
532
533template <std::floating_point Real, AltitudeValue T>
535 const std::vector<AttributeOrGroup>& attributes,
536 NodeIdSpace outputSpace) {
537 MMCFILTERS_CONTRACT_CHECKED_ONLY(valuedTree.requireTopologyUnchanged("AttributeComputation::computeAttributesFromAltitudeSpan"));
538 return detail::castComputedAttributeData<Real>(detail::materializeAttributes<double>(valuedTree.topology(), valuedTree.nodeAltitudes(), attributes, outputSpace));
539}
540
541template <std::floating_point Real, AltitudeValue T>
543 std::span<const Real> nodeValues) {
545}
546
547template <std::floating_point Real, AltitudeValue T>
549 const std::vector<Real>& nodeValues) {
550 return projectNodeValuesToExportedHigra<Real>(tree, attrNames, std::span<const Real>(nodeValues));
551}
552
553template <std::floating_point Real, AltitudeValue T>
555 std::span<const Real> nodeValues) {
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);
560 } else {
561 std::vector<double> internalValues;
562 internalValues.reserve(nodeValues.size());
563 for (const Real value : nodeValues) {
564 internalValues.push_back(static_cast<double>(value));
565 }
566 return detail::castAttributeValues<Real>(
567 detail::projectNodeValuesToExportedHigraTyped<double>(tree.topology(), tree.nodeAltitudes(), attrNames, std::span<const double>(internalValues)));
568 }
569}
570
571template <std::floating_point Real, AltitudeValue T>
573 const std::vector<Real>& nodeValues) {
574 return projectNodeValuesToExportedHigra<Real>(tree, attrNames, std::span<const Real>(nodeValues));
575}
576
577template <std::floating_point 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);
581}
582
583template <std::floating_point 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);
588}
589
590} // namespace mmcfilters
typename detail::AltitudeDifferenceSelector< T >::type AltitudeDifference
Arithmetic result type for altitude differences.
Definition Altitude.hpp:72
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
std::shared_ptr< Image< PixelType > > ImagePtr
Shared pointer alias for an image with arbitrary pixel type.
Definition Image.hpp:285
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.
Definition Image.hpp:105
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.