MorphologicalAttributeFilters
Public API documentation
Loading...
Searching...
No Matches
BitquadAttributeComputer.hpp
1#pragma once
2
3#include "AttributeComputerDomain.hpp"
4#include "AttributeComputerFamily.hpp"
5#include "../detail/AttributeKernelSupport.hpp"
6#include "detail/BitquadAttributeMaterialization.hpp"
7#include "detail/BitquadLocalEventComputation.hpp"
8
9#include <array>
10#include <numbers>
11#include <span>
12#include <stdexcept>
13#include <string_view>
14
15namespace mmcfilters::attributes::computers {
16
34public:
36 static constexpr std::string_view familyName = "bitquad";
37
39 static constexpr AttributeComputerFamily family = AttributeComputerFamily::Bitquad;
40
42 static constexpr AttributeComputerDomain domain = AttributeComputerDomain::Topology;
43
47 inline static constexpr std::array<Attribute, 9> producedAttributes{
48 BITQUADS_AREA,
49 BITQUADS_NUMBER_EULER,
50 BITQUADS_NUMBER_HOLES,
51 BITQUADS_PERIMETER,
52 BITQUADS_PERIMETER_CONTINUOUS,
53 BITQUADS_CIRCULARITY,
54 BITQUADS_PERIMETER_AVERAGE,
55 BITQUADS_LENGTH_AVERAGE,
56 BITQUADS_WIDTH_AVERAGE};
57
68 template <std::floating_point Real>
70 requireAttributeBufferShape(context.tree, context.buffer, context.attrNames);
71 const auto familyDeltas = detail::BitquadLocalEventComputation::computeBitquadFamilyDeltas(context.tree);
72 const auto familyCounts = detail::BitquadLocalEventComputation::aggregateBitquadFamilyDeltas(context.tree, familyDeltas);
73 detail::BitquadAttributeMaterialization::materializeAttributesFromBitquadFamilyCounts(
74 context.tree,
76 context.buffer,
77 context.attrNames,
78 context.requestedAttributes);
79 }
80
89 template<std::floating_point Real, AltitudeValue T>
91 requireAttributeBufferShape(context.tree, context.buffer, context.attrNames);
92 const auto familyDeltas = detail::BitquadLocalEventComputation::computeBitquadFamilyDeltas(context.tree);
93 const auto familyCounts = detail::BitquadLocalEventComputation::aggregateBitquadFamilyDeltas(context.tree, familyDeltas);
94 detail::BitquadAttributeMaterialization::materializeAttributesFromBitquadFamilyCounts(
95 context.tree,
96 context.altitude,
98 context.buffer,
99 context.attrNames,
100 context.requestedAttributes);
101 }
102
114 template <std::floating_point Real>
116 requireUnitAttributeBufferShape(context.tree, context.unitProperParts, context.buffer, context.attrNames);
117 const AdjacencyRelation* adjacency = context.tree.getAdjacencyRelation();
118 if (adjacency == nullptr) {
119 throw std::invalid_argument("Local-event BitQuads attributes require an adjacency relation.");
120 }
121
122 const bool is4Connectivity = adjacency->is4connectivity();
123 auto unitValue = [&](Attribute attribute) -> Real {
124 if (is4Connectivity) {
125 switch (attribute) {
126 case BITQUADS_AREA: return Real{0};
127 case BITQUADS_NUMBER_EULER: return Real{1};
128 case BITQUADS_NUMBER_HOLES: return Real{0};
129 case BITQUADS_PERIMETER: return Real{0};
130 case BITQUADS_PERIMETER_CONTINUOUS: return Real{0};
131 case BITQUADS_CIRCULARITY: return Real{0};
132 case BITQUADS_PERIMETER_AVERAGE: return Real{0};
133 case BITQUADS_LENGTH_AVERAGE: return Real{0};
134 case BITQUADS_WIDTH_AVERAGE: return Real{0};
135 default: break;
136 }
137 }
138
139 switch (attribute) {
140 case BITQUADS_AREA: return Real{1};
141 case BITQUADS_NUMBER_EULER: return Real{0};
142 case BITQUADS_NUMBER_HOLES: return Real{1};
143 case BITQUADS_PERIMETER: return Real{4};
144 case BITQUADS_PERIMETER_CONTINUOUS: return Real{8} / Real{3};
145 case BITQUADS_CIRCULARITY: return Real{9} * std::numbers::pi_v<Real> / Real{16};
146 case BITQUADS_PERIMETER_AVERAGE: return Real{0};
147 case BITQUADS_LENGTH_AVERAGE: return Real{0};
148 case BITQUADS_WIDTH_AVERAGE: return static_cast<Real>(0.75);
149 default: break;
150 }
151 throw std::runtime_error("Unsupported local-event BitQuads unit attribute.");
152 };
153
154 constexpr std::array<Attribute, 9> unitAttributes{
155 BITQUADS_AREA,
156 BITQUADS_NUMBER_EULER,
157 BITQUADS_NUMBER_HOLES,
158 BITQUADS_PERIMETER,
159 BITQUADS_PERIMETER_CONTINUOUS,
160 BITQUADS_CIRCULARITY,
161 BITQUADS_PERIMETER_AVERAGE,
162 BITQUADS_LENGTH_AVERAGE,
163 BITQUADS_WIDTH_AVERAGE};
164
165 for (Attribute attribute : unitAttributes) {
166 if (!requestsAttribute(context.requestedAttributes, attribute)) {
167 continue;
168 }
169 const Real value = unitValue(attribute);
170 for (NodeId leafIndex = 0; leafIndex < static_cast<NodeId>(context.unitProperParts.size()); ++leafIndex) {
171 context.buffer[context.attrNames.linearIndex(leafIndex, attribute)] = value;
172 }
173 }
174 }
175};
176
177} // namespace mmcfilters::attributes::computers
Two-dimensional adjacency relation with configurable radius and efficient iteration.
static constexpr std::array< Attribute, 9 > producedAttributes
Canonical list of scalar bitquad attributes materialized by this computer.
static void computeUnitRows(const UnitAttributeComputeContext< Real > &context)
Materializes bitquad attributes for unit proper-part supports.
static constexpr AttributeComputerDomain domain
Execution domain required by the computer.
static constexpr AttributeComputerFamily family
Stable family id used by the scheduler.
static constexpr std::string_view familyName
Family name used in dependency-plan diagnostics.
static void compute(const AttributeComputeContext< Real > &context)
Computes requested scalar bitquad attributes for every live node.
static void compute(const AltitudeAttributeComputeContext< Real, T > &context)
Computes requested bitquad attributes using a generic altitude span.
Owning result for one computed scalar attribute layout and buffer.