diff --git a/src/Plugins/SimplnxCore/CMakeLists.txt b/src/Plugins/SimplnxCore/CMakeLists.txt index 3a15ef4cb3..21d6772945 100644 --- a/src/Plugins/SimplnxCore/CMakeLists.txt +++ b/src/Plugins/SimplnxCore/CMakeLists.txt @@ -21,7 +21,7 @@ set(FilterList ChangeAngleRepresentationFilter CombineAttributeArraysFilter CombineStlFilesFilter - ComputeFeatureRectFilter + CalculateFeatureBoundingBoxesFilter ComputeMomentInvariants2DFilter ConditionalSetValueFilter ConvertColorToGrayScaleFilter @@ -148,7 +148,7 @@ set(AlgorithmList CalculateTriangleGroupCurvatures CombineAttributeArrays CombineStlFiles - ComputeFeatureRect + CalculateFeatureBoundingBoxes ComputeMomentInvariants2D ConvertColorToGrayScale ConvertData diff --git a/src/Plugins/SimplnxCore/docs/ComputeFeatureRectFilter.md b/src/Plugins/SimplnxCore/docs/CalculateFeatureBoundingBoxes.md similarity index 97% rename from src/Plugins/SimplnxCore/docs/ComputeFeatureRectFilter.md rename to src/Plugins/SimplnxCore/docs/CalculateFeatureBoundingBoxes.md index 83b7a4e09b..4453bf9795 100644 --- a/src/Plugins/SimplnxCore/docs/ComputeFeatureRectFilter.md +++ b/src/Plugins/SimplnxCore/docs/CalculateFeatureBoundingBoxes.md @@ -1,4 +1,4 @@ -# Compute Feature Corners +# Calculate Feature Bounding Box ## Group (Subgroup) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeatureRect.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CalculateFeatureBoundingBoxes.cpp similarity index 86% rename from src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeatureRect.cpp rename to src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CalculateFeatureBoundingBoxes.cpp index 4bad48f4ee..78ebad241f 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeatureRect.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CalculateFeatureBoundingBoxes.cpp @@ -1,4 +1,4 @@ -#include "ComputeFeatureRect.hpp" +#include "CalculateFeatureBoundingBoxes.hpp" #include "simplnx/DataStructure/DataArray.hpp" @@ -14,7 +14,8 @@ usize IndexFromCoord(const std::vector& tDims, usize x, usize y, usize z) } // namespace // ----------------------------------------------------------------------------- -ComputeFeatureRect::ComputeFeatureRect(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeFeatureRectInputValues* inputValues) +CalculateFeatureBoundingBoxes::CalculateFeatureBoundingBoxes(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + CalculateFeatureBoundingBoxesInputValues* inputValues) : m_DataStructure(dataStructure) , m_InputValues(inputValues) , m_ShouldCancel(shouldCancel) @@ -23,16 +24,16 @@ ComputeFeatureRect::ComputeFeatureRect(DataStructure& dataStructure, const IFilt } // ----------------------------------------------------------------------------- -ComputeFeatureRect::~ComputeFeatureRect() noexcept = default; +CalculateFeatureBoundingBoxes::~CalculateFeatureBoundingBoxes() noexcept = default; // ----------------------------------------------------------------------------- -const std::atomic_bool& ComputeFeatureRect::getCancel() +const std::atomic_bool& CalculateFeatureBoundingBoxes::getCancel() { return m_ShouldCancel; } // ----------------------------------------------------------------------------- -Result<> ComputeFeatureRect::operator()() +Result<> CalculateFeatureBoundingBoxes::operator()() { const auto& featureIds = m_DataStructure.getDataRefAs(m_InputValues->FeatureIdsArrayPath); auto& corners = m_DataStructure.getDataRefAs(m_InputValues->FeatureRectArrayPath); diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CalculateFeatureBoundingBoxes.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CalculateFeatureBoundingBoxes.hpp new file mode 100644 index 0000000000..9323f7569c --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CalculateFeatureBoundingBoxes.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT CalculateFeatureBoundingBoxesInputValues +{ + DataPath FeatureIdsArrayPath; + DataPath FeatureDataAttributeMatrixPath; + DataPath FeatureRectArrayPath; +}; + +class SIMPLNXCORE_EXPORT CalculateFeatureBoundingBoxes +{ +public: + CalculateFeatureBoundingBoxes(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, CalculateFeatureBoundingBoxesInputValues* inputValues); + ~CalculateFeatureBoundingBoxes() noexcept; + + CalculateFeatureBoundingBoxes(const CalculateFeatureBoundingBoxes&) = delete; + CalculateFeatureBoundingBoxes(CalculateFeatureBoundingBoxes&&) noexcept = delete; + CalculateFeatureBoundingBoxes& operator=(const CalculateFeatureBoundingBoxes&) = delete; + CalculateFeatureBoundingBoxes& operator=(CalculateFeatureBoundingBoxes&&) noexcept = delete; + + Result<> operator()(); + + const std::atomic_bool& getCancel(); + +private: + DataStructure& m_DataStructure; + const CalculateFeatureBoundingBoxesInputValues* m_InputValues = nullptr; + const std::atomic_bool& m_ShouldCancel; + const IFilter::MessageHandler& m_MessageHandler; +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeatureRect.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeatureRect.hpp deleted file mode 100644 index 1a3f82ce17..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeatureRect.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" - -#include "simplnx/DataStructure/DataPath.hpp" -#include "simplnx/DataStructure/DataStructure.hpp" -#include "simplnx/Filter/IFilter.hpp" - -namespace nx::core -{ - -struct SIMPLNXCORE_EXPORT ComputeFeatureRectInputValues -{ - DataPath FeatureIdsArrayPath; - DataPath FeatureDataAttributeMatrixPath; - DataPath FeatureRectArrayPath; -}; - -class SIMPLNXCORE_EXPORT ComputeFeatureRect -{ -public: - ComputeFeatureRect(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeFeatureRectInputValues* inputValues); - ~ComputeFeatureRect() noexcept; - - ComputeFeatureRect(const ComputeFeatureRect&) = delete; - ComputeFeatureRect(ComputeFeatureRect&&) noexcept = delete; - ComputeFeatureRect& operator=(const ComputeFeatureRect&) = delete; - ComputeFeatureRect& operator=(ComputeFeatureRect&&) noexcept = delete; - - Result<> operator()(); - - const std::atomic_bool& getCancel(); - -private: - DataStructure& m_DataStructure; - const ComputeFeatureRectInputValues* m_InputValues = nullptr; - const std::atomic_bool& m_ShouldCancel; - const IFilter::MessageHandler& m_MessageHandler; -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedFeatures.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedFeatures.cpp index 254e05c81e..feabd809c0 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedFeatures.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedFeatures.cpp @@ -1,6 +1,6 @@ #include "RemoveFlaggedFeatures.hpp" -#include "SimplnxCore/Filters/ComputeFeatureRectFilter.hpp" +#include "SimplnxCore/Filters/CalculateFeatureBoundingBoxesFilter.hpp" #include "SimplnxCore/Filters/CropImageGeometryFilter.hpp" #include "simplnx/DataStructure/DataArray.hpp" @@ -314,12 +314,12 @@ Result<> RemoveFlaggedFeatures::operator()() m_MessageHandler(IFilter::ProgressMessage{IFilter::Message::Type::Info, fmt::format("Beginning Feature Extraction")}); { - ComputeFeatureRectFilter filter; + CalculateFeatureBoundingBoxesFilter filter; Arguments args; - args.insert(ComputeFeatureRectFilter::k_FeatureIdsArrayPath_Key, std::make_any(m_InputValues->FeatureIdsArrayPath)); - args.insert(ComputeFeatureRectFilter::k_FeatureDataAttributeMatrixPath_Key, std::make_any(m_InputValues->TempBoundsPath.getParent())); - args.insert(ComputeFeatureRectFilter::k_FeatureRectArrayName_Key, std::make_any(m_InputValues->TempBoundsPath.getTargetName())); + args.insert(CalculateFeatureBoundingBoxesFilter::k_FeatureIdsArrayPath_Key, std::make_any(m_InputValues->FeatureIdsArrayPath)); + args.insert(CalculateFeatureBoundingBoxesFilter::k_FeatureDataAttributeMatrixPath_Key, std::make_any(m_InputValues->TempBoundsPath.getParent())); + args.insert(CalculateFeatureBoundingBoxesFilter::k_FeatureRectArrayName_Key, std::make_any(m_InputValues->TempBoundsPath.getTargetName())); auto preflightResult = filter.preflight(m_DataStructure, args); if(preflightResult.outputActions.invalid()) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeFeatureRectFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CalculateFeatureBoundingBoxesFilter.cpp similarity index 74% rename from src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeFeatureRectFilter.cpp rename to src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CalculateFeatureBoundingBoxesFilter.cpp index b58ad7f135..07cdb597d1 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeFeatureRectFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CalculateFeatureBoundingBoxesFilter.cpp @@ -1,6 +1,6 @@ -#include "ComputeFeatureRectFilter.hpp" +#include "CalculateFeatureBoundingBoxesFilter.hpp" -#include "SimplnxCore/Filters/Algorithms/ComputeFeatureRect.hpp" +#include "SimplnxCore/Filters/Algorithms/CalculateFeatureBoundingBoxes.hpp" #include "simplnx/DataStructure/Geometry/IGridGeometry.hpp" #include "simplnx/Filter/Actions/CreateArrayAction.hpp" @@ -16,37 +16,37 @@ using namespace nx::core; namespace nx::core { //------------------------------------------------------------------------------ -std::string ComputeFeatureRectFilter::name() const +std::string CalculateFeatureBoundingBoxesFilter::name() const { - return FilterTraits::name.str(); + return FilterTraits::name.str(); } //------------------------------------------------------------------------------ -std::string ComputeFeatureRectFilter::className() const +std::string CalculateFeatureBoundingBoxesFilter::className() const { - return FilterTraits::className; + return FilterTraits::className; } //------------------------------------------------------------------------------ -Uuid ComputeFeatureRectFilter::uuid() const +Uuid CalculateFeatureBoundingBoxesFilter::uuid() const { - return FilterTraits::uuid; + return FilterTraits::uuid; } //------------------------------------------------------------------------------ -std::string ComputeFeatureRectFilter::humanName() const +std::string CalculateFeatureBoundingBoxesFilter::humanName() const { - return "Compute Feature Corners"; + return "Calculate Feature Bounding Box"; } //------------------------------------------------------------------------------ -std::vector ComputeFeatureRectFilter::defaultTags() const +std::vector CalculateFeatureBoundingBoxesFilter::defaultTags() const { - return {className(), "#Statistics", "#Reconstruction", "#Rect", "#Calculate"}; + return {className(), "Statistics", "Reconstruction", "Rect", "Calculate", "Find", "Bounding Box"}; } //------------------------------------------------------------------------------ -Parameters ComputeFeatureRectFilter::parameters() const +Parameters CalculateFeatureBoundingBoxesFilter::parameters() const { Parameters params; @@ -63,14 +63,14 @@ Parameters ComputeFeatureRectFilter::parameters() const } //------------------------------------------------------------------------------ -IFilter::UniquePointer ComputeFeatureRectFilter::clone() const +IFilter::UniquePointer CalculateFeatureBoundingBoxesFilter::clone() const { - return std::make_unique(); + return std::make_unique(); } //------------------------------------------------------------------------------ -IFilter::PreflightResult ComputeFeatureRectFilter::preflightImpl(const DataStructure& dataStructure, const Arguments& filterArgs, const MessageHandler& messageHandler, - const std::atomic_bool& shouldCancel) const +IFilter::PreflightResult CalculateFeatureBoundingBoxesFilter::preflightImpl(const DataStructure& dataStructure, const Arguments& filterArgs, const MessageHandler& messageHandler, + const std::atomic_bool& shouldCancel) const { auto pFeatureIdsArrayPathValue = filterArgs.value(k_FeatureIdsArrayPath_Key); auto pFeatureDataAttributeMatrixPathValue = filterArgs.value(k_FeatureDataAttributeMatrixPath_Key); @@ -106,16 +106,16 @@ IFilter::PreflightResult ComputeFeatureRectFilter::preflightImpl(const DataStruc } //------------------------------------------------------------------------------ -Result<> ComputeFeatureRectFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, - const std::atomic_bool& shouldCancel) const +Result<> CalculateFeatureBoundingBoxesFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, + const std::atomic_bool& shouldCancel) const { - ComputeFeatureRectInputValues inputValues; + CalculateFeatureBoundingBoxesInputValues inputValues; inputValues.FeatureIdsArrayPath = filterArgs.value(k_FeatureIdsArrayPath_Key); inputValues.FeatureDataAttributeMatrixPath = filterArgs.value(k_FeatureDataAttributeMatrixPath_Key); inputValues.FeatureRectArrayPath = inputValues.FeatureDataAttributeMatrixPath.createChildPath(filterArgs.value(k_FeatureRectArrayName_Key)); - return ComputeFeatureRect(dataStructure, messageHandler, shouldCancel, &inputValues)(); + return CalculateFeatureBoundingBoxes(dataStructure, messageHandler, shouldCancel, &inputValues)(); } namespace @@ -127,9 +127,9 @@ constexpr StringLiteral k_FeatureRectArrayPathKey = "FeatureRectArrayPath"; } // namespace SIMPL } // namespace -Result ComputeFeatureRectFilter::FromSIMPLJson(const nlohmann::json& json) +Result CalculateFeatureBoundingBoxesFilter::FromSIMPLJson(const nlohmann::json& json) { - Arguments args = ComputeFeatureRectFilter().getDefaultArguments(); + Arguments args = CalculateFeatureBoundingBoxesFilter().getDefaultArguments(); std::vector> results; diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeFeatureRectFilter.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CalculateFeatureBoundingBoxesFilter.hpp similarity index 81% rename from src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeFeatureRectFilter.hpp rename to src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CalculateFeatureBoundingBoxesFilter.hpp index d58125a304..973993fa8c 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeFeatureRectFilter.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CalculateFeatureBoundingBoxesFilter.hpp @@ -8,26 +8,26 @@ namespace nx::core { /** - * @class ComputeFeatureRectFilter + * @class CalculateFeatureBoundingBoxesFilter * @brief This filter computes the XYZ minimum and maximum coordinates for each Feature in a segmentation. * This data can be important for finding the smallest encompassing volume. The values are given in pixel * coordinates. */ -class SIMPLNXCORE_EXPORT ComputeFeatureRectFilter : public IFilter +class SIMPLNXCORE_EXPORT CalculateFeatureBoundingBoxesFilter : public IFilter { public: - ComputeFeatureRectFilter() = default; - ~ComputeFeatureRectFilter() noexcept override = default; + CalculateFeatureBoundingBoxesFilter() = default; + ~CalculateFeatureBoundingBoxesFilter() noexcept override = default; - ComputeFeatureRectFilter(const ComputeFeatureRectFilter&) = delete; - ComputeFeatureRectFilter(ComputeFeatureRectFilter&&) noexcept = delete; + CalculateFeatureBoundingBoxesFilter(const CalculateFeatureBoundingBoxesFilter&) = delete; + CalculateFeatureBoundingBoxesFilter(CalculateFeatureBoundingBoxesFilter&&) noexcept = delete; - ComputeFeatureRectFilter& operator=(const ComputeFeatureRectFilter&) = delete; - ComputeFeatureRectFilter& operator=(ComputeFeatureRectFilter&&) noexcept = delete; + CalculateFeatureBoundingBoxesFilter& operator=(const CalculateFeatureBoundingBoxesFilter&) = delete; + CalculateFeatureBoundingBoxesFilter& operator=(CalculateFeatureBoundingBoxesFilter&&) noexcept = delete; // Parameter Keys static inline constexpr StringLiteral k_FeatureIdsArrayPath_Key = "feature_ids_array_path"; - static inline constexpr StringLiteral k_FeatureRectArrayName_Key = "feature_rect_array_name"; + static inline constexpr StringLiteral k_FeatureRectArrayName_Key = "output_bounding_box_array_name"; static inline constexpr StringLiteral k_FeatureDataAttributeMatrixPath_Key = "feature_data_attribute_matrix_path"; /** @@ -104,5 +104,5 @@ class SIMPLNXCORE_EXPORT ComputeFeatureRectFilter : public IFilter }; } // namespace nx::core -SIMPLNX_DEF_FILTER_TRAITS(nx::core, ComputeFeatureRectFilter, "bf947c45-8610-44c9-917a-405e88f73fe7"); +SIMPLNX_DEF_FILTER_TRAITS(nx::core, CalculateFeatureBoundingBoxesFilter, "bf947c45-8610-44c9-917a-405e88f73fe7"); /* LEGACY UUID FOR THIS FILTER 6eda8dbf-dbd8-562a-ae1a-f2904157c189 */ diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CalculateFeatureSizesFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CalculateFeatureSizesFilter.cpp index 2ada87fba6..5fd9f56983 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CalculateFeatureSizesFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CalculateFeatureSizesFilter.cpp @@ -9,9 +9,10 @@ #include "simplnx/Parameters/BoolParameter.hpp" #include "simplnx/Parameters/DataObjectNameParameter.hpp" #include "simplnx/Parameters/GeometrySelectionParameter.hpp" - #include "simplnx/Utilities/SIMPLConversion.hpp" +#include "SimplnxCore/Filters/Algorithms/CalculateFeatureBoundingBoxes.hpp" + #include namespace nx::core @@ -23,6 +24,7 @@ constexpr nx::core::int32 k_MissingFeatureIds = -74789; constexpr nx::core::int32 k_MissingFeatureAttributeMatrix = -74769; constexpr nx::core::int32 k_BadFeatureCount = -78231; constexpr nx::core::float32 k_PI = numbers::pi_v; + } // namespace std::string CalculateFeatureSizesFilter::name() const @@ -69,9 +71,10 @@ Parameters CalculateFeatureSizesFilter::parameters() const DataPath({"CellFeatureData"}))); params.insertSeparator(Parameters::Separator{"Created Feature Data"}); - params.insert(std::make_unique(k_EquivalentDiametersName_Key, "Equivalent Diameters", "DataPath to equivalent diameters array", "EquivalentDiameters")); - params.insert(std::make_unique(k_NumElementsName_Key, "Number of Elements", "DataPath to Num Elements array", "NumElements")); - params.insert(std::make_unique(k_VolumesName_Key, "Volumes", "DataPath to volumes array", "Volumes")); + params.insert(std::make_unique(k_EquivalentDiametersName_Key, "Equivalent Diameters", "Equivalent diameters array name", "EquivalentDiameters")); + params.insert(std::make_unique(k_NumElementsName_Key, "Number of Elements", "Output Num Elements array name", "NumElements")); + params.insert(std::make_unique(k_VolumesName_Key, "Volumes", "Output Volumes array name", "Volumes")); + params.insert(std::make_unique(k_FeretDiameterName_Key, "Feret Diameter (Caliper Diameter)", "Output Feret diameter array name", "Feret Diameter")); return params; } @@ -91,9 +94,12 @@ IFilter::PreflightResult CalculateFeatureSizesFilter::preflightImpl(const DataSt auto volumesName = args.value(k_VolumesName_Key); auto equivalentDiametersName = args.value(k_EquivalentDiametersName_Key); auto numElementsName = args.value(k_NumElementsName_Key); + auto feretName = args.value(k_FeretDiameterName_Key); + DataPath volumesPath = featureAttributeMatrixPath.createChildPath(volumesName); DataPath equivalentDiametersPath = featureAttributeMatrixPath.createChildPath(equivalentDiametersName); DataPath numElementsPath = featureAttributeMatrixPath.createChildPath(numElementsName); + DataPath feretDiameterPath = featureAttributeMatrixPath.createChildPath(feretName); const auto* featureIdsArray = dataStructure.getDataAs(featureIdsPath); @@ -124,11 +130,13 @@ IFilter::PreflightResult CalculateFeatureSizesFilter::preflightImpl(const DataSt auto createVolumesAction = std::make_unique(DataType::float32, tupleDimensions, std::vector{numberOfComponents}, volumesPath, arrayDataFormat); auto createEquivalentDiametersAction = std::make_unique(DataType::float32, tupleDimensions, std::vector{numberOfComponents}, equivalentDiametersPath, arrayDataFormat); auto createNumElementsAction = std::make_unique(DataType::int32, tupleDimensions, std::vector{numberOfComponents}, numElementsPath, arrayDataFormat); + auto createFeretDiametersAction = std::make_unique(DataType::float32, tupleDimensions, std::vector{7}, feretDiameterPath, arrayDataFormat); OutputActions actions; actions.appendAction(std::move(createVolumesAction)); actions.appendAction(std::move(createEquivalentDiametersAction)); actions.appendAction(std::move(createNumElementsAction)); + actions.appendAction(std::move(createFeretDiametersAction)); return {std::move(actions)}; } @@ -141,26 +149,31 @@ Result<> CalculateFeatureSizesFilter::executeImpl(DataStructure& dataStructure, const auto& featureIdsArray = dataStructure.getDataRefAs(featureIdsPath); const auto& featureIds = featureIdsArray.getDataStoreRef(); + auto featureAttributeMatrixPath = args.value(k_CellFeatureAttributeMatrixPath_Key); + auto volumesName = args.value(k_VolumesName_Key); + auto equivalentDiametersName = args.value(k_EquivalentDiametersName_Key); + auto numElementsName = args.value(k_NumElementsName_Key); + auto feretDiamName = args.value(k_FeretDiameterName_Key); + + DataPath volumesPath = featureAttributeMatrixPath.createChildPath(volumesName); + DataPath equivalentDiametersPath = featureAttributeMatrixPath.createChildPath(equivalentDiametersName); + DataPath numElementsPath = featureAttributeMatrixPath.createChildPath(numElementsName); + DataPath feretDiamPath = featureAttributeMatrixPath.createChildPath(feretDiamName); + + auto& volumes = dataStructure.getDataRefAs(volumesPath); + auto& equivalentDiameters = dataStructure.getDataRefAs(equivalentDiametersPath); + auto& numElements = dataStructure.getDataRefAs(numElementsPath); + auto& feretDiameters = dataStructure.getDataRefAs(feretDiamPath); + usize totalPoints = featureIdsArray.getNumberOfTuples(); auto geomPath = args.value(k_GeometryPath_Key); - auto* geom = dataStructure.getDataAs(geomPath); + auto* geom = dataStructure.getDataAs(geomPath); // If the geometry is an ImageGeometry or a RectilinearGeometry auto* imageGeom = dynamic_cast(geom); - if(nullptr != imageGeom) + if(nullptr != imageGeom) // Image Geometry { - auto featureAttributeMatrixPath = args.value(k_CellFeatureAttributeMatrixPath_Key); - auto volumesName = args.value(k_VolumesName_Key); - auto equivalentDiametersName = args.value(k_EquivalentDiametersName_Key); - auto numElementsName = args.value(k_NumElementsName_Key); - - DataPath volumesPath = featureAttributeMatrixPath.createChildPath(volumesName); - DataPath equivalentDiametersPath = featureAttributeMatrixPath.createChildPath(equivalentDiametersName); - DataPath numElementsPath = featureAttributeMatrixPath.createChildPath(numElementsName); - auto& volumes = dataStructure.getDataRefAs(volumesPath); - auto& equivalentDiameters = dataStructure.getDataRefAs(equivalentDiametersPath); - auto& numElements = dataStructure.getDataRefAs(numElementsPath); usize featureIdsMaxIdx = std::distance(featureIds.begin(), std::max_element(featureIds.cbegin(), featureIds.cend())); usize maxValue = featureIds[featureIdsMaxIdx]; @@ -176,7 +189,7 @@ Result<> CalculateFeatureSizesFilter::executeImpl(DataStructure& dataStructure, } FloatVec3 spacing = imageGeom->getSpacing(); - + // 2D Case if(imageGeom->getNumXCells() == 1 || imageGeom->getNumYCells() == 1 || imageGeom->getNumZCells() == 1) { float res_scalar = 0.0f; @@ -242,16 +255,8 @@ Result<> CalculateFeatureSizesFilter::executeImpl(DataStructure& dataStructure, } } } - else + else // Rectilinear Grid { - auto volumesPath = args.value(k_VolumesName_Key); - auto equivalentDiametersPath = args.value(k_EquivalentDiametersName_Key); - auto numElementsPath = args.value(k_NumElementsName_Key); - - auto& volumes = dataStructure.getDataRefAs(volumesPath); - auto& equivalentDiameters = dataStructure.getDataRefAs(equivalentDiametersPath); - auto& numElements = dataStructure.getDataRefAs(numElementsPath); - usize numfeatures = volumes.getNumberOfTuples(); if(!geom->getElementSizes()) @@ -291,6 +296,101 @@ Result<> CalculateFeatureSizesFilter::executeImpl(DataStructure& dataStructure, } } + // Calculate the Feret Diameters (Caliper diameters) + { + auto featureAttrMat = dataStructure.getDataRefAs(featureAttributeMatrixPath); + auto numFeatures = featureAttrMat.getNumTuples(); + + std::vector corners(numFeatures * 6); + // Create corners array, which stores pixel coordinates for the top-left and bottom-right coordinates of each feature object + for(usize i = 0; i < numFeatures; i++) + { + corners[i * 6 + 0] = std::numeric_limits::max(); + corners[i * 6 + 1] = std::numeric_limits::max(); + corners[i * 6 + 2] = std::numeric_limits::max(); + corners[i * 6 + 3] = std::numeric_limits::min(); + corners[i * 6 + 4] = std::numeric_limits::min(); + corners[i * 6 + 5] = std::numeric_limits::min(); + } + auto imageDims = geom->getDimensions(); + + const usize xDim = imageDims[0]; + const usize yDim = imageDims[1]; + const usize zDim = imageDims[2]; + + usize index = 0; + // Store the coordinates in the corners array + for(uint32 z = 0; z < zDim; z++) + { + if(shouldCancel) + { + return {}; + } + + for(uint32 y = 0; y < yDim; y++) + { + for(uint32 x = 0; x < xDim; x++) + { + index = (imageDims[1] * imageDims[0] * z) + (imageDims[0] * y) + x; // Index into featureIds array + + const int32 featureId = featureIds[index]; + if(featureId == 0) + { + continue; + } + + if(featureId >= numFeatures) + { + return MakeErrorResult( + -31000, fmt::format("The largest featureId is '{}' but the Feature Attribute Matrix '{}' only allows '{}' features.", featureId, featureAttributeMatrixPath.toString(), numFeatures)); + } + + const uint32 indices[3] = {x, y, z}; // Sequence dependent DO NOT REORDER + const int32 featureShift = featureId * 6; + for(uint8 l = 0; l < 6; l++) // unsigned is faster with modulo + { + if(l > 2) + { + corners[featureShift + l] = std::max(corners[featureShift + l], indices[l - 3]); + } + else + { + corners[featureShift + l] = std::min(corners[featureShift + l], indices[l]); + } + } + } + } + } + + for(size_t featureIdx = 1; featureIdx < numFeatures; featureIdx++) + { + auto cellBounds = geom->getCellBounds(static_cast(corners[featureIdx * 6 + 0]), static_cast(corners[featureIdx * 6 + 1]), static_cast(corners[featureIdx * 6 + 2])); + Point3Df minCoord = cellBounds.first; + cellBounds = geom->getCellBounds(static_cast(corners[featureIdx * 6 + 3]), static_cast(corners[featureIdx * 6 + 4]), static_cast(corners[featureIdx * 6 + 5])); + Point3Df maxCoord = cellBounds.second; + + float xDist = maxCoord[0] - minCoord[0]; + float yDist = maxCoord[1] - minCoord[1]; + float zDist = maxCoord[2] - minCoord[2]; + + float xyDist = (Point3Df(maxCoord[0], maxCoord[1], minCoord[2]) - Point3Df(minCoord[0], minCoord[1], minCoord[2])).magnitude(); + float xzDist = (Point3Df(maxCoord[0], minCoord[1], maxCoord[2]) - Point3Df(minCoord[0], minCoord[1], minCoord[2])).magnitude(); + float yzDist = (Point3Df(minCoord[0], maxCoord[1], maxCoord[2]) - Point3Df(minCoord[0], minCoord[1], minCoord[2])).magnitude(); + + float spaceDiag = (Point3Df(maxCoord[0], maxCoord[1], maxCoord[2]) - Point3Df(minCoord[0], minCoord[1], minCoord[2])).magnitude(); + + feretDiameters.setComponent(featureIdx, 0, xDist); + feretDiameters.setComponent(featureIdx, 1, yDist); + feretDiameters.setComponent(featureIdx, 2, zDist); + + feretDiameters.setComponent(featureIdx, 3, xyDist); + feretDiameters.setComponent(featureIdx, 4, xzDist); + feretDiameters.setComponent(featureIdx, 5, yzDist); + + feretDiameters.setComponent(featureIdx, 6, spaceDiag); + } + } + return {}; } diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CalculateFeatureSizesFilter.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CalculateFeatureSizesFilter.hpp index 92718af9c4..7e36296ede 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CalculateFeatureSizesFilter.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CalculateFeatureSizesFilter.hpp @@ -33,6 +33,7 @@ class SIMPLNXCORE_EXPORT CalculateFeatureSizesFilter : public IFilter static inline constexpr StringLiteral k_VolumesName_Key = "volumes_name"; static inline constexpr StringLiteral k_EquivalentDiametersName_Key = "equivalent_diameters_name"; static inline constexpr StringLiteral k_NumElementsName_Key = "num_elements_name"; + static inline constexpr StringLiteral k_FeretDiameterName_Key = "feret_diameter_name"; /** * @brief Reads SIMPL json and converts it simplnx Arguments. diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/SimplnxCoreLegacyUUIDMapping.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/SimplnxCoreLegacyUUIDMapping.hpp index 97f0db619a..512184bcde 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/SimplnxCoreLegacyUUIDMapping.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/SimplnxCoreLegacyUUIDMapping.hpp @@ -96,7 +96,7 @@ #include "SimplnxCore/Filters/ExecuteProcessFilter.hpp" #include "SimplnxCore/Filters/FindVertexToTriangleDistancesFilter.hpp" #include "SimplnxCore/Filters/ApplyTransformationToGeometryFilter.hpp" -#include "SimplnxCore/Filters/ComputeFeatureRectFilter.hpp" +#include "SimplnxCore/Filters/CalculateFeatureBoundingBoxesFilter.hpp" #include "SimplnxCore/Filters/FindLargestCrossSectionsFilter.hpp" #include "SimplnxCore/Filters/WriteStlFileFilter.hpp" #include "SimplnxCore/Filters/AddBadDataFilter.hpp" @@ -222,7 +222,7 @@ namespace nx::core {nx::core::Uuid::FromString("27a132b2-a592-519a-8cb7-38599a7f28ec").value(), {nx::core::FilterTraits::uuid, &ComputeMomentInvariants2DFilter::FromSIMPLJson}}, // ComputeMomentInvariants2D {nx::core::Uuid::FromString("fcdde553-36b4-5731-bc88-fc499806cb4e").value(), {nx::core::FilterTraits::uuid, &FindVertexToTriangleDistancesFilter::FromSIMPLJson}}, // FindVertexToTriangleDistances {nx::core::Uuid::FromString("c681caf4-22f2-5885-bbc9-a0476abc72eb").value(), {nx::core::FilterTraits::uuid, {}}}, // ApplyTransformationToGeometry - {nx::core::Uuid::FromString("6eda8dbf-dbd8-562a-ae1a-f2904157c189").value(), {nx::core::FilterTraits::uuid, &ComputeFeatureRectFilter::FromSIMPLJson}}, // ComputeFeatureRect + {nx::core::Uuid::FromString("6eda8dbf-dbd8-562a-ae1a-f2904157c189").value(), {nx::core::FilterTraits::uuid, &CalculateFeatureBoundingBoxesFilter::FromSIMPLJson}}, // ComputeFeatureRect {nx::core::Uuid::FromString("9f77b4a9-6416-5220-a688-115f4e14c90d").value(), {nx::core::FilterTraits::uuid, &FindLargestCrossSectionsFilter::FromSIMPLJson}}, // FindLargestCrossSections {nx::core::Uuid::FromString("b9134758-d5e5-59dd-9907-28d23e0e0143").value(), {nx::core::FilterTraits::uuid, &WriteStlFileFilter::FromSIMPLJson}}, // WriteStlFile {nx::core::Uuid::FromString("ac99b706-d1e0-5f78-9246-fbbe1efd93d2").value(), {nx::core::FilterTraits::uuid, &AddBadDataFilter::FromSIMPLJson}}, // AddBadData diff --git a/src/Plugins/SimplnxCore/test/CMakeLists.txt b/src/Plugins/SimplnxCore/test/CMakeLists.txt index 75b7e7050d..d533b9e429 100644 --- a/src/Plugins/SimplnxCore/test/CMakeLists.txt +++ b/src/Plugins/SimplnxCore/test/CMakeLists.txt @@ -20,7 +20,7 @@ set(${PLUGIN_NAME}UnitTest_SRCS ChangeAngleRepresentationTest.cpp CombineAttributeArraysTest.cpp CombineStlFilesTest.cpp - ComputeFeatureRectTest.cpp + CalculateFeatureBoundingBoxesTest.cpp ComputeMomentInvariants2DTest.cpp ConditionalSetValueTest.cpp ConvertColorToGrayScaleTest.cpp diff --git a/src/Plugins/SimplnxCore/test/ComputeFeatureRectTest.cpp b/src/Plugins/SimplnxCore/test/CalculateFeatureBoundingBoxesTest.cpp similarity index 86% rename from src/Plugins/SimplnxCore/test/ComputeFeatureRectTest.cpp rename to src/Plugins/SimplnxCore/test/CalculateFeatureBoundingBoxesTest.cpp index 4402ca5244..c5a0f3f076 100644 --- a/src/Plugins/SimplnxCore/test/ComputeFeatureRectTest.cpp +++ b/src/Plugins/SimplnxCore/test/CalculateFeatureBoundingBoxesTest.cpp @@ -1,7 +1,7 @@ #include "simplnx/DataStructure/Geometry/ImageGeom.hpp" #include "simplnx/UnitTest/UnitTestCommon.hpp" -#include "SimplnxCore/Filters/ComputeFeatureRectFilter.hpp" +#include "SimplnxCore/Filters/CalculateFeatureBoundingBoxesFilter.hpp" #include "SimplnxCore/SimplnxCore_test_dirs.hpp" #include @@ -97,18 +97,18 @@ DataStructure CreateTestData() } } // namespace -TEST_CASE("SimplnxCore::ComputeFeatureRectFilter: Valid filter execution", "[SimplnxCore][ComputeFeatureRectFilter]") +TEST_CASE("SimplnxCore::CalculateFeatureBoundingBoxesFilter: Valid filter execution", "[SimplnxCore][CalculateFeatureBoundingBoxesFilter]") { Application::GetOrCreateInstance()->loadPlugins(unit_test::k_BuildDir.view(), true); // Instantiate the filter, a DataStructure object and an Arguments Object - ComputeFeatureRectFilter filter; + CalculateFeatureBoundingBoxesFilter filter; DataStructure dataStructure = CreateTestData(); Arguments args; - args.insertOrAssign(ComputeFeatureRectFilter::k_FeatureIdsArrayPath_Key, std::make_any(DataPath{{k_ImageGeometryName, k_CellAttrMatrixName, k_FeatureIdsArrayName}})); - args.insertOrAssign(ComputeFeatureRectFilter::k_FeatureDataAttributeMatrixPath_Key, std::make_any(DataPath{{k_ImageGeometryName, k_FeatureAttrMatrixName}})); - args.insertOrAssign(ComputeFeatureRectFilter::k_FeatureRectArrayName_Key, std::make_any(k_RectCoordsArrayName)); + args.insertOrAssign(CalculateFeatureBoundingBoxesFilter::k_FeatureIdsArrayPath_Key, std::make_any(DataPath{{k_ImageGeometryName, k_CellAttrMatrixName, k_FeatureIdsArrayName}})); + args.insertOrAssign(CalculateFeatureBoundingBoxesFilter::k_FeatureDataAttributeMatrixPath_Key, std::make_any(DataPath{{k_ImageGeometryName, k_FeatureAttrMatrixName}})); + args.insertOrAssign(CalculateFeatureBoundingBoxesFilter::k_FeatureRectArrayName_Key, std::make_any(k_RectCoordsArrayName)); // Preflight the filter and check result auto preflightResult = filter.preflight(dataStructure, args); diff --git a/src/simplnx/DataStructure/Geometry/IGridGeometry.hpp b/src/simplnx/DataStructure/Geometry/IGridGeometry.hpp index 0d55fb01ae..67749f94a4 100644 --- a/src/simplnx/DataStructure/Geometry/IGridGeometry.hpp +++ b/src/simplnx/DataStructure/Geometry/IGridGeometry.hpp @@ -116,6 +116,15 @@ class SIMPLNX_EXPORT IGridGeometry : public IGeometry */ virtual Point3D getCoordsf(usize x, usize y, usize z) const = 0; + /** + * @brief Returns the min and max coordinates of the cell specified by the the X, Y, Z index + * @param x + * @param y + * @param z + * @return + */ + virtual std::pair getCellBounds(usize x, usize y, usize z) const = 0; + /** * @brief * @param idx diff --git a/src/simplnx/DataStructure/Geometry/ImageGeom.cpp b/src/simplnx/DataStructure/Geometry/ImageGeom.cpp index 94743edb6b..c373808bff 100644 --- a/src/simplnx/DataStructure/Geometry/ImageGeom.cpp +++ b/src/simplnx/DataStructure/Geometry/ImageGeom.cpp @@ -2,11 +2,8 @@ #include "simplnx/DataStructure/DataStore.hpp" #include "simplnx/DataStructure/DataStructure.hpp" -#include "simplnx/Utilities/GeometryHelpers.hpp" #include "simplnx/Utilities/StringUtilities.hpp" -#include - using namespace nx::core; ImageGeom::ImageGeom(DataStructure& dataStructure, std::string name) @@ -167,13 +164,9 @@ Point3D ImageGeom::getParametricCenter() const void ImageGeom::getShapeFunctions(const Point3D& pCoords, float64* shape) const { - float64 rm = 0.0; - float64 sm = 0.0; - float64 tm = 0.0; - - rm = 1.0 - pCoords[0]; - sm = 1.0 - pCoords[1]; - tm = 1.0 - pCoords[2]; + float64 rm = 1.0 - pCoords[0]; + float64 sm = 1.0 - pCoords[1]; + float64 tm = 1.0 - pCoords[2]; // r derivatives shape[0] = -sm * tm; @@ -311,6 +304,20 @@ Point3D ImageGeom::getPlaneCoords(usize idx) const return coords; } +std::pair ImageGeom::getCellBounds(usize x, usize y, usize z) const +{ + Point3Df minCoords; + minCoords[0] = x * m_Spacing[0] + m_Origin[0]; + minCoords[1] = y * m_Spacing[1] + m_Origin[1]; + minCoords[2] = z * m_Spacing[2] + m_Origin[2]; + + Point3Df maxCoords; + maxCoords[0] = x * m_Spacing[0] + m_Origin[0] + m_Spacing[0]; + maxCoords[1] = y * m_Spacing[1] + m_Origin[1] + m_Spacing[1]; + maxCoords[2] = z * m_Spacing[2] + m_Origin[2] + m_Spacing[2]; + return {minCoords, maxCoords}; +} + Point3D ImageGeom::getCoordsf(usize idx[3]) const { Point3D coords; diff --git a/src/simplnx/DataStructure/Geometry/ImageGeom.hpp b/src/simplnx/DataStructure/Geometry/ImageGeom.hpp index 63fc282cc6..157030cbfd 100644 --- a/src/simplnx/DataStructure/Geometry/ImageGeom.hpp +++ b/src/simplnx/DataStructure/Geometry/ImageGeom.hpp @@ -268,6 +268,15 @@ class SIMPLNX_EXPORT ImageGeom : public IGridGeometry */ Point3D getPlaneCoords(usize idx) const override; + /** + * @brief Returns the min and max coordinates of the cell specified by the the X, Y, Z index + * @param x + * @param y + * @param z + * @return + */ + std::pair getCellBounds(usize x, usize y, usize z) const override; + /** * @brief * @param idx diff --git a/src/simplnx/DataStructure/Geometry/RectGridGeom.cpp b/src/simplnx/DataStructure/Geometry/RectGridGeom.cpp index 0927fbf724..a8bf3376a7 100644 --- a/src/simplnx/DataStructure/Geometry/RectGridGeom.cpp +++ b/src/simplnx/DataStructure/Geometry/RectGridGeom.cpp @@ -3,7 +3,6 @@ #include "simplnx/DataStructure/DataStore.hpp" #include "simplnx/DataStructure/DataStructure.hpp" #include "simplnx/Utilities/DataObjectUtilities.hpp" -#include "simplnx/Utilities/GeometryHelpers.hpp" #include #include @@ -544,6 +543,24 @@ Point3D RectGridGeom::getPlaneCoords(usize idx) const return coords; } +std::pair RectGridGeom::getCellBounds(usize x, usize y, usize z) const +{ + auto xBnds = getXBounds(); + auto yBnds = getYBounds(); + auto zBnds = getZBounds(); + + Point3Df minCoords; + minCoords[0] = static_cast((*xBnds)[x]); + minCoords[1] = static_cast((*yBnds)[y]); + minCoords[2] = static_cast((*zBnds)[z]); + + Point3Df maxCoords; + maxCoords[0] = (*xBnds)[x + 1]; + maxCoords[1] = (*yBnds)[y + 1]; + maxCoords[2] = (*zBnds)[z + 1]; + return {minCoords, maxCoords}; +} + Point3D RectGridGeom::getCoordsf(usize idx[3]) const { auto xBnds = getXBounds(); diff --git a/src/simplnx/DataStructure/Geometry/RectGridGeom.hpp b/src/simplnx/DataStructure/Geometry/RectGridGeom.hpp index f3eb646dcc..91d257ee87 100644 --- a/src/simplnx/DataStructure/Geometry/RectGridGeom.hpp +++ b/src/simplnx/DataStructure/Geometry/RectGridGeom.hpp @@ -305,6 +305,15 @@ class SIMPLNX_EXPORT RectGridGeom : public IGridGeometry */ Point3D getPlaneCoords(usize idx) const override; + /** + * @brief Returns the min and max coordinates of the cell specified by the the X, Y, Z index + * @param x + * @param y + * @param z + * @return + */ + std::pair getCellBounds(usize x, usize y, usize z) const override; + /** * @brief * @param idx