3#include "AttributeComputerDomain.hpp"
4#include "AttributeComputerFamily.hpp"
5#include "../detail/AttributeKernelSupport.hpp"
6#include "../../trees/detail/TreeTraversalDetail.hpp"
7#include "../../trees/MorphologicalTree.hpp"
17namespace mmcfilters::attributes::computers {
20inline NodeId boundingBoxSlotOf(
const MorphologicalTree&, NodeId nodeId)
noexcept {
24struct BoundingBoxRequest {
27 bool rectangularity =
false;
33 bool diagonalLength =
false;
35 [[nodiscard]]
bool any() const noexcept {
36 return width || height || rectangularity || ratioWH || colMin ||
37 colMax || rowMin || rowMax || diagonalLength;
40 [[nodiscard]]
bool needsAreaDependency() const noexcept {
41 return rectangularity;
44 [[nodiscard]]
static BoundingBoxRequest from(std::span<const Attribute> requestedAttributes) {
46 .width = contains(requestedAttributes, BOX_WIDTH),
47 .height = contains(requestedAttributes, BOX_HEIGHT),
48 .rectangularity = contains(requestedAttributes, RECTANGULARITY),
49 .ratioWH = contains(requestedAttributes, RATIO_WH),
50 .colMin = contains(requestedAttributes, BOX_COL_MIN),
51 .colMax = contains(requestedAttributes, BOX_COL_MAX),
52 .rowMin = contains(requestedAttributes, BOX_ROW_MIN),
53 .rowMax = contains(requestedAttributes, BOX_ROW_MAX),
54 .diagonalLength = contains(requestedAttributes, DIAGONAL_LENGTH)};
58 [[nodiscard]]
static bool contains(std::span<const Attribute> requestedAttributes, Attribute attribute) {
59 return std::find(requestedAttributes.begin(), requestedAttributes.end(), attribute) != requestedAttributes.end();
90 static constexpr std::string_view
familyName =
"bounding-box";
93 static constexpr AttributeComputerFamily
family = AttributeComputerFamily::BoundingBox;
96 static constexpr AttributeComputerDomain
domain = AttributeComputerDomain::Topology;
122 template <std::
floating_po
int Real>
147 ? &
context.dependencies.require(AREA)
155 std::vector<int> xmin(n, numCols);
156 std::vector<int> xmax(n, 0);
157 std::vector<int> ymin(n, numRows);
158 std::vector<int> ymax(n, 0);
160 ::mmcfilters::detail::traversePostOrder(
164 const NodeId idx = detail::boundingBoxSlotOf(tree, nodeId);
170 for (int p : tree.getProperParts(nodeId)) {
171 auto [y, x] = ImageUtils::to2D(p, numCols);
172 xmin[idx] = std::min(xmin[idx], x);
173 xmax[idx] = std::max(xmax[idx], x);
174 ymin[idx] = std::min(ymin[idx], y);
175 ymax[idx] = std::max(ymax[idx], y);
181 xmin[
pid] = std::min(xmin[
pid], xmin[
cid]);
182 xmax[
pid] = std::max(xmax[
pid], xmax[
cid]);
183 ymin[
pid] = std::min(ymin[
pid], ymin[
cid]);
184 ymax[
pid] = std::max(ymax[
pid], ymax[
cid]);
199 ::mmcfilters::attributes::numeric::safeDivide(
area,
denom);
205 ::mmcfilters::attributes::numeric::safeDivide(std::max(width, height), std::min(width, height));
208 buffer[indexOfColMin(idx)] =
static_cast<Real
>(xmin[idx]);
210 buffer[indexOfColMax(idx)] =
static_cast<Real
>(xmax[idx]);
212 buffer[indexOfRowMin(idx)] =
static_cast<Real
>(ymin[idx]);
214 buffer[indexOfRowMax(idx)] =
static_cast<Real
>(ymax[idx]);
215 if(request.diagonalLength) {
216 Real width =
static_cast<Real
>(xmax[idx] - xmin[idx] + 1);
217 Real height =
static_cast<Real
>(ymax[idx] - ymin[idx] + 1);
218 buffer[indexOfDiagonalLength(idx)] =
219 ::mmcfilters::attributes::numeric::safeSqrt(width * width + height * height);
231 template <std::
floating_po
int Real>
236 const detail::BoundingBoxRequest
request = detail::BoundingBoxRequest::from(
context.requestedAttributes);
241 const int numCols =
context.tree.getNumColsOfImage();
int NodeId
Node identifier type used throughout the project.
Layout object that maps scalar attributes to flat-buffer offsets.
static std::pair< int, int > to2D(int index, int numCols) noexcept
Converts a row-major linear index to (row, col).
Mutable morphological tree built directly on proper parts and dense node ids.
int getNumInternalNodeSlots() const
Returns the size of the dense internal-node id domain.
NodeId getRoot() const
Returns the current hierarchy root.
int getNumColsOfImage() const
Returns the number of image columns in the attached 2D domain.
int getNumRowsOfImage() const
Returns the number of image rows in the attached 2D domain.
Computes descriptors derived from the axis-aligned bounding box of the node support.
static constexpr AttributeComputerFamily family
Stable family id used by the scheduler.
static void computeUnitRows(const UnitAttributeComputeContext< Real > &context)
Materializes bounding-box descriptors for one-pixel unit supports.
static constexpr std::string_view familyName
Family name used in dependency-plan diagnostics.
static void compute(const AttributeComputeContext< Real > &context)
Computes the requested bounding-box descriptors.
static constexpr AttributeComputerDomain domain
Execution domain required by the computer.
static constexpr std::array< Attribute, 9 > producedAttributes
Canonical list of bounding-box descriptors produced by this computer.
Owning result for one computed scalar attribute layout and buffer.