diff --git a/src/Plugins/OrientationAnalysis/CMakeLists.txt b/src/Plugins/OrientationAnalysis/CMakeLists.txt index 818b9f05ad..226516fb36 100644 --- a/src/Plugins/OrientationAnalysis/CMakeLists.txt +++ b/src/Plugins/OrientationAnalysis/CMakeLists.txt @@ -176,21 +176,22 @@ set(filter_algorithms ComputeFaceIPFColoring ComputeFeatureFaceMisorientation ComputeFeatureNeighborCAxisMisalignments + ComputeFeatureNeighborMisorientations ComputeFeatureReferenceCAxisMisorientations ComputeFeatureReferenceMisorientations + ComputeFZQuaternions ComputeGBCD ComputeGBCDMetricBased ComputeGBCDPoleFigure ComputeGBPDMetricBased ComputeIPFColors ComputeKernelAvgMisorientations - ComputeFeatureNeighborMisorientations ComputeMisorientations ComputeQuaternionConjugate ComputeSchmids ComputeShapes - ComputeSlipTransmissionMetrics ComputeShapesTriangleGeom + ComputeSlipTransmissionMetrics ComputeTwinBoundaries ConvertHexGridToSquareGrid ConvertOrientations diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ComputeFZQuaternions.cpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ComputeFZQuaternions.cpp new file mode 100644 index 0000000000..9577476b0b --- /dev/null +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ComputeFZQuaternions.cpp @@ -0,0 +1,180 @@ +#include "ComputeFZQuaternions.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" +#include "simplnx/Utilities/ParallelDataAlgorithm.hpp" + +#include "EbsdLib/Core/EbsdLibConstants.h" +#include "EbsdLib/LaueOps/LaueOps.h" + +using namespace nx::core; + +namespace +{ +/** + * @brief The GenerateFZQuatsImpl class implements a threaded algorithm that computes the Fundamental Zone Quaternion + * for a given Quaternion and Laue Class (which is based from the crystalStructures array + */ +template +class GenerateFZQuatsImpl +{ +public: + GenerateFZQuatsImpl(Float32Array& quats, Int32Array& phases, UInt32Array& crystalStructures, int32_t numPhases, MaskArrayType* goodVoxels, Float32Array& fzQuats, + const std::atomic_bool& shouldCancel, std::atomic_int32_t& warningCount) + : m_Quats(quats) + , m_CellPhases(phases) + , m_CrystalStructures(crystalStructures) + , m_NumPhases(numPhases) + , m_GoodVoxels(goodVoxels) + , m_FZQuats(fzQuats) + , m_ShouldCancel(shouldCancel) + , m_WarningCount(warningCount) + { + } + + virtual ~GenerateFZQuatsImpl() = default; + + /** + * @brief convert + * @param start + * @param end + */ + void convert(size_t start, size_t end) const + { + std::vector ops = LaueOps::GetAllOrientationOps(); + int32_t phase = 0; + bool generateFZQuat = false; + size_t index = 0; + + for(size_t i = start; i < end; i++) + { + if(m_ShouldCancel) + { + break; + } + phase = m_CellPhases[i]; + + generateFZQuat = true; + if(nullptr != m_GoodVoxels) + { + generateFZQuat = static_cast((*m_GoodVoxels)[i]); + } + + // Sanity check the phase data to make sure we do not walk off the end of the array + if(phase >= m_NumPhases) + { + m_WarningCount++; + } + + // Initialize the output to zero. There really isn't a good value to use. + index = i * 4; + m_FZQuats[index] = 0.0f; + m_FZQuats[index + 1] = 0.0f; + m_FZQuats[index + 2] = 0.0f; + m_FZQuats[index + 3] = 0.0f; + + if(phase < m_NumPhases && generateFZQuat && m_CrystalStructures[phase] < EbsdLib::CrystalStructure::LaueGroupEnd) + { + QuatD quatD = QuatD(m_Quats[index], m_Quats[index + 1], m_Quats[index + 2], m_Quats[index + 3]); // Makes a copy into q + int32_t xtal = static_cast(m_CrystalStructures[phase]); // get the Laue Group + quatD = ops[xtal]->getFZQuat(quatD); + m_FZQuats[index] = quatD.x(); + m_FZQuats[index + 1] = quatD.y(); + m_FZQuats[index + 2] = quatD.z(); + m_FZQuats[index + 3] = quatD.w(); + } + } + } + + void operator()(const Range& range) const + { + convert(range.min(), range.max()); + } + +private: + Float32Array& m_Quats; + Int32Array& m_CellPhases; + UInt32Array& m_CrystalStructures; + int32_t m_NumPhases = 0; + MaskArrayType* m_GoodVoxels; + Float32Array& m_FZQuats; + const std::atomic_bool& m_ShouldCancel; + std::atomic_int32_t& m_WarningCount; +}; +} // namespace + +// ----------------------------------------------------------------------------- +ComputeFZQuaternions::ComputeFZQuaternions(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeFZQuaternionsInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ComputeFZQuaternions::~ComputeFZQuaternions() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ComputeFZQuaternions::operator()() +{ + + Int32Array& phaseArray = m_DataStructure.getDataRefAs(m_InputValues->CellPhasesArrayPath); + Float32Array& quatArray = m_DataStructure.getDataRefAs(m_InputValues->InputQuatsArrayPath); + UInt32Array& xtalArray = m_DataStructure.getDataRefAs(m_InputValues->CrystalStructuresArrayPath); + IDataArray* maskArray = m_DataStructure.getDataAs(m_InputValues->MaskArrayPath); + Float32Array& fzQuatArray = m_DataStructure.getDataRefAs(m_InputValues->InputQuatsArrayPath.replaceName(m_InputValues->OutputFzQuatsArrayName)); + + std::atomic_int32_t warningCount = 0; + int32_t numPhases = static_cast(xtalArray.getNumberOfTuples()); + + typename IParallelAlgorithm::AlgorithmArrays algArrays; + algArrays.push_back(&phaseArray); + algArrays.push_back(&quatArray); + algArrays.push_back(&xtalArray); + algArrays.push_back(&fzQuatArray); + + if(m_InputValues->UseMask) + { + algArrays.push_back(maskArray); + } + + // Parallel algorithm + ParallelDataAlgorithm dataAlg; + dataAlg.setRange(0ULL, static_cast(quatArray.getNumberOfTuples())); + dataAlg.requireArraysInMemory(algArrays); + + if(m_InputValues->UseMask) + { + if(maskArray->getDataType() == DataType::boolean) + { + BoolArray* goodVoxelsArray = m_DataStructure.getDataAs(m_InputValues->MaskArrayPath); + dataAlg.execute(::GenerateFZQuatsImpl(quatArray, phaseArray, xtalArray, numPhases, goodVoxelsArray, fzQuatArray, m_ShouldCancel, warningCount)); + } + else if(maskArray->getDataType() == DataType::uint8) + { + UInt32Array* goodVoxelsArray = m_DataStructure.getDataAs(m_InputValues->MaskArrayPath); + dataAlg.execute(::GenerateFZQuatsImpl(quatArray, phaseArray, xtalArray, numPhases, goodVoxelsArray, fzQuatArray, m_ShouldCancel, warningCount)); + } + else if(maskArray->getDataType() == DataType::int8) + { + Int8Array* goodVoxelsArray = m_DataStructure.getDataAs(m_InputValues->MaskArrayPath); + dataAlg.execute(::GenerateFZQuatsImpl(quatArray, phaseArray, xtalArray, numPhases, goodVoxelsArray, fzQuatArray, m_ShouldCancel, warningCount)); + } + } + else + { + dataAlg.execute(::GenerateFZQuatsImpl(quatArray, phaseArray, xtalArray, numPhases, nullptr, fzQuatArray, m_ShouldCancel, warningCount)); + } + + if(warningCount > 0) + { + std::string errorMessage = fmt::format("The Ensemble Phase information only references {} phase(s) but {} cell(s) had a phase value greater than {}. \ +This indicates a problem with the input cell phase data. DREAM3D-NX may have given INCORRECT RESULTS.", + numPhases - 1, warningCount.load(), numPhases - 1); + + return {MakeErrorResult<>(-49008, errorMessage)}; + } + + return {}; +} diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ComputeFZQuaternions.hpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ComputeFZQuaternions.hpp new file mode 100644 index 0000000000..526f6d4b85 --- /dev/null +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ComputeFZQuaternions.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "OrientationAnalysis/OrientationAnalysis_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" + +namespace nx::core +{ + +struct ORIENTATIONANALYSIS_EXPORT ComputeFZQuaternionsInputValues +{ + ArraySelectionParameter::ValueType CellPhasesArrayPath; + ArraySelectionParameter::ValueType CrystalStructuresArrayPath; + ArraySelectionParameter::ValueType InputQuatsArrayPath; + ArraySelectionParameter::ValueType MaskArrayPath; + DataObjectNameParameter::ValueType OutputFzQuatsArrayName; + BoolParameter::ValueType UseMask; +}; + +/** + * @class ComputeFZQuaternions + * @brief This algorithm implements support code for the ComputeFZQuaternionsFilter + */ + +class ORIENTATIONANALYSIS_EXPORT ComputeFZQuaternions +{ +public: + ComputeFZQuaternions(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeFZQuaternionsInputValues* inputValues); + ~ComputeFZQuaternions() noexcept; + + ComputeFZQuaternions(const ComputeFZQuaternions&) = delete; + ComputeFZQuaternions(ComputeFZQuaternions&&) noexcept = delete; + ComputeFZQuaternions& operator=(const ComputeFZQuaternions&) = delete; + ComputeFZQuaternions& operator=(ComputeFZQuaternions&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ComputeFZQuaternionsInputValues* m_InputValues = nullptr; + const std::atomic_bool& m_ShouldCancel; + const IFilter::MessageHandler& m_MessageHandler; +}; + +} // namespace nx::core diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ConvertOrientations.cpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ConvertOrientations.cpp index fbec61359f..294cf2ceeb 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ConvertOrientations.cpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ConvertOrientations.cpp @@ -1,29 +1,20 @@ #include "ConvertOrientations.hpp" -#include "simplnx/Common/Result.hpp" -#include "simplnx/Common/Types.hpp" #include "simplnx/DataStructure/DataArray.hpp" #include "simplnx/DataStructure/DataGroup.hpp" -#include "simplnx/Filter/IFilter.hpp" -#include "simplnx/Parameters/ChoicesParameter.hpp" #include "simplnx/Utilities/ParallelDataAlgorithm.hpp" -// #include "EbsdLib/Core/EbsdLibConstants.h" #include "EbsdLib/Core/Orientation.hpp" -#include "EbsdLib/Core/OrientationRepresentation.h" #include "EbsdLib/Core/OrientationTransformation.hpp" #include "EbsdLib/Core/Quaternion.hpp" -#include - -#ifndef _MSC_VER -#pragma clang diagnostic push -#pragma ide diagnostic ignored "UnusedValue" -#endif +#include "EbsdLib/LaueOps/LaueOps.h" +#include "EbsdLib/OrientationMath/OrientationConverter.hpp" using namespace nx::core; namespace { + template struct EulerCheck { @@ -286,8 +277,8 @@ class FromQuaternion CheckFunc m_CheckFunc; typename Quaternion::Order m_Layout; }; -} // namespace +} // namespace // ----------------------------------------------------------------------------- ConvertOrientations::ConvertOrientations(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ConvertOrientationsInputValues* inputValues) : m_DataStructure(dataStructure) @@ -300,377 +291,395 @@ ConvertOrientations::ConvertOrientations(DataStructure& dataStructure, const IFi // ----------------------------------------------------------------------------- ConvertOrientations::~ConvertOrientations() noexcept = default; -// ----------------------------------------------------------------------------- -const std::atomic_bool& ConvertOrientations::getCancel() -{ - return m_ShouldCancel; -} - // ----------------------------------------------------------------------------- Result<> ConvertOrientations::operator()() { + + /**************************************************************************** + * Extract the actual input values from the 'filterArgs' object + ***************************************************************************/ + auto inputType = static_cast(m_InputValues->InputRepresentationIndex); + auto outputType = static_cast(m_InputValues->OutputRepresentationIndex); + auto pInputOrientationArrayPathValue = m_InputValues->InputOrientationArrayPath; + auto pOutputOrientationArrayNameValue = pInputOrientationArrayPathValue.replaceName(m_InputValues->OutputOrientationArrayName); + // Quaternion::Order qLayout = Quaternion::Order::VectorScalar; - using OutputType = Orientation; - using InputType = Orientation; - using QuaterionType = Quaternion; - using QuaternionType = Quaternion; + using OutputType = Orientation; + using InputType = Orientation; + using QuaterionType = Quaternion; + using QuaternionType = Quaternion; using ConversionFunctionType = std::function; - using ValidateInputDataFunctionType = std::function; + using ValidateInputDataFunctionType = std::function; using ToQuaternionFunctionType = std::function::Order)>; using FromQuaternionFunctionType = std::function::Order)>; - auto inputArray = m_DataStructure.getDataRefAs(m_InputValues->InputOrientationArrayPath); - auto outputArray = m_DataStructure.getDataRefAs(m_InputValues->OutputOrientationArrayPath); - size_t totalPoints = inputArray.getNumberOfTuples(); + auto& inputDataArray = m_DataStructure.getDataRefAs(pInputOrientationArrayPathValue); + auto& outputDataArray = m_DataStructure.getDataRefAs(pOutputOrientationArrayNameValue); + size_t totalPoints = inputDataArray.getNumberOfTuples(); - const ValidateInputDataFunctionType euCheck = EulerCheck(); - const ValidateInputDataFunctionType omCheck = OrientationMatrixCheck(); - const ValidateInputDataFunctionType quCheck = QuaternionCheck(); - const ValidateInputDataFunctionType axCheck = AxisAngleCheck(); - const ValidateInputDataFunctionType roCheck = RodriguesCheck(); - const ValidateInputDataFunctionType hoCheck = HomochoricCheck(); - const ValidateInputDataFunctionType cuCheck = CubochoricCheck(); - const ValidateInputDataFunctionType stCheck = StereographicCheck(); + const ValidateInputDataFunctionType euCheck = EulerCheck(); + const ValidateInputDataFunctionType omCheck = OrientationMatrixCheck(); + const ValidateInputDataFunctionType quCheck = QuaternionCheck(); + const ValidateInputDataFunctionType axCheck = AxisAngleCheck(); + const ValidateInputDataFunctionType roCheck = RodriguesCheck(); + const ValidateInputDataFunctionType hoCheck = HomochoricCheck(); + const ValidateInputDataFunctionType cuCheck = CubochoricCheck(); + const ValidateInputDataFunctionType stCheck = StereographicCheck(); - // This next block of code was generated from the ConvertOrientationsTest::_make_code() function. + // Allow data-based parallelization ParallelDataAlgorithm parallelAlgorithm; parallelAlgorithm.setRange(0, totalPoints); - if(m_InputValues->InputType == OrientationRepresentation::Type::Euler && m_InputValues->OutputType == OrientationRepresentation::Type::OrientationMatrix) + // This next block of code was generated from the ConvertOrientationsTest::_make_code() function. + if(inputType == OrientationRepresentation::Type::Euler && outputType == OrientationRepresentation::Type::OrientationMatrix) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Euler to OrientationMatrix"}); ConversionFunctionType eu2om = OrientationTransformation::eu2om; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, eu2om, euCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, eu2om, euCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Euler && m_InputValues->OutputType == OrientationRepresentation::Type::Quaternion) + else if(inputType == OrientationRepresentation::Type::Euler && outputType == OrientationRepresentation::Type::Quaternion) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Euler to Quaternion"}); ToQuaternionFunctionType eu2qu = OrientationTransformation::eu2qu; - parallelAlgorithm.execute(::ToQuaternion(inputArray, outputArray, eu2qu, euCheck, QuaternionType::Order::VectorScalar)); + parallelAlgorithm.execute( + ::ToQuaternion(inputDataArray, outputDataArray, eu2qu, euCheck, QuaternionType::Order::VectorScalar)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Euler && m_InputValues->OutputType == OrientationRepresentation::Type::AxisAngle) + else if(inputType == OrientationRepresentation::Type::Euler && outputType == OrientationRepresentation::Type::AxisAngle) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Euler to AxisAngle"}); ConversionFunctionType eu2ax = OrientationTransformation::eu2ax; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, eu2ax, euCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, eu2ax, euCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Euler && m_InputValues->OutputType == OrientationRepresentation::Type::Rodrigues) + else if(inputType == OrientationRepresentation::Type::Euler && outputType == OrientationRepresentation::Type::Rodrigues) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Euler to Rodrigues"}); ConversionFunctionType eu2ro = OrientationTransformation::eu2ro; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, eu2ro, euCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, eu2ro, euCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Euler && m_InputValues->OutputType == OrientationRepresentation::Type::Homochoric) + else if(inputType == OrientationRepresentation::Type::Euler && outputType == OrientationRepresentation::Type::Homochoric) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Euler to Homochoric"}); ConversionFunctionType eu2ho = OrientationTransformation::eu2ho; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, eu2ho, euCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, eu2ho, euCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Euler && m_InputValues->OutputType == OrientationRepresentation::Type::Cubochoric) + else if(inputType == OrientationRepresentation::Type::Euler && outputType == OrientationRepresentation::Type::Cubochoric) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Euler to Cubochoric"}); ConversionFunctionType eu2cu = OrientationTransformation::eu2cu; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, eu2cu, euCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, eu2cu, euCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Euler && m_InputValues->OutputType == OrientationRepresentation::Type::Stereographic) + else if(inputType == OrientationRepresentation::Type::Euler && outputType == OrientationRepresentation::Type::Stereographic) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Euler to Stereographic"}); ConversionFunctionType eu2st = OrientationTransformation::eu2st; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, eu2st, euCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, eu2st, euCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::OrientationMatrix && m_InputValues->OutputType == OrientationRepresentation::Type::Euler) + else if(inputType == OrientationRepresentation::Type::OrientationMatrix && outputType == OrientationRepresentation::Type::Euler) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting OrientationMatrix to Euler"}); ConversionFunctionType om2eu = OrientationTransformation::om2eu; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, om2eu, omCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, om2eu, omCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::OrientationMatrix && m_InputValues->OutputType == OrientationRepresentation::Type::Quaternion) + else if(inputType == OrientationRepresentation::Type::OrientationMatrix && outputType == OrientationRepresentation::Type::Quaternion) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting OrientationMatrix to Quaternion"}); ToQuaternionFunctionType om2qu = OrientationTransformation::om2qu; - parallelAlgorithm.execute(::ToQuaternion(inputArray, outputArray, om2qu, omCheck, QuaternionType::Order::VectorScalar)); + parallelAlgorithm.execute( + ::ToQuaternion(inputDataArray, outputDataArray, om2qu, omCheck, QuaternionType::Order::VectorScalar)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::OrientationMatrix && m_InputValues->OutputType == OrientationRepresentation::Type::AxisAngle) + else if(inputType == OrientationRepresentation::Type::OrientationMatrix && outputType == OrientationRepresentation::Type::AxisAngle) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting OrientationMatrix to AxisAngle"}); ConversionFunctionType om2ax = OrientationTransformation::om2ax; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, om2ax, omCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, om2ax, omCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::OrientationMatrix && m_InputValues->OutputType == OrientationRepresentation::Type::Rodrigues) + else if(inputType == OrientationRepresentation::Type::OrientationMatrix && outputType == OrientationRepresentation::Type::Rodrigues) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting OrientationMatrix to Rodrigues"}); ConversionFunctionType om2ro = OrientationTransformation::om2ro; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, om2ro, omCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, om2ro, omCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::OrientationMatrix && m_InputValues->OutputType == OrientationRepresentation::Type::Homochoric) + else if(inputType == OrientationRepresentation::Type::OrientationMatrix && outputType == OrientationRepresentation::Type::Homochoric) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting OrientationMatrix to Homochoric"}); ConversionFunctionType om2ho = OrientationTransformation::om2ho; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, om2ho, omCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, om2ho, omCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::OrientationMatrix && m_InputValues->OutputType == OrientationRepresentation::Type::Cubochoric) + else if(inputType == OrientationRepresentation::Type::OrientationMatrix && outputType == OrientationRepresentation::Type::Cubochoric) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting OrientationMatrix to Cubochoric"}); ConversionFunctionType om2cu = OrientationTransformation::om2cu; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, om2cu, omCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, om2cu, omCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::OrientationMatrix && m_InputValues->OutputType == OrientationRepresentation::Type::Stereographic) + else if(inputType == OrientationRepresentation::Type::OrientationMatrix && outputType == OrientationRepresentation::Type::Stereographic) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting OrientationMatrix to Stereographic"}); ConversionFunctionType om2st = OrientationTransformation::om2st; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, om2st, omCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, om2st, omCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Quaternion && m_InputValues->OutputType == OrientationRepresentation::Type::Euler) + else if(inputType == OrientationRepresentation::Type::Quaternion && outputType == OrientationRepresentation::Type::Euler) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Quaternion to Euler"}); FromQuaternionFunctionType qu2eu = OrientationTransformation::qu2eu; - parallelAlgorithm.execute(::FromQuaternion(inputArray, outputArray, qu2eu, quCheck, QuaternionType::Order::VectorScalar)); + parallelAlgorithm.execute( + ::FromQuaternion(inputDataArray, outputDataArray, qu2eu, quCheck, QuaternionType::Order::VectorScalar)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Quaternion && m_InputValues->OutputType == OrientationRepresentation::Type::OrientationMatrix) + else if(inputType == OrientationRepresentation::Type::Quaternion && outputType == OrientationRepresentation::Type::OrientationMatrix) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Quaternion to OrientationMatrix"}); FromQuaternionFunctionType qu2om = OrientationTransformation::qu2om; - parallelAlgorithm.execute(::FromQuaternion(inputArray, outputArray, qu2om, quCheck, QuaternionType::Order::VectorScalar)); + parallelAlgorithm.execute( + ::FromQuaternion(inputDataArray, outputDataArray, qu2om, quCheck, QuaternionType::Order::VectorScalar)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Quaternion && m_InputValues->OutputType == OrientationRepresentation::Type::AxisAngle) + else if(inputType == OrientationRepresentation::Type::Quaternion && outputType == OrientationRepresentation::Type::AxisAngle) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Quaternion to AxisAngle"}); FromQuaternionFunctionType qu2ax = OrientationTransformation::qu2ax; - parallelAlgorithm.execute(::FromQuaternion(inputArray, outputArray, qu2ax, quCheck, QuaternionType::Order::VectorScalar)); + parallelAlgorithm.execute( + ::FromQuaternion(inputDataArray, outputDataArray, qu2ax, quCheck, QuaternionType::Order::VectorScalar)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Quaternion && m_InputValues->OutputType == OrientationRepresentation::Type::Rodrigues) + else if(inputType == OrientationRepresentation::Type::Quaternion && outputType == OrientationRepresentation::Type::Rodrigues) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Quaternion to Rodrigues"}); FromQuaternionFunctionType qu2ro = OrientationTransformation::qu2ro; - parallelAlgorithm.execute(::FromQuaternion(inputArray, outputArray, qu2ro, quCheck, QuaternionType::Order::VectorScalar)); + parallelAlgorithm.execute( + ::FromQuaternion(inputDataArray, outputDataArray, qu2ro, quCheck, QuaternionType::Order::VectorScalar)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Quaternion && m_InputValues->OutputType == OrientationRepresentation::Type::Homochoric) + else if(inputType == OrientationRepresentation::Type::Quaternion && outputType == OrientationRepresentation::Type::Homochoric) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Quaternion to Homochoric"}); FromQuaternionFunctionType qu2ho = OrientationTransformation::qu2ho; - parallelAlgorithm.execute(::FromQuaternion(inputArray, outputArray, qu2ho, quCheck, QuaternionType::Order::VectorScalar)); + parallelAlgorithm.execute( + ::FromQuaternion(inputDataArray, outputDataArray, qu2ho, quCheck, QuaternionType::Order::VectorScalar)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Quaternion && m_InputValues->OutputType == OrientationRepresentation::Type::Cubochoric) + else if(inputType == OrientationRepresentation::Type::Quaternion && outputType == OrientationRepresentation::Type::Cubochoric) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Quaternion to Cubochoric"}); FromQuaternionFunctionType qu2cu = OrientationTransformation::qu2cu; - parallelAlgorithm.execute(::FromQuaternion(inputArray, outputArray, qu2cu, quCheck, QuaternionType::Order::VectorScalar)); + parallelAlgorithm.execute( + ::FromQuaternion(inputDataArray, outputDataArray, qu2cu, quCheck, QuaternionType::Order::VectorScalar)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Quaternion && m_InputValues->OutputType == OrientationRepresentation::Type::Stereographic) + else if(inputType == OrientationRepresentation::Type::Quaternion && outputType == OrientationRepresentation::Type::Stereographic) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Quaternion to Stereographic"}); FromQuaternionFunctionType qu2st = OrientationTransformation::qu2st; - parallelAlgorithm.execute(::FromQuaternion(inputArray, outputArray, qu2st, quCheck, QuaternionType::Order::VectorScalar)); + parallelAlgorithm.execute( + ::FromQuaternion(inputDataArray, outputDataArray, qu2st, quCheck, QuaternionType::Order::VectorScalar)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::AxisAngle && m_InputValues->OutputType == OrientationRepresentation::Type::Euler) + else if(inputType == OrientationRepresentation::Type::AxisAngle && outputType == OrientationRepresentation::Type::Euler) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting AxisAngle to Euler"}); ConversionFunctionType ax2eu = OrientationTransformation::ax2eu; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ax2eu, axCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ax2eu, axCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::AxisAngle && m_InputValues->OutputType == OrientationRepresentation::Type::OrientationMatrix) + else if(inputType == OrientationRepresentation::Type::AxisAngle && outputType == OrientationRepresentation::Type::OrientationMatrix) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting AxisAngle to OrientationMatrix"}); ConversionFunctionType ax2om = OrientationTransformation::ax2om; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ax2om, axCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ax2om, axCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::AxisAngle && m_InputValues->OutputType == OrientationRepresentation::Type::Quaternion) + else if(inputType == OrientationRepresentation::Type::AxisAngle && outputType == OrientationRepresentation::Type::Quaternion) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting AxisAngle to Quaternion"}); ToQuaternionFunctionType ax2qu = OrientationTransformation::ax2qu; - parallelAlgorithm.execute(::ToQuaternion(inputArray, outputArray, ax2qu, axCheck, QuaternionType::Order::VectorScalar)); + parallelAlgorithm.execute( + ::ToQuaternion(inputDataArray, outputDataArray, ax2qu, axCheck, QuaternionType::Order::VectorScalar)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::AxisAngle && m_InputValues->OutputType == OrientationRepresentation::Type::Rodrigues) + else if(inputType == OrientationRepresentation::Type::AxisAngle && outputType == OrientationRepresentation::Type::Rodrigues) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting AxisAngle to Rodrigues"}); ConversionFunctionType ax2ro = OrientationTransformation::ax2ro; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ax2ro, axCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ax2ro, axCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::AxisAngle && m_InputValues->OutputType == OrientationRepresentation::Type::Homochoric) + else if(inputType == OrientationRepresentation::Type::AxisAngle && outputType == OrientationRepresentation::Type::Homochoric) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting AxisAngle to Homochoric"}); ConversionFunctionType ax2ho = OrientationTransformation::ax2ho; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ax2ho, axCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ax2ho, axCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::AxisAngle && m_InputValues->OutputType == OrientationRepresentation::Type::Cubochoric) + else if(inputType == OrientationRepresentation::Type::AxisAngle && outputType == OrientationRepresentation::Type::Cubochoric) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting AxisAngle to Cubochoric"}); ConversionFunctionType ax2cu = OrientationTransformation::ax2cu; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ax2cu, axCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ax2cu, axCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::AxisAngle && m_InputValues->OutputType == OrientationRepresentation::Type::Stereographic) + else if(inputType == OrientationRepresentation::Type::AxisAngle && outputType == OrientationRepresentation::Type::Stereographic) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting AxisAngle to Stereographic"}); ConversionFunctionType ax2st = OrientationTransformation::ax2st; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ax2st, axCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ax2st, axCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Rodrigues && m_InputValues->OutputType == OrientationRepresentation::Type::Euler) + else if(inputType == OrientationRepresentation::Type::Rodrigues && outputType == OrientationRepresentation::Type::Euler) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Rodrigues to Euler"}); ConversionFunctionType ro2eu = OrientationTransformation::ro2eu; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ro2eu, roCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ro2eu, roCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Rodrigues && m_InputValues->OutputType == OrientationRepresentation::Type::OrientationMatrix) + else if(inputType == OrientationRepresentation::Type::Rodrigues && outputType == OrientationRepresentation::Type::OrientationMatrix) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Rodrigues to OrientationMatrix"}); ConversionFunctionType ro2om = OrientationTransformation::ro2om; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ro2om, roCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ro2om, roCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Rodrigues && m_InputValues->OutputType == OrientationRepresentation::Type::Quaternion) + else if(inputType == OrientationRepresentation::Type::Rodrigues && outputType == OrientationRepresentation::Type::Quaternion) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Rodrigues to Quaternion"}); ToQuaternionFunctionType ro2qu = OrientationTransformation::ro2qu; - parallelAlgorithm.execute(::ToQuaternion(inputArray, outputArray, ro2qu, roCheck, QuaternionType::Order::VectorScalar)); + parallelAlgorithm.execute( + ::ToQuaternion(inputDataArray, outputDataArray, ro2qu, roCheck, QuaternionType::Order::VectorScalar)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Rodrigues && m_InputValues->OutputType == OrientationRepresentation::Type::AxisAngle) + else if(inputType == OrientationRepresentation::Type::Rodrigues && outputType == OrientationRepresentation::Type::AxisAngle) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Rodrigues to AxisAngle"}); ConversionFunctionType ro2ax = OrientationTransformation::ro2ax; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ro2ax, roCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ro2ax, roCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Rodrigues && m_InputValues->OutputType == OrientationRepresentation::Type::Homochoric) + else if(inputType == OrientationRepresentation::Type::Rodrigues && outputType == OrientationRepresentation::Type::Homochoric) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Rodrigues to Homochoric"}); ConversionFunctionType ro2ho = OrientationTransformation::ro2ho; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ro2ho, roCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ro2ho, roCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Rodrigues && m_InputValues->OutputType == OrientationRepresentation::Type::Cubochoric) + else if(inputType == OrientationRepresentation::Type::Rodrigues && outputType == OrientationRepresentation::Type::Cubochoric) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Rodrigues to Cubochoric"}); ConversionFunctionType ro2cu = OrientationTransformation::ro2cu; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ro2cu, roCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ro2cu, roCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Rodrigues && m_InputValues->OutputType == OrientationRepresentation::Type::Stereographic) + else if(inputType == OrientationRepresentation::Type::Rodrigues && outputType == OrientationRepresentation::Type::Stereographic) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Rodrigues to Stereographic"}); ConversionFunctionType ro2st = OrientationTransformation::ro2st; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ro2st, roCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ro2st, roCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Homochoric && m_InputValues->OutputType == OrientationRepresentation::Type::Euler) + else if(inputType == OrientationRepresentation::Type::Homochoric && outputType == OrientationRepresentation::Type::Euler) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Homochoric to Euler"}); ConversionFunctionType ho2eu = OrientationTransformation::ho2eu; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ho2eu, hoCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ho2eu, hoCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Homochoric && m_InputValues->OutputType == OrientationRepresentation::Type::OrientationMatrix) + else if(inputType == OrientationRepresentation::Type::Homochoric && outputType == OrientationRepresentation::Type::OrientationMatrix) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Homochoric to OrientationMatrix"}); ConversionFunctionType ho2om = OrientationTransformation::ho2om; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ho2om, hoCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ho2om, hoCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Homochoric && m_InputValues->OutputType == OrientationRepresentation::Type::Quaternion) + else if(inputType == OrientationRepresentation::Type::Homochoric && outputType == OrientationRepresentation::Type::Quaternion) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Homochoric to Quaternion"}); ToQuaternionFunctionType ho2qu = OrientationTransformation::ho2qu; - parallelAlgorithm.execute(::ToQuaternion(inputArray, outputArray, ho2qu, hoCheck, QuaternionType::Order::VectorScalar)); + parallelAlgorithm.execute( + ::ToQuaternion(inputDataArray, outputDataArray, ho2qu, hoCheck, QuaternionType::Order::VectorScalar)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Homochoric && m_InputValues->OutputType == OrientationRepresentation::Type::AxisAngle) + else if(inputType == OrientationRepresentation::Type::Homochoric && outputType == OrientationRepresentation::Type::AxisAngle) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Homochoric to AxisAngle"}); ConversionFunctionType ho2ax = OrientationTransformation::ho2ax; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ho2ax, hoCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ho2ax, hoCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Homochoric && m_InputValues->OutputType == OrientationRepresentation::Type::Rodrigues) + else if(inputType == OrientationRepresentation::Type::Homochoric && outputType == OrientationRepresentation::Type::Rodrigues) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Homochoric to Rodrigues"}); ConversionFunctionType ho2ro = OrientationTransformation::ho2ro; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ho2ro, hoCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ho2ro, hoCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Homochoric && m_InputValues->OutputType == OrientationRepresentation::Type::Cubochoric) + else if(inputType == OrientationRepresentation::Type::Homochoric && outputType == OrientationRepresentation::Type::Cubochoric) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Homochoric to Cubochoric"}); ConversionFunctionType ho2cu = OrientationTransformation::ho2cu; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ho2cu, hoCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ho2cu, hoCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Homochoric && m_InputValues->OutputType == OrientationRepresentation::Type::Stereographic) + else if(inputType == OrientationRepresentation::Type::Homochoric && outputType == OrientationRepresentation::Type::Stereographic) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Homochoric to Stereographic"}); ConversionFunctionType ho2st = OrientationTransformation::ho2st; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, ho2st, hoCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ho2st, hoCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Cubochoric && m_InputValues->OutputType == OrientationRepresentation::Type::Euler) + else if(inputType == OrientationRepresentation::Type::Cubochoric && outputType == OrientationRepresentation::Type::Euler) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Cubochoric to Euler"}); ConversionFunctionType cu2eu = OrientationTransformation::cu2eu; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, cu2eu, cuCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, cu2eu, cuCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Cubochoric && m_InputValues->OutputType == OrientationRepresentation::Type::OrientationMatrix) + else if(inputType == OrientationRepresentation::Type::Cubochoric && outputType == OrientationRepresentation::Type::OrientationMatrix) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Cubochoric to OrientationMatrix"}); ConversionFunctionType cu2om = OrientationTransformation::cu2om; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, cu2om, cuCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, cu2om, cuCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Cubochoric && m_InputValues->OutputType == OrientationRepresentation::Type::Quaternion) + else if(inputType == OrientationRepresentation::Type::Cubochoric && outputType == OrientationRepresentation::Type::Quaternion) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Cubochoric to Quaternion"}); ToQuaternionFunctionType cu2qu = OrientationTransformation::cu2qu; - parallelAlgorithm.execute(::ToQuaternion(inputArray, outputArray, cu2qu, cuCheck, QuaternionType::Order::VectorScalar)); + parallelAlgorithm.execute( + ::ToQuaternion(inputDataArray, outputDataArray, cu2qu, cuCheck, QuaternionType::Order::VectorScalar)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Cubochoric && m_InputValues->OutputType == OrientationRepresentation::Type::AxisAngle) + else if(inputType == OrientationRepresentation::Type::Cubochoric && outputType == OrientationRepresentation::Type::AxisAngle) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Cubochoric to AxisAngle"}); ConversionFunctionType cu2ax = OrientationTransformation::cu2ax; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, cu2ax, cuCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, cu2ax, cuCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Cubochoric && m_InputValues->OutputType == OrientationRepresentation::Type::Rodrigues) + else if(inputType == OrientationRepresentation::Type::Cubochoric && outputType == OrientationRepresentation::Type::Rodrigues) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Cubochoric to Rodrigues"}); ConversionFunctionType cu2ro = OrientationTransformation::cu2ro; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, cu2ro, cuCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, cu2ro, cuCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Cubochoric && m_InputValues->OutputType == OrientationRepresentation::Type::Homochoric) + else if(inputType == OrientationRepresentation::Type::Cubochoric && outputType == OrientationRepresentation::Type::Homochoric) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Cubochoric to Homochoric"}); ConversionFunctionType cu2ho = OrientationTransformation::cu2ho; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, cu2ho, cuCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, cu2ho, cuCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Cubochoric && m_InputValues->OutputType == OrientationRepresentation::Type::Stereographic) + else if(inputType == OrientationRepresentation::Type::Cubochoric && outputType == OrientationRepresentation::Type::Stereographic) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Cubochoric to Stereographic"}); ConversionFunctionType cu2st = OrientationTransformation::cu2st; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, cu2st, cuCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, cu2st, cuCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Stereographic && m_InputValues->OutputType == OrientationRepresentation::Type::Euler) + else if(inputType == OrientationRepresentation::Type::Stereographic && outputType == OrientationRepresentation::Type::Euler) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Stereographic to Euler"}); ConversionFunctionType st2eu = OrientationTransformation::st2eu; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, st2eu, stCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, st2eu, stCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Stereographic && m_InputValues->OutputType == OrientationRepresentation::Type::OrientationMatrix) + else if(inputType == OrientationRepresentation::Type::Stereographic && outputType == OrientationRepresentation::Type::OrientationMatrix) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Stereographic to OrientationMatrix"}); ConversionFunctionType st2om = OrientationTransformation::st2om; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, st2om, stCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, st2om, stCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Stereographic && m_InputValues->OutputType == OrientationRepresentation::Type::Quaternion) + else if(inputType == OrientationRepresentation::Type::Stereographic && outputType == OrientationRepresentation::Type::Quaternion) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Stereographic to Quaternion"}); ToQuaternionFunctionType st2qu = OrientationTransformation::st2qu; - parallelAlgorithm.execute(::ToQuaternion(inputArray, outputArray, st2qu, stCheck, QuaternionType::Order::VectorScalar)); + parallelAlgorithm.execute( + ::ToQuaternion(inputDataArray, outputDataArray, st2qu, stCheck, QuaternionType::Order::VectorScalar)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Stereographic && m_InputValues->OutputType == OrientationRepresentation::Type::AxisAngle) + else if(inputType == OrientationRepresentation::Type::Stereographic && outputType == OrientationRepresentation::Type::AxisAngle) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Stereographic to AxisAngle"}); ConversionFunctionType st2ax = OrientationTransformation::st2ax; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, st2ax, stCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, st2ax, stCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Stereographic && m_InputValues->OutputType == OrientationRepresentation::Type::Rodrigues) + else if(inputType == OrientationRepresentation::Type::Stereographic && outputType == OrientationRepresentation::Type::Rodrigues) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Stereographic to Rodrigues"}); ConversionFunctionType st2ro = OrientationTransformation::st2ro; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, st2ro, stCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, st2ro, stCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Stereographic && m_InputValues->OutputType == OrientationRepresentation::Type::Homochoric) + else if(inputType == OrientationRepresentation::Type::Stereographic && outputType == OrientationRepresentation::Type::Homochoric) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Stereographic to Homochoric"}); ConversionFunctionType st2ho = OrientationTransformation::st2ho; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, st2ho, stCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, st2ho, stCheck)); } - else if(m_InputValues->InputType == OrientationRepresentation::Type::Stereographic && m_InputValues->OutputType == OrientationRepresentation::Type::Cubochoric) + else if(inputType == OrientationRepresentation::Type::Stereographic && outputType == OrientationRepresentation::Type::Cubochoric) { m_MessageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Stereographic to Cubochoric"}); ConversionFunctionType st2cu = OrientationTransformation::st2cu; - parallelAlgorithm.execute(::ConvertOrientation(inputArray, outputArray, st2cu, stCheck)); + parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, st2cu, stCheck)); } return {}; diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ConvertOrientations.hpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ConvertOrientations.hpp index 9929838ab5..884219ac22 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ConvertOrientations.hpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ConvertOrientations.hpp @@ -2,39 +2,39 @@ #include "OrientationAnalysis/OrientationAnalysis_export.hpp" -#include "simplnx/DataStructure/DataArray.hpp" #include "simplnx/DataStructure/DataPath.hpp" #include "simplnx/DataStructure/DataStructure.hpp" #include "simplnx/Filter/IFilter.hpp" -#include "simplnx/Parameters/ArrayCreationParameter.hpp" #include "simplnx/Parameters/ArraySelectionParameter.hpp" -#include "simplnx/Parameters/BoolParameter.hpp" #include "simplnx/Parameters/ChoicesParameter.hpp" - -#include "EbsdLib/Core/OrientationRepresentation.h" - -#include +#include "simplnx/Parameters/DataObjectNameParameter.hpp" namespace nx::core { + +namespace convert_orientations_constants +{ // Error Code constants -constexpr nx::core::int32 k_InputRepresentationTypeError = -67001; -constexpr nx::core::int32 k_OutputRepresentationTypeError = -67002; -constexpr nx::core::int32 k_InputComponentDimensionError = -67003; -constexpr nx::core::int32 k_InputComponentCountError = -67004; -constexpr nx::core::int32 k_MatchingTypesError = -67005; +constexpr int32 k_InputRepresentationTypeError = -67001; +constexpr int32 k_OutputRepresentationTypeError = -67002; +constexpr int32 k_InputComponentDimensionError = -67003; +constexpr int32 k_InputComponentCountError = -67004; +constexpr int32 k_MatchingTypesError = -67005; +} // namespace convert_orientations_constants struct ORIENTATIONANALYSIS_EXPORT ConvertOrientationsInputValues { - OrientationRepresentation::Type InputType; - OrientationRepresentation::Type OutputType; - DataPath InputOrientationArrayPath; - DataPath OutputOrientationArrayPath; + ArraySelectionParameter::ValueType InputOrientationArrayPath; + ChoicesParameter::ValueType InputRepresentationIndex; + DataObjectNameParameter::ValueType OutputOrientationArrayName; + ChoicesParameter::ValueType OutputRepresentationIndex; }; /** - * @class + * @class ConvertOrientations + * @brief This algorithm implements support code for the ConvertOrientationsFilter */ + class ORIENTATIONANALYSIS_EXPORT ConvertOrientations { public: @@ -48,8 +48,6 @@ class ORIENTATIONANALYSIS_EXPORT ConvertOrientations Result<> operator()(); - const std::atomic_bool& getCancel(); - private: DataStructure& m_DataStructure; const ConvertOrientationsInputValues* m_InputValues = nullptr; diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ConvertOrientationsToVertexGeometry.cpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ConvertOrientationsToVertexGeometry.cpp index 22ad8ffbe3..97e2b49480 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ConvertOrientationsToVertexGeometry.cpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ConvertOrientationsToVertexGeometry.cpp @@ -62,10 +62,10 @@ Result<> ConvertOrientationsToVertexGeometry::operator()() Float32Array::CreateWithStore(tmpDs, quatsArrayName, inputArray.getTupleShape(), {4}); ConvertOrientationsInputValues inputValues; - inputValues.InputType = m_InputValues->InputOrientationType; - inputValues.OutputType = OrientationRepresentation::Type::Quaternion; + inputValues.InputRepresentationIndex = static_cast(m_InputValues->InputOrientationType); + inputValues.OutputRepresentationIndex = static_cast(OrientationRepresentation::Type::Quaternion); inputValues.InputOrientationArrayPath = DataPath({m_InputValues->InputOrientationArrayPath.getTargetName()}); - inputValues.OutputOrientationArrayPath = quatsArrayPath; + inputValues.OutputOrientationArrayName = quatsArrayPath.getTargetName(); Result<> result = ConvertOrientations(tmpDs, m_MessageHandler, m_ShouldCancel, &inputValues)(); if(result.invalid()) { diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ComputeFZQuaternionsFilter.cpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ComputeFZQuaternionsFilter.cpp index 31dd808848..c296935eaa 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ComputeFZQuaternionsFilter.cpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ComputeFZQuaternionsFilter.cpp @@ -1,13 +1,13 @@ #include "ComputeFZQuaternionsFilter.hpp" +#include "OrientationAnalysis/Filters/Algorithms/ComputeFZQuaternions.hpp" + #include "simplnx/DataStructure/DataArray.hpp" #include "simplnx/DataStructure/DataPath.hpp" #include "simplnx/Filter/Actions/CreateArrayAction.hpp" #include "simplnx/Parameters/ArraySelectionParameter.hpp" #include "simplnx/Parameters/BoolParameter.hpp" #include "simplnx/Parameters/DataObjectNameParameter.hpp" -#include "simplnx/Utilities/MaskCompareUtilities.hpp" -#include "simplnx/Utilities/ParallelDataAlgorithm.hpp" #include "simplnx/Utilities/SIMPLConversion.hpp" #include @@ -16,159 +16,6 @@ using namespace nx::core; -namespace -{ -/** - * @brief The GenerateFZQuatsImpl class implements a threaded algorithm that computes the Fundamental Zone Quaternion - * for a given Quaternion and Laue Class (which is based from the crystalStructures array - */ -class GenerateMaskedFZQuatsImpl -{ -public: - GenerateMaskedFZQuatsImpl(const Float32AbstractDataStore& quats, const Int32AbstractDataStore& phases, const UInt32AbstractDataStore& crystalStructures, const int32 numPhases, - std::unique_ptr& goodVoxels, Float32AbstractDataStore& fzQuats, const std::atomic_bool& shouldCancel, std::atomic_int32_t& warningCount) - : m_Quats(quats) - , m_CellPhases(phases) - , m_CrystalStructures(crystalStructures) - , m_NumPhases(numPhases) - , m_GoodVoxels(goodVoxels) - , m_FZQuats(fzQuats) - , m_ShouldCancel(shouldCancel) - , m_WarningCount(warningCount) - { - } - - ~GenerateMaskedFZQuatsImpl() = default; - - /** - * @brief convert - * @param start - * @param end - */ - void convert(size_t start, size_t end) const - { - std::vector ops = LaueOps::GetAllOrientationOps(); - int32 phase = 0; - size_t index = 0; - - for(size_t i = start; i < end; i++) - { - if(m_ShouldCancel) - { - break; - } - phase = m_CellPhases.getValue(i); - - // Sanity check the phase data to make sure we do not walk off the end of the array - if(phase >= m_NumPhases) - { - m_WarningCount++; - } - - // Output initialized to zero by default - index = i * 4; - if(phase < m_NumPhases && m_GoodVoxels->isTrue(i) && m_CrystalStructures.getValue(phase) < EbsdLib::CrystalStructure::LaueGroupEnd) - { - QuatD quatD = QuatD(m_Quats.getValue(index), m_Quats.getValue(index + 1), m_Quats.getValue(index + 2), m_Quats.getValue(index + 3)); // Makes a copy into q - auto xtal = static_cast(m_CrystalStructures.getValue(phase)); // get the Laue Group - quatD = ops[xtal]->getFZQuat(quatD); - m_FZQuats.setValue(index, static_cast(quatD.x())); - m_FZQuats.setValue(index + 1, static_cast(quatD.y())); - m_FZQuats.setValue(index + 2, static_cast(quatD.z())); - m_FZQuats.setValue(index + 3, static_cast(quatD.w())); - } - } - } - - void operator()(const Range& range) const - { - convert(range.min(), range.max()); - } - -private: - const Float32AbstractDataStore& m_Quats; - const Int32AbstractDataStore& m_CellPhases; - const UInt32AbstractDataStore& m_CrystalStructures; - const int32 m_NumPhases = 0; - std::unique_ptr& m_GoodVoxels; - Float32AbstractDataStore& m_FZQuats; - const std::atomic_bool& m_ShouldCancel; - std::atomic_int32_t& m_WarningCount; -}; - -class GenerateFZQuatsImpl -{ -public: - GenerateFZQuatsImpl(const Float32AbstractDataStore& quats, const Int32AbstractDataStore& phases, const UInt32AbstractDataStore& crystalStructures, const int32 numPhases, - Float32AbstractDataStore& fzQuats, const std::atomic_bool& shouldCancel, std::atomic_int32_t& warningCount) - : m_Quats(quats) - , m_CellPhases(phases) - , m_CrystalStructures(crystalStructures) - , m_NumPhases(numPhases) - , m_FZQuats(fzQuats) - , m_ShouldCancel(shouldCancel) - , m_WarningCount(warningCount) - { - } - - ~GenerateFZQuatsImpl() = default; - - /** - * @brief convert - * @param start - * @param end - */ - void convert(size_t start, size_t end) const - { - std::vector ops = LaueOps::GetAllOrientationOps(); - int32 phase = 0; - size_t index = 0; - - for(size_t i = start; i < end; i++) - { - if(m_ShouldCancel) - { - break; - } - phase = m_CellPhases.getValue(i); - - // Sanity check the phase data to make sure we do not walk off the end of the array - if(phase >= m_NumPhases) - { - m_WarningCount++; - } - - // Output initialized to zero by default - index = i * 4; - if(phase < m_NumPhases && m_CrystalStructures.getValue(phase) < EbsdLib::CrystalStructure::LaueGroupEnd) - { - QuatD quatD = QuatD(m_Quats.getValue(index), m_Quats.getValue(index + 1), m_Quats.getValue(index + 2), m_Quats.getValue(index + 3)); // Makes a copy into q - auto xtal = static_cast(m_CrystalStructures.getValue(phase)); // get the Laue Group - quatD = ops[xtal]->getFZQuat(quatD); - m_FZQuats.setValue(index, static_cast(quatD.x())); - m_FZQuats.setValue(index + 1, static_cast(quatD.y())); - m_FZQuats.setValue(index + 2, static_cast(quatD.z())); - m_FZQuats.setValue(index + 3, static_cast(quatD.w())); - } - } - } - - void operator()(const Range& range) const - { - convert(range.min(), range.max()); - } - -private: - const Float32AbstractDataStore& m_Quats; - const Int32AbstractDataStore& m_CellPhases; - const UInt32AbstractDataStore& m_CrystalStructures; - const int32 m_NumPhases = 0; - Float32AbstractDataStore& m_FZQuats; - const std::atomic_bool& m_ShouldCancel; - std::atomic_int32_t& m_WarningCount; -}; -} // namespace - namespace nx::core { //------------------------------------------------------------------------------ @@ -286,76 +133,15 @@ IFilter::PreflightResult ComputeFZQuaternionsFilter::preflightImpl(const DataStr Result<> ComputeFZQuaternionsFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { - auto pUseGoodVoxelsValue = filterArgs.value(k_UseMask_Key); - auto pQuatsArrayPathValue = filterArgs.value(k_QuatsArrayPath_Key); - auto pCellPhasesArrayPathValue = filterArgs.value(k_CellPhasesArrayPath_Key); - auto pGoodVoxelsArrayPathValue = filterArgs.value(k_MaskArrayPath_Key); - auto pCrystalStructuresArrayPathValue = filterArgs.value(k_CrystalStructuresArrayPath_Key); - auto pFZQuatsArrayPathValue = pQuatsArrayPathValue.replaceName(filterArgs.value(k_FZQuatsArrayName_Key)); - - auto& phaseArray = dataStructure.getDataRefAs(pCellPhasesArrayPathValue); - auto& quatArray = dataStructure.getDataRefAs(pQuatsArrayPathValue); - auto& xtalArray = dataStructure.getDataRefAs(pCrystalStructuresArrayPathValue); - auto* maskArray = dataStructure.getDataAs(pGoodVoxelsArrayPathValue); - auto& fzQuatArray = dataStructure.getDataRefAs(pFZQuatsArrayPathValue); - - std::atomic_int32_t warningCount = 0; - auto numPhases = static_cast(xtalArray.getNumberOfTuples()); - - typename IParallelAlgorithm::AlgorithmArrays algArrays; - algArrays.push_back(&phaseArray); - algArrays.push_back(&quatArray); - algArrays.push_back(&xtalArray); - algArrays.push_back(&fzQuatArray); - - if(pUseGoodVoxelsValue) - { - algArrays.push_back(maskArray); - } - - try - { - // Parallel algorithm - ParallelDataAlgorithm dataAlg; - dataAlg.setRange(0ULL, static_cast(quatArray.getNumberOfTuples())); - dataAlg.requireArraysInMemory(algArrays); - - if(pUseGoodVoxelsValue) - { - std::unique_ptr maskArrayPtr = nullptr; - try - { - maskArrayPtr = MaskCompareUtilities::InstantiateMaskCompare(dataStructure, pGoodVoxelsArrayPathValue); - } catch(const std::out_of_range& exception) - { - // This really should NOT be happening as the path was verified during preflight BUT we may be calling this from - // some other context that is NOT going through the normal nx::core::IFilter API of Preflight and Execute - return MakeErrorResult(-49003, fmt::format("Mask Array DataPath does not exist or is not of the correct type (Bool | UInt8) {}", pGoodVoxelsArrayPathValue.toString())); - } - - dataAlg.execute(::GenerateMaskedFZQuatsImpl(quatArray.getDataStoreRef(), phaseArray.getDataStoreRef(), xtalArray.getDataStoreRef(), numPhases, maskArrayPtr, fzQuatArray.getDataStoreRef(), - shouldCancel, warningCount)); - } - else - { - dataAlg.execute( - ::GenerateFZQuatsImpl(quatArray.getDataStoreRef(), phaseArray.getDataStoreRef(), xtalArray.getDataStoreRef(), numPhases, fzQuatArray.getDataStoreRef(), shouldCancel, warningCount)); - } - - if(warningCount > 0) - { - std::string errorMessage = fmt::format("The Ensemble Phase information only references {} phase(s) but {} cell(s) had a phase value greater than {}. This indicates a problem with the input " - "cell phase data. DREAM3D-NX may have given INCORRECT RESULTS.", - numPhases - 1, warningCount.load(), numPhases - 1); - - return {MakeErrorResult<>(-49004, errorMessage)}; - } - } catch(const EbsdLib::method_not_implemented& e) - { - return {MakeErrorResult<>(-49005, fmt::format("EbsdLib threw an exception when computing the fundamental zone data. {}", e.what()))}; - } - - return {}; + ComputeFZQuaternionsInputValues inputValues; + // Replace the keys below with the variables from the header. + inputValues.CellPhasesArrayPath = filterArgs.value(k_CellPhasesArrayPath_Key); + inputValues.CrystalStructuresArrayPath = filterArgs.value(k_CrystalStructuresArrayPath_Key); + inputValues.InputQuatsArrayPath = filterArgs.value(k_QuatsArrayPath_Key); + inputValues.MaskArrayPath = filterArgs.value(k_MaskArrayPath_Key); + inputValues.OutputFzQuatsArrayName = filterArgs.value(k_FZQuatsArrayName_Key); + inputValues.UseMask = filterArgs.value(k_UseMask_Key); + return ComputeFZQuaternions(dataStructure, messageHandler, shouldCancel, &inputValues)(); } namespace diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ComputeFeatureReferenceMisorientationsFilter.cpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ComputeFeatureReferenceMisorientationsFilter.cpp index ebf104fc4c..2a67ff7f5b 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ComputeFeatureReferenceMisorientationsFilter.cpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ComputeFeatureReferenceMisorientationsFilter.cpp @@ -1,4 +1,5 @@ #include "ComputeFeatureReferenceMisorientationsFilter.hpp" + #include "OrientationAnalysis/Filters/Algorithms/ComputeFeatureReferenceMisorientations.hpp" #include "simplnx/DataStructure/AttributeMatrix.hpp" @@ -8,10 +9,8 @@ #include "simplnx/Parameters/ArraySelectionParameter.hpp" #include "simplnx/Parameters/AttributeMatrixSelectionParameter.hpp" #include "simplnx/Parameters/ChoicesParameter.hpp" - -#include "simplnx/Utilities/SIMPLConversion.hpp" - #include "simplnx/Parameters/DataObjectNameParameter.hpp" +#include "simplnx/Utilities/SIMPLConversion.hpp" using namespace nx::core; diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ConvertOrientationsFilter.cpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ConvertOrientationsFilter.cpp index 3472f66c8d..de450ab482 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ConvertOrientationsFilter.cpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ConvertOrientationsFilter.cpp @@ -1,21 +1,17 @@ #include "ConvertOrientationsFilter.hpp" +#include "Algorithms/ConvertOrientations.hpp" + #include "simplnx/DataStructure/DataArray.hpp" #include "simplnx/DataStructure/DataPath.hpp" #include "simplnx/Filter/Actions/CreateArrayAction.hpp" #include "simplnx/Parameters/ArraySelectionParameter.hpp" #include "simplnx/Parameters/ChoicesParameter.hpp" #include "simplnx/Parameters/DataObjectNameParameter.hpp" -#include "simplnx/Utilities/ParallelDataAlgorithm.hpp" #include "simplnx/Utilities/SIMPLConversion.hpp" -#include "EbsdLib/Core/Orientation.hpp" -#include "EbsdLib/Core/OrientationTransformation.hpp" -#include "EbsdLib/Core/Quaternion.hpp" +#include "EbsdLib/Core/EbsdDataArray.hpp" #include "EbsdLib/OrientationMath/OrientationConverter.hpp" -#include - -#include "OrientationAnalysis/Filters/Algorithms/ConvertOrientations.hpp" #include @@ -25,273 +21,6 @@ #endif using namespace nx::core; -namespace -{ -template -struct EulerCheck -{ - - void operator()(T* euler) const - { - euler[0] = static_cast(std::fmod(euler[0], EbsdLib::Constants::k_2PiD)); - euler[1] = static_cast(std::fmod(euler[1], EbsdLib::Constants::k_PiD)); - euler[2] = static_cast(std::fmod(euler[2], EbsdLib::Constants::k_2PiD)); - - if(euler[0] < 0.0) - { - euler[0] *= static_cast(-1.0); - } - if(euler[1] < 0.0) - { - euler[1] *= static_cast(-1.0); - } - if(euler[2] < 0.0) - { - euler[2] *= static_cast(-1.0); - } - } -}; - -template -struct OrientationMatrixCheck -{ - using OrientationType = Orientation; - using ResultType = OrientationTransformation::ResultType; - - void operator()(T* inPtr) const - { - OrientationType oaType(inPtr, 9); - - ResultType res = OrientationTransformation::om_check(oaType); - if(res.result <= 0) - { - std::cout << res.msg << std::endl; - printRepresentation(std::cout, inPtr, std::string("Bad OM")); - } - } - void printRepresentation(std::ostream& out, T* om, const std::string& label = std::string("Om")) const - { - out.precision(16); - out << label << om[0] << '\t' << om[1] << '\t' << om[2] << std::endl; - out << label << om[3] << '\t' << om[4] << '\t' << om[5] << std::endl; - out << label << om[6] << '\t' << om[7] << '\t' << om[8] << std::endl; - } -}; - -template -struct QuaternionCheck -{ - using OrientationType = Orientation; - using ResultType = OrientationTransformation::ResultType; - - void operator()(T* inPtr) const - { - // This is a no-op at this point. - } -}; - -template -struct AxisAngleCheck -{ - using OrientationType = Orientation; - using ResultType = OrientationTransformation::ResultType; - - void operator()(T* inPtr) const - { - // This is a no-op at this point. - } -}; - -template -struct RodriguesCheck -{ - using OrientationType = Orientation; - using ResultType = OrientationTransformation::ResultType; - - void operator()(T* inPtr) const - { - // This is a no-op at this point. - } -}; - -template -struct HomochoricCheck -{ - using OrientationType = Orientation; - using ResultType = OrientationTransformation::ResultType; - - void operator()(T* inPtr) const - { - // This is a no-op at this point. - } -}; - -template -struct CubochoricCheck -{ - using OrientationType = Orientation; - using ResultType = OrientationTransformation::ResultType; - - void operator()(T* inPtr) const - { - // This is a no-op at this point. - } -}; - -template -struct StereographicCheck -{ - using OrientationType = Orientation; - using ResultType = OrientationTransformation::ResultType; - - void operator()(T* inPtr) const - { - // This is a no-op at this point. - } -}; - -/** - * - */ -template -class ConvertOrientation -{ -public: - ConvertOrientation(const DataArray& inputArray, DataArray& outputArray, TransformFunc transformFunc, CheckFunc checkFunc) - : m_InputArray(inputArray) - , m_OutputArray(outputArray) - , m_TransformFunc(std::move(transformFunc)) - , m_CheckFunc(std::move(checkFunc)) - { - } - - void operator()(const Range& range) const - { - auto& inDataStore = m_InputArray.getDataStoreRef(); - auto& outDataStore = m_OutputArray.getDataStoreRef(); - - Orientation input(InCompSize); - for(size_t tIndex = range.min(); tIndex < range.max(); tIndex++) - { - - for(size_t cIndex = 0; cIndex < InCompSize; cIndex++) - { - input[cIndex] = inDataStore.getValue(tIndex * InCompSize + cIndex); - } - - m_CheckFunc(input.data()); - - Orientation output = m_TransformFunc(input); // Do the actual Conversion - for(size_t cIndex = 0; cIndex < OutCompSize; cIndex++) - { - outDataStore.setValue(tIndex * OutCompSize + cIndex, output[cIndex]); - } - } - } - -private: - const DataArray& m_InputArray; - DataArray& m_OutputArray; - TransformFunc m_TransformFunc; - CheckFunc m_CheckFunc; -}; - -/** - * - */ -template -class ToQuaternion -{ -public: - ToQuaternion(DataArray& inputArray, DataArray& outputArray, TransformFunc transformFunc, CheckFunc checkFunc, typename Quaternion::Order layout) - : m_InputArray(inputArray) - , m_OutputArray(outputArray) - , m_TransformFunc(std::move(transformFunc)) - , m_CheckFunc(std::move(checkFunc)) - , m_Layout(layout) - { - } - - void operator()(const Range& range) const - { - using QuaterionType = Quaternion; - size_t numTuples = m_InputArray.getNumberOfTuples(); - auto& inDataStore = m_InputArray.getDataStoreRef(); - auto& outDataStore = m_OutputArray.getDataStoreRef(); - - Orientation input(InCompSize); - for(size_t tIndex = range.min(); tIndex < range.max(); tIndex++) - { - for(size_t cIndex = 0; cIndex < InCompSize; cIndex++) - { - input[cIndex] = inDataStore.getValue(tIndex * InCompSize + cIndex); - } - m_CheckFunc(input.data()); - QuaterionType output = m_TransformFunc(input, m_Layout); // Do the actual Conversion - for(size_t cIndex = 0; cIndex < OutCompSize; cIndex++) - { - outDataStore.setValue(tIndex * OutCompSize + cIndex, output[cIndex]); - } - } - } - -private: - const DataArray& m_InputArray; - DataArray& m_OutputArray; - TransformFunc m_TransformFunc; - CheckFunc m_CheckFunc; - typename Quaternion::Order m_Layout; -}; - -/** - * - */ -template -class FromQuaternion -{ -public: - FromQuaternion(const DataArray& inputArray, DataArray& outputArray, TransformFunc transformFunc, CheckFunc checkFunc, typename Quaternion::Order layout) - : m_InputArray(inputArray) - , m_OutputArray(outputArray) - , m_TransformFunc(std::move(transformFunc)) - , m_CheckFunc(std::move(checkFunc)) - , m_Layout(layout) - { - } - - void operator()(const Range& range) const - { - using QuaterionType = Quaternion; - auto& inDataStore = m_InputArray.getDataStoreRef(); - auto& outDataStore = m_OutputArray.getDataStoreRef(); - - std::array input = {0.0, 0.0, 0.0, 0.0}; - for(size_t tIndex = range.min(); tIndex < range.max(); tIndex++) - { - for(size_t cIndex = 0; cIndex < InCompSize; cIndex++) - { - input[cIndex] = inDataStore.getValue(tIndex * InCompSize + cIndex); - } - m_CheckFunc(input.data()); - QuaterionType inputQuat = QuaterionType(input[0], input[1], input[2], input[3]).getPositiveOrientation(); - Orientation output = m_TransformFunc(inputQuat, m_Layout); // Do the actual Conversion - for(size_t cIndex = 0; cIndex < OutCompSize; cIndex++) - { - outDataStore.setValue(tIndex * OutCompSize + cIndex, output[cIndex]); - } - } - } - -private: - const DataArray& m_InputArray; - DataArray& m_OutputArray; - TransformFunc m_TransformFunc; - CheckFunc m_CheckFunc; - typename Quaternion::Order m_Layout; -}; - -} // namespace - namespace nx::core { //------------------------------------------------------------------------------ @@ -365,17 +94,20 @@ IFilter::PreflightResult ConvertOrientationsFilter::preflightImpl(const DataStru if(static_cast(inputType) < 0 || inputType >= OrientationRepresentation::Type::Unknown) { - return {MakeErrorResult(::k_InputRepresentationTypeError, fmt::format("Input Representation Type must be a value from 0 to 6. '{}'", fmt::underlying(inputType)))}; + return {MakeErrorResult(convert_orientations_constants::k_InputRepresentationTypeError, + fmt::format("Input Representation Type must be a value from 0 to 6. '{}'", fmt::underlying(inputType)))}; } if(static_cast(outputType) < 0 || outputType >= OrientationRepresentation::Type::Unknown) { - return {MakeErrorResult(::k_OutputRepresentationTypeError, fmt::format("Output Representation Type must be a value from 0 to 6. '{}'", fmt::underlying(outputType)))}; + return {MakeErrorResult(convert_orientations_constants::k_OutputRepresentationTypeError, + fmt::format("Output Representation Type must be a value from 0 to 6. '{}'", fmt::underlying(outputType)))}; } if(inputType == outputType) { - return {MakeErrorResult(::k_MatchingTypesError, fmt::format("The Input Representation Type and the Output Representation Type cannot be the same!", fmt::underlying(outputType)))}; + return {MakeErrorResult(convert_orientations_constants::k_MatchingTypesError, + fmt::format("The Input Representation Type and the Output Representation Type cannot be the same!", fmt::underlying(outputType)))}; } auto pInputArrayPath = filterArgs.value(k_InputOrientationArrayPath_Key); @@ -384,7 +116,8 @@ IFilter::PreflightResult ConvertOrientationsFilter::preflightImpl(const DataStru if(inputCompShape.size() > 1) { - return {MakeErrorResult(::k_InputComponentDimensionError, fmt::format("Input Component Shape has multiple dimensions. It can only have 1 dimension. '{}'", inputCompShape.size()))}; + return {MakeErrorResult(convert_orientations_constants::k_InputComponentDimensionError, + fmt::format("Input Component Shape has multiple dimensions. It can only have 1 dimension. '{}'", inputCompShape.size()))}; } using OrientationConverterType = OrientationConverter, float>; auto representationNames = OrientationConverterType::GetOrientationTypeStrings>(); @@ -395,7 +128,7 @@ IFilter::PreflightResult ConvertOrientationsFilter::preflightImpl(const DataStru std::stringstream message; message << "Number of components for input array is not correct for input representation type. " << representationNames[static_cast(inputType)] << " should have " << representationElementCount[static_cast(inputType)] << " components but the selected input array has " << inputCompShape[0]; - return {MakeErrorResult(::k_InputComponentCountError, message.str())}; + return {MakeErrorResult(convert_orientations_constants::k_InputComponentCountError, message.str())}; } auto pOutputArrayPath = pInputArrayPath.replaceName(filterArgs.value(k_OutputOrientationArrayName_Key)); @@ -414,394 +147,13 @@ IFilter::PreflightResult ConvertOrientationsFilter::preflightImpl(const DataStru Result<> ConvertOrientationsFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { - /**************************************************************************** - * Extract the actual input values from the 'filterArgs' object - ***************************************************************************/ - auto inputType = static_cast(filterArgs.value(k_InputType_Key)); - auto outputType = static_cast(filterArgs.value(k_OutputType_Key)); - auto pInputOrientationArrayPathValue = filterArgs.value(k_InputOrientationArrayPath_Key); - auto pOutputOrientationArrayNameValue = pInputOrientationArrayPathValue.replaceName(filterArgs.value(k_OutputOrientationArrayName_Key)); - - // Quaternion::Order qLayout = Quaternion::Order::VectorScalar; - - using OutputType = Orientation; - using InputType = Orientation; - using QuaterionType = Quaternion; - using QuaternionType = Quaternion; - using ConversionFunctionType = std::function; - using ValidateInputDataFunctionType = std::function; - using ToQuaternionFunctionType = std::function::Order)>; - using FromQuaternionFunctionType = std::function::Order)>; - - auto& inputDataArray = dataStructure.getDataRefAs(pInputOrientationArrayPathValue); - auto& outputDataArray = dataStructure.getDataRefAs(pOutputOrientationArrayNameValue); - size_t totalPoints = inputDataArray.getNumberOfTuples(); - - const ValidateInputDataFunctionType euCheck = EulerCheck(); - const ValidateInputDataFunctionType omCheck = OrientationMatrixCheck(); - const ValidateInputDataFunctionType quCheck = QuaternionCheck(); - const ValidateInputDataFunctionType axCheck = AxisAngleCheck(); - const ValidateInputDataFunctionType roCheck = RodriguesCheck(); - const ValidateInputDataFunctionType hoCheck = HomochoricCheck(); - const ValidateInputDataFunctionType cuCheck = CubochoricCheck(); - const ValidateInputDataFunctionType stCheck = StereographicCheck(); - - // Allow data-based parallelization - ParallelDataAlgorithm parallelAlgorithm; - parallelAlgorithm.setRange(0, totalPoints); - // This next block of code was generated from the ConvertOrientationsTest::_make_code() function. - if(inputType == OrientationRepresentation::Type::Euler && outputType == OrientationRepresentation::Type::OrientationMatrix) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Euler to OrientationMatrix"}); - ConversionFunctionType eu2om = OrientationTransformation::eu2om; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, eu2om, euCheck)); - } - else if(inputType == OrientationRepresentation::Type::Euler && outputType == OrientationRepresentation::Type::Quaternion) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Euler to Quaternion"}); - ToQuaternionFunctionType eu2qu = OrientationTransformation::eu2qu; - parallelAlgorithm.execute( - ::ToQuaternion(inputDataArray, outputDataArray, eu2qu, euCheck, QuaternionType::Order::VectorScalar)); - } - else if(inputType == OrientationRepresentation::Type::Euler && outputType == OrientationRepresentation::Type::AxisAngle) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Euler to AxisAngle"}); - ConversionFunctionType eu2ax = OrientationTransformation::eu2ax; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, eu2ax, euCheck)); - } - else if(inputType == OrientationRepresentation::Type::Euler && outputType == OrientationRepresentation::Type::Rodrigues) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Euler to Rodrigues"}); - ConversionFunctionType eu2ro = OrientationTransformation::eu2ro; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, eu2ro, euCheck)); - } - else if(inputType == OrientationRepresentation::Type::Euler && outputType == OrientationRepresentation::Type::Homochoric) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Euler to Homochoric"}); - ConversionFunctionType eu2ho = OrientationTransformation::eu2ho; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, eu2ho, euCheck)); - } - else if(inputType == OrientationRepresentation::Type::Euler && outputType == OrientationRepresentation::Type::Cubochoric) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Euler to Cubochoric"}); - ConversionFunctionType eu2cu = OrientationTransformation::eu2cu; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, eu2cu, euCheck)); - } - else if(inputType == OrientationRepresentation::Type::Euler && outputType == OrientationRepresentation::Type::Stereographic) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Euler to Stereographic"}); - ConversionFunctionType eu2st = OrientationTransformation::eu2st; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, eu2st, euCheck)); - } - else if(inputType == OrientationRepresentation::Type::OrientationMatrix && outputType == OrientationRepresentation::Type::Euler) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting OrientationMatrix to Euler"}); - ConversionFunctionType om2eu = OrientationTransformation::om2eu; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, om2eu, omCheck)); - } - else if(inputType == OrientationRepresentation::Type::OrientationMatrix && outputType == OrientationRepresentation::Type::Quaternion) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting OrientationMatrix to Quaternion"}); - ToQuaternionFunctionType om2qu = OrientationTransformation::om2qu; - parallelAlgorithm.execute( - ::ToQuaternion(inputDataArray, outputDataArray, om2qu, omCheck, QuaternionType::Order::VectorScalar)); - } - else if(inputType == OrientationRepresentation::Type::OrientationMatrix && outputType == OrientationRepresentation::Type::AxisAngle) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting OrientationMatrix to AxisAngle"}); - ConversionFunctionType om2ax = OrientationTransformation::om2ax; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, om2ax, omCheck)); - } - else if(inputType == OrientationRepresentation::Type::OrientationMatrix && outputType == OrientationRepresentation::Type::Rodrigues) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting OrientationMatrix to Rodrigues"}); - ConversionFunctionType om2ro = OrientationTransformation::om2ro; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, om2ro, omCheck)); - } - else if(inputType == OrientationRepresentation::Type::OrientationMatrix && outputType == OrientationRepresentation::Type::Homochoric) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting OrientationMatrix to Homochoric"}); - ConversionFunctionType om2ho = OrientationTransformation::om2ho; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, om2ho, omCheck)); - } - else if(inputType == OrientationRepresentation::Type::OrientationMatrix && outputType == OrientationRepresentation::Type::Cubochoric) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting OrientationMatrix to Cubochoric"}); - ConversionFunctionType om2cu = OrientationTransformation::om2cu; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, om2cu, omCheck)); - } - else if(inputType == OrientationRepresentation::Type::OrientationMatrix && outputType == OrientationRepresentation::Type::Stereographic) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting OrientationMatrix to Stereographic"}); - ConversionFunctionType om2st = OrientationTransformation::om2st; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, om2st, omCheck)); - } - else if(inputType == OrientationRepresentation::Type::Quaternion && outputType == OrientationRepresentation::Type::Euler) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Quaternion to Euler"}); - FromQuaternionFunctionType qu2eu = OrientationTransformation::qu2eu; - parallelAlgorithm.execute( - ::FromQuaternion(inputDataArray, outputDataArray, qu2eu, quCheck, QuaternionType::Order::VectorScalar)); - } - else if(inputType == OrientationRepresentation::Type::Quaternion && outputType == OrientationRepresentation::Type::OrientationMatrix) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Quaternion to OrientationMatrix"}); - FromQuaternionFunctionType qu2om = OrientationTransformation::qu2om; - parallelAlgorithm.execute( - ::FromQuaternion(inputDataArray, outputDataArray, qu2om, quCheck, QuaternionType::Order::VectorScalar)); - } - else if(inputType == OrientationRepresentation::Type::Quaternion && outputType == OrientationRepresentation::Type::AxisAngle) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Quaternion to AxisAngle"}); - FromQuaternionFunctionType qu2ax = OrientationTransformation::qu2ax; - parallelAlgorithm.execute( - ::FromQuaternion(inputDataArray, outputDataArray, qu2ax, quCheck, QuaternionType::Order::VectorScalar)); - } - else if(inputType == OrientationRepresentation::Type::Quaternion && outputType == OrientationRepresentation::Type::Rodrigues) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Quaternion to Rodrigues"}); - FromQuaternionFunctionType qu2ro = OrientationTransformation::qu2ro; - parallelAlgorithm.execute( - ::FromQuaternion(inputDataArray, outputDataArray, qu2ro, quCheck, QuaternionType::Order::VectorScalar)); - } - else if(inputType == OrientationRepresentation::Type::Quaternion && outputType == OrientationRepresentation::Type::Homochoric) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Quaternion to Homochoric"}); - FromQuaternionFunctionType qu2ho = OrientationTransformation::qu2ho; - parallelAlgorithm.execute( - ::FromQuaternion(inputDataArray, outputDataArray, qu2ho, quCheck, QuaternionType::Order::VectorScalar)); - } - else if(inputType == OrientationRepresentation::Type::Quaternion && outputType == OrientationRepresentation::Type::Cubochoric) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Quaternion to Cubochoric"}); - FromQuaternionFunctionType qu2cu = OrientationTransformation::qu2cu; - parallelAlgorithm.execute( - ::FromQuaternion(inputDataArray, outputDataArray, qu2cu, quCheck, QuaternionType::Order::VectorScalar)); - } - else if(inputType == OrientationRepresentation::Type::Quaternion && outputType == OrientationRepresentation::Type::Stereographic) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Quaternion to Stereographic"}); - FromQuaternionFunctionType qu2st = OrientationTransformation::qu2st; - parallelAlgorithm.execute( - ::FromQuaternion(inputDataArray, outputDataArray, qu2st, quCheck, QuaternionType::Order::VectorScalar)); - } - else if(inputType == OrientationRepresentation::Type::AxisAngle && outputType == OrientationRepresentation::Type::Euler) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting AxisAngle to Euler"}); - ConversionFunctionType ax2eu = OrientationTransformation::ax2eu; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ax2eu, axCheck)); - } - else if(inputType == OrientationRepresentation::Type::AxisAngle && outputType == OrientationRepresentation::Type::OrientationMatrix) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting AxisAngle to OrientationMatrix"}); - ConversionFunctionType ax2om = OrientationTransformation::ax2om; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ax2om, axCheck)); - } - else if(inputType == OrientationRepresentation::Type::AxisAngle && outputType == OrientationRepresentation::Type::Quaternion) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting AxisAngle to Quaternion"}); - ToQuaternionFunctionType ax2qu = OrientationTransformation::ax2qu; - parallelAlgorithm.execute( - ::ToQuaternion(inputDataArray, outputDataArray, ax2qu, axCheck, QuaternionType::Order::VectorScalar)); - } - else if(inputType == OrientationRepresentation::Type::AxisAngle && outputType == OrientationRepresentation::Type::Rodrigues) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting AxisAngle to Rodrigues"}); - ConversionFunctionType ax2ro = OrientationTransformation::ax2ro; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ax2ro, axCheck)); - } - else if(inputType == OrientationRepresentation::Type::AxisAngle && outputType == OrientationRepresentation::Type::Homochoric) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting AxisAngle to Homochoric"}); - ConversionFunctionType ax2ho = OrientationTransformation::ax2ho; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ax2ho, axCheck)); - } - else if(inputType == OrientationRepresentation::Type::AxisAngle && outputType == OrientationRepresentation::Type::Cubochoric) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting AxisAngle to Cubochoric"}); - ConversionFunctionType ax2cu = OrientationTransformation::ax2cu; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ax2cu, axCheck)); - } - else if(inputType == OrientationRepresentation::Type::AxisAngle && outputType == OrientationRepresentation::Type::Stereographic) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting AxisAngle to Stereographic"}); - ConversionFunctionType ax2st = OrientationTransformation::ax2st; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ax2st, axCheck)); - } - else if(inputType == OrientationRepresentation::Type::Rodrigues && outputType == OrientationRepresentation::Type::Euler) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Rodrigues to Euler"}); - ConversionFunctionType ro2eu = OrientationTransformation::ro2eu; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ro2eu, roCheck)); - } - else if(inputType == OrientationRepresentation::Type::Rodrigues && outputType == OrientationRepresentation::Type::OrientationMatrix) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Rodrigues to OrientationMatrix"}); - ConversionFunctionType ro2om = OrientationTransformation::ro2om; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ro2om, roCheck)); - } - else if(inputType == OrientationRepresentation::Type::Rodrigues && outputType == OrientationRepresentation::Type::Quaternion) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Rodrigues to Quaternion"}); - ToQuaternionFunctionType ro2qu = OrientationTransformation::ro2qu; - parallelAlgorithm.execute( - ::ToQuaternion(inputDataArray, outputDataArray, ro2qu, roCheck, QuaternionType::Order::VectorScalar)); - } - else if(inputType == OrientationRepresentation::Type::Rodrigues && outputType == OrientationRepresentation::Type::AxisAngle) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Rodrigues to AxisAngle"}); - ConversionFunctionType ro2ax = OrientationTransformation::ro2ax; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ro2ax, roCheck)); - } - else if(inputType == OrientationRepresentation::Type::Rodrigues && outputType == OrientationRepresentation::Type::Homochoric) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Rodrigues to Homochoric"}); - ConversionFunctionType ro2ho = OrientationTransformation::ro2ho; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ro2ho, roCheck)); - } - else if(inputType == OrientationRepresentation::Type::Rodrigues && outputType == OrientationRepresentation::Type::Cubochoric) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Rodrigues to Cubochoric"}); - ConversionFunctionType ro2cu = OrientationTransformation::ro2cu; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ro2cu, roCheck)); - } - else if(inputType == OrientationRepresentation::Type::Rodrigues && outputType == OrientationRepresentation::Type::Stereographic) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Rodrigues to Stereographic"}); - ConversionFunctionType ro2st = OrientationTransformation::ro2st; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ro2st, roCheck)); - } - else if(inputType == OrientationRepresentation::Type::Homochoric && outputType == OrientationRepresentation::Type::Euler) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Homochoric to Euler"}); - ConversionFunctionType ho2eu = OrientationTransformation::ho2eu; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ho2eu, hoCheck)); - } - else if(inputType == OrientationRepresentation::Type::Homochoric && outputType == OrientationRepresentation::Type::OrientationMatrix) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Homochoric to OrientationMatrix"}); - ConversionFunctionType ho2om = OrientationTransformation::ho2om; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ho2om, hoCheck)); - } - else if(inputType == OrientationRepresentation::Type::Homochoric && outputType == OrientationRepresentation::Type::Quaternion) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Homochoric to Quaternion"}); - ToQuaternionFunctionType ho2qu = OrientationTransformation::ho2qu; - parallelAlgorithm.execute( - ::ToQuaternion(inputDataArray, outputDataArray, ho2qu, hoCheck, QuaternionType::Order::VectorScalar)); - } - else if(inputType == OrientationRepresentation::Type::Homochoric && outputType == OrientationRepresentation::Type::AxisAngle) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Homochoric to AxisAngle"}); - ConversionFunctionType ho2ax = OrientationTransformation::ho2ax; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ho2ax, hoCheck)); - } - else if(inputType == OrientationRepresentation::Type::Homochoric && outputType == OrientationRepresentation::Type::Rodrigues) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Homochoric to Rodrigues"}); - ConversionFunctionType ho2ro = OrientationTransformation::ho2ro; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ho2ro, hoCheck)); - } - else if(inputType == OrientationRepresentation::Type::Homochoric && outputType == OrientationRepresentation::Type::Cubochoric) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Homochoric to Cubochoric"}); - ConversionFunctionType ho2cu = OrientationTransformation::ho2cu; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ho2cu, hoCheck)); - } - else if(inputType == OrientationRepresentation::Type::Homochoric && outputType == OrientationRepresentation::Type::Stereographic) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Homochoric to Stereographic"}); - ConversionFunctionType ho2st = OrientationTransformation::ho2st; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, ho2st, hoCheck)); - } - else if(inputType == OrientationRepresentation::Type::Cubochoric && outputType == OrientationRepresentation::Type::Euler) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Cubochoric to Euler"}); - ConversionFunctionType cu2eu = OrientationTransformation::cu2eu; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, cu2eu, cuCheck)); - } - else if(inputType == OrientationRepresentation::Type::Cubochoric && outputType == OrientationRepresentation::Type::OrientationMatrix) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Cubochoric to OrientationMatrix"}); - ConversionFunctionType cu2om = OrientationTransformation::cu2om; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, cu2om, cuCheck)); - } - else if(inputType == OrientationRepresentation::Type::Cubochoric && outputType == OrientationRepresentation::Type::Quaternion) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Cubochoric to Quaternion"}); - ToQuaternionFunctionType cu2qu = OrientationTransformation::cu2qu; - parallelAlgorithm.execute( - ::ToQuaternion(inputDataArray, outputDataArray, cu2qu, cuCheck, QuaternionType::Order::VectorScalar)); - } - else if(inputType == OrientationRepresentation::Type::Cubochoric && outputType == OrientationRepresentation::Type::AxisAngle) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Cubochoric to AxisAngle"}); - ConversionFunctionType cu2ax = OrientationTransformation::cu2ax; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, cu2ax, cuCheck)); - } - else if(inputType == OrientationRepresentation::Type::Cubochoric && outputType == OrientationRepresentation::Type::Rodrigues) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Cubochoric to Rodrigues"}); - ConversionFunctionType cu2ro = OrientationTransformation::cu2ro; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, cu2ro, cuCheck)); - } - else if(inputType == OrientationRepresentation::Type::Cubochoric && outputType == OrientationRepresentation::Type::Homochoric) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Cubochoric to Homochoric"}); - ConversionFunctionType cu2ho = OrientationTransformation::cu2ho; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, cu2ho, cuCheck)); - } - else if(inputType == OrientationRepresentation::Type::Cubochoric && outputType == OrientationRepresentation::Type::Stereographic) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Cubochoric to Stereographic"}); - ConversionFunctionType cu2st = OrientationTransformation::cu2st; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, cu2st, cuCheck)); - } - else if(inputType == OrientationRepresentation::Type::Stereographic && outputType == OrientationRepresentation::Type::Euler) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Stereographic to Euler"}); - ConversionFunctionType st2eu = OrientationTransformation::st2eu; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, st2eu, stCheck)); - } - else if(inputType == OrientationRepresentation::Type::Stereographic && outputType == OrientationRepresentation::Type::OrientationMatrix) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Stereographic to OrientationMatrix"}); - ConversionFunctionType st2om = OrientationTransformation::st2om; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, st2om, stCheck)); - } - else if(inputType == OrientationRepresentation::Type::Stereographic && outputType == OrientationRepresentation::Type::Quaternion) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Stereographic to Quaternion"}); - ToQuaternionFunctionType st2qu = OrientationTransformation::st2qu; - parallelAlgorithm.execute( - ::ToQuaternion(inputDataArray, outputDataArray, st2qu, stCheck, QuaternionType::Order::VectorScalar)); - } - else if(inputType == OrientationRepresentation::Type::Stereographic && outputType == OrientationRepresentation::Type::AxisAngle) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Stereographic to AxisAngle"}); - ConversionFunctionType st2ax = OrientationTransformation::st2ax; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, st2ax, stCheck)); - } - else if(inputType == OrientationRepresentation::Type::Stereographic && outputType == OrientationRepresentation::Type::Rodrigues) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Stereographic to Rodrigues"}); - ConversionFunctionType st2ro = OrientationTransformation::st2ro; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, st2ro, stCheck)); - } - else if(inputType == OrientationRepresentation::Type::Stereographic && outputType == OrientationRepresentation::Type::Homochoric) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Stereographic to Homochoric"}); - ConversionFunctionType st2ho = OrientationTransformation::st2ho; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, st2ho, stCheck)); - } - else if(inputType == OrientationRepresentation::Type::Stereographic && outputType == OrientationRepresentation::Type::Cubochoric) - { - messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, "Converting Stereographic to Cubochoric"}); - ConversionFunctionType st2cu = OrientationTransformation::st2cu; - parallelAlgorithm.execute(::ConvertOrientation(inputDataArray, outputDataArray, st2cu, stCheck)); - } - - return {}; + ConvertOrientationsInputValues inputValues; + // Replace the keys below with the variables from the header. + inputValues.InputOrientationArrayPath = filterArgs.value(k_InputOrientationArrayPath_Key); + inputValues.InputRepresentationIndex = filterArgs.value(k_InputType_Key); + inputValues.OutputOrientationArrayName = filterArgs.value(k_OutputOrientationArrayName_Key); + inputValues.OutputRepresentationIndex = filterArgs.value(k_OutputType_Key); + return ConvertOrientations(dataStructure, messageHandler, shouldCancel, &inputValues)(); } } // namespace nx::core diff --git a/src/Plugins/OrientationAnalysis/test/ConvertOrientationsTest.cpp b/src/Plugins/OrientationAnalysis/test/ConvertOrientationsTest.cpp index dfa541184e..a0afa571a2 100644 --- a/src/Plugins/OrientationAnalysis/test/ConvertOrientationsTest.cpp +++ b/src/Plugins/OrientationAnalysis/test/ConvertOrientationsTest.cpp @@ -270,5 +270,5 @@ TEST_CASE("OrientationAnalysis::ConvertOrientations: Equal Representations") // Preflight the filter and check result auto preflightResult = filter.preflight(dataStructure, args); SIMPLNX_RESULT_REQUIRE_INVALID(preflightResult.outputActions); - REQUIRE(preflightResult.outputActions.errors()[0].code == ::k_MatchingTypesError); + REQUIRE(preflightResult.outputActions.errors()[0].code == convert_orientations_constants::k_MatchingTypesError); } diff --git a/src/Plugins/SimplnxCore/CMakeLists.txt b/src/Plugins/SimplnxCore/CMakeLists.txt index 00bf09bae0..338e3ba8d5 100644 --- a/src/Plugins/SimplnxCore/CMakeLists.txt +++ b/src/Plugins/SimplnxCore/CMakeLists.txt @@ -163,13 +163,16 @@ set(ActionList ) set(AlgorithmList + AlignGeometries AddBadData AlignSectionsFeatureCentroid AlignSectionsList AppendImageGeometry ApplyTransformationToGeometry + ApproximatePointCloudHull ArrayCalculator CalculateTriangleGroupCurvatures + ChangeAngleRepresentation CombineAttributeArrays CombineNodeBasedGeometries CombineStlFiles @@ -182,44 +185,76 @@ set(AlgorithmList ComputeBoundingBoxStats ComputeCoordinatesImageGeom ComputeCoordinateThreshold + ComputeBoundaryElementFractions + ComputeDifferencesMap ComputeEuclideanDistMap ComputeFeatureBounds ComputeFeatureCentroids ComputeFeatureClustering + ComputeFeatureNeighbors + ComputeFeaturePhases + ComputeFeaturePhasesBinary ComputeFeatureRect + ComputeFeatureSizes ComputeKMeans ComputeKMedoids ComputeLargestCrossSections ComputeMomentInvariants2D ComputeNeighborhoods ComputeNeighborListStatistics +# ComputeNumFeatures ComputeSurfaceAreaToVolume + ComputeSurfaceFeatures +# ComputeTriangleAreas ComputeTriangleGeomCentroids ComputeTriangleGeomVolumes ComputeVectorColors ComputeVertexToTriangleDistances +# ComputeVolumeFractions ConcatenateDataArrays + ConditionalSetValue ConvertColorToGrayScale ConvertData + CopyDataObject + CopyFeatureArrayToElementArray CreateAMScanPaths + CreateAttributeMatrix CreateColorMap + CreateDataArray + CreateDataArrayAdvanced + CreateDataGroup + CreateFeatureArrayFromElementArray + CreateGeometry + CreateImageGeometry CreatePythonSkeleton CropEdgeGeometry + CropImageGeometry + CropVertexGeometry DBSCAN + DeleteData ErodeDilateBadData ErodeDilateCoordinationNumber ErodeDilateMask ExecuteProcess ExtractComponentAsArray + ExtractInternalSurfacesFromTriangleGeometry + ExtractPipelineToFile ExtractVertexGeometry FeatureFaceCurvature FillBadData FindNRingNeighbors FlyingEdges3D IdentifyDuplicateVertices + IdentifySample InitializeData + InitializeImageGeomCellData + InterpolatePointCloudToRegularGrid + IterativeClosestPoint LabelTriangleGeometry LaplacianSmoothing + MapPointCloudToRegularGrid + MoveData + MultiThresholdObjects NearestPointFuseRegularGrids PadImageGeometry PartitionGeometry @@ -229,9 +264,12 @@ set(AlgorithmList ReadBinaryCTNorthstar ReadCSVFile ReadDeformKeyFileV12 + ReadDREAM3D + ReadHDF5Dataset ReadRawBinary ReadStlFile ReadStringDataArray + ReadTextDataArray ReadVolumeGraphicsFile ReadVtkStructuredPoints ReadZeissTxmFile @@ -239,12 +277,18 @@ set(AlgorithmList RemoveFlaggedEdges RemoveFlaggedFeatures RemoveFlaggedTriangles + RemoveFlaggedVertices + RenameDataObject ReplaceElementAttributesWithNeighborValues RequireMinNumNeighbors ResampleImageGeom ResampleRectGridToImageGeom ReshapeDataArray + ReverseTriangleWinding + RobustAutomaticThreshold + RotateSampleRefFrame ScalarSegmentFeatures + SetImageGeomOriginScaling SharedFeatureFace Silhouette SliceTriangleGeometry @@ -252,12 +296,18 @@ set(AlgorithmList SplitDataArrayByTuple SurfaceNets TriangleCentroid + TriangleDihedralAngle + TriangleNormal TupleTransfer UncertainRegularGridSampleSurfaceMesh VerifyTriangleWinding WriteAbaqusHexahedron + WriteASCIIData WriteAvizoRectilinearCoordinate WriteAvizoUniformCoordinate + WriteBinaryData + WriteDREAM3D + WriteFeatureDataCSV WriteLosAlamosFFT WriteNodesAndElementsFiles WriteSPParksSites diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/AlignGeometries.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/AlignGeometries.cpp new file mode 100644 index 0000000000..4393e1643b --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/AlignGeometries.cpp @@ -0,0 +1,409 @@ +#include "AlignGeometries.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" +#include "simplnx/DataStructure/Geometry/EdgeGeom.hpp" +#include "simplnx/DataStructure/Geometry/INodeGeometry2D.hpp" +#include "simplnx/DataStructure/Geometry/INodeGeometry3D.hpp" +#include "simplnx/DataStructure/Geometry/ImageGeom.hpp" +#include "simplnx/DataStructure/Geometry/RectGridGeom.hpp" +#include "simplnx/DataStructure/Geometry/VertexGeom.hpp" + +using namespace nx::core; + +namespace +{ +FloatVec3 extractOrigin(const IGeometry& geometry) +{ + auto geomType = geometry.getGeomType(); + switch(geomType) + { + case IGeometry::Type::Image: { + auto& image = dynamic_cast(geometry); + return image.getOrigin(); + } + case IGeometry::Type::RectGrid: { + auto& rectGrid = dynamic_cast(geometry); + const auto& xBounds = rectGrid.getXBounds()->getDataStoreRef(); + const auto& yBounds = rectGrid.getYBounds()->getDataStoreRef(); + const auto& zBounds = rectGrid.getZBounds()->getDataStoreRef(); + FloatVec3 origin(std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()); + for(size_t i = 0; i < xBounds.getNumberOfTuples(); i++) + { + if(xBounds[i] < origin[0]) + { + origin[0] = xBounds[i]; + } + } + for(size_t i = 0; i < yBounds.getNumberOfTuples(); i++) + { + if(yBounds[i] < origin[1]) + { + origin[1] = yBounds[i]; + } + } + for(size_t i = 0; i < zBounds.getNumberOfTuples(); i++) + { + if(zBounds[i] < origin[2]) + { + origin[2] = zBounds[i]; + } + } + return origin; + } + case IGeometry::Type::Vertex: { + auto& vertex = dynamic_cast(geometry); + const auto& vertices = vertex.getVertices()->getDataStoreRef(); + FloatVec3 origin(std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()); + + for(size_t i = 0; i < vertex.getNumberOfVertices(); i++) + { + for(size_t j = 0; j < 3; j++) + { + if(vertices[3 * i + j] < origin[j]) + { + origin[j] = vertices[3 * i + j]; + } + } + } + return origin; + } + case IGeometry::Type::Edge: { + const auto& edge = dynamic_cast(geometry); + const auto& vertices = edge.getVertices()->getDataStoreRef(); + FloatVec3 origin(std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()); + + for(size_t i = 0; i < edge.getNumberOfVertices(); i++) + { + for(size_t j = 0; j < 3; j++) + { + if(vertices[3 * i + j] < origin[j]) + { + origin[j] = vertices[3 * i + j]; + } + } + } + return origin; + } + // 2D + case IGeometry::Type::Triangle: + [[fallthrough]]; + case IGeometry::Type::Quad: { + const auto& geometry2d = dynamic_cast(geometry); + const auto& vertices = geometry2d.getVertices()->getDataStoreRef(); + FloatVec3 origin(std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()); + + for(size_t i = 0; i < geometry2d.getNumberOfVertices(); i++) + { + for(size_t j = 0; j < 3; j++) + { + if(vertices[3 * i + j] < origin[j]) + { + origin[j] = vertices[3 * i + j]; + } + } + } + return origin; + } + // 3D + case IGeometry::Type::Hexahedral: + [[fallthrough]]; + case IGeometry::Type::Tetrahedral: { + const auto& geometry3d = dynamic_cast(geometry); + const auto& vertices = geometry3d.getVertices()->getDataStoreRef(); + FloatVec3 origin(std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()); + + for(size_t i = 0; i < geometry3d.getNumberOfVertices(); i++) + { + for(size_t j = 0; j < 3; j++) + { + if(vertices[3 * i + j] < origin[j]) + { + origin[j] = vertices[3 * i + j]; + } + } + } + return origin; + } + default: + break; + } + + FloatVec3 origin(std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()); + return origin; +} + +FloatVec3 extractCentroid(const IGeometry& geometry) +{ + FloatVec3 centroid(0.0f, 0.0f, 0.0f); + switch(geometry.getGeomType()) + { + case IGeometry::Type::Image: { + const auto& image = dynamic_cast(geometry); + SizeVec3 dims = image.getDimensions(); + FloatVec3 origin = image.getOrigin(); + FloatVec3 res = image.getSpacing(); + + centroid[0] = (static_cast(dims[0]) * res[0] / 2.0f) + origin[0]; + centroid[1] = (static_cast(dims[1]) * res[1] / 2.0f) + origin[1]; + centroid[2] = (static_cast(dims[2]) * res[2] / 2.0f) + origin[2]; + return centroid; + } + case IGeometry::Type::RectGrid: { + const auto& rectGrid = dynamic_cast(geometry); + const auto& xBounds = rectGrid.getXBounds()->getDataStoreRef(); + const auto& yBounds = rectGrid.getYBounds()->getDataStoreRef(); + const auto& zBounds = rectGrid.getZBounds()->getDataStoreRef(); + float min[3] = {std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()}; + float max[3] = {std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min()}; + for(size_t i = 0; i < xBounds.getNumberOfTuples(); i++) + { + if(xBounds[i] < min[0]) + { + min[0] = xBounds[i]; + } + if(xBounds[i] > max[0]) + { + max[0] = xBounds[i]; + } + } + for(size_t i = 0; i < yBounds.getNumberOfTuples(); i++) + { + if(yBounds[i] < min[1]) + { + min[1] = yBounds[i]; + } + if(yBounds[i] > max[1]) + { + max[1] = yBounds[i]; + } + } + for(size_t i = 0; i < zBounds.getNumberOfTuples(); i++) + { + if(zBounds[i] < min[2]) + { + min[2] = zBounds[i]; + } + if(zBounds[i] > max[2]) + { + max[2] = zBounds[i]; + } + } + centroid[0] = (max[0] - min[0]) / 2.0f; + centroid[1] = (max[1] - min[1]) / 2.0f; + centroid[2] = (max[2] - min[2]) / 2.0f; + return centroid; + } + case IGeometry::Type::Vertex: { + const auto& vertex = dynamic_cast(geometry); + const auto& vertices = vertex.getVertices()->getDataStoreRef(); + centroid[0] = 0.0f; + centroid[1] = 0.0f; + centroid[2] = 0.0f; + for(size_t i = 0; i < vertex.getNumberOfVertices(); i++) + { + centroid[0] += vertices[3 * i + 0]; + centroid[1] += vertices[3 * i + 1]; + centroid[2] += vertices[3 * i + 2]; + } + centroid[0] /= static_cast(vertex.getNumberOfVertices()); + centroid[1] /= static_cast(vertex.getNumberOfVertices()); + centroid[2] /= static_cast(vertex.getNumberOfVertices()); + return centroid; + } + case IGeometry::Type::Edge: { + const auto& edge = dynamic_cast(geometry); + const auto& vertices = edge.getVertices()->getDataStoreRef(); + centroid[0] = 0.0f; + centroid[1] = 0.0f; + centroid[2] = 0.0f; + for(size_t i = 0; i < edge.getNumberOfVertices(); i++) + { + centroid[0] += vertices[3 * i + 0]; + centroid[1] += vertices[3 * i + 1]; + centroid[2] += vertices[3 * i + 2]; + } + centroid[0] /= static_cast(edge.getNumberOfVertices()); + centroid[1] /= static_cast(edge.getNumberOfVertices()); + centroid[2] /= static_cast(edge.getNumberOfVertices()); + return centroid; + } + // 2D Types + case IGeometry::Type::Triangle: + [[fallthrough]]; + case IGeometry::Type::Quad: { + auto& geometry2d = dynamic_cast(geometry); + const auto& vertices = geometry2d.getVertices()->getDataStoreRef(); + centroid[0] = 0.0f; + centroid[1] = 0.0f; + centroid[2] = 0.0f; + for(size_t i = 0; i < geometry2d.getNumberOfVertices(); i++) + { + centroid[0] += vertices[3 * i + 0]; + centroid[1] += vertices[3 * i + 1]; + centroid[2] += vertices[3 * i + 2]; + } + centroid[0] /= static_cast(geometry2d.getNumberOfVertices()); + centroid[1] /= static_cast(geometry2d.getNumberOfVertices()); + centroid[2] /= static_cast(geometry2d.getNumberOfVertices()); + return centroid; + } + // 3D Types + case IGeometry::Type::Hexahedral: + [[fallthrough]]; + case IGeometry::Type::Tetrahedral: { + const auto& geometry3d = dynamic_cast(geometry); + const auto& vertices = geometry3d.getVertices()->getDataStoreRef(); + centroid[0] = 0.0f; + centroid[1] = 0.0f; + centroid[2] = 0.0f; + for(size_t i = 0; i < geometry3d.getNumberOfVertices(); i++) + { + centroid[0] += vertices[3 * i + 0]; + centroid[1] += vertices[3 * i + 1]; + centroid[2] += vertices[3 * i + 2]; + } + centroid[0] /= static_cast(geometry3d.getNumberOfVertices()); + centroid[1] /= static_cast(geometry3d.getNumberOfVertices()); + centroid[2] /= static_cast(geometry3d.getNumberOfVertices()); + return centroid; + } + } + + return centroid; +} + +void translateGeometry(IGeometry& geometry, const FloatVec3& translation) +{ + switch(geometry.getGeomType()) + { + case IGeometry::Type::Image: { + auto& image = dynamic_cast(geometry); + FloatVec3 origin = image.getOrigin(); + origin[0] += translation[0]; + origin[1] += translation[1]; + origin[2] += translation[2]; + image.setOrigin(origin); + return; + } + case IGeometry::Type::RectGrid: { + auto& rectGrid = dynamic_cast(geometry); + auto& xBounds = rectGrid.getXBounds()->getDataStoreRef(); + auto& yBounds = rectGrid.getYBounds()->getDataStoreRef(); + auto& zBounds = rectGrid.getZBounds()->getDataStoreRef(); + for(size_t i = 0; i < rectGrid.getNumXCells(); i++) + { + xBounds[i] += translation[0]; + } + for(size_t i = 0; i < rectGrid.getNumYCells(); i++) + { + yBounds[i] += translation[1]; + } + for(size_t i = 0; i < rectGrid.getNumZCells(); i++) + { + zBounds[i] += translation[2]; + } + return; + } + case IGeometry::Type::Vertex: { + auto& vertex = dynamic_cast(geometry); + auto& vertices = vertex.getVertices()->getDataStoreRef(); + for(size_t i = 0; i < vertex.getNumberOfVertices(); i++) + { + vertices[3 * i + 0] += translation[0]; + vertices[3 * i + 1] += translation[1]; + vertices[3 * i + 2] += translation[2]; + } + return; + } + case IGeometry::Type::Edge: { + auto& edge = dynamic_cast(geometry); + auto& vertices = edge.getVertices()->getDataStoreRef(); + for(size_t i = 0; i < edge.getNumberOfVertices(); i++) + { + vertices[3 * i + 0] += translation[0]; + vertices[3 * i + 1] += translation[1]; + vertices[3 * i + 2] += translation[2]; + } + return; + } + // 2D Geometries + case IGeometry::Type::Quad: + [[fallthrough]]; + case IGeometry::Type::Triangle: { + auto& geometry2d = dynamic_cast(geometry); + auto& vertices = geometry2d.getVertices()->getDataStoreRef(); + for(size_t i = 0; i < geometry2d.getNumberOfVertices(); i++) + { + vertices[3 * i + 0] += translation[0]; + vertices[3 * i + 1] += translation[1]; + vertices[3 * i + 2] += translation[2]; + } + return; + } + // 3D Geometries + case IGeometry::Type::Hexahedral: + [[fallthrough]]; + case IGeometry::Type::Tetrahedral: { + auto& geometry3d = dynamic_cast(geometry); + auto& vertices = geometry3d.getVertices()->getDataStoreRef(); + for(size_t i = 0; i < geometry3d.getNumberOfVertices(); i++) + { + vertices[3 * i + 0] += translation[0]; + vertices[3 * i + 1] += translation[1]; + vertices[3 * i + 2] += translation[2]; + } + return; + } + } +} + +} // namespace + +// ----------------------------------------------------------------------------- +AlignGeometries::AlignGeometries(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, AlignGeometriesInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +AlignGeometries::~AlignGeometries() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> AlignGeometries::operator()() +{ + + auto movingGeometryPath = m_InputValues->InputMovingGeometryPath; + auto targetGeometryPath = m_InputValues->InputTargetGeometryPath; + auto alignmentType = m_InputValues->AlignmentTypeIndex; + + auto& moving = m_DataStructure.getDataRefAs(movingGeometryPath); + auto& target = m_DataStructure.getDataRefAs(targetGeometryPath); + + if(alignmentType == 0) + { + FloatVec3 movingOrigin = extractOrigin(moving); + FloatVec3 targetOrigin = extractOrigin(target); + + float translation[3] = {targetOrigin[0] - movingOrigin[0], targetOrigin[1] - movingOrigin[1], targetOrigin[2] - movingOrigin[2]}; + translateGeometry(moving, translation); + } + else if(alignmentType == 1) + { + FloatVec3 movingCentroid = extractCentroid(moving); + FloatVec3 targetCentroid = extractCentroid(target); + + float translation[3] = {targetCentroid[0] - movingCentroid[0], targetCentroid[0] - movingCentroid[0], targetCentroid[0] - movingCentroid[0]}; + translateGeometry(moving, translation); + } + else + { + std::string ss = fmt::format("Invalid selection for alignment type"); + return {MakeErrorResult<>(-13423, ss)}; + } + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/AlignGeometries.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/AlignGeometries.hpp new file mode 100644 index 0000000000..a17a6d6ce7 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/AlignGeometries.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ChoicesParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + AlignGeometriesInputValues inputValues; + inputValues.AlignmentTypeIndex = filterArgs.value(alignment_type_index); + inputValues.InputMovingGeometryPath = filterArgs.value(input_moving_geometry_path); + inputValues.InputTargetGeometryPath = filterArgs.value(input_target_geometry_path); + return AlignGeometries(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT AlignGeometriesInputValues +{ + ChoicesParameter::ValueType AlignmentTypeIndex; + GeometrySelectionParameter::ValueType InputMovingGeometryPath; + GeometrySelectionParameter::ValueType InputTargetGeometryPath; +}; + +/** + * @class AlignGeometries + * @brief This algorithm implements support code for the AlignGeometriesFilter + */ + +class SIMPLNXCORE_EXPORT AlignGeometries +{ +public: + AlignGeometries(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, AlignGeometriesInputValues* inputValues); + ~AlignGeometries() noexcept; + + AlignGeometries(const AlignGeometries&) = delete; + AlignGeometries(AlignGeometries&&) noexcept = delete; + AlignGeometries& operator=(const AlignGeometries&) = delete; + AlignGeometries& operator=(AlignGeometries&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const AlignGeometriesInputValues* 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/ApproximatePointCloudHull.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ApproximatePointCloudHull.cpp new file mode 100644 index 0000000000..a025c93218 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ApproximatePointCloudHull.cpp @@ -0,0 +1,220 @@ +#include "ApproximatePointCloudHull.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/Geometry/ImageGeom.hpp" +#include "simplnx/DataStructure/Geometry/VertexGeom.hpp" + +using namespace nx::core; + +namespace +{ +bool validNeighbor(const SizeVec3& dims, const int64 neighborhood[78], usize index, int64 x, int64 y, int64 z) +{ + int64 modX = x + neighborhood[3 * index + 0]; + int64 modY = y + neighborhood[3 * index + 1]; + int64 modZ = z + neighborhood[3 * index + 2]; + + return (modX >= 0 && modX < dims[0]) && (modY >= 0 && modY < dims[1]) && (modZ >= 0 && modZ < dims[2]); +} +} // namespace + +// ----------------------------------------------------------------------------- +ApproximatePointCloudHull::ApproximatePointCloudHull(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + ApproximatePointCloudHullInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ApproximatePointCloudHull::~ApproximatePointCloudHull() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ApproximatePointCloudHull::operator()() +{ + float inverseResolution[3] = {1.0f / m_InputValues->GridResolution[0], 1.0f / m_InputValues->GridResolution[1], 1.0f / m_InputValues->GridResolution[2]}; + + auto* source = m_DataStructure.getDataAs(m_InputValues->InputVertexGeometryPath); + auto* verts = source->getVertices(); + + DataStructure temp; + auto* samplingGrid = ImageGeom::Create(temp, "Image Geometry"); + samplingGrid->setSpacing(m_InputValues->GridResolution[0], m_InputValues->GridResolution[1], m_InputValues->GridResolution[2]); + + usize numVerts = source->getNumberOfVertices(); + auto& vertex = source->getVertices()->getDataStoreRef(); + + std::vector meshMaxExtents; + std::vector meshMinExtents; + + for(usize i = 0; i < 3; i++) + { + meshMaxExtents.push_back(std::numeric_limits::lowest()); + meshMinExtents.push_back(std::numeric_limits::max()); + } + + for(int64 i = 0; i < numVerts; i++) + { + if(vertex[3 * i] > meshMaxExtents[0]) + { + meshMaxExtents[0] = vertex[3 * i]; + } + if(vertex[3 * i + 1] > meshMaxExtents[1]) + { + meshMaxExtents[1] = vertex[3 * i + 1]; + } + if(vertex[3 * i + 2] > meshMaxExtents[2]) + { + meshMaxExtents[2] = vertex[3 * i + 2]; + } + if(vertex[3 * i] < meshMinExtents[0]) + { + meshMinExtents[0] = vertex[3 * i]; + } + if(vertex[3 * i + 1] < meshMinExtents[1]) + { + meshMinExtents[1] = vertex[3 * i + 1]; + } + if(vertex[3 * i + 2] < meshMinExtents[2]) + { + meshMinExtents[2] = vertex[3 * i + 2]; + } + } + + for(auto i = 0; i < 3; i++) + { + meshMinExtents[i] -= (inverseResolution[i] / 2.0f); + meshMaxExtents[i] += (inverseResolution[i] / 2.0f); + } + + int64 bboxMin[3] = {0, 0, 0}; + int64 bboxMax[3] = {0, 0, 0}; + + bboxMin[0] = static_cast(std::floor(meshMinExtents[0] * inverseResolution[0])); + bboxMin[1] = static_cast(std::floor(meshMinExtents[1] * inverseResolution[1])); + bboxMin[2] = static_cast(std::floor(meshMinExtents[2] * inverseResolution[2])); + + bboxMax[0] = static_cast(std::floor(meshMaxExtents[0] * inverseResolution[0])); + bboxMax[1] = static_cast(std::floor(meshMaxExtents[1] * inverseResolution[1])); + bboxMax[2] = static_cast(std::floor(meshMaxExtents[2] * inverseResolution[2])); + + auto dims1 = static_cast(bboxMax[0] - bboxMin[0] + 1); + auto dims2 = static_cast(bboxMax[1] - bboxMin[1] + 1); + auto dims3 = static_cast(bboxMax[2] - bboxMin[2] + 1); + SizeVec3 dims(std::vector{dims1, dims2, dims3}); + samplingGrid->setDimensions(dims); + + int64 multiplier[3] = {1, static_cast(samplingGrid->getNumXCells()), static_cast(samplingGrid->getNumXCells() * samplingGrid->getNumYCells())}; + std::vector> vertsInVoxels(samplingGrid->getNumberOfCells()); + + int64 progIncrement = numVerts / 100; + int64 prog = 1; + int64 progressInt = 0; + + for(int64 v = 0; v < numVerts; v++) + { + auto i = static_cast(std::floor((*verts)[3 * v + 0] * inverseResolution[0]) - static_cast(bboxMin[0])); + auto j = static_cast(std::floor((*verts)[3 * v + 1] * inverseResolution[1]) - static_cast(bboxMin[1])); + auto k = static_cast(std::floor((*verts)[3 * v + 2] * inverseResolution[2]) - static_cast(bboxMin[2])); + int64 index = i * multiplier[0] + j * multiplier[1] + k * multiplier[2]; + vertsInVoxels[index].push_back(v); + + if(v > prog) + { + progressInt = static_cast((static_cast(v) / numVerts) * 100.0f); + std::string ss = fmt::format("Mapping Vertices to Voxels || {}% Complete", progressInt); + // notifyStatusMessage(ss); + prog = prog + progIncrement; + } + } + + std::vector tmpVerts; + int64 neighborhood[78] = {1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1, 1, 1, 0, -1, 1, 0, 1, -1, 0, -1, -1, 0, 1, 0, 1, 1, 0, -1, -1, 0, 1, + -1, 0, -1, 0, 1, 1, 0, 1, -1, 0, -1, 1, 0, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1}; + + progIncrement = (dims[0] * dims[1] * dims[2]) / 100; + prog = 1; + progressInt = 0; + int64 counter = 0; + int64 vertCounter = 0; + float xAvg = 0.0f; + float yAvg = 0.0f; + float zAvg = 0.0f; + + for(int64 z = 0; z < dims[2]; z++) + { + for(int64 y = 0; y < dims[1]; y++) + { + for(int64 x = 0; x < dims[0]; x++) + { + usize index = (z * dims[1] * dims[0]) + (y * dims[0]) + x; + if(vertsInVoxels[index].empty()) + { + counter++; + continue; + } + + usize emtpyNeighbors = 0; + + for(usize n = 0; n < 26; n++) + { + if(validNeighbor(dims, neighborhood, n, x, y, z)) + { + usize neighborIndex = ((z + neighborhood[3 * n + 2]) * dims[1] * dims[0]) + ((y + neighborhood[3 * n + 1]) * dims[0]) + (x + neighborhood[3 * n + 0]); + if(vertsInVoxels[neighborIndex].empty()) + { + emtpyNeighbors++; + } + } + } + + if(emtpyNeighbors > m_InputValues->MinEmptyNeighbors) + { + for(auto vert : vertsInVoxels[index]) + { + vertCounter++; + xAvg += (*verts)[3 * vert + 0]; + yAvg += (*verts)[3 * vert + 1]; + zAvg += (*verts)[3 * vert + 2]; + } + xAvg /= static_cast(vertCounter); + yAvg /= static_cast(vertCounter); + zAvg /= static_cast(vertCounter); + tmpVerts.push_back(xAvg); + tmpVerts.push_back(yAvg); + tmpVerts.push_back(zAvg); + vertCounter = 0; + xAvg = 0.0f; + yAvg = 0.0f; + zAvg = 0.0f; + } + + if(counter > prog) + { + progressInt = static_cast((static_cast(counter) / (dims[0] * dims[1] * dims[2])) * 100.0f); + std::string ss = fmt::format("Trimming Interior Voxels || {}% Complete", progressInt); + // notifyStatusMessage(ss); + prog = prog + progIncrement; + } + counter++; + } + } + } + + auto* hull = m_DataStructure.getDataAs(m_InputValues->OutputVertexGeometryPath); + hull->resizeVertexList(tmpVerts.size() / 3); + if(hull->getVertexAttributeMatrix() != nullptr) + { + hull->getVertexAttributeMatrix()->resizeTuples({tmpVerts.size() / 3}); + } + auto* hullVerts = hull->getVertices(); + auto tmpVertData = tmpVerts.data(); + for(usize i = 0; i < hull->getNumberOfVertices() * 3; i++) + { + (*hullVerts)[i] = tmpVertData[i]; + } + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ApproximatePointCloudHull.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ApproximatePointCloudHull.hpp new file mode 100644 index 0000000000..141480e646 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ApproximatePointCloudHull.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/DataGroupCreationParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" +#include "simplnx/Parameters/NumberParameter.hpp" +#include "simplnx/Parameters/VectorParameter.hpp" + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT ApproximatePointCloudHullInputValues +{ + VectorFloat32Parameter::ValueType GridResolution; + GeometrySelectionParameter::ValueType InputVertexGeometryPath; + UInt64Parameter::ValueType MinEmptyNeighbors; + DataGroupCreationParameter::ValueType OutputVertexGeometryPath; +}; + +/** + * @class ApproximatePointCloudHull + * @brief This algorithm implements support code for the ApproximatePointCloudHullFilter + */ + +class SIMPLNXCORE_EXPORT ApproximatePointCloudHull +{ +public: + ApproximatePointCloudHull(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ApproximatePointCloudHullInputValues* inputValues); + ~ApproximatePointCloudHull() noexcept; + + ApproximatePointCloudHull(const ApproximatePointCloudHull&) = delete; + ApproximatePointCloudHull(ApproximatePointCloudHull&&) noexcept = delete; + ApproximatePointCloudHull& operator=(const ApproximatePointCloudHull&) = delete; + ApproximatePointCloudHull& operator=(ApproximatePointCloudHull&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ApproximatePointCloudHullInputValues* 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/ChangeAngleRepresentation.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ChangeAngleRepresentation.cpp new file mode 100644 index 0000000000..3b0d3ff001 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ChangeAngleRepresentation.cpp @@ -0,0 +1,26 @@ +#include "ChangeAngleRepresentation.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +ChangeAngleRepresentation::ChangeAngleRepresentation(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + ChangeAngleRepresentationInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ChangeAngleRepresentation::~ChangeAngleRepresentation() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ChangeAngleRepresentation::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ChangeAngleRepresentation.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ChangeAngleRepresentation.hpp new file mode 100644 index 0000000000..5d8e5acdd2 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ChangeAngleRepresentation.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/ChoicesParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + ChangeAngleRepresentationInputValues inputValues; + inputValues.AnglesArrayPath = filterArgs.value(angles_array_path); + inputValues.ConversionTypeIndex = filterArgs.value(conversion_type_index); + return ChangeAngleRepresentation(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT ChangeAngleRepresentationInputValues +{ + ArraySelectionParameter::ValueType AnglesArrayPath; + ChoicesParameter::ValueType ConversionTypeIndex; +}; + +/** + * @class ChangeAngleRepresentation + * @brief This algorithm implements support code for the ChangeAngleRepresentationFilter + */ + +class SIMPLNXCORE_EXPORT ChangeAngleRepresentation +{ +public: + ChangeAngleRepresentation(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ChangeAngleRepresentationInputValues* inputValues); + ~ChangeAngleRepresentation() noexcept; + + ChangeAngleRepresentation(const ChangeAngleRepresentation&) = delete; + ChangeAngleRepresentation(ChangeAngleRepresentation&&) noexcept = delete; + ChangeAngleRepresentation& operator=(const ChangeAngleRepresentation&) = delete; + ChangeAngleRepresentation& operator=(ChangeAngleRepresentation&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ChangeAngleRepresentationInputValues* 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/ComputeBoundaryElementFractions.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeBoundaryElementFractions.cpp new file mode 100644 index 0000000000..0e40cb9a9b --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeBoundaryElementFractions.cpp @@ -0,0 +1,49 @@ +#include "ComputeBoundaryElementFractions.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +ComputeBoundaryElementFractions::ComputeBoundaryElementFractions(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + ComputeBoundaryElementFractionsInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ComputeBoundaryElementFractions::~ComputeBoundaryElementFractions() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ComputeBoundaryElementFractions::operator()() +{ + + auto& featureIds = m_DataStructure.getDataRefAs(m_InputValues->FeatureIdsArrayPath); + auto& boundaryCells = m_DataStructure.getDataRefAs(m_InputValues->BoundaryCellsArrayPath); + auto& boundaryCellFractions = m_DataStructure.getDataRefAs(m_InputValues->FeatureDataAttributeMatrixPath.createChildPath(m_InputValues->BoundaryCellFractionsArrayName)); + + usize totalPoints = featureIds.getNumberOfTuples(); + usize numFeatures = boundaryCellFractions.getNumberOfTuples(); + + std::vector surfVoxCounts(numFeatures, 0); + std::vector voxCounts(numFeatures, 0); + + for(usize j = 0; j < totalPoints; j++) + { + int32 gnum = featureIds[j]; + voxCounts[gnum]++; + if(boundaryCells[j] > 0) + { + surfVoxCounts[gnum]++; + } + } + for(usize i = 1; i < numFeatures; i++) + { + boundaryCellFractions[i] = surfVoxCounts[i] / voxCounts[i]; + } + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeBoundaryElementFractions.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeBoundaryElementFractions.hpp new file mode 100644 index 0000000000..b684795272 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeBoundaryElementFractions.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/AttributeMatrixSelectionParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT ComputeBoundaryElementFractionsInputValues +{ + DataObjectNameParameter::ValueType BoundaryCellFractionsArrayName; + ArraySelectionParameter::ValueType BoundaryCellsArrayPath; + AttributeMatrixSelectionParameter::ValueType FeatureDataAttributeMatrixPath; + ArraySelectionParameter::ValueType FeatureIdsArrayPath; +}; + +/** + * @class ComputeBoundaryElementFractions + * @brief This algorithm implements support code for the ComputeBoundaryElementFractionsFilter + */ + +class SIMPLNXCORE_EXPORT ComputeBoundaryElementFractions +{ +public: + ComputeBoundaryElementFractions(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + ComputeBoundaryElementFractionsInputValues* inputValues); + ~ComputeBoundaryElementFractions() noexcept; + + ComputeBoundaryElementFractions(const ComputeBoundaryElementFractions&) = delete; + ComputeBoundaryElementFractions(ComputeBoundaryElementFractions&&) noexcept = delete; + ComputeBoundaryElementFractions& operator=(const ComputeBoundaryElementFractions&) = delete; + ComputeBoundaryElementFractions& operator=(ComputeBoundaryElementFractions&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ComputeBoundaryElementFractionsInputValues* 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/ComputeDifferencesMap.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeDifferencesMap.cpp new file mode 100644 index 0000000000..348c62f573 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeDifferencesMap.cpp @@ -0,0 +1,61 @@ +#include "ComputeDifferencesMap.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/Utilities/FilterUtilities.hpp" + +using namespace nx::core; +namespace +{ +struct ExecuteFindDifferenceMapFunctor +{ + template + void operator()(IDataArray* firstArrayPtr, IDataArray* secondArrayPtr, IDataArray* differenceMapPtr) + { + using store_type = AbstractDataStore; + + auto& firstArray = firstArrayPtr->template getIDataStoreRefAs(); + auto& secondArray = secondArrayPtr->template getIDataStoreRefAs(); + auto& differenceMap = differenceMapPtr->template getIDataStoreRefAs(); + + usize numTuples = firstArray.getNumberOfTuples(); + int32 numComps = firstArray.getNumberOfComponents(); + + for(usize i = 0; i < numTuples; i++) + { + for(int32 j = 0; j < numComps; j++) + { + auto firstVal = firstArray[numComps * i + j]; + auto secondVal = secondArray[numComps * i + j]; + auto diffVal = firstVal > secondVal ? firstVal - secondVal : secondVal - firstVal; + differenceMap[numComps * i + j] = diffVal; + } + } + } +}; +} // namespace + +// ----------------------------------------------------------------------------- +ComputeDifferencesMap::ComputeDifferencesMap(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + ComputeDifferencesMapInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ComputeDifferencesMap::~ComputeDifferencesMap() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ComputeDifferencesMap::operator()() +{ + + auto* firstInputArray = m_DataStructure.getDataAs(m_InputValues->FirstInputArrayPath); + auto* secondInputArray = m_DataStructure.getDataAs(m_InputValues->SecondInputArrayPath); + auto* differenceMapArray = m_DataStructure.getDataAs(m_InputValues->DifferenceMapArrayPath); + + ExecuteDataFunction(ExecuteFindDifferenceMapFunctor{}, firstInputArray->getDataType(), firstInputArray, secondInputArray, differenceMapArray); + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeDifferencesMap.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeDifferencesMap.hpp new file mode 100644 index 0000000000..a1f1760f8f --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeDifferencesMap.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArrayCreationParameter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT ComputeDifferencesMapInputValues +{ + ArrayCreationParameter::ValueType DifferenceMapArrayPath; + ArraySelectionParameter::ValueType FirstInputArrayPath; + ArraySelectionParameter::ValueType SecondInputArrayPath; +}; + +/** + * @class ComputeDifferencesMap + * @brief This algorithm implements support code for the ComputeDifferencesMapFilter + */ + +class SIMPLNXCORE_EXPORT ComputeDifferencesMap +{ +public: + ComputeDifferencesMap(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeDifferencesMapInputValues* inputValues); + ~ComputeDifferencesMap() noexcept; + + ComputeDifferencesMap(const ComputeDifferencesMap&) = delete; + ComputeDifferencesMap(ComputeDifferencesMap&&) noexcept = delete; + ComputeDifferencesMap& operator=(const ComputeDifferencesMap&) = delete; + ComputeDifferencesMap& operator=(ComputeDifferencesMap&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ComputeDifferencesMapInputValues* 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/ComputeFeatureNeighbors.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeatureNeighbors.cpp new file mode 100644 index 0000000000..896aad513f --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeatureNeighbors.cpp @@ -0,0 +1,26 @@ +#include "ComputeFeatureNeighbors.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +ComputeFeatureNeighbors::ComputeFeatureNeighbors(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + ComputeFeatureNeighborsInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ComputeFeatureNeighbors::~ComputeFeatureNeighbors() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ComputeFeatureNeighbors::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeatureNeighbors.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeatureNeighbors.hpp new file mode 100644 index 0000000000..bdbed61c6a --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeatureNeighbors.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/AttributeMatrixSelectionParameter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + ComputeFeatureNeighborsInputValues inputValues; + inputValues.BoundaryCellsName = filterArgs.value(boundary_cells_name); + inputValues.CellFeatureArrayPath = filterArgs.value(cell_feature_array_path); + inputValues.FeatureIdsPath = filterArgs.value(feature_ids_path); + inputValues.InputImageGeometryPath = filterArgs.value(input_image_geometry_path); + inputValues.NeighborListName = filterArgs.value(neighbor_list_name); + inputValues.NumberOfNeighborsName = filterArgs.value(number_of_neighbors_name); + inputValues.SharedSurfaceAreaListName = filterArgs.value(shared_surface_area_list_name); + inputValues.StoreBoundaryCells = filterArgs.value(store_boundary_cells); + inputValues.StoreSurfaceFeatures = filterArgs.value(store_surface_features); + inputValues.SurfaceFeaturesName = filterArgs.value(surface_features_name); + return ComputeFeatureNeighbors(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT ComputeFeatureNeighborsInputValues +{ + DataObjectNameParameter::ValueType BoundaryCellsName; + AttributeMatrixSelectionParameter::ValueType CellFeatureArrayPath; + ArraySelectionParameter::ValueType FeatureIdsPath; + GeometrySelectionParameter::ValueType InputImageGeometryPath; + DataObjectNameParameter::ValueType NeighborListName; + DataObjectNameParameter::ValueType NumberOfNeighborsName; + DataObjectNameParameter::ValueType SharedSurfaceAreaListName; + BoolParameter::ValueType StoreBoundaryCells; + BoolParameter::ValueType StoreSurfaceFeatures; + DataObjectNameParameter::ValueType SurfaceFeaturesName; +}; + +/** + * @class ComputeFeatureNeighbors + * @brief This algorithm implements support code for the ComputeFeatureNeighborsFilter + */ + +class SIMPLNXCORE_EXPORT ComputeFeatureNeighbors +{ +public: + ComputeFeatureNeighbors(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeFeatureNeighborsInputValues* inputValues); + ~ComputeFeatureNeighbors() noexcept; + + ComputeFeatureNeighbors(const ComputeFeatureNeighbors&) = delete; + ComputeFeatureNeighbors(ComputeFeatureNeighbors&&) noexcept = delete; + ComputeFeatureNeighbors& operator=(const ComputeFeatureNeighbors&) = delete; + ComputeFeatureNeighbors& operator=(ComputeFeatureNeighbors&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ComputeFeatureNeighborsInputValues* 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/ComputeFeaturePhases.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeaturePhases.cpp new file mode 100644 index 0000000000..a7a5ae2793 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeaturePhases.cpp @@ -0,0 +1,25 @@ +#include "ComputeFeaturePhases.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +ComputeFeaturePhases::ComputeFeaturePhases(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeFeaturePhasesInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ComputeFeaturePhases::~ComputeFeaturePhases() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ComputeFeaturePhases::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeaturePhases.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeaturePhases.hpp new file mode 100644 index 0000000000..806ba846a0 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeaturePhases.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/AttributeMatrixSelectionParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + ComputeFeaturePhasesInputValues inputValues; + inputValues.CellFeaturesAttributeMatrixPath = filterArgs.value(cell_features_attribute_matrix_path); + inputValues.CellPhasesArrayPath = filterArgs.value(cell_phases_array_path); + inputValues.FeatureIdsPath = filterArgs.value(feature_ids_path); + inputValues.FeaturePhasesArrayName = filterArgs.value(feature_phases_array_name); + return ComputeFeaturePhases(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT ComputeFeaturePhasesInputValues +{ + AttributeMatrixSelectionParameter::ValueType CellFeaturesAttributeMatrixPath; + ArraySelectionParameter::ValueType CellPhasesArrayPath; + ArraySelectionParameter::ValueType FeatureIdsPath; + DataObjectNameParameter::ValueType FeaturePhasesArrayName; +}; + +/** + * @class ComputeFeaturePhases + * @brief This algorithm implements support code for the ComputeFeaturePhasesFilter + */ + +class SIMPLNXCORE_EXPORT ComputeFeaturePhases +{ +public: + ComputeFeaturePhases(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeFeaturePhasesInputValues* inputValues); + ~ComputeFeaturePhases() noexcept; + + ComputeFeaturePhases(const ComputeFeaturePhases&) = delete; + ComputeFeaturePhases(ComputeFeaturePhases&&) noexcept = delete; + ComputeFeaturePhases& operator=(const ComputeFeaturePhases&) = delete; + ComputeFeaturePhases& operator=(ComputeFeaturePhases&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ComputeFeaturePhasesInputValues* 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/ComputeFeaturePhasesBinary.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeaturePhasesBinary.cpp new file mode 100644 index 0000000000..5f370ae5e3 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeaturePhasesBinary.cpp @@ -0,0 +1,26 @@ +#include "ComputeFeaturePhasesBinary.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +ComputeFeaturePhasesBinary::ComputeFeaturePhasesBinary(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + ComputeFeaturePhasesBinaryInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ComputeFeaturePhasesBinary::~ComputeFeaturePhasesBinary() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ComputeFeaturePhasesBinary::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeaturePhasesBinary.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeaturePhasesBinary.hpp new file mode 100644 index 0000000000..49e824281d --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeaturePhasesBinary.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/AttributeMatrixSelectionParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + ComputeFeaturePhasesBinaryInputValues inputValues; + inputValues.CellDataAttributeMatrixPath = filterArgs.value(cell_data_attribute_matrix_path); + inputValues.FeatureIdsArrayPath = filterArgs.value(feature_ids_array_path); + inputValues.FeaturePhasesArrayName = filterArgs.value(feature_phases_array_name); + inputValues.MaskArrayPath = filterArgs.value(mask_array_path); + return ComputeFeaturePhasesBinary(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT ComputeFeaturePhasesBinaryInputValues +{ + AttributeMatrixSelectionParameter::ValueType CellDataAttributeMatrixPath; + ArraySelectionParameter::ValueType FeatureIdsArrayPath; + DataObjectNameParameter::ValueType FeaturePhasesArrayName; + ArraySelectionParameter::ValueType MaskArrayPath; +}; + +/** + * @class ComputeFeaturePhasesBinary + * @brief This algorithm implements support code for the ComputeFeaturePhasesBinaryFilter + */ + +class SIMPLNXCORE_EXPORT ComputeFeaturePhasesBinary +{ +public: + ComputeFeaturePhasesBinary(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeFeaturePhasesBinaryInputValues* inputValues); + ~ComputeFeaturePhasesBinary() noexcept; + + ComputeFeaturePhasesBinary(const ComputeFeaturePhasesBinary&) = delete; + ComputeFeaturePhasesBinary(ComputeFeaturePhasesBinary&&) noexcept = delete; + ComputeFeaturePhasesBinary& operator=(const ComputeFeaturePhasesBinary&) = delete; + ComputeFeaturePhasesBinary& operator=(ComputeFeaturePhasesBinary&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ComputeFeaturePhasesBinaryInputValues* 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/ComputeFeatureSizes.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeatureSizes.cpp new file mode 100644 index 0000000000..b4522e289e --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeatureSizes.cpp @@ -0,0 +1,188 @@ +#include "ComputeFeatureSizes.hpp" + +#include "simplnx/Common/Numbers.hpp" +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" +#include "simplnx/DataStructure/Geometry/ImageGeom.hpp" +#include "simplnx/Utilities/DataArrayUtilities.hpp" + +#include + +using namespace nx::core; + +namespace +{ +constexpr nx::core::int32 k_BadFeatureCount = -78231; +constexpr nx::core::float32 k_PI = nx::core::numbers::pi_v; + +} // namespace + +// ----------------------------------------------------------------------------- +ComputeFeatureSizes::ComputeFeatureSizes(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeFeatureSizesInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ComputeFeatureSizes::~ComputeFeatureSizes() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ComputeFeatureSizes::operator()() +{ + + auto saveElementSizes = m_InputValues->SaveElementSizes; + + auto featureIdsArrayPath = m_InputValues->FeatureIdsPath; + auto featureIdsArrayPtr = m_DataStructure.getDataAs(featureIdsArrayPath); + const auto& featureIdsStoreRef = featureIdsArrayPtr->getDataStoreRef(); + { + auto featureAttributeMatrixPath = m_InputValues->FeatureAttributeMatrixPath; + auto validateNumFeatResult = ValidateFeatureIdsToFeatureAttributeMatrixIndexing(m_DataStructure, featureAttributeMatrixPath, *featureIdsArrayPtr, false, m_MessageHandler); + if(validateNumFeatResult.invalid()) + { + return validateNumFeatResult; + } + } + usize totalPoints = featureIdsStoreRef.getNumberOfTuples(); + + auto geomPath = m_InputValues->InputImageGeometryPath; + auto* geom = m_DataStructure.getDataAs(geomPath); + auto featureAttributeMatrixPath = m_InputValues->FeatureAttributeMatrixPath; + + DataPath volumesPath = featureAttributeMatrixPath.createChildPath(m_InputValues->VolumesName); + DataPath equivDiamPath = featureAttributeMatrixPath.createChildPath(m_InputValues->EquivalentDiametersName); + DataPath numElementsPath = featureAttributeMatrixPath.createChildPath(m_InputValues->NumElementsName); + + // If the geometry is an ImageGeometry or a RectilinearGeometry + auto* imageGeom = dynamic_cast(geom); + if(nullptr != imageGeom) + { + + auto& volumes = m_DataStructure.getDataAs(volumesPath)->getDataStoreRef(); + auto& equivalentDiameters = m_DataStructure.getDataAs(equivDiamPath)->getDataStoreRef(); + auto& numElements = m_DataStructure.getDataAs(numElementsPath)->getDataStoreRef(); + + usize featureIdsMaxIdx = std::distance(featureIdsStoreRef.begin(), std::max_element(featureIdsStoreRef.cbegin(), featureIdsStoreRef.cend())); + usize maxValue = featureIdsStoreRef[featureIdsMaxIdx]; + usize numFeatures = maxValue + 1; + + std::vector featureCounts(numFeatures, 0); + + for(size_t j = 0; j < totalPoints; j++) + { + int32_t gnum = featureIdsStoreRef[j]; + auto temp = featureCounts[gnum] + 1; + featureCounts[gnum] = temp; + } + + FloatVec3 spacing = imageGeom->getSpacing(); + + if(imageGeom->getNumXCells() == 1 || imageGeom->getNumYCells() == 1 || imageGeom->getNumZCells() == 1) + { + float res_scalar = 0.0f; + if(imageGeom->getNumXCells() == 1) + { + res_scalar = spacing[1] * spacing[2]; + } + else if(imageGeom->getNumYCells() == 1) + { + res_scalar = spacing[0] * spacing[2]; + } + else if(imageGeom->getNumZCells() == 1) + { + res_scalar = spacing[0] * spacing[1]; + } + + for(size_t i = 1; i < numFeatures; i++) + { + numElements[i] = static_cast(featureCounts[i]); + if(featureCounts[i] > 9007199254740992ULL) + { + std::string ss = fmt::format("Number of voxels belonging to feature {} ({}) is greater than 9007199254740992", i, featureCounts[i]); + return MakeErrorResult(k_BadFeatureCount, ss); + } + volumes[i] = static_cast(featureCounts[i]) * static_cast(res_scalar); + + float32 rad = volumes[i] / k_PI; + float32 diameter = (2 * sqrtf(rad)); + equivalentDiameters[i] = diameter; + } + } + else + { + float32 res_scalar = spacing[0] * spacing[1] * spacing[2]; + float vol_term = (4.0f / 3.0f) * k_PI; + for(usize i = 1; i < numFeatures; i++) + { + numElements[i] = static_cast(featureCounts[i]); + if(featureCounts[i] > 9007199254740992ULL) + { + std::string ss = fmt::format("Number of voxels belonging to feature {} ({}) is greater than 9007199254740992", i, featureCounts[i]); + return MakeErrorResult(k_BadFeatureCount, ss); + } + + volumes[i] = static_cast(featureCounts[i]) * static_cast(res_scalar); + + float32 rad = volumes[i] / vol_term; + float32 diameter = 2.0f * powf(rad, 0.3333333333f); + equivalentDiameters[i] = diameter; + } + } + + if(saveElementSizes) + { + int32 err = imageGeom->findElementSizes(false); + if(err < 0) + { + std::string ss = fmt::format("Error computing Element sizes for Geometry type {}", imageGeom->getTypeName()); + return MakeErrorResult(err, ss); + } + } + } + else + { + auto& volumes = m_DataStructure.getDataAs(volumesPath)->getDataStoreRef(); + auto& equivalentDiameters = m_DataStructure.getDataAs(equivDiamPath)->getDataStoreRef(); + auto& numElements = m_DataStructure.getDataAs(numElementsPath)->getDataStoreRef(); + + usize numFeatures = volumes.getNumberOfTuples(); + + int32_t err = geom->findElementSizes(false); + if(err < 0) + { + std::string ss = fmt::format("Error computing Element sizes for Geometry type {}", geom->getTypeName()); + return MakeErrorResult(err, ss); + } + + const Float32Array* elemSizes = geom->getElementSizes(); + + std::vector featureCounts(numFeatures, 1); + + for(size_t j = 0; j < totalPoints; j++) + { + int32 gnum = featureIdsStoreRef[j]; + auto temp = featureCounts[gnum] + 1; + featureCounts[gnum] = temp; + auto temp2 = volumes[gnum]; + volumes[gnum] = temp2 + (*elemSizes)[j]; + } + float vol_term = (4.0f / 3.0f) * k_PI; + for(size_t i = 1; i < numFeatures; i++) + { + numElements[i] = static_cast(featureCounts[i]); + float rad = volumes[i] / vol_term; + float diameter = 2.0f * powf(rad, 0.3333333333f); + equivalentDiameters[i] = diameter; + } + + if(!saveElementSizes) + { + geom->deleteElementSizes(); + } + } + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeatureSizes.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeatureSizes.hpp new file mode 100644 index 0000000000..40b1f053f3 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeFeatureSizes.hpp @@ -0,0 +1,58 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/AttributeMatrixSelectionParameter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT ComputeFeatureSizesInputValues +{ + DataObjectNameParameter::ValueType EquivalentDiametersName; + AttributeMatrixSelectionParameter::ValueType FeatureAttributeMatrixPath; + ArraySelectionParameter::ValueType FeatureIdsPath; + GeometrySelectionParameter::ValueType InputImageGeometryPath; + DataObjectNameParameter::ValueType NumElementsName; + BoolParameter::ValueType SaveElementSizes; + DataObjectNameParameter::ValueType VolumesName; +}; + +/** + * @class ComputeFeatureSizes + * @brief This algorithm implements support code for the ComputeFeatureSizesFilter + */ + +class SIMPLNXCORE_EXPORT ComputeFeatureSizes +{ +public: + ComputeFeatureSizes(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeFeatureSizesInputValues* inputValues); + ~ComputeFeatureSizes() noexcept; + + ComputeFeatureSizes(const ComputeFeatureSizes&) = delete; + ComputeFeatureSizes(ComputeFeatureSizes&&) noexcept = delete; + ComputeFeatureSizes& operator=(const ComputeFeatureSizes&) = delete; + ComputeFeatureSizes& operator=(ComputeFeatureSizes&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ComputeFeatureSizesInputValues* 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/ComputeSurfaceFeatures.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeSurfaceFeatures.cpp new file mode 100644 index 0000000000..9dcf86a149 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeSurfaceFeatures.cpp @@ -0,0 +1,231 @@ +#include "ComputeSurfaceFeatures.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/Geometry/ImageGeom.hpp" +#include "simplnx/Utilities/DataArrayUtilities.hpp" + +using namespace nx::core; + +namespace +{ +bool IsPointASurfaceFeature(const Point2D& point, usize xPoints, usize yPoints, bool markFeature0Neighbors, const Int32AbstractDataStore& featureIds) +{ + const usize yStride = point.getY() * xPoints; + + if(point.getX() <= 0 || point.getX() >= xPoints - 1) + { + return true; + } + if(point.getY() <= 0 || point.getY() >= yPoints - 1) + { + return true; + } + + if(markFeature0Neighbors) + { + if(featureIds[yStride + point.getX() - 1] == 0) + { + return true; + } + if(featureIds[yStride + point.getX() + 1] == 0) + { + return true; + } + if(featureIds[yStride + point.getX() - xPoints] == 0) + { + return true; + } + if(featureIds[yStride + point.getX() + xPoints] == 0) + { + return true; + } + } + + return false; +} + +bool IsPointASurfaceFeature(const Point3D& point, usize xPoints, usize yPoints, usize zPoints, bool markFeature0Neighbors, const Int32AbstractDataStore& featureIds) +{ + usize yStride = point.getY() * xPoints; + usize zStride = point.getZ() * xPoints * yPoints; + + if(point.getX() <= 0 || point.getX() >= xPoints - 1) + { + return true; + } + if(point.getY() <= 0 || point.getY() >= yPoints - 1) + { + return true; + } + if(point.getZ() <= 0 || point.getZ() >= zPoints - 1) + { + return true; + } + + if(markFeature0Neighbors) + { + if(featureIds[zStride + yStride + point.getX() - 1] == 0) + { + return true; + } + if(featureIds[zStride + yStride + point.getX() + 1] == 0) + { + return true; + } + if(featureIds[zStride + yStride + point.getX() - xPoints] == 0) + { + return true; + } + if(featureIds[zStride + yStride + point.getX() + xPoints] == 0) + { + return true; + } + if(featureIds[zStride + yStride + point.getX() - (xPoints * yPoints)] == 0) + { + return true; + } + if(featureIds[zStride + yStride + point.getX() + (xPoints * yPoints)] == 0) + { + return true; + } + } + + return false; +} + +void findSurfaceFeatures3D(DataStructure& dataStructure, const DataPath& featureGeometryPathValue, const DataPath& featureIdsArrayPathValue, const DataPath& surfaceFeaturesArrayPathValue, + bool markFeature0Neighbors, const std::atomic_bool& shouldCancel) +{ + const auto& featureGeometry = dataStructure.getDataRefAs(featureGeometryPathValue); + const auto& featureIds = dataStructure.getDataAs(featureIdsArrayPathValue)->getDataStoreRef(); + auto& surfaceFeatures = dataStructure.getDataAs(surfaceFeaturesArrayPathValue)->getDataStoreRef(); + + const usize xPoints = featureGeometry.getNumXCells(); + const usize yPoints = featureGeometry.getNumYCells(); + const usize zPoints = featureGeometry.getNumZCells(); + + for(usize z = 0; z < zPoints; z++) + { + const usize zStride = z * xPoints * yPoints; + for(usize y = 0; y < yPoints; y++) + { + const usize yStride = y * xPoints; + for(usize x = 0; x < xPoints; x++) + { + if(shouldCancel) + { + return; + } + + const int32 gNum = featureIds[zStride + yStride + x]; + if(gNum != 0 && !surfaceFeatures[gNum]) + { + if(IsPointASurfaceFeature(Point3D{x, y, z}, xPoints, yPoints, zPoints, markFeature0Neighbors, featureIds)) + { + surfaceFeatures[gNum] = 1; + } + } + } + } + } +} + +void findSurfaceFeatures2D(DataStructure& dataStructure, const DataPath& featureGeometryPathValue, const DataPath& featureIdsArrayPathValue, const DataPath& surfaceFeaturesArrayPathValue, + bool markFeature0Neighbors, const std::atomic_bool& shouldCancel) +{ + const auto& featureGeometry = dataStructure.getDataRefAs(featureGeometryPathValue); + const auto& featureIds = dataStructure.getDataAs(featureIdsArrayPathValue)->getDataStoreRef(); + auto& surfaceFeatures = dataStructure.getDataAs(surfaceFeaturesArrayPathValue)->getDataStoreRef(); + + usize xPoints = 0; + usize yPoints = 0; + + if(featureGeometry.getNumXCells() == 1) + { + xPoints = featureGeometry.getNumYCells(); + yPoints = featureGeometry.getNumZCells(); + } + if(featureGeometry.getNumYCells() == 1) + { + xPoints = featureGeometry.getNumXCells(); + yPoints = featureGeometry.getNumZCells(); + } + if(featureGeometry.getNumZCells() == 1) + { + xPoints = featureGeometry.getNumXCells(); + yPoints = featureGeometry.getNumYCells(); + } + + for(usize y = 0; y < yPoints; y++) + { + const usize yStride = y * xPoints; + + for(usize x = 0; x < xPoints; x++) + { + if(shouldCancel) + { + return; + } + + const int32 gNum = featureIds[yStride + x]; + if(gNum != 0 && surfaceFeatures[gNum] == 0) + { + if(IsPointASurfaceFeature(Point2D{x, y}, xPoints, yPoints, markFeature0Neighbors, featureIds)) + { + surfaceFeatures[gNum] = 1; + } + } + } + } +} +} // namespace + +// ----------------------------------------------------------------------------- +ComputeSurfaceFeatures::ComputeSurfaceFeatures(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + ComputeSurfaceFeaturesInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ComputeSurfaceFeatures::~ComputeSurfaceFeatures() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ComputeSurfaceFeatures::operator()() +{ + + const auto pMarkFeature0NeighborsValue = m_InputValues->MarkFeature0Neighbors; + const auto pFeatureGeometryPathValue = m_InputValues->InputImageGeometryPath; + const auto pFeatureIdsArrayPathValue = m_InputValues->FeatureIdsPath; + const auto pFeaturesAttributeMatrixPathValue = m_InputValues->FeatureAttributeMatrixPath; + const auto pSurfaceFeaturesArrayPathValue = pFeaturesAttributeMatrixPathValue.createChildPath(m_InputValues->SurfaceFeaturesArrayName); + + // Resize the surface features array to the proper size + const auto& featureIdsArray = m_DataStructure.getDataRefAs(pFeatureIdsArrayPathValue); + + auto validateNumFeatResult = ValidateFeatureIdsToFeatureAttributeMatrixIndexing(m_DataStructure, pFeaturesAttributeMatrixPathValue, featureIdsArray, false, m_MessageHandler); + if(validateNumFeatResult.invalid()) + { + return validateNumFeatResult; + } + + // Find surface features + const auto& featureGeometry = m_DataStructure.getDataRefAs(pFeatureGeometryPathValue); + if(const usize geometryDimensionality = featureGeometry.getDimensionality(); geometryDimensionality == 3) + { + findSurfaceFeatures3D(m_DataStructure, pFeatureGeometryPathValue, pFeatureIdsArrayPathValue, pSurfaceFeaturesArrayPathValue, pMarkFeature0NeighborsValue, m_ShouldCancel); + } + else if(geometryDimensionality == 2) + { + findSurfaceFeatures2D(m_DataStructure, pFeatureGeometryPathValue, pFeatureIdsArrayPathValue, pSurfaceFeaturesArrayPathValue, pMarkFeature0NeighborsValue, m_ShouldCancel); + } + else + { + MakeErrorResult(-1000, fmt::format("Image Geometry at path '{}' must be either 3D or 2D", pFeatureGeometryPathValue.toString())); + } + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeSurfaceFeatures.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeSurfaceFeatures.hpp new file mode 100644 index 0000000000..0c825a2b1b --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ComputeSurfaceFeatures.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/AttributeMatrixSelectionParameter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT ComputeSurfaceFeaturesInputValues +{ + AttributeMatrixSelectionParameter::ValueType FeatureAttributeMatrixPath; + ArraySelectionParameter::ValueType FeatureIdsPath; + GeometrySelectionParameter::ValueType InputImageGeometryPath; + BoolParameter::ValueType MarkFeature0Neighbors; + DataObjectNameParameter::ValueType SurfaceFeaturesArrayName; +}; + +/** + * @class ComputeSurfaceFeatures + * @brief This algorithm implements support code for the ComputeSurfaceFeaturesFilter + */ + +class SIMPLNXCORE_EXPORT ComputeSurfaceFeatures +{ +public: + ComputeSurfaceFeatures(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeSurfaceFeaturesInputValues* inputValues); + ~ComputeSurfaceFeatures() noexcept; + + ComputeSurfaceFeatures(const ComputeSurfaceFeatures&) = delete; + ComputeSurfaceFeatures(ComputeSurfaceFeatures&&) noexcept = delete; + ComputeSurfaceFeatures& operator=(const ComputeSurfaceFeatures&) = delete; + ComputeSurfaceFeatures& operator=(ComputeSurfaceFeatures&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ComputeSurfaceFeaturesInputValues* 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/ConditionalSetValue.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ConditionalSetValue.cpp new file mode 100644 index 0000000000..9a67608222 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ConditionalSetValue.cpp @@ -0,0 +1,67 @@ +#include "ConditionalSetValue.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/Utilities/DataArrayUtilities.hpp" +#include "simplnx/Utilities/FilterUtilities.hpp" +#include "simplnx/Utilities/StringInterpretationUtilities.hpp" + +using namespace nx::core; + +namespace +{ +struct ReplaceValueInArrayFunctor +{ + template + void operator()(IDataArray& workingArray, const std::string& removeValue, const std::string& replaceValue) + { + auto& dataStore = workingArray.template getIDataStoreRefAs>(); + + ScalarType removeVal = StringInterpretationUtilities::Convert(removeValue).value(); + ScalarType replaceVal = StringInterpretationUtilities::Convert(replaceValue).value(); + + const auto size = dataStore.getNumberOfTuples() * dataStore.getNumberOfComponents(); + + for(usize index = 0; index < size; index++) + { + if(dataStore[index] == removeVal) + { + dataStore[index] = replaceVal; + } + } + } +}; +} // namespace + +// ----------------------------------------------------------------------------- +ConditionalSetValue::ConditionalSetValue(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ConditionalSetValueInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ConditionalSetValue::~ConditionalSetValue() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ConditionalSetValue::operator()() +{ + if(m_InputValues->UseConditional) + { + DataObject& inputDataObject = m_DataStructure.getDataRef(m_InputValues->SelectedArrayPath); + + const IDataArray& conditionalArray = m_DataStructure.getDataRefAs(m_InputValues->ConditionalArrayPath); + + Result<> result = ConditionalReplaceValueInArray(m_InputValues->ReplaceValue, inputDataObject, conditionalArray, m_InputValues->InvertMask); + + return result; + } + else + { + auto& inputDataArray = m_DataStructure.getDataRefAs(m_InputValues->SelectedArrayPath); + ExecuteDataFunction(ReplaceValueInArrayFunctor{}, inputDataArray.getDataType(), inputDataArray, m_InputValues->RemoveValue, m_InputValues->ReplaceValue); + } + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ConditionalSetValue.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ConditionalSetValue.hpp new file mode 100644 index 0000000000..1d3baddd78 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ConditionalSetValue.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/StringParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT ConditionalSetValueInputValues +{ + ArraySelectionParameter::ValueType ConditionalArrayPath; + BoolParameter::ValueType InvertMask; + StringParameter::ValueType RemoveValue; + StringParameter::ValueType ReplaceValue; + ArraySelectionParameter::ValueType SelectedArrayPath; + BoolParameter::ValueType UseConditional; +}; + +/** + * @class ConditionalSetValue + * @brief This algorithm implements support code for the ConditionalSetValueFilter + */ + +class SIMPLNXCORE_EXPORT ConditionalSetValue +{ +public: + ConditionalSetValue(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ConditionalSetValueInputValues* inputValues); + ~ConditionalSetValue() noexcept; + + ConditionalSetValue(const ConditionalSetValue&) = delete; + ConditionalSetValue(ConditionalSetValue&&) noexcept = delete; + ConditionalSetValue& operator=(const ConditionalSetValue&) = delete; + ConditionalSetValue& operator=(ConditionalSetValue&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ConditionalSetValueInputValues* 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/CopyDataObject.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CopyDataObject.cpp new file mode 100644 index 0000000000..9e72d1a2e0 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CopyDataObject.cpp @@ -0,0 +1,25 @@ +#include "CopyDataObject.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +CopyDataObject::CopyDataObject(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, CopyDataObjectInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +CopyDataObject::~CopyDataObject() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> CopyDataObject::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CopyDataObject.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CopyDataObject.hpp new file mode 100644 index 0000000000..c46fbeaa4c --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CopyDataObject.hpp @@ -0,0 +1,60 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/DataGroupSelectionParameter.hpp" +#include "simplnx/Parameters/MultiPathSelectionParameter.hpp" +#include "simplnx/Parameters/StringParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + CopyDataObjectInputValues inputValues; + inputValues.ExistingDataPath = filterArgs.value(existing_data_path); + inputValues.NewDataPath = filterArgs.value(new_data_path); + inputValues.NewPathSuffix = filterArgs.value(new_path_suffix); + inputValues.UseNewParent = filterArgs.value(use_new_parent); + return CopyDataObject(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT CopyDataObjectInputValues +{ + MultiPathSelectionParameter::ValueType ExistingDataPath; + DataGroupSelectionParameter::ValueType NewDataPath; + StringParameter::ValueType NewPathSuffix; + BoolParameter::ValueType UseNewParent; +}; + +/** + * @class CopyDataObject + * @brief This algorithm implements support code for the CopyDataObjectFilter + */ + +class SIMPLNXCORE_EXPORT CopyDataObject +{ +public: + CopyDataObject(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, CopyDataObjectInputValues* inputValues); + ~CopyDataObject() noexcept; + + CopyDataObject(const CopyDataObject&) = delete; + CopyDataObject(CopyDataObject&&) noexcept = delete; + CopyDataObject& operator=(const CopyDataObject&) = delete; + CopyDataObject& operator=(CopyDataObject&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const CopyDataObjectInputValues* 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/CopyFeatureArrayToElementArray.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CopyFeatureArrayToElementArray.cpp new file mode 100644 index 0000000000..5ddb093596 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CopyFeatureArrayToElementArray.cpp @@ -0,0 +1,26 @@ +#include "CopyFeatureArrayToElementArray.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +CopyFeatureArrayToElementArray::CopyFeatureArrayToElementArray(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + CopyFeatureArrayToElementArrayInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +CopyFeatureArrayToElementArray::~CopyFeatureArrayToElementArray() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> CopyFeatureArrayToElementArray::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CopyFeatureArrayToElementArray.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CopyFeatureArrayToElementArray.hpp new file mode 100644 index 0000000000..f5a8cec417 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CopyFeatureArrayToElementArray.hpp @@ -0,0 +1,58 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/MultiArraySelectionParameter.hpp" +#include "simplnx/Parameters/StringParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + CopyFeatureArrayToElementArrayInputValues inputValues; + inputValues.CreatedArraySuffix = filterArgs.value(created_array_suffix); + inputValues.FeatureIdsPath = filterArgs.value(feature_ids_path); + inputValues.SelectedFeatureArrayPaths = filterArgs.value(selected_feature_array_paths); + return CopyFeatureArrayToElementArray(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT CopyFeatureArrayToElementArrayInputValues +{ + StringParameter::ValueType CreatedArraySuffix; + ArraySelectionParameter::ValueType FeatureIdsPath; + MultiArraySelectionParameter::ValueType SelectedFeatureArrayPaths; +}; + +/** + * @class CopyFeatureArrayToElementArray + * @brief This algorithm implements support code for the CopyFeatureArrayToElementArrayFilter + */ + +class SIMPLNXCORE_EXPORT CopyFeatureArrayToElementArray +{ +public: + CopyFeatureArrayToElementArray(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + CopyFeatureArrayToElementArrayInputValues* inputValues); + ~CopyFeatureArrayToElementArray() noexcept; + + CopyFeatureArrayToElementArray(const CopyFeatureArrayToElementArray&) = delete; + CopyFeatureArrayToElementArray(CopyFeatureArrayToElementArray&&) noexcept = delete; + CopyFeatureArrayToElementArray& operator=(const CopyFeatureArrayToElementArray&) = delete; + CopyFeatureArrayToElementArray& operator=(CopyFeatureArrayToElementArray&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const CopyFeatureArrayToElementArrayInputValues* 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/CreateAttributeMatrix.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateAttributeMatrix.cpp new file mode 100644 index 0000000000..fad10112b5 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateAttributeMatrix.cpp @@ -0,0 +1,26 @@ +#include "CreateAttributeMatrix.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +CreateAttributeMatrix::CreateAttributeMatrix(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + CreateAttributeMatrixInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +CreateAttributeMatrix::~CreateAttributeMatrix() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> CreateAttributeMatrix::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateAttributeMatrix.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateAttributeMatrix.hpp new file mode 100644 index 0000000000..c44b97f518 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateAttributeMatrix.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/DataGroupCreationParameter.hpp" +#include "simplnx/Parameters/DynamicTableParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + CreateAttributeMatrixInputValues inputValues; + inputValues.DataObjectPath = filterArgs.value(data_object_path); + inputValues.TupleDimensions = filterArgs.value(tuple_dimensions); + return CreateAttributeMatrix(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT CreateAttributeMatrixInputValues +{ + DataGroupCreationParameter::ValueType DataObjectPath; + DynamicTableParameter::ValueType TupleDimensions; +}; + +/** + * @class CreateAttributeMatrix + * @brief This algorithm implements support code for the CreateAttributeMatrixFilter + */ + +class SIMPLNXCORE_EXPORT CreateAttributeMatrix +{ +public: + CreateAttributeMatrix(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, CreateAttributeMatrixInputValues* inputValues); + ~CreateAttributeMatrix() noexcept; + + CreateAttributeMatrix(const CreateAttributeMatrix&) = delete; + CreateAttributeMatrix(CreateAttributeMatrix&&) noexcept = delete; + CreateAttributeMatrix& operator=(const CreateAttributeMatrix&) = delete; + CreateAttributeMatrix& operator=(CreateAttributeMatrix&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const CreateAttributeMatrixInputValues* 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/CreateDataArray.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateDataArray.cpp new file mode 100644 index 0000000000..d42501e8ef --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateDataArray.cpp @@ -0,0 +1,25 @@ +#include "CreateDataArray.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +CreateDataArray::CreateDataArray(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, CreateDataArrayInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +CreateDataArray::~CreateDataArray() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> CreateDataArray::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateDataArray.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateDataArray.hpp new file mode 100644 index 0000000000..aa08a2a053 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateDataArray.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArrayCreationParameter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/DataStoreFormatParameter.hpp" +#include "simplnx/Parameters/DynamicTableParameter.hpp" +#include "simplnx/Parameters/NumberParameter.hpp" +#include "simplnx/Parameters/NumericTypeParameter.hpp" +#include "simplnx/Parameters/StringParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + CreateDataArrayInputValues inputValues; + inputValues.ComponentCount = filterArgs.value(component_count); + inputValues.DataFormat = filterArgs.value(data_format); + inputValues.InitializationValueStr = filterArgs.value(initialization_value_str); + inputValues.NumericTypeIndex = filterArgs.value(numeric_type_index); + inputValues.OutputArrayPath = filterArgs.value(output_array_path); + inputValues.SetTupleDimensions = filterArgs.value(set_tuple_dimensions); + inputValues.TupleDimensions = filterArgs.value(tuple_dimensions); + return CreateDataArray(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT CreateDataArrayInputValues +{ + UInt64Parameter::ValueType ComponentCount; + DataStoreFormatParameter::ValueType DataFormat; + StringParameter::ValueType InitializationValueStr; + NumericTypeParameter::ValueType NumericTypeIndex; + ArrayCreationParameter::ValueType OutputArrayPath; + BoolParameter::ValueType SetTupleDimensions; + DynamicTableParameter::ValueType TupleDimensions; +}; + +/** + * @class CreateDataArray + * @brief This algorithm implements support code for the CreateDataArrayFilter + */ + +class SIMPLNXCORE_EXPORT CreateDataArray +{ +public: + CreateDataArray(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, CreateDataArrayInputValues* inputValues); + ~CreateDataArray() noexcept; + + CreateDataArray(const CreateDataArray&) = delete; + CreateDataArray(CreateDataArray&&) noexcept = delete; + CreateDataArray& operator=(const CreateDataArray&) = delete; + CreateDataArray& operator=(CreateDataArray&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const CreateDataArrayInputValues* 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/CreateDataArrayAdvanced.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateDataArrayAdvanced.cpp new file mode 100644 index 0000000000..a0a27288f8 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateDataArrayAdvanced.cpp @@ -0,0 +1,26 @@ +#include "CreateDataArrayAdvanced.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +CreateDataArrayAdvanced::CreateDataArrayAdvanced(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + CreateDataArrayAdvancedInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +CreateDataArrayAdvanced::~CreateDataArrayAdvanced() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> CreateDataArrayAdvanced::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateDataArrayAdvanced.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateDataArrayAdvanced.hpp new file mode 100644 index 0000000000..8615fa6a30 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateDataArrayAdvanced.hpp @@ -0,0 +1,91 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArrayCreationParameter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/ChoicesParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" +#include "simplnx/Parameters/DataStoreFormatParameter.hpp" +#include "simplnx/Parameters/DynamicTableParameter.hpp" +#include "simplnx/Parameters/NumberParameter.hpp" +#include "simplnx/Parameters/NumericTypeParameter.hpp" +#include "simplnx/Parameters/StringParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + CreateDataArrayAdvancedInputValues inputValues; + inputValues.ComponentDimensions = filterArgs.value(component_dimensions); + inputValues.DataFormat = filterArgs.value(data_format); + inputValues.InitEndRange = filterArgs.value(init_end_range); + inputValues.InitStartRange = filterArgs.value(init_start_range); + inputValues.InitTypeIndex = filterArgs.value(init_type_index); + inputValues.InitValue = filterArgs.value(init_value); + inputValues.NumericTypeIndex = filterArgs.value(numeric_type_index); + inputValues.OutputArrayPath = filterArgs.value(output_array_path); + inputValues.SeedArrayName = filterArgs.value(seed_array_name); + inputValues.SeedValue = filterArgs.value(seed_value); + inputValues.SetTupleDimensions = filterArgs.value(set_tuple_dimensions); + inputValues.StandardizeSeed = filterArgs.value(standardize_seed); + inputValues.StartingFillValue = filterArgs.value(starting_fill_value); + inputValues.StepOperationIndex = filterArgs.value(step_operation_index); + inputValues.StepValue = filterArgs.value(step_value); + inputValues.TupleDimensions = filterArgs.value(tuple_dimensions); + inputValues.UseSeed = filterArgs.value(use_seed); + return CreateDataArrayAdvanced(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT CreateDataArrayAdvancedInputValues +{ + DynamicTableParameter::ValueType ComponentDimensions; + DataStoreFormatParameter::ValueType DataFormat; + StringParameter::ValueType InitEndRange; + StringParameter::ValueType InitStartRange; + ChoicesParameter::ValueType InitTypeIndex; + StringParameter::ValueType InitValue; + NumericTypeParameter::ValueType NumericTypeIndex; + ArrayCreationParameter::ValueType OutputArrayPath; + DataObjectNameParameter::ValueType SeedArrayName; + UInt64Parameter::ValueType SeedValue; + BoolParameter::ValueType SetTupleDimensions; + BoolParameter::ValueType StandardizeSeed; + StringParameter::ValueType StartingFillValue; + ChoicesParameter::ValueType StepOperationIndex; + StringParameter::ValueType StepValue; + DynamicTableParameter::ValueType TupleDimensions; + BoolParameter::ValueType UseSeed; +}; + +/** + * @class CreateDataArrayAdvanced + * @brief This algorithm implements support code for the CreateDataArrayAdvancedFilter + */ + +class SIMPLNXCORE_EXPORT CreateDataArrayAdvanced +{ +public: + CreateDataArrayAdvanced(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, CreateDataArrayAdvancedInputValues* inputValues); + ~CreateDataArrayAdvanced() noexcept; + + CreateDataArrayAdvanced(const CreateDataArrayAdvanced&) = delete; + CreateDataArrayAdvanced(CreateDataArrayAdvanced&&) noexcept = delete; + CreateDataArrayAdvanced& operator=(const CreateDataArrayAdvanced&) = delete; + CreateDataArrayAdvanced& operator=(CreateDataArrayAdvanced&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const CreateDataArrayAdvancedInputValues* 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/CreateDataGroup.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateDataGroup.cpp new file mode 100644 index 0000000000..c79e488f69 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateDataGroup.cpp @@ -0,0 +1,25 @@ +#include "CreateDataGroup.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +CreateDataGroup::CreateDataGroup(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, CreateDataGroupInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +CreateDataGroup::~CreateDataGroup() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> CreateDataGroup::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateDataGroup.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateDataGroup.hpp new file mode 100644 index 0000000000..32198682c3 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateDataGroup.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/DataGroupCreationParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + CreateDataGroupInputValues inputValues; + inputValues.DataObjectPath = filterArgs.value(data_object_path); + return CreateDataGroup(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT CreateDataGroupInputValues +{ + DataGroupCreationParameter::ValueType DataObjectPath; +}; + +/** + * @class CreateDataGroup + * @brief This algorithm implements support code for the CreateDataGroupFilter + */ + +class SIMPLNXCORE_EXPORT CreateDataGroup +{ +public: + CreateDataGroup(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, CreateDataGroupInputValues* inputValues); + ~CreateDataGroup() noexcept; + + CreateDataGroup(const CreateDataGroup&) = delete; + CreateDataGroup(CreateDataGroup&&) noexcept = delete; + CreateDataGroup& operator=(const CreateDataGroup&) = delete; + CreateDataGroup& operator=(CreateDataGroup&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const CreateDataGroupInputValues* 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/CreateFeatureArrayFromElementArray.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateFeatureArrayFromElementArray.cpp new file mode 100644 index 0000000000..b3b695dc18 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateFeatureArrayFromElementArray.cpp @@ -0,0 +1,26 @@ +#include "CreateFeatureArrayFromElementArray.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +CreateFeatureArrayFromElementArray::CreateFeatureArrayFromElementArray(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + CreateFeatureArrayFromElementArrayInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +CreateFeatureArrayFromElementArray::~CreateFeatureArrayFromElementArray() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> CreateFeatureArrayFromElementArray::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateFeatureArrayFromElementArray.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateFeatureArrayFromElementArray.hpp new file mode 100644 index 0000000000..c6f2df5d87 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateFeatureArrayFromElementArray.hpp @@ -0,0 +1,60 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/AttributeMatrixSelectionParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + CreateFeatureArrayFromElementArrayInputValues inputValues; + inputValues.CellFeatureAttributeMatrixPath = filterArgs.value(cell_feature_attribute_matrix_path); + inputValues.CreatedArrayName = filterArgs.value(created_array_name); + inputValues.FeatureIdsPath = filterArgs.value(feature_ids_path); + inputValues.SelectedCellArrayPath = filterArgs.value(selected_cell_array_path); + return CreateFeatureArrayFromElementArray(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT CreateFeatureArrayFromElementArrayInputValues +{ + AttributeMatrixSelectionParameter::ValueType CellFeatureAttributeMatrixPath; + DataObjectNameParameter::ValueType CreatedArrayName; + ArraySelectionParameter::ValueType FeatureIdsPath; + ArraySelectionParameter::ValueType SelectedCellArrayPath; +}; + +/** + * @class CreateFeatureArrayFromElementArray + * @brief This algorithm implements support code for the CreateFeatureArrayFromElementArrayFilter + */ + +class SIMPLNXCORE_EXPORT CreateFeatureArrayFromElementArray +{ +public: + CreateFeatureArrayFromElementArray(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + CreateFeatureArrayFromElementArrayInputValues* inputValues); + ~CreateFeatureArrayFromElementArray() noexcept; + + CreateFeatureArrayFromElementArray(const CreateFeatureArrayFromElementArray&) = delete; + CreateFeatureArrayFromElementArray(CreateFeatureArrayFromElementArray&&) noexcept = delete; + CreateFeatureArrayFromElementArray& operator=(const CreateFeatureArrayFromElementArray&) = delete; + CreateFeatureArrayFromElementArray& operator=(CreateFeatureArrayFromElementArray&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const CreateFeatureArrayFromElementArrayInputValues* 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/CreateGeometry.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateGeometry.cpp new file mode 100644 index 0000000000..b78ae2fbd3 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateGeometry.cpp @@ -0,0 +1,25 @@ +#include "CreateGeometry.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +CreateGeometry::CreateGeometry(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, CreateGeometryInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +CreateGeometry::~CreateGeometry() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> CreateGeometry::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateGeometry.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateGeometry.hpp new file mode 100644 index 0000000000..febf349aa4 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateGeometry.hpp @@ -0,0 +1,96 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/ChoicesParameter.hpp" +#include "simplnx/Parameters/DataGroupCreationParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" +#include "simplnx/Parameters/VectorParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + CreateGeometryInputValues inputValues; + inputValues.ArrayHandlingIndex = filterArgs.value(array_handling_index); + inputValues.CellAttributeMatrixName = filterArgs.value(cell_attribute_matrix_name); + inputValues.Dimensions = filterArgs.value(dimensions); + inputValues.EdgeAttributeMatrixName = filterArgs.value(edge_attribute_matrix_name); + inputValues.EdgeListPath = filterArgs.value(edge_list_path); + inputValues.FaceAttributeMatrixName = filterArgs.value(face_attribute_matrix_name); + inputValues.GeometryTypeIndex = filterArgs.value(geometry_type_index); + inputValues.HexahedralListPath = filterArgs.value(hexahedral_list_path); + inputValues.LengthUnitIndex = filterArgs.value(length_unit_index); + inputValues.Origin = filterArgs.value(origin); + inputValues.OutputGeometryPath = filterArgs.value(output_geometry_path); + inputValues.QuadrilateralListPath = filterArgs.value(quadrilateral_list_path); + inputValues.Spacing = filterArgs.value(spacing); + inputValues.TetrahedralListPath = filterArgs.value(tetrahedral_list_path); + inputValues.TriangleListPath = filterArgs.value(triangle_list_path); + inputValues.VertexAttributeMatrixName = filterArgs.value(vertex_attribute_matrix_name); + inputValues.VertexListPath = filterArgs.value(vertex_list_path); + inputValues.WarningsAsErrors = filterArgs.value(warnings_as_errors); + inputValues.XBoundsPath = filterArgs.value(x_bounds_path); + inputValues.YBoundsPath = filterArgs.value(y_bounds_path); + inputValues.ZBoundsPath = filterArgs.value(z_bounds_path); + return CreateGeometry(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT CreateGeometryInputValues +{ + ChoicesParameter::ValueType ArrayHandlingIndex; + DataObjectNameParameter::ValueType CellAttributeMatrixName; + VectorUInt64Parameter::ValueType Dimensions; + DataObjectNameParameter::ValueType EdgeAttributeMatrixName; + ArraySelectionParameter::ValueType EdgeListPath; + DataObjectNameParameter::ValueType FaceAttributeMatrixName; + ChoicesParameter::ValueType GeometryTypeIndex; + ArraySelectionParameter::ValueType HexahedralListPath; + ChoicesParameter::ValueType LengthUnitIndex; + VectorFloat32Parameter::ValueType Origin; + DataGroupCreationParameter::ValueType OutputGeometryPath; + ArraySelectionParameter::ValueType QuadrilateralListPath; + VectorFloat32Parameter::ValueType Spacing; + ArraySelectionParameter::ValueType TetrahedralListPath; + ArraySelectionParameter::ValueType TriangleListPath; + DataObjectNameParameter::ValueType VertexAttributeMatrixName; + ArraySelectionParameter::ValueType VertexListPath; + BoolParameter::ValueType WarningsAsErrors; + ArraySelectionParameter::ValueType XBoundsPath; + ArraySelectionParameter::ValueType YBoundsPath; + ArraySelectionParameter::ValueType ZBoundsPath; +}; + +/** + * @class CreateGeometry + * @brief This algorithm implements support code for the CreateGeometryFilter + */ + +class SIMPLNXCORE_EXPORT CreateGeometry +{ +public: + CreateGeometry(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, CreateGeometryInputValues* inputValues); + ~CreateGeometry() noexcept; + + CreateGeometry(const CreateGeometry&) = delete; + CreateGeometry(CreateGeometry&&) noexcept = delete; + CreateGeometry& operator=(const CreateGeometry&) = delete; + CreateGeometry& operator=(CreateGeometry&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const CreateGeometryInputValues* 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/CreateImageGeometry.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateImageGeometry.cpp new file mode 100644 index 0000000000..63225f3565 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateImageGeometry.cpp @@ -0,0 +1,25 @@ +#include "CreateImageGeometry.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +CreateImageGeometry::CreateImageGeometry(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, CreateImageGeometryInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +CreateImageGeometry::~CreateImageGeometry() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> CreateImageGeometry::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateImageGeometry.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateImageGeometry.hpp new file mode 100644 index 0000000000..237efaa95f --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CreateImageGeometry.hpp @@ -0,0 +1,61 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/DataGroupCreationParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" +#include "simplnx/Parameters/VectorParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + CreateImageGeometryInputValues inputValues; + inputValues.CellDataName = filterArgs.value(cell_data_name); + inputValues.Dimensions = filterArgs.value(dimensions); + inputValues.Origin = filterArgs.value(origin); + inputValues.OutputImageGeometryPath = filterArgs.value(output_image_geometry_path); + inputValues.Spacing = filterArgs.value(spacing); + return CreateImageGeometry(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT CreateImageGeometryInputValues +{ + DataObjectNameParameter::ValueType CellDataName; + VectorUInt64Parameter::ValueType Dimensions; + VectorFloat32Parameter::ValueType Origin; + DataGroupCreationParameter::ValueType OutputImageGeometryPath; + VectorFloat32Parameter::ValueType Spacing; +}; + +/** + * @class CreateImageGeometry + * @brief This algorithm implements support code for the CreateImageGeometryFilter + */ + +class SIMPLNXCORE_EXPORT CreateImageGeometry +{ +public: + CreateImageGeometry(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, CreateImageGeometryInputValues* inputValues); + ~CreateImageGeometry() noexcept; + + CreateImageGeometry(const CreateImageGeometry&) = delete; + CreateImageGeometry(CreateImageGeometry&&) noexcept = delete; + CreateImageGeometry& operator=(const CreateImageGeometry&) = delete; + CreateImageGeometry& operator=(CreateImageGeometry&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const CreateImageGeometryInputValues* 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/CropImageGeometry.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CropImageGeometry.cpp new file mode 100644 index 0000000000..6d35e3867d --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CropImageGeometry.cpp @@ -0,0 +1,25 @@ +#include "CropImageGeometry.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +CropImageGeometry::CropImageGeometry(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, CropImageGeometryInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +CropImageGeometry::~CropImageGeometry() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> CropImageGeometry::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CropImageGeometry.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CropImageGeometry.hpp new file mode 100644 index 0000000000..f461ecea5b --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CropImageGeometry.hpp @@ -0,0 +1,82 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/AttributeMatrixSelectionParameter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/DataGroupCreationParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" +#include "simplnx/Parameters/VectorParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + CropImageGeometryInputValues inputValues; + inputValues.CellFeatureAttributeMatrixPath = filterArgs.value(cell_feature_attribute_matrix_path); + inputValues.CropXDim = filterArgs.value(crop_x_dim); + inputValues.CropYDim = filterArgs.value(crop_y_dim); + inputValues.CropZDim = filterArgs.value(crop_z_dim); + inputValues.FeatureIdsPath = filterArgs.value(feature_ids_path); + inputValues.InputImageGeometryPath = filterArgs.value(input_image_geometry_path); + inputValues.MaxCoord = filterArgs.value(max_coord); + inputValues.MaxVoxel = filterArgs.value(max_voxel); + inputValues.MinCoord = filterArgs.value(min_coord); + inputValues.MinVoxel = filterArgs.value(min_voxel); + inputValues.OutputImageGeometryPath = filterArgs.value(output_image_geometry_path); + inputValues.RemoveOriginalGeometry = filterArgs.value(remove_original_geometry); + inputValues.RenumberFeatures = filterArgs.value(renumber_features); + inputValues.UsePhysicalBounds = filterArgs.value(use_physical_bounds); + return CropImageGeometry(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT CropImageGeometryInputValues +{ + AttributeMatrixSelectionParameter::ValueType CellFeatureAttributeMatrixPath; + BoolParameter::ValueType CropXDim; + BoolParameter::ValueType CropYDim; + BoolParameter::ValueType CropZDim; + ArraySelectionParameter::ValueType FeatureIdsPath; + GeometrySelectionParameter::ValueType InputImageGeometryPath; + VectorFloat64Parameter::ValueType MaxCoord; + VectorUInt64Parameter::ValueType MaxVoxel; + VectorFloat64Parameter::ValueType MinCoord; + VectorUInt64Parameter::ValueType MinVoxel; + DataGroupCreationParameter::ValueType OutputImageGeometryPath; + BoolParameter::ValueType RemoveOriginalGeometry; + BoolParameter::ValueType RenumberFeatures; + BoolParameter::ValueType UsePhysicalBounds; +}; + +/** + * @class CropImageGeometry + * @brief This algorithm implements support code for the CropImageGeometryFilter + */ + +class SIMPLNXCORE_EXPORT CropImageGeometry +{ +public: + CropImageGeometry(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, CropImageGeometryInputValues* inputValues); + ~CropImageGeometry() noexcept; + + CropImageGeometry(const CropImageGeometry&) = delete; + CropImageGeometry(CropImageGeometry&&) noexcept = delete; + CropImageGeometry& operator=(const CropImageGeometry&) = delete; + CropImageGeometry& operator=(CropImageGeometry&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const CropImageGeometryInputValues* 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/CropVertexGeometry.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CropVertexGeometry.cpp new file mode 100644 index 0000000000..8f5ec2a499 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CropVertexGeometry.cpp @@ -0,0 +1,25 @@ +#include "CropVertexGeometry.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +CropVertexGeometry::CropVertexGeometry(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, CropVertexGeometryInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +CropVertexGeometry::~CropVertexGeometry() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> CropVertexGeometry::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CropVertexGeometry.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CropVertexGeometry.hpp new file mode 100644 index 0000000000..35aaf8be1e --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/CropVertexGeometry.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/DataGroupCreationParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" +#include "simplnx/Parameters/MultiArraySelectionParameter.hpp" +#include "simplnx/Parameters/VectorParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + CropVertexGeometryInputValues inputValues; + inputValues.InputVertexGeometryPath = filterArgs.value(input_vertex_geometry_path); + inputValues.MaxPos = filterArgs.value(max_pos); + inputValues.MinPos = filterArgs.value(min_pos); + inputValues.OutputVertexGeometryPath = filterArgs.value(output_vertex_geometry_path); + inputValues.TargetArrayPaths = filterArgs.value(target_array_paths); + inputValues.VertexAttributeMatrixName = filterArgs.value(vertex_attribute_matrix_name); + return CropVertexGeometry(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT CropVertexGeometryInputValues +{ + GeometrySelectionParameter::ValueType InputVertexGeometryPath; + VectorFloat32Parameter::ValueType MaxPos; + VectorFloat32Parameter::ValueType MinPos; + DataGroupCreationParameter::ValueType OutputVertexGeometryPath; + MultiArraySelectionParameter::ValueType TargetArrayPaths; + DataObjectNameParameter::ValueType VertexAttributeMatrixName; +}; + +/** + * @class CropVertexGeometry + * @brief This algorithm implements support code for the CropVertexGeometryFilter + */ + +class SIMPLNXCORE_EXPORT CropVertexGeometry +{ +public: + CropVertexGeometry(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, CropVertexGeometryInputValues* inputValues); + ~CropVertexGeometry() noexcept; + + CropVertexGeometry(const CropVertexGeometry&) = delete; + CropVertexGeometry(CropVertexGeometry&&) noexcept = delete; + CropVertexGeometry& operator=(const CropVertexGeometry&) = delete; + CropVertexGeometry& operator=(CropVertexGeometry&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const CropVertexGeometryInputValues* 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/DeleteData.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/DeleteData.cpp new file mode 100644 index 0000000000..a67e7bf452 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/DeleteData.cpp @@ -0,0 +1,25 @@ +#include "DeleteData.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +DeleteData::DeleteData(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, DeleteDataInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +DeleteData::~DeleteData() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> DeleteData::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/DeleteData.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/DeleteData.hpp new file mode 100644 index 0000000000..6ff8ad4da8 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/DeleteData.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/MultiPathSelectionParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + DeleteDataInputValues inputValues; + inputValues.RemovedDataPath = filterArgs.value(removed_data_path); + return DeleteData(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT DeleteDataInputValues +{ + MultiPathSelectionParameter::ValueType RemovedDataPath; +}; + +/** + * @class DeleteData + * @brief This algorithm implements support code for the DeleteDataFilter + */ + +class SIMPLNXCORE_EXPORT DeleteData +{ +public: + DeleteData(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, DeleteDataInputValues* inputValues); + ~DeleteData() noexcept; + + DeleteData(const DeleteData&) = delete; + DeleteData(DeleteData&&) noexcept = delete; + DeleteData& operator=(const DeleteData&) = delete; + DeleteData& operator=(DeleteData&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const DeleteDataInputValues* 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/ExtractInternalSurfacesFromTriangleGeometry.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ExtractInternalSurfacesFromTriangleGeometry.cpp new file mode 100644 index 0000000000..6f6c81d508 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ExtractInternalSurfacesFromTriangleGeometry.cpp @@ -0,0 +1,202 @@ +#include "ExtractInternalSurfacesFromTriangleGeometry.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/Geometry/TriangleGeom.hpp" +#include "simplnx/Utilities/FilterUtilities.hpp" + +#include +#include + +using namespace nx::core; + +namespace +{ + +struct RemoveFlaggedVerticesFunctor +{ + // copy data to masked geometry + template + void operator()(IDataArray* inputDataPtr, IDataArray* outputDataArray, const std::vector& indexMapping) const + { + auto& inputData = inputDataPtr->template getIDataStoreRefAs>(); + auto& outputData = outputDataArray->template getIDataStoreRefAs>(); + usize nComps = inputData.getNumberOfComponents(); + IGeometry::MeshIndexType notSeen = std::numeric_limits::max(); + + for(usize i = 0; i < indexMapping.size(); i++) + { + IGeometry::MeshIndexType newIndex = indexMapping[i]; + if(newIndex != notSeen) + { + for(usize compIdx = 0; compIdx < nComps; compIdx++) + { + usize destinationIndex = newIndex * nComps + compIdx; + usize sourceIndex = i * nComps + compIdx; + outputData[destinationIndex] = inputData[sourceIndex]; + } + } + } + } +}; + +} // namespace + +// ----------------------------------------------------------------------------- +ExtractInternalSurfacesFromTriangleGeometry::ExtractInternalSurfacesFromTriangleGeometry(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + ExtractInternalSurfacesFromTriangleGeometryInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ExtractInternalSurfacesFromTriangleGeometry::~ExtractInternalSurfacesFromTriangleGeometry() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ExtractInternalSurfacesFromTriangleGeometry::operator()() +{ + // auto nodeTypesArrayPath = filterArgs.value(k_NodeTypesPath_Key); + // auto triangleGeomPath = filterArgs.value(k_SelectedTriangleGeometryPath_Key); + auto internalTrianglesPath = m_InputValues->OutputTriangleGeometryPath; + // auto copyVertexPaths = filterArgs.value>(k_CopyVertexPaths_Key); + // auto copyTrianglePaths = filterArgs.value>(k_CopyTrianglePaths_Key); + // auto vertexDataName = filterArgs.value(k_VertexAttributeMatrixName_Key); + // auto faceDataName = filterArgs.value(k_TriangleAttributeMatrixName_Key); + auto minMaxNodeValues = m_InputValues->NodeTypeRange; + + auto& triangleGeom = m_DataStructure.getDataRefAs(m_InputValues->InputTriangleGeometryPath); + auto& internalTriangleGeom = m_DataStructure.getDataRefAs(internalTrianglesPath); + auto& vertices = *triangleGeom.getVertices(); + auto& triangles = *triangleGeom.getFaces(); + auto numVerts = triangleGeom.getNumberOfVertices(); + auto numTris = triangleGeom.getNumberOfFaces(); + + auto& nodeTypes = m_DataStructure.getDataRefAs(m_InputValues->NodeTypesPath); + + auto internalVerticesPath = internalTrianglesPath.createChildPath(TriangleGeom::k_SharedVertexListName); + internalTriangleGeom.setVertices(*m_DataStructure.getDataAs(internalVerticesPath)); + + auto internalFacesPath = internalTrianglesPath.createChildPath(TriangleGeom::k_SharedFacesListName); + internalTriangleGeom.setFaceList(*m_DataStructure.getDataAs(internalFacesPath)); + + // int64 progIncrement = numTris / 100; + // int64 prog = 1; + // int64 progressInt = 0; + // int64 counter = 0; + using MeshIndexType = IGeometry::MeshIndexType; + + const MeshIndexType notSeen = std::numeric_limits::max(); + + std::vector vertNewIndex(numVerts, notSeen); + std::vector triNewIndex(numTris, notSeen); + MeshIndexType currentNewTriIndex = 0; + MeshIndexType currentNewVertIndex = 0; + + // Loop over all the triangles mapping the triangle and the vertices to the new array locations + for(MeshIndexType triIndex = 0; triIndex < numTris; triIndex++) + { + MeshIndexType v0Index = triangles[3 * triIndex + 0]; + MeshIndexType v1Index = triangles[3 * triIndex + 1]; + MeshIndexType v2Index = triangles[3 * triIndex + 2]; + // Check if the NodeType is either 2, 3, 4 + if((nodeTypes[v0Index] >= minMaxNodeValues[0] && nodeTypes[v0Index] <= minMaxNodeValues[1]) && (nodeTypes[v1Index] >= minMaxNodeValues[0] && nodeTypes[v1Index] <= minMaxNodeValues[1]) && + (nodeTypes[v2Index] >= minMaxNodeValues[0] && nodeTypes[v2Index] <= minMaxNodeValues[1])) + { + // All Nodes are the correct type + triNewIndex[triIndex] = currentNewTriIndex; + currentNewTriIndex++; // increment the index into which this triangle would be place in the new triangle array + // Now figure out if we have seen each vertex + if(vertNewIndex[v0Index] == notSeen) + { + vertNewIndex[v0Index] = currentNewVertIndex; + currentNewVertIndex++; + } + if(vertNewIndex[v1Index] == notSeen) + { + vertNewIndex[v1Index] = currentNewVertIndex; + currentNewVertIndex++; + } + if(vertNewIndex[v2Index] == notSeen) + { + vertNewIndex[v2Index] = currentNewVertIndex; + currentNewVertIndex++; + } + } + + if(m_ShouldCancel) + { + return {}; + } + } + + // Resize the vertex and triangle arrays + internalTriangleGeom.resizeVertexList(currentNewVertIndex); + internalTriangleGeom.resizeFaceList(currentNewTriIndex); + internalTriangleGeom.getVertexAttributeMatrix()->resizeTuples({currentNewVertIndex}); + internalTriangleGeom.getFaceAttributeMatrix()->resizeTuples({currentNewTriIndex}); + + IGeometry::SharedVertexList* internalVerts = internalTriangleGeom.getVertices(); + IGeometry::SharedFaceList* internalTriangles = internalTriangleGeom.getFaces(); + + // Transfer the data from the old SharedVertexList to the new VertexList + for(MeshIndexType vertIndex = 0; vertIndex < numVerts; vertIndex++) + { + MeshIndexType mappedIndex = vertNewIndex[vertIndex]; + if(mappedIndex != notSeen) + { + // Get the actual XYZ coordinate + float x = vertices[vertIndex * 3 + 0]; + float y = vertices[vertIndex * 3 + 1]; + float z = vertices[vertIndex * 3 + 2]; + + (*internalVerts)[mappedIndex * 3 + 0] = x; + (*internalVerts)[mappedIndex * 3 + 1] = y; + (*internalVerts)[mappedIndex * 3 + 2] = z; + } + } + + // Transfer the data from the old SharedTriangleList to the new TriangleList + for(MeshIndexType triIndex = 0; triIndex < numTris; triIndex++) + { + MeshIndexType mappedIndex = triNewIndex[triIndex]; + if(mappedIndex != notSeen) + { + // Get the 3 original vertex indices for this triangle + MeshIndexType v0 = triangles[triIndex * 3 + 0]; + MeshIndexType v1 = triangles[triIndex * 3 + 1]; + MeshIndexType v2 = triangles[triIndex * 3 + 2]; + + MeshIndexType v0New = vertNewIndex[v0]; + MeshIndexType v1New = vertNewIndex[v1]; + MeshIndexType v2New = vertNewIndex[v2]; + + (*internalTriangles)[mappedIndex * 3 + 0] = v0New; + (*internalTriangles)[mappedIndex * 3 + 1] = v1New; + (*internalTriangles)[mappedIndex * 3 + 2] = v2New; + } + } + + // Copy any Vertex and Triangle DataArrays to extracted surface mesh + for(const auto& targetArrayPath : m_InputValues->CopyVertexArrayPaths) + { + DataPath destinationPath = internalTrianglesPath.createChildPath(m_InputValues->VertexAttributeMatrixName).createChildPath(targetArrayPath.getTargetName()); + auto* src = m_DataStructure.getDataAs(targetArrayPath); + auto* dest = m_DataStructure.getDataAs(destinationPath); + + ExecuteDataFunction(RemoveFlaggedVerticesFunctor{}, src->getDataType(), src, dest, vertNewIndex); + } + + for(const auto& targetArrayPath : m_InputValues->CopyTriangleArrayPaths) + { + DataPath destinationPath = internalTrianglesPath.createChildPath(m_InputValues->TriangleAttributeMatrixName).createChildPath(targetArrayPath.getTargetName()); + auto* src = m_DataStructure.getDataAs(targetArrayPath); + auto* dest = m_DataStructure.getDataAs(destinationPath); + dest->resizeTuples({currentNewTriIndex}); + + ExecuteDataFunction(RemoveFlaggedVerticesFunctor{}, src->getDataType(), src, dest, triNewIndex); + } + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ExtractInternalSurfacesFromTriangleGeometry.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ExtractInternalSurfacesFromTriangleGeometry.hpp new file mode 100644 index 0000000000..60504734d5 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ExtractInternalSurfacesFromTriangleGeometry.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/DataGroupCreationParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" +#include "simplnx/Parameters/MultiArraySelectionParameter.hpp" +#include "simplnx/Parameters/VectorParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT ExtractInternalSurfacesFromTriangleGeometryInputValues +{ + MultiArraySelectionParameter::ValueType CopyTriangleArrayPaths; + MultiArraySelectionParameter::ValueType CopyVertexArrayPaths; + GeometrySelectionParameter::ValueType InputTriangleGeometryPath; + VectorInt8Parameter::ValueType NodeTypeRange; + ArraySelectionParameter::ValueType NodeTypesPath; + DataGroupCreationParameter::ValueType OutputTriangleGeometryPath; + DataObjectNameParameter::ValueType TriangleAttributeMatrixName; + DataObjectNameParameter::ValueType VertexAttributeMatrixName; +}; + +/** + * @class ExtractInternalSurfacesFromTriangleGeometry + * @brief This algorithm implements support code for the ExtractInternalSurfacesFromTriangleGeometryFilter + */ + +class SIMPLNXCORE_EXPORT ExtractInternalSurfacesFromTriangleGeometry +{ +public: + ExtractInternalSurfacesFromTriangleGeometry(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + ExtractInternalSurfacesFromTriangleGeometryInputValues* inputValues); + ~ExtractInternalSurfacesFromTriangleGeometry() noexcept; + + ExtractInternalSurfacesFromTriangleGeometry(const ExtractInternalSurfacesFromTriangleGeometry&) = delete; + ExtractInternalSurfacesFromTriangleGeometry(ExtractInternalSurfacesFromTriangleGeometry&&) noexcept = delete; + ExtractInternalSurfacesFromTriangleGeometry& operator=(const ExtractInternalSurfacesFromTriangleGeometry&) = delete; + ExtractInternalSurfacesFromTriangleGeometry& operator=(ExtractInternalSurfacesFromTriangleGeometry&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ExtractInternalSurfacesFromTriangleGeometryInputValues* 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/ExtractPipelineToFile.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ExtractPipelineToFile.cpp new file mode 100644 index 0000000000..93e9e24da5 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ExtractPipelineToFile.cpp @@ -0,0 +1,26 @@ +#include "ExtractPipelineToFile.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +ExtractPipelineToFile::ExtractPipelineToFile(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + ExtractPipelineToFileInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ExtractPipelineToFile::~ExtractPipelineToFile() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ExtractPipelineToFile::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ExtractPipelineToFile.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ExtractPipelineToFile.hpp new file mode 100644 index 0000000000..b2f4e05efc --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ExtractPipelineToFile.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/FileSystemPathParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + ExtractPipelineToFileInputValues inputValues; + inputValues.InputFilePath = filterArgs.value(input_file_path); + inputValues.OutputFilePath = filterArgs.value(output_file_path); + return ExtractPipelineToFile(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT ExtractPipelineToFileInputValues +{ + FileSystemPathParameter::ValueType InputFilePath; + FileSystemPathParameter::ValueType OutputFilePath; +}; + +/** + * @class ExtractPipelineToFile + * @brief This algorithm implements support code for the ExtractPipelineToFileFilter + */ + +class SIMPLNXCORE_EXPORT ExtractPipelineToFile +{ +public: + ExtractPipelineToFile(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ExtractPipelineToFileInputValues* inputValues); + ~ExtractPipelineToFile() noexcept; + + ExtractPipelineToFile(const ExtractPipelineToFile&) = delete; + ExtractPipelineToFile(ExtractPipelineToFile&&) noexcept = delete; + ExtractPipelineToFile& operator=(const ExtractPipelineToFile&) = delete; + ExtractPipelineToFile& operator=(ExtractPipelineToFile&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ExtractPipelineToFileInputValues* 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/IdentifySample.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/IdentifySample.cpp new file mode 100644 index 0000000000..c210de3fa6 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/IdentifySample.cpp @@ -0,0 +1,445 @@ +#include "IdentifySample.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/Geometry/ImageGeom.hpp" +#include "simplnx/Utilities/FilterUtilities.hpp" + +using namespace nx::core; + +namespace +{ +struct IdentifySampleFunctor +{ + template + void operator()(const ImageGeom* imageGeom, IDataArray* goodVoxelsPtr, bool fillHoles) + { + std::vector cDims = {1}; + auto& goodVoxels = goodVoxelsPtr->template getIDataStoreRefAs>(); + + const auto totalPoints = static_cast(goodVoxelsPtr->getNumberOfTuples()); + + SizeVec3 uDims = imageGeom->getDimensions(); + + const int64 dims[3] = { + static_cast(uDims[0]), + static_cast(uDims[1]), + static_cast(uDims[2]), + }; + + int64 neighborPoints[6] = {0, 0, 0, 0, 0, 0}; + const int64 xp = dims[0]; + const int64 yp = dims[1]; + const int64 zp = dims[2]; + + neighborPoints[0] = -(xp * yp); + neighborPoints[1] = -xp; + neighborPoints[2] = -1; + neighborPoints[3] = 1; + neighborPoints[4] = xp; + neighborPoints[5] = (xp * yp); + std::vector currentVList; + std::vector checked(totalPoints, false); + std::vector sample(totalPoints, false); + int64 biggestBlock = 0; + + int64 neighbor = 0; + + // In this loop over the data we are finding the biggest contiguous set of GoodVoxels and calling that the 'sample' All GoodVoxels that do not touch the 'sample' + // are flipped to be called 'bad' voxels or 'not sample' + float threshold = 0.0f; + for(int64 i = 0; i < totalPoints; i++) + { + const float percentIncrement = static_cast(i) / static_cast(totalPoints) * 100.0f; + if(percentIncrement > threshold) + { + threshold = threshold + 5.0f; + if(threshold < percentIncrement) + { + threshold = percentIncrement; + } + } + + if(!checked[i] && goodVoxels.getValue(i)) + { + currentVList.push_back(i); + usize count = 0; + while(count < currentVList.size()) + { + int64 index = currentVList[count]; + int64 column = index % xp; + int64 row = (index / xp) % yp; + int64 plane = index / (xp * yp); + for(int32 j = 0; j < 6; j++) + { + int32 good = 1; + neighbor = index + neighborPoints[j]; + if(j == 0 && plane == 0) + { + good = 0; + } + if(j == 5 && plane == (zp - 1)) + { + good = 0; + } + if(j == 1 && row == 0) + { + good = 0; + } + if(j == 4 && row == (yp - 1)) + { + good = 0; + } + if(j == 2 && column == 0) + { + good = 0; + } + if(j == 3 && column == (xp - 1)) + { + good = 0; + } + if(good == 1 && !checked[neighbor] && goodVoxels.getValue(neighbor)) + { + currentVList.push_back(neighbor); + checked[neighbor] = true; + } + } + count++; + } + if(static_cast(currentVList.size()) >= biggestBlock) + { + biggestBlock = currentVList.size(); + sample.assign(totalPoints, false); + for(int64 j = 0; j < biggestBlock; j++) + { + sample[currentVList[j]] = true; + } + } + currentVList.clear(); + } + } + for(int64 i = 0; i < totalPoints; i++) + { + if(!sample[i] && goodVoxels.getValue(i)) + { + goodVoxels.setValue(i, false); + } + } + sample.clear(); + checked.assign(totalPoints, false); + + // In this loop we are going to 'close' all the 'holes' inside the region already identified as the 'sample' if the user chose to do so. + // This is done by flipping all 'bad' voxel features that do not touch the outside of the sample (i.e. they are fully contained inside the 'sample'). + threshold = 0.0F; + if(fillHoles) + { + bool touchesBoundary = false; + for(int64 i = 0; i < totalPoints; i++) + { + const float percentIncrement = static_cast(i) / static_cast(totalPoints) * 100.0f; + if(percentIncrement > threshold) + { + threshold = threshold + 5.0f; + if(threshold < percentIncrement) + { + threshold = percentIncrement; + } + } + + if(!checked[i] && !goodVoxels.getValue(i)) + { + currentVList.push_back(i); + usize count = 0; + touchesBoundary = false; + while(count < currentVList.size()) + { + int64 index = currentVList[count]; + int64 column = index % xp; + int64 row = (index / xp) % yp; + int64 plane = index / (xp * yp); + if(column == 0 || column == (xp - 1) || row == 0 || row == (yp - 1) || plane == 0 || plane == (zp - 1)) + { + touchesBoundary = true; + } + for(int32 j = 0; j < 6; j++) + { + int32 good = 1; + neighbor = index + neighborPoints[j]; + if(j == 0 && plane == 0) + { + good = 0; + } + if(j == 5 && plane == (zp - 1)) + { + good = 0; + } + if(j == 1 && row == 0) + { + good = 0; + } + if(j == 4 && row == (yp - 1)) + { + good = 0; + } + if(j == 2 && column == 0) + { + good = 0; + } + if(j == 3 && column == (xp - 1)) + { + good = 0; + } + if(good == 1 && !checked[neighbor] && !goodVoxels.getValue(neighbor)) + { + currentVList.push_back(neighbor); + checked[neighbor] = true; + } + } + count++; + } + if(!touchesBoundary) + { + for(int64_t j : currentVList) + { + goodVoxels.setValue(j, true); + } + } + currentVList.clear(); + } + } + } + checked.clear(); + } +}; + +struct IdentifySampleSliceBySliceFunctor +{ + enum class Plane + { + XY, + XZ, + YZ + }; + + template + void operator()(const ImageGeom* imageGeom, IDataArray* goodVoxelsPtr, bool fillHoles, Plane plane) + { + auto& goodVoxels = goodVoxelsPtr->template getIDataStoreRefAs>(); + + SizeVec3 uDims = imageGeom->getDimensions(); + const int64 dimX = static_cast(uDims[0]); + const int64 dimY = static_cast(uDims[1]); + const int64 dimZ = static_cast(uDims[2]); + + int64 planeDim1, planeDim2, fixedDim; + int64 stride1, stride2, fixedStride; + + switch(plane) + { + case Plane::XY: + planeDim1 = dimX; + planeDim2 = dimY; + fixedDim = dimZ; + stride1 = 1; + stride2 = dimX; + fixedStride = dimX * dimY; + break; + + case Plane::XZ: + planeDim1 = dimX; + planeDim2 = dimZ; + fixedDim = dimY; + stride1 = 1; + stride2 = dimX * dimY; + fixedStride = dimX; + break; + + case Plane::YZ: + planeDim1 = dimY; + planeDim2 = dimZ; + fixedDim = dimX; + stride1 = dimX; + stride2 = dimX * dimY; + fixedStride = 1; + break; + } + + for(int64 fixedIdx = 0; fixedIdx < fixedDim; ++fixedIdx) // Process each slice + { + std::vector checked(planeDim1 * planeDim2, false); + std::vector sample(planeDim1 * planeDim2, false); + std::vector currentVList; + int64 biggestBlock = 0; + + // Identify the largest contiguous set of good voxels in the slice + for(int64 p2 = 0; p2 < planeDim2; ++p2) + { + for(int64 p1 = 0; p1 < planeDim1; ++p1) + { + int64 planeIndex = p2 * planeDim1 + p1; + int64 globalIndex = fixedIdx * fixedStride + p2 * stride2 + p1 * stride1; + + if(!checked[planeIndex] && goodVoxels.getValue(globalIndex)) + { + currentVList.push_back(planeIndex); + int64 count = 0; + + while(count < currentVList.size()) + { + int64 localIdx = currentVList[count]; + int64 localP1 = localIdx % planeDim1; + int64 localP2 = localIdx / planeDim1; + + for(int j = 0; j < 4; ++j) + { + int64 dp1[4] = {0, 0, -1, 1}; + int64 dp2[4] = {-1, 1, 0, 0}; + + int64 neighborP1 = localP1 + dp1[j]; + int64 neighborP2 = localP2 + dp2[j]; + + if(neighborP1 >= 0 && neighborP1 < planeDim1 && neighborP2 >= 0 && neighborP2 < planeDim2) + { + int64 neighborIdx = neighborP2 * planeDim1 + neighborP1; + int64 globalNeighborIdx = fixedIdx * fixedStride + neighborP2 * stride2 + neighborP1 * stride1; + + if(!checked[neighborIdx] && goodVoxels.getValue(globalNeighborIdx)) + { + currentVList.push_back(neighborIdx); + checked[neighborIdx] = true; + } + } + } + count++; + } + + if(static_cast(currentVList.size()) > biggestBlock) + { + biggestBlock = currentVList.size(); + sample.assign(planeDim1 * planeDim2, false); + for(int64 idx : currentVList) + { + sample[idx] = true; + } + } + currentVList.clear(); + } + } + } + + for(int64 p2 = 0; p2 < planeDim2; ++p2) + { + for(int64 p1 = 0; p1 < planeDim1; ++p1) + { + int64 planeIndex = p2 * planeDim1 + p1; + int64 globalIndex = fixedIdx * fixedStride + p2 * stride2 + p1 * stride1; + + if(!sample[planeIndex]) + { + goodVoxels.setValue(globalIndex, false); + } + } + } + + if(fillHoles) + { + for(int64 p2 = 0; p2 < planeDim2; ++p2) + { + for(int64 p1 = 0; p1 < planeDim1; ++p1) + { + int64 planeIndex = p2 * planeDim1 + p1; + int64 globalIndex = fixedIdx * fixedStride + p2 * stride2 + p1 * stride1; + + if(!checked[planeIndex] && !goodVoxels.getValue(globalIndex)) + { + currentVList.push_back(planeIndex); + int64 count = 0; + bool touchesBoundary = false; + + while(count < currentVList.size()) + { + int64 localIdx = currentVList[count]; + int64 localP1 = localIdx % planeDim1; + int64 localP2 = localIdx / planeDim1; + + if(localP1 == 0 || localP1 == planeDim1 - 1 || localP2 == 0 || localP2 == planeDim2 - 1) + { + touchesBoundary = true; + } + + for(int j = 0; j < 4; ++j) + { + int64 dp1[4] = {0, 0, -1, 1}; + int64 dp2[4] = {-1, 1, 0, 0}; + + int64 neighborP1 = localP1 + dp1[j]; + int64 neighborP2 = localP2 + dp2[j]; + + if(neighborP1 >= 0 && neighborP1 < planeDim1 && neighborP2 >= 0 && neighborP2 < planeDim2) + { + int64 neighborIdx = neighborP2 * planeDim1 + neighborP1; + int64 globalNeighborIdx = fixedIdx * fixedStride + neighborP2 * stride2 + neighborP1 * stride1; + + if(!checked[neighborIdx] && !goodVoxels.getValue(globalNeighborIdx)) + { + currentVList.push_back(neighborIdx); + checked[neighborIdx] = true; + } + } + } + count++; + } + + if(!touchesBoundary) + { + for(int64 idx : currentVList) + { + goodVoxels.setValue(fixedIdx * fixedStride + idx, true); + } + } + currentVList.clear(); + } + } + } + } + } + } +}; +} // namespace + +// ----------------------------------------------------------------------------- +IdentifySample::IdentifySample(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, IdentifySampleInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +IdentifySample::~IdentifySample() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> IdentifySample::operator()() +{ + + // const auto fillHoles = filterArgs.value(k_FillHoles_Key); + // const auto sliceBySlice = filterArgs.value(k_SliceBySlice_Key); + // const auto sliceBySlicePlane = static_cast(filterArgs.value(k_SliceBySlicePlane_Key)); + // const auto imageGeomPath = filterArgs.value(k_SelectedImageGeometryPath_Key); + // const auto goodVoxelsArrayPath = filterArgs.value(k_MaskArrayPath_Key); + + auto* inputData = m_DataStructure.getDataAs(m_InputValues->MaskArrayPath); + const auto* imageGeom = m_DataStructure.getDataAs(m_InputValues->InputImageGeometryPath); + + if(m_InputValues->SliceBySlice) + { + ExecuteDataFunction(IdentifySampleSliceBySliceFunctor{}, inputData->getDataType(), imageGeom, inputData, m_InputValues->FillHoles, + static_cast(m_InputValues->SliceBySlicePlaneIndex)); + } + else + { + ExecuteDataFunction(IdentifySampleFunctor{}, inputData->getDataType(), imageGeom, inputData, m_InputValues->FillHoles); + } + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/IdentifySample.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/IdentifySample.hpp new file mode 100644 index 0000000000..a24a219f25 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/IdentifySample.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/ChoicesParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT IdentifySampleInputValues +{ + BoolParameter::ValueType FillHoles; + GeometrySelectionParameter::ValueType InputImageGeometryPath; + ArraySelectionParameter::ValueType MaskArrayPath; + BoolParameter::ValueType SliceBySlice; + ChoicesParameter::ValueType SliceBySlicePlaneIndex; +}; + +/** + * @class IdentifySample + * @brief This algorithm implements support code for the IdentifySampleFilter + */ + +class SIMPLNXCORE_EXPORT IdentifySample +{ +public: + IdentifySample(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, IdentifySampleInputValues* inputValues); + ~IdentifySample() noexcept; + + IdentifySample(const IdentifySample&) = delete; + IdentifySample(IdentifySample&&) noexcept = delete; + IdentifySample& operator=(const IdentifySample&) = delete; + IdentifySample& operator=(IdentifySample&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const IdentifySampleInputValues* 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/InitializeImageGeomCellData.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeImageGeomCellData.cpp new file mode 100644 index 0000000000..313cca8137 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeImageGeomCellData.cpp @@ -0,0 +1,26 @@ +#include "InitializeImageGeomCellData.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +InitializeImageGeomCellData::InitializeImageGeomCellData(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + InitializeImageGeomCellDataInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +InitializeImageGeomCellData::~InitializeImageGeomCellData() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> InitializeImageGeomCellData::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeImageGeomCellData.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeImageGeomCellData.hpp new file mode 100644 index 0000000000..8d983088de --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeImageGeomCellData.hpp @@ -0,0 +1,75 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/ChoicesParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" +#include "simplnx/Parameters/MultiArraySelectionParameter.hpp" +#include "simplnx/Parameters/NumberParameter.hpp" +#include "simplnx/Parameters/VectorParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + InitializeImageGeomCellDataInputValues inputValues; + inputValues.CellArrays = filterArgs.value(cell_arrays); + inputValues.InitRange = filterArgs.value(init_range); + inputValues.InitTypeIndex = filterArgs.value(init_type_index); + inputValues.InitValue = filterArgs.value(init_value); + inputValues.InputImageGeometryPath = filterArgs.value(input_image_geometry_path); + inputValues.MaxPoint = filterArgs.value(max_point); + inputValues.MinPoint = filterArgs.value(min_point); + inputValues.SeedArrayName = filterArgs.value(seed_array_name); + inputValues.SeedValue = filterArgs.value(seed_value); + inputValues.UseSeed = filterArgs.value(use_seed); + return InitializeImageGeomCellData(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT InitializeImageGeomCellDataInputValues +{ + MultiArraySelectionParameter::ValueType CellArrays; + VectorFloat64Parameter::ValueType InitRange; + ChoicesParameter::ValueType InitTypeIndex; + Float64Parameter::ValueType InitValue; + GeometrySelectionParameter::ValueType InputImageGeometryPath; + VectorUInt64Parameter::ValueType MaxPoint; + VectorUInt64Parameter::ValueType MinPoint; + DataObjectNameParameter::ValueType SeedArrayName; + UInt64Parameter::ValueType SeedValue; + BoolParameter::ValueType UseSeed; +}; + +/** + * @class InitializeImageGeomCellData + * @brief This algorithm implements support code for the InitializeImageGeomCellDataFilter + */ + +class SIMPLNXCORE_EXPORT InitializeImageGeomCellData +{ +public: + InitializeImageGeomCellData(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, InitializeImageGeomCellDataInputValues* inputValues); + ~InitializeImageGeomCellData() noexcept; + + InitializeImageGeomCellData(const InitializeImageGeomCellData&) = delete; + InitializeImageGeomCellData(InitializeImageGeomCellData&&) noexcept = delete; + InitializeImageGeomCellData& operator=(const InitializeImageGeomCellData&) = delete; + InitializeImageGeomCellData& operator=(InitializeImageGeomCellData&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const InitializeImageGeomCellDataInputValues* 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/InterpolatePointCloudToRegularGrid.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InterpolatePointCloudToRegularGrid.cpp new file mode 100644 index 0000000000..33cf429901 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InterpolatePointCloudToRegularGrid.cpp @@ -0,0 +1,26 @@ +#include "InterpolatePointCloudToRegularGrid.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +InterpolatePointCloudToRegularGrid::InterpolatePointCloudToRegularGrid(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + InterpolatePointCloudToRegularGridInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +InterpolatePointCloudToRegularGrid::~InterpolatePointCloudToRegularGrid() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> InterpolatePointCloudToRegularGrid::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InterpolatePointCloudToRegularGrid.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InterpolatePointCloudToRegularGrid.hpp new file mode 100644 index 0000000000..12c85435e9 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InterpolatePointCloudToRegularGrid.hpp @@ -0,0 +1,82 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/ChoicesParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" +#include "simplnx/Parameters/MultiArraySelectionParameter.hpp" +#include "simplnx/Parameters/VectorParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + InterpolatePointCloudToRegularGridInputValues inputValues; + inputValues.CopyArrays = filterArgs.value(copy_arrays); + inputValues.GaussianSigmas = filterArgs.value(gaussian_sigmas); + inputValues.InputImageGeometryPath = filterArgs.value(input_image_geometry_path); + inputValues.InputMaskPath = filterArgs.value(input_mask_path); + inputValues.InputVertexGeometryPath = filterArgs.value(input_vertex_geometry_path); + inputValues.InterpolateArrays = filterArgs.value(interpolate_arrays); + inputValues.InterpolatedGroupName = filterArgs.value(interpolated_group_name); + inputValues.InterpolationIndex = filterArgs.value(interpolation_index); + inputValues.KernelDistancesArrayName = filterArgs.value(kernel_distances_array_name); + inputValues.KernelSize = filterArgs.value(kernel_size); + inputValues.StoreKernelDistances = filterArgs.value(store_kernel_distances); + inputValues.UseMask = filterArgs.value(use_mask); + inputValues.VoxelIndicesPath = filterArgs.value(voxel_indices_path); + return InterpolatePointCloudToRegularGrid(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT InterpolatePointCloudToRegularGridInputValues +{ + MultiArraySelectionParameter::ValueType CopyArrays; + VectorFloat32Parameter::ValueType GaussianSigmas; + GeometrySelectionParameter::ValueType InputImageGeometryPath; + ArraySelectionParameter::ValueType InputMaskPath; + GeometrySelectionParameter::ValueType InputVertexGeometryPath; + MultiArraySelectionParameter::ValueType InterpolateArrays; + DataObjectNameParameter::ValueType InterpolatedGroupName; + ChoicesParameter::ValueType InterpolationIndex; + DataObjectNameParameter::ValueType KernelDistancesArrayName; + VectorFloat32Parameter::ValueType KernelSize; + BoolParameter::ValueType StoreKernelDistances; + BoolParameter::ValueType UseMask; + ArraySelectionParameter::ValueType VoxelIndicesPath; +}; + +/** + * @class InterpolatePointCloudToRegularGrid + * @brief This algorithm implements support code for the InterpolatePointCloudToRegularGridFilter + */ + +class SIMPLNXCORE_EXPORT InterpolatePointCloudToRegularGrid +{ +public: + InterpolatePointCloudToRegularGrid(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + InterpolatePointCloudToRegularGridInputValues* inputValues); + ~InterpolatePointCloudToRegularGrid() noexcept; + + InterpolatePointCloudToRegularGrid(const InterpolatePointCloudToRegularGrid&) = delete; + InterpolatePointCloudToRegularGrid(InterpolatePointCloudToRegularGrid&&) noexcept = delete; + InterpolatePointCloudToRegularGrid& operator=(const InterpolatePointCloudToRegularGrid&) = delete; + InterpolatePointCloudToRegularGrid& operator=(InterpolatePointCloudToRegularGrid&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const InterpolatePointCloudToRegularGridInputValues* 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/IterativeClosestPoint.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/IterativeClosestPoint.cpp new file mode 100644 index 0000000000..f51aed5130 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/IterativeClosestPoint.cpp @@ -0,0 +1,207 @@ +#include "IterativeClosestPoint.hpp" + +#include "SimplnxCore/utils/nanoflann.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/Geometry/VertexGeom.hpp" + +#include + +using namespace nx::core; + +namespace +{ +constexpr int32 k_MissingVertices = -4503; +constexpr int32 k_EmptyVertices = -4505; + +template +struct VertexGeomAdaptor +{ + const Derived& obj; + AbstractDataStore* verts; + size_t m_NumComponents = 0; + size_t m_NumTuples = 0; + + explicit VertexGeomAdaptor(const Derived& obj_) + : obj(obj_) + { + // These values never change for the lifetime of this object so cache them now. + verts = derived()->getVertices()->getDataStore(); + m_NumComponents = verts->getNumberOfComponents(); + m_NumTuples = verts->getNumberOfTuples(); + } + + [[nodiscard]] const Derived& derived() const + { + return obj; + } + + [[nodiscard]] usize kdtree_get_point_count() const + { + return m_NumTuples; + } + + [[nodiscard]] float kdtree_get_pt(const usize idx, const usize dim) const + { + auto offset = idx * m_NumComponents; + return verts->getValue(offset + dim); + } + + template + bool kdtree_get_bbox(BBOX& /*bb*/) const + { + return false; + } +}; +} // namespace + +// ----------------------------------------------------------------------------- +IterativeClosestPoint::IterativeClosestPoint(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + IterativeClosestPointInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +IterativeClosestPoint::~IterativeClosestPoint() noexcept = default; + +// ----------------------------------------------------------------------------- +void IterativeClosestPoint::updateProgress(const std::string& message) +{ + m_MessageHandler(IFilter::Message::Type::Info, message); +} + +// ----------------------------------------------------------------------------- +const std::atomic_bool& IterativeClosestPoint::getCancel() +{ + return m_ShouldCancel; +} + +// ----------------------------------------------------------------------------- +Result<> IterativeClosestPoint::operator()() +{ + auto movingVertexGeom = m_DataStructure.getDataAs(m_InputValues->MovingVertexPath); + auto targetVertexGeom = m_DataStructure.getDataAs(m_InputValues->TargetVertexPath); + + if(movingVertexGeom == nullptr) + { + return MakeErrorResult(k_MissingVertices, fmt::format("Moving Vertex Geometry not found at path '{}'", m_InputValues->MovingVertexPath.toString())); + } + if(targetVertexGeom == nullptr) + { + return MakeErrorResult(k_MissingVertices, fmt::format("Target Vertex Geometry not found at path '{}'", m_InputValues->TargetVertexPath.toString())); + } + + if(movingVertexGeom->getVertices() == nullptr) + { + return MakeErrorResult(k_MissingVertices, fmt::format("Moving Vertex Geometry does not contain a vertex array")); + } + if(targetVertexGeom->getVertices() == nullptr) + { + return MakeErrorResult(k_MissingVertices, fmt::format("Target Vertex Geometry does not contain a vertex array")); + } + + Float32AbstractDataStore& movingStore = movingVertexGeom->getVertices()->getDataStoreRef(); + if(movingStore.getNumberOfTuples() == 0) + { + return MakeErrorResult(k_EmptyVertices, fmt::format("Moving Vertex Geometry does not contain any vertices")); + } + Float32AbstractDataStore& targetStore = targetVertexGeom->getVertices()->getDataStoreRef(); + if(targetStore.getNumberOfTuples() == 0) + { + return MakeErrorResult(k_EmptyVertices, fmt::format("Target Vertex Geometry does not contain any vertices")); + } + + std::vector movingVector(movingStore.begin(), movingStore.end()); + float32* movingCopyPtr = movingVector.data(); + DataStructure tmp; + + usize numMovingVerts = movingVertexGeom->getNumberOfVertices(); + std::vector dynTarget(numMovingVerts * 3, 0.0F); + float* dynTargetPtr = dynTarget.data(); + + using Adaptor = VertexGeomAdaptor; + const Adaptor adaptor(targetVertexGeom); + + m_MessageHandler("Building kd-tree index..."); + + using KDtree = nanoflann::KDTreeSingleIndexAdaptor, Adaptor, 3>; + KDtree index(3, adaptor, nanoflann::KDTreeSingleIndexAdaptorParams(30)); + index.buildIndex(); + + const usize nn = 1; + + typedef Eigen::Matrix PointCloud; + typedef Eigen::Matrix UmeyamaTransform; + + UmeyamaTransform globalTransform; + globalTransform << 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1; + + auto start = std::chrono::steady_clock::now(); + for(usize i = 0; i < m_InputValues->NumIterations; i++) + { + if(m_ShouldCancel) + { + return {}; + } + + for(usize j = 0; j < numMovingVerts; j++) + { + usize identifier; + float dist; + nanoflann::KNNResultSet results(nn); + results.init(&identifier, &dist); + index.findNeighbors(results, movingCopyPtr + (3 * j), nanoflann::SearchParams()); + dynTargetPtr[3 * j + 0] = targetStore[3 * identifier + 0]; + dynTargetPtr[3 * j + 1] = targetStore[3 * identifier + 1]; + dynTargetPtr[3 * j + 2] = targetStore[3 * identifier + 2]; + } + + Eigen::Map moving_(movingCopyPtr, 3, numMovingVerts); + Eigen::Map target_(dynTargetPtr, 3, numMovingVerts); + + UmeyamaTransform transform = Eigen::umeyama(moving_, target_, false); + + for(usize j = 0; j < numMovingVerts; j++) + { + Eigen::Vector4f position(movingCopyPtr[3 * j + 0], movingCopyPtr[3 * j + 1], movingCopyPtr[3 * j + 2], 1); + Eigen::Vector4f transformedPosition = transform * position; + std::memcpy(movingCopyPtr + (3 * j), transformedPosition.data(), sizeof(float) * 3); + } + // Update the global transform + globalTransform = transform * globalTransform; + + auto now = std::chrono::steady_clock::now(); + if(std::chrono::duration_cast(now - start).count() > 1000) + { + m_MessageHandler(fmt::format("Performing Registration Iterations || {}% Completed", static_cast((static_cast(i) / m_InputValues->NumIterations) * 100.0f))); + start = now; + } + } + + auto& transformStore = m_DataStructure.getDataAs(m_InputValues->TransformArrayPath)->getDataStoreRef(); + + if(m_InputValues->ApplyTransformation) + { + for(usize j = 0; j < numMovingVerts; j++) + { + Eigen::Vector4f position(movingStore[3 * j + 0], movingStore[3 * j + 1], movingStore[3 * j + 2], 1); + Eigen::Vector4f transformedPosition = globalTransform * position; + for(usize k = 0; k < 3; k++) + { + movingStore[3 * j + k] = transformedPosition.data()[k]; + } + } + } + + globalTransform.transposeInPlace(); + for(usize j = 0; j < 16; j++) + { + transformStore[j] = globalTransform.data()[j]; + } + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/IterativeClosestPoint.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/IterativeClosestPoint.hpp new file mode 100644 index 0000000000..81ebd2bcf8 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/IterativeClosestPoint.hpp @@ -0,0 +1,46 @@ +#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 IterativeClosestPointInputValues +{ + bool ApplyTransformation; + uint64 NumIterations; + DataPath MovingVertexPath; + DataPath TargetVertexPath; + DataPath TransformArrayPath; +}; + +/** + * @class + */ +class SIMPLNXCORE_EXPORT IterativeClosestPoint +{ +public: + IterativeClosestPoint(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, IterativeClosestPointInputValues* inputValues); + ~IterativeClosestPoint() noexcept; + + IterativeClosestPoint(const IterativeClosestPoint&) = delete; + IterativeClosestPoint(IterativeClosestPoint&&) noexcept = delete; + IterativeClosestPoint& operator=(const IterativeClosestPoint&) = delete; + IterativeClosestPoint& operator=(IterativeClosestPoint&&) noexcept = delete; + + Result<> operator()(); + void updateProgress(const std::string& message); + const std::atomic_bool& getCancel(); + +private: + DataStructure& m_DataStructure; + const IterativeClosestPointInputValues* 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/MapPointCloudToRegularGrid.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/MapPointCloudToRegularGrid.cpp new file mode 100644 index 0000000000..19b0554a3a --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/MapPointCloudToRegularGrid.cpp @@ -0,0 +1,190 @@ +#include "MapPointCloudToRegularGrid.hpp" + +#include "simplnx/DataStructure/Geometry/ImageGeom.hpp" +#include "simplnx/DataStructure/Geometry/VertexGeom.hpp" +#include "simplnx/Utilities/MaskCompareUtilities.hpp" + +using namespace nx::core; + +namespace +{ +constexpr nx::core::StringLiteral k_SilentMode = "Silent"; +constexpr nx::core::StringLiteral k_WarningMode = "Warning with Count"; +constexpr nx::core::StringLiteral k_ErrorMode = "Error at First Instance"; +const nx::core::ChoicesParameter::ValueType k_SilentModeIndex = 0; +const nx::core::ChoicesParameter::ValueType k_WarningModeIndex = 1; +const nx::core::ChoicesParameter::ValueType k_ErrorModeIndex = 2; + +constexpr int64 k_MaskCompareInvalid = -2605; +constexpr int64 k_ErrorOutOfBounds = -2607; +constexpr int64 k_WarningOutOfBounds = -2608; +constexpr int64 k_InvalidHandlingValue = -2609; + +template +struct OutOfBoundsType +{ + // Compile time checks for bounding, no runtime overhead + static_assert((UseSilent && !UseWarning && !UseError) || (!UseSilent && UseWarning && !UseError) || (!UseSilent && !UseWarning && UseError), + "struct `OutOfBoundsType` can only have one true bool in its instantiation"); + + static constexpr bool UsingSilent = UseSilent; + static constexpr bool UsingWarning = UseWarning; + static constexpr bool UsingError = UseError; +}; + +using SilentType = OutOfBoundsType; +using WarningType = OutOfBoundsType; +using ErrorType = OutOfBoundsType; + +template +Result<> ProcessVertices(const IFilter::MessageHandler& messageHandler, const VertexGeom& vertices, const ImageGeom& image, UInt64AbstractDataStore& voxelIndices, + const std::unique_ptr& maskCompare, uint64 outOfBoundsValue) +{ + // Out of Bounds Counter + usize count = 0; + + // Execution + usize numVerts = vertices.getNumberOfVertices(); + auto start = std::chrono::steady_clock::now(); + for(int64 i = 0; i < numVerts; i++) + { + if constexpr(UseMask) + { + if(!maskCompare->isTrue(i)) + { + continue; + } + } + + auto coords = vertices.getVertexCoordinate(i); + const auto indexResult = image.getIndex(coords[0], coords[1], coords[2]); + if(indexResult.has_value()) + { + voxelIndices[i] = indexResult.value(); + } + else + { + if constexpr(OutOfBoundsType::UsingError) + { + BoundingBox3Df imageBounds = image.getBoundingBoxf(); + const Point3Df& minPoint = imageBounds.getMinPoint(); + const Point3Df& maxPoint = imageBounds.getMaxPoint(); + return MakeErrorResult( + k_ErrorOutOfBounds, + fmt::format("Out of bounds value encountered.\nVertex Index: {}\nVertex Coordinates [X,Y,Z]: [{},{},{}]\nImage Coordinate Bounds:\nX: {} to {}\nY: {} to {}\nZ: {} to {}", i, coords[0], + coords[1], coords[2], minPoint.getX(), maxPoint.getX(), minPoint.getY(), maxPoint.getY(), minPoint.getZ(), maxPoint.getZ())); + } + + // Out of bounds value + voxelIndices[i] = outOfBoundsValue; + count++; + } + + auto now = std::chrono::steady_clock::now(); + if(std::chrono::duration_cast(now - start).count() > 1000) + { + messageHandler(fmt::format("Computing Point Cloud Voxel Indices || {}% Completed", static_cast((static_cast(i) / numVerts) * 100.0f))); + start = now; + } + } + + if constexpr(OutOfBoundsType::UsingWarning) + { + if(count > 0) + { + return MakeWarningVoidResult(k_WarningOutOfBounds, fmt::format("Mapping Complete. Number of value outside image bounds: {}", count)); + } + } + + return {}; +} +} // namespace + +// ----------------------------------------------------------------------------- +MapPointCloudToRegularGrid::MapPointCloudToRegularGrid(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + MapPointCloudToRegularGridInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +MapPointCloudToRegularGrid::~MapPointCloudToRegularGrid() noexcept = default; + +// ----------------------------------------------------------------------------- +void MapPointCloudToRegularGrid::updateProgress(const std::string& message) +{ + m_MessageHandler(IFilter::Message::Type::Info, message); +} + +// ----------------------------------------------------------------------------- +const std::atomic_bool& MapPointCloudToRegularGrid::getCancel() +{ + return m_ShouldCancel; +} + +// ----------------------------------------------------------------------------- +Result<> MapPointCloudToRegularGrid::operator()() +{ + // Get the target image as a pointer + const auto& image = m_DataStructure.getDataRefAs(m_InputValues->ImageGeomPath); + + // Create the Mask + std::unique_ptr maskCompare; + try + { + maskCompare = MaskCompareUtilities::InstantiateMaskCompare(m_DataStructure, m_InputValues->MaskArrayPath); + } catch(const std::out_of_range& exception) + { + // This really should NOT be happening as the path was verified during preflight BUT we may be calling this from + // somewhere else that is NOT going through the normal nx::core::IFilter API of Preflight and Execute + std::string message = fmt::format("Mask Array DataPath does not exist or is not of the correct type (Bool | UInt8) {}", m_InputValues->MaskArrayPath.toString()); + return MakeErrorResult(k_MaskCompareInvalid, message); + } + + // Cache all the needed objects for ::ProcessVertices + const auto& vertices = m_DataStructure.getDataRefAs(m_InputValues->VertexGeomPath); + auto& voxelIndices = m_DataStructure.getDataAs(m_InputValues->VoxelIndicesPath)->getDataStoreRef(); + + // Execute the correct ::ProcessVertices, else error out + if(m_InputValues->UseMask) + { + switch(m_InputValues->OutOfBoundsHandling) + { + case k_SilentModeIndex: { + return ProcessVertices(m_MessageHandler, vertices, image, voxelIndices, maskCompare, m_InputValues->OutOfBoundsValue); + } + case k_WarningModeIndex: { + return ProcessVertices(m_MessageHandler, vertices, image, voxelIndices, maskCompare, m_InputValues->OutOfBoundsValue); + } + case k_ErrorModeIndex: { + return ProcessVertices(m_MessageHandler, vertices, image, voxelIndices, maskCompare, m_InputValues->OutOfBoundsValue); + } + default: { + return MakeErrorResult(k_InvalidHandlingValue, fmt::format("Unexpected Out of Bounds Handing Option. Received : {}. Expected: {} ({}), {} ({}), {} ({})", m_InputValues->OutOfBoundsHandling, + k_SilentMode, k_SilentModeIndex, k_WarningMode, k_WarningModeIndex, k_ErrorMode, k_ErrorModeIndex)); + } + } + } + else + { + switch(m_InputValues->OutOfBoundsHandling) + { + case k_SilentModeIndex: { + return ProcessVertices(m_MessageHandler, vertices, image, voxelIndices, maskCompare, m_InputValues->OutOfBoundsValue); + } + case k_WarningModeIndex: { + return ProcessVertices(m_MessageHandler, vertices, image, voxelIndices, maskCompare, m_InputValues->OutOfBoundsValue); + } + case k_ErrorModeIndex: { + return ProcessVertices(m_MessageHandler, vertices, image, voxelIndices, maskCompare, m_InputValues->OutOfBoundsValue); + } + default: { + return MakeErrorResult(k_InvalidHandlingValue, fmt::format("Unexpected Out of Bounds Handing Option. Received : {}. Expected: {} ({}), {} ({}), {} ({})", m_InputValues->OutOfBoundsHandling, + k_SilentMode, k_SilentModeIndex, k_WarningMode, k_WarningModeIndex, k_ErrorMode, k_ErrorModeIndex)); + } + } + } +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/MapPointCloudToRegularGrid.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/MapPointCloudToRegularGrid.hpp new file mode 100644 index 0000000000..0b1f5db8ee --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/MapPointCloudToRegularGrid.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ChoicesParameter.hpp" + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT MapPointCloudToRegularGridInputValues +{ + bool UseMask; + DataPath ImageGeomPath; + DataPath MaskArrayPath; + DataPath VertexGeomPath; + DataPath VoxelIndicesPath; + uint64 OutOfBoundsValue; + ChoicesParameter::ValueType OutOfBoundsHandling; +}; + +/** + * @class + */ +class SIMPLNXCORE_EXPORT MapPointCloudToRegularGrid +{ +public: + MapPointCloudToRegularGrid(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, MapPointCloudToRegularGridInputValues* inputValues); + ~MapPointCloudToRegularGrid() noexcept; + + MapPointCloudToRegularGrid(const MapPointCloudToRegularGrid&) = delete; + MapPointCloudToRegularGrid(MapPointCloudToRegularGrid&&) noexcept = delete; + MapPointCloudToRegularGrid& operator=(const MapPointCloudToRegularGrid&) = delete; + MapPointCloudToRegularGrid& operator=(MapPointCloudToRegularGrid&&) noexcept = delete; + + Result<> operator()(); + void updateProgress(const std::string& message); + const std::atomic_bool& getCancel(); + +private: + DataStructure& m_DataStructure; + const MapPointCloudToRegularGridInputValues* 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/MoveData.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/MoveData.cpp new file mode 100644 index 0000000000..65c5b24a71 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/MoveData.cpp @@ -0,0 +1,25 @@ +#include "MoveData.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +MoveData::MoveData(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, MoveDataInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +MoveData::~MoveData() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> MoveData::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/MoveData.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/MoveData.hpp new file mode 100644 index 0000000000..6133ebfdad --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/MoveData.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/DataGroupSelectionParameter.hpp" +#include "simplnx/Parameters/MultiPathSelectionParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + MoveDataInputValues inputValues; + inputValues.DestinationParentPath = filterArgs.value(destination_parent_path); + inputValues.SourceDataPaths = filterArgs.value(source_data_paths); + return MoveData(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT MoveDataInputValues +{ + DataGroupSelectionParameter::ValueType DestinationParentPath; + MultiPathSelectionParameter::ValueType SourceDataPaths; +}; + +/** + * @class MoveData + * @brief This algorithm implements support code for the MoveDataFilter + */ + +class SIMPLNXCORE_EXPORT MoveData +{ +public: + MoveData(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, MoveDataInputValues* inputValues); + ~MoveData() noexcept; + + MoveData(const MoveData&) = delete; + MoveData(MoveData&&) noexcept = delete; + MoveData& operator=(const MoveData&) = delete; + MoveData& operator=(MoveData&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const MoveDataInputValues* 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/MultiThresholdObjects.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/MultiThresholdObjects.cpp new file mode 100644 index 0000000000..50c5b0bf43 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/MultiThresholdObjects.cpp @@ -0,0 +1,26 @@ +#include "MultiThresholdObjects.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +MultiThresholdObjects::MultiThresholdObjects(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + MultiThresholdObjectsInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +MultiThresholdObjects::~MultiThresholdObjects() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> MultiThresholdObjects::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/MultiThresholdObjects.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/MultiThresholdObjects.hpp new file mode 100644 index 0000000000..2371efc102 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/MultiThresholdObjects.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArrayThresholdsParameter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" +#include "simplnx/Parameters/DataTypeParameter.hpp" +#include "simplnx/Parameters/NumberParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + MultiThresholdObjectsInputValues inputValues; + inputValues.ArrayThresholdsObject = filterArgs.value(array_thresholds_object); + inputValues.CreatedMaskType = filterArgs.value(created_mask_type); + inputValues.CustomFalseValue = filterArgs.value(custom_false_value); + inputValues.CustomTrueValue = filterArgs.value(custom_true_value); + inputValues.OutputDataArrayName = filterArgs.value(output_data_array_name); + inputValues.UseCustomFalseValue = filterArgs.value(use_custom_false_value); + inputValues.UseCustomTrueValue = filterArgs.value(use_custom_true_value); + return MultiThresholdObjects(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT MultiThresholdObjectsInputValues +{ + ArrayThresholdsParameter::ValueType ArrayThresholdsObject; + DataTypeParameter::ValueType CreatedMaskType; + Float64Parameter::ValueType CustomFalseValue; + Float64Parameter::ValueType CustomTrueValue; + DataObjectNameParameter::ValueType OutputDataArrayName; + BoolParameter::ValueType UseCustomFalseValue; + BoolParameter::ValueType UseCustomTrueValue; +}; + +/** + * @class MultiThresholdObjects + * @brief This algorithm implements support code for the MultiThresholdObjectsFilter + */ + +class SIMPLNXCORE_EXPORT MultiThresholdObjects +{ +public: + MultiThresholdObjects(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, MultiThresholdObjectsInputValues* inputValues); + ~MultiThresholdObjects() noexcept; + + MultiThresholdObjects(const MultiThresholdObjects&) = delete; + MultiThresholdObjects(MultiThresholdObjects&&) noexcept = delete; + MultiThresholdObjects& operator=(const MultiThresholdObjects&) = delete; + MultiThresholdObjects& operator=(MultiThresholdObjects&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const MultiThresholdObjectsInputValues* 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/ReadDREAM3D.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReadDREAM3D.cpp new file mode 100644 index 0000000000..e486fcc657 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReadDREAM3D.cpp @@ -0,0 +1,25 @@ +#include "ReadDREAM3D.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +ReadDREAM3D::ReadDREAM3D(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ReadDREAM3DInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ReadDREAM3D::~ReadDREAM3D() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ReadDREAM3D::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReadDREAM3D.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReadDREAM3D.hpp new file mode 100644 index 0000000000..4f9455cea1 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReadDREAM3D.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/Dream3dImportParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + ReadDREAM3DInputValues inputValues; + inputValues.ImportDataObject = filterArgs.value(import_data_object); + return ReadDREAM3D(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT ReadDREAM3DInputValues +{ + Dream3dImportParameter::ValueType ImportDataObject; +}; + +/** + * @class ReadDREAM3D + * @brief This algorithm implements support code for the ReadDREAM3DFilter + */ + +class SIMPLNXCORE_EXPORT ReadDREAM3D +{ +public: + ReadDREAM3D(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ReadDREAM3DInputValues* inputValues); + ~ReadDREAM3D() noexcept; + + ReadDREAM3D(const ReadDREAM3D&) = delete; + ReadDREAM3D(ReadDREAM3D&&) noexcept = delete; + ReadDREAM3D& operator=(const ReadDREAM3D&) = delete; + ReadDREAM3D& operator=(ReadDREAM3D&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ReadDREAM3DInputValues* 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/ReadHDF5Dataset.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReadHDF5Dataset.cpp new file mode 100644 index 0000000000..0c3a8b7184 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReadHDF5Dataset.cpp @@ -0,0 +1,25 @@ +#include "ReadHDF5Dataset.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +ReadHDF5Dataset::ReadHDF5Dataset(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ReadHDF5DatasetInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ReadHDF5Dataset::~ReadHDF5Dataset() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ReadHDF5Dataset::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReadHDF5Dataset.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReadHDF5Dataset.hpp new file mode 100644 index 0000000000..2f1a967c07 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReadHDF5Dataset.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ReadHDF5DatasetParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + ReadHDF5DatasetInputValues inputValues; + inputValues.ImportHdf5Object = filterArgs.value(import_hdf5_object); + return ReadHDF5Dataset(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT ReadHDF5DatasetInputValues +{ + ReadHDF5DatasetParameter::ValueType ImportHdf5Object; +}; + +/** + * @class ReadHDF5Dataset + * @brief This algorithm implements support code for the ReadHDF5DatasetFilter + */ + +class SIMPLNXCORE_EXPORT ReadHDF5Dataset +{ +public: + ReadHDF5Dataset(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ReadHDF5DatasetInputValues* inputValues); + ~ReadHDF5Dataset() noexcept; + + ReadHDF5Dataset(const ReadHDF5Dataset&) = delete; + ReadHDF5Dataset(ReadHDF5Dataset&&) noexcept = delete; + ReadHDF5Dataset& operator=(const ReadHDF5Dataset&) = delete; + ReadHDF5Dataset& operator=(ReadHDF5Dataset&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ReadHDF5DatasetInputValues* 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/ReadTextDataArray.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReadTextDataArray.cpp new file mode 100644 index 0000000000..3aca36667b --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReadTextDataArray.cpp @@ -0,0 +1,25 @@ +#include "ReadTextDataArray.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +ReadTextDataArray::ReadTextDataArray(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ReadTextDataArrayInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ReadTextDataArray::~ReadTextDataArray() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ReadTextDataArray::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReadTextDataArray.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReadTextDataArray.hpp new file mode 100644 index 0000000000..6fe38d1b6a --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReadTextDataArray.hpp @@ -0,0 +1,74 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArrayCreationParameter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/ChoicesParameter.hpp" +#include "simplnx/Parameters/DataStoreFormatParameter.hpp" +#include "simplnx/Parameters/DynamicTableParameter.hpp" +#include "simplnx/Parameters/FileSystemPathParameter.hpp" +#include "simplnx/Parameters/NumberParameter.hpp" +#include "simplnx/Parameters/NumericTypeParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + ReadTextDataArrayInputValues inputValues; + inputValues.DataFormat = filterArgs.value(data_format); + inputValues.DelimiterIndex = filterArgs.value(delimiter_index); + inputValues.InputFile = filterArgs.value(input_file); + inputValues.NumberComp = filterArgs.value(number_comp); + inputValues.NumberTuples = filterArgs.value(number_tuples); + inputValues.OutputDataArrayPath = filterArgs.value(output_data_array_path); + inputValues.ScalarTypeIndex = filterArgs.value(scalar_type_index); + inputValues.SetTupleDimensions = filterArgs.value(set_tuple_dimensions); + inputValues.SkipLineCount = filterArgs.value(skip_line_count); + return ReadTextDataArray(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT ReadTextDataArrayInputValues +{ + DataStoreFormatParameter::ValueType DataFormat; + ChoicesParameter::ValueType DelimiterIndex; + FileSystemPathParameter::ValueType InputFile; + UInt64Parameter::ValueType NumberComp; + DynamicTableParameter::ValueType NumberTuples; + ArrayCreationParameter::ValueType OutputDataArrayPath; + NumericTypeParameter::ValueType ScalarTypeIndex; + BoolParameter::ValueType SetTupleDimensions; + UInt64Parameter::ValueType SkipLineCount; +}; + +/** + * @class ReadTextDataArray + * @brief This algorithm implements support code for the ReadTextDataArrayFilter + */ + +class SIMPLNXCORE_EXPORT ReadTextDataArray +{ +public: + ReadTextDataArray(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ReadTextDataArrayInputValues* inputValues); + ~ReadTextDataArray() noexcept; + + ReadTextDataArray(const ReadTextDataArray&) = delete; + ReadTextDataArray(ReadTextDataArray&&) noexcept = delete; + ReadTextDataArray& operator=(const ReadTextDataArray&) = delete; + ReadTextDataArray& operator=(ReadTextDataArray&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ReadTextDataArrayInputValues* 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/RemoveFlaggedVertices.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedVertices.cpp new file mode 100644 index 0000000000..9cd183c747 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedVertices.cpp @@ -0,0 +1,26 @@ +#include "RemoveFlaggedVertices.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +RemoveFlaggedVertices::RemoveFlaggedVertices(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + RemoveFlaggedVerticesInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +RemoveFlaggedVertices::~RemoveFlaggedVertices() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> RemoveFlaggedVertices::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedVertices.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedVertices.hpp new file mode 100644 index 0000000000..db9fb99608 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedVertices.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/DataGroupCreationParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + RemoveFlaggedVerticesInputValues inputValues; + inputValues.InputVertexGeometryPath = filterArgs.value(input_vertex_geometry_path); + inputValues.MaskPath = filterArgs.value(mask_path); + inputValues.OutputVertexGeometryPath = filterArgs.value(output_vertex_geometry_path); + return RemoveFlaggedVertices(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT RemoveFlaggedVerticesInputValues +{ + GeometrySelectionParameter::ValueType InputVertexGeometryPath; + ArraySelectionParameter::ValueType MaskPath; + DataGroupCreationParameter::ValueType OutputVertexGeometryPath; +}; + +/** + * @class RemoveFlaggedVertices + * @brief This algorithm implements support code for the RemoveFlaggedVerticesFilter + */ + +class SIMPLNXCORE_EXPORT RemoveFlaggedVertices +{ +public: + RemoveFlaggedVertices(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, RemoveFlaggedVerticesInputValues* inputValues); + ~RemoveFlaggedVertices() noexcept; + + RemoveFlaggedVertices(const RemoveFlaggedVertices&) = delete; + RemoveFlaggedVertices(RemoveFlaggedVertices&&) noexcept = delete; + RemoveFlaggedVertices& operator=(const RemoveFlaggedVertices&) = delete; + RemoveFlaggedVertices& operator=(RemoveFlaggedVertices&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const RemoveFlaggedVerticesInputValues* 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/RenameDataObject.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RenameDataObject.cpp new file mode 100644 index 0000000000..5fe5ff6d6e --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RenameDataObject.cpp @@ -0,0 +1,25 @@ +#include "RenameDataObject.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +RenameDataObject::RenameDataObject(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, RenameDataObjectInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +RenameDataObject::~RenameDataObject() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> RenameDataObject::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RenameDataObject.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RenameDataObject.hpp new file mode 100644 index 0000000000..6416b44969 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RenameDataObject.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/DataPathSelectionParameter.hpp" +#include "simplnx/Parameters/StringParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + RenameDataObjectInputValues inputValues; + inputValues.AllowOverwrite = filterArgs.value(allow_overwrite); + inputValues.NewName = filterArgs.value(new_name); + inputValues.SourceDataObjectPath = filterArgs.value(source_data_object_path); + return RenameDataObject(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT RenameDataObjectInputValues +{ + BoolParameter::ValueType AllowOverwrite; + StringParameter::ValueType NewName; + DataPathSelectionParameter::ValueType SourceDataObjectPath; +}; + +/** + * @class RenameDataObject + * @brief This algorithm implements support code for the RenameDataObjectFilter + */ + +class SIMPLNXCORE_EXPORT RenameDataObject +{ +public: + RenameDataObject(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, RenameDataObjectInputValues* inputValues); + ~RenameDataObject() noexcept; + + RenameDataObject(const RenameDataObject&) = delete; + RenameDataObject(RenameDataObject&&) noexcept = delete; + RenameDataObject& operator=(const RenameDataObject&) = delete; + RenameDataObject& operator=(RenameDataObject&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const RenameDataObjectInputValues* 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/RequireMinimumSizeFeatures.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RequireMinimumSizeFeatures.cpp new file mode 100644 index 0000000000..7f3494e068 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RequireMinimumSizeFeatures.cpp @@ -0,0 +1,26 @@ +#include "RequireMinimumSizeFeatures.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +RequireMinimumSizeFeatures::RequireMinimumSizeFeatures(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + RequireMinimumSizeFeaturesInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +RequireMinimumSizeFeatures::~RequireMinimumSizeFeatures() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> RequireMinimumSizeFeatures::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RequireMinimumSizeFeatures.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RequireMinimumSizeFeatures.hpp new file mode 100644 index 0000000000..fd37d97ece --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RequireMinimumSizeFeatures.hpp @@ -0,0 +1,66 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" +#include "simplnx/Parameters/NumberParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + RequireMinimumSizeFeaturesInputValues inputValues; + inputValues.ApplySinglePhase = filterArgs.value(apply_single_phase); + inputValues.FeatureIdsPath = filterArgs.value(feature_ids_path); + inputValues.FeaturePhasesPath = filterArgs.value(feature_phases_path); + inputValues.InputImageGeometryPath = filterArgs.value(input_image_geometry_path); + inputValues.MinAllowedFeaturesSize = filterArgs.value(min_allowed_features_size); + inputValues.NumCellsPath = filterArgs.value(num_cells_path); + inputValues.PhaseNumber = filterArgs.value(phase_number); + return RequireMinimumSizeFeatures(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT RequireMinimumSizeFeaturesInputValues +{ + BoolParameter::ValueType ApplySinglePhase; + ArraySelectionParameter::ValueType FeatureIdsPath; + ArraySelectionParameter::ValueType FeaturePhasesPath; + GeometrySelectionParameter::ValueType InputImageGeometryPath; + Int64Parameter::ValueType MinAllowedFeaturesSize; + ArraySelectionParameter::ValueType NumCellsPath; + Int64Parameter::ValueType PhaseNumber; +}; + +/** + * @class RequireMinimumSizeFeatures + * @brief This algorithm implements support code for the RequireMinimumSizeFeaturesFilter + */ + +class SIMPLNXCORE_EXPORT RequireMinimumSizeFeatures +{ +public: + RequireMinimumSizeFeatures(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, RequireMinimumSizeFeaturesInputValues* inputValues); + ~RequireMinimumSizeFeatures() noexcept; + + RequireMinimumSizeFeatures(const RequireMinimumSizeFeatures&) = delete; + RequireMinimumSizeFeatures(RequireMinimumSizeFeatures&&) noexcept = delete; + RequireMinimumSizeFeatures& operator=(const RequireMinimumSizeFeatures&) = delete; + RequireMinimumSizeFeatures& operator=(RequireMinimumSizeFeatures&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const RequireMinimumSizeFeaturesInputValues* 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/ReverseTriangleWinding.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReverseTriangleWinding.cpp new file mode 100644 index 0000000000..f235312a94 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReverseTriangleWinding.cpp @@ -0,0 +1,26 @@ +#include "ReverseTriangleWinding.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +ReverseTriangleWinding::ReverseTriangleWinding(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + ReverseTriangleWindingInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ReverseTriangleWinding::~ReverseTriangleWinding() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ReverseTriangleWinding::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReverseTriangleWinding.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReverseTriangleWinding.hpp new file mode 100644 index 0000000000..8beb567220 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ReverseTriangleWinding.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + ReverseTriangleWindingInputValues inputValues; + inputValues.InputTriangleGeometryPath = filterArgs.value(input_triangle_geometry_path); + return ReverseTriangleWinding(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT ReverseTriangleWindingInputValues +{ + GeometrySelectionParameter::ValueType InputTriangleGeometryPath; +}; + +/** + * @class ReverseTriangleWinding + * @brief This algorithm implements support code for the ReverseTriangleWindingFilter + */ + +class SIMPLNXCORE_EXPORT ReverseTriangleWinding +{ +public: + ReverseTriangleWinding(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ReverseTriangleWindingInputValues* inputValues); + ~ReverseTriangleWinding() noexcept; + + ReverseTriangleWinding(const ReverseTriangleWinding&) = delete; + ReverseTriangleWinding(ReverseTriangleWinding&&) noexcept = delete; + ReverseTriangleWinding& operator=(const ReverseTriangleWinding&) = delete; + ReverseTriangleWinding& operator=(ReverseTriangleWinding&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ReverseTriangleWindingInputValues* 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/RobustAutomaticThreshold.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RobustAutomaticThreshold.cpp new file mode 100644 index 0000000000..3e9626e79d --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RobustAutomaticThreshold.cpp @@ -0,0 +1,26 @@ +#include "RobustAutomaticThreshold.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +RobustAutomaticThreshold::RobustAutomaticThreshold(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + RobustAutomaticThresholdInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +RobustAutomaticThreshold::~RobustAutomaticThreshold() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> RobustAutomaticThreshold::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RobustAutomaticThreshold.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RobustAutomaticThreshold.hpp new file mode 100644 index 0000000000..e7f3b64ad8 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RobustAutomaticThreshold.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + RobustAutomaticThresholdInputValues inputValues; + inputValues.CreatedMaskName = filterArgs.value(created_mask_name); + inputValues.GradientArrayPath = filterArgs.value(gradient_array_path); + inputValues.InputArrayPath = filterArgs.value(input_array_path); + return RobustAutomaticThreshold(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT RobustAutomaticThresholdInputValues +{ + DataObjectNameParameter::ValueType CreatedMaskName; + ArraySelectionParameter::ValueType GradientArrayPath; + ArraySelectionParameter::ValueType InputArrayPath; +}; + +/** + * @class RobustAutomaticThreshold + * @brief This algorithm implements support code for the RobustAutomaticThresholdFilter + */ + +class SIMPLNXCORE_EXPORT RobustAutomaticThreshold +{ +public: + RobustAutomaticThreshold(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, RobustAutomaticThresholdInputValues* inputValues); + ~RobustAutomaticThreshold() noexcept; + + RobustAutomaticThreshold(const RobustAutomaticThreshold&) = delete; + RobustAutomaticThreshold(RobustAutomaticThreshold&&) noexcept = delete; + RobustAutomaticThreshold& operator=(const RobustAutomaticThreshold&) = delete; + RobustAutomaticThreshold& operator=(RobustAutomaticThreshold&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const RobustAutomaticThresholdInputValues* 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/RotateSampleRefFrame.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RotateSampleRefFrame.cpp new file mode 100644 index 0000000000..f9816530e5 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RotateSampleRefFrame.cpp @@ -0,0 +1,107 @@ +#include "RotateSampleRefFrame.hpp" + +#include "simplnx/Utilities/DataGroupUtilities.hpp" +#include "simplnx/Utilities/ImageRotationUtilities.hpp" +#include "simplnx/Utilities/ParallelAlgorithmUtilities.hpp" +#include "simplnx/Utilities/ParallelTaskAlgorithm.hpp" + +#include + +using namespace nx::core; + +namespace +{ +using RotationRepresentationType = RotateSampleRefFrame::RotationRepresentation; + +constexpr float32 k_Threshold = 0.01f; + +const Eigen::Vector3f k_XAxis = Eigen::Vector3f::UnitX(); +const Eigen::Vector3f k_YAxis = Eigen::Vector3f::UnitY(); +const Eigen::Vector3f k_ZAxis = Eigen::Vector3f::UnitZ(); + +} // namespace + +// ----------------------------------------------------------------------------- +RotateSampleRefFrame::RotateSampleRefFrame(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, RotateSampleRefFrameInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +RotateSampleRefFrame::~RotateSampleRefFrame() noexcept = default; + +// ----------------------------------------------------------------------------- +void RotateSampleRefFrame::updateProgress(const std::string& message) +{ + m_MessageHandler(IFilter::Message::Type::Info, message); +} + +// ----------------------------------------------------------------------------- +const std::atomic_bool& RotateSampleRefFrame::getCancel() +{ + return m_ShouldCancel; +} + +// ----------------------------------------------------------------------------- +Result<> RotateSampleRefFrame::operator()() +{ + auto& srcImageGeom = m_DataStructure.getDataRefAs(m_InputValues->SourceGeometryPath); + auto& destImageGeom = m_DataStructure.getDataRefAs(m_InputValues->DestGeometryPath); + + ImageRotationUtilities::Matrix4fR rotationMatrix; + + switch(static_cast(m_InputValues->RotationRepresentationIndex)) + { + case RotationRepresentationType::AxisAngle: { + rotationMatrix = ImageRotationUtilities::GenerateRotationTransformationMatrix(m_InputValues->RotationAxisAngle); + break; + } + case RotationRepresentationType::RotationMatrix: { + rotationMatrix = ImageRotationUtilities::GenerateManualTransformationMatrix(m_InputValues->RotationMatrixTable); + break; + } + } + + ImageRotationUtilities::RotateArgs rotateArgs = ImageRotationUtilities::CreateRotationArgs(srcImageGeom, rotationMatrix); + + auto selectedCellDataChildren = GetAllChildArrayDataPaths(m_DataStructure, srcImageGeom.getCellDataPath()); + auto selectedCellArrays = selectedCellDataChildren.has_value() ? selectedCellDataChildren.value() : std::vector{}; + + ImageRotationUtilities::FilterProgressCallback filterProgressCallback(m_MessageHandler, m_ShouldCancel); + + // The actual rotating of the dataStructure arrays is done in parallel where parallel here + // refers to the cropping of each DataArray being done on a separate thread. + ParallelTaskAlgorithm taskRunner; + taskRunner.setParallelizationEnabled(true); + const DataPath srcCelLDataAMPath = srcImageGeom.getCellDataPath(); + const auto& srcCellDataAM = srcImageGeom.getCellDataRef(); + + const DataPath destCellDataAMPath = destImageGeom.getCellDataPath(); + + for(const auto& [dataId, srcDataObject] : srcCellDataAM) + { + if(m_ShouldCancel) + { + return {}; + } + + const auto* srcDataArray = m_DataStructure.getDataAs(srcCelLDataAMPath.createChildPath(srcDataObject->getName())); + auto* destDataArray = m_DataStructure.getDataAs(destCellDataAMPath.createChildPath(srcDataObject->getName())); + m_MessageHandler(fmt::format("Rotating Volume || Copying Data Array {}", srcDataObject->getName())); + + ExecuteParallelFunction(srcDataArray->getDataType(), taskRunner, srcDataArray, destDataArray, rotateArgs, rotationMatrix, + m_InputValues->SliceBySlice, &filterProgressCallback); + } + + taskRunner.wait(); // This will spill over if the number of DataArrays to process does not divide evenly by the number of threads. + + if(m_InputValues->KeepInputGeometryOrigin) + { + destImageGeom.setOrigin(srcImageGeom.getOrigin()); + } + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RotateSampleRefFrame.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RotateSampleRefFrame.hpp new file mode 100644 index 0000000000..33432a5401 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RotateSampleRefFrame.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ChoicesParameter.hpp" +#include "simplnx/Parameters/DynamicTableParameter.hpp" +#include "simplnx/Parameters/VectorParameter.hpp" + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT RotateSampleRefFrameInputValues +{ + bool SliceBySlice; + ChoicesParameter::ValueType RotationRepresentationIndex; + DataPath SourceGeometryPath; + DataPath DestGeometryPath; + VectorFloat32Parameter::ValueType RotationAxisAngle; + DynamicTableParameter::ValueType RotationMatrixTable; + bool KeepInputGeometryOrigin; +}; + +/** + * @class + */ +class SIMPLNXCORE_EXPORT RotateSampleRefFrame +{ +public: + RotateSampleRefFrame(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, RotateSampleRefFrameInputValues* inputValues); + ~RotateSampleRefFrame() noexcept; + + RotateSampleRefFrame(const RotateSampleRefFrame&) = delete; + RotateSampleRefFrame(RotateSampleRefFrame&&) noexcept = delete; + RotateSampleRefFrame& operator=(const RotateSampleRefFrame&) = delete; + RotateSampleRefFrame& operator=(RotateSampleRefFrame&&) noexcept = delete; + + enum class RotationRepresentation : uint64 + { + AxisAngle = 0, + RotationMatrix = 1 + }; + + Result<> operator()(); + void updateProgress(const std::string& message); + const std::atomic_bool& getCancel(); + +private: + DataStructure& m_DataStructure; + const RotateSampleRefFrameInputValues* 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/SetImageGeomOriginScaling.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/SetImageGeomOriginScaling.cpp new file mode 100644 index 0000000000..78c4aef766 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/SetImageGeomOriginScaling.cpp @@ -0,0 +1,26 @@ +#include "SetImageGeomOriginScaling.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +SetImageGeomOriginScaling::SetImageGeomOriginScaling(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + SetImageGeomOriginScalingInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +SetImageGeomOriginScaling::~SetImageGeomOriginScaling() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> SetImageGeomOriginScaling::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/SetImageGeomOriginScaling.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/SetImageGeomOriginScaling.hpp new file mode 100644 index 0000000000..fbe133d0b3 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/SetImageGeomOriginScaling.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" +#include "simplnx/Parameters/VectorParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + SetImageGeomOriginScalingInputValues inputValues; + inputValues.CenterOrigin = filterArgs.value(center_origin); + inputValues.ChangeOrigin = filterArgs.value(change_origin); + inputValues.ChangeSpacing = filterArgs.value(change_spacing); + inputValues.InputImageGeometryPath = filterArgs.value(input_image_geometry_path); + inputValues.Origin = filterArgs.value(origin); + inputValues.Spacing = filterArgs.value(spacing); + return SetImageGeomOriginScaling(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT SetImageGeomOriginScalingInputValues +{ + BoolParameter::ValueType CenterOrigin; + BoolParameter::ValueType ChangeOrigin; + BoolParameter::ValueType ChangeSpacing; + GeometrySelectionParameter::ValueType InputImageGeometryPath; + VectorFloat32Parameter::ValueType Origin; + VectorFloat32Parameter::ValueType Spacing; +}; + +/** + * @class SetImageGeomOriginScaling + * @brief This algorithm implements support code for the SetImageGeomOriginScalingFilter + */ + +class SIMPLNXCORE_EXPORT SetImageGeomOriginScaling +{ +public: + SetImageGeomOriginScaling(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, SetImageGeomOriginScalingInputValues* inputValues); + ~SetImageGeomOriginScaling() noexcept; + + SetImageGeomOriginScaling(const SetImageGeomOriginScaling&) = delete; + SetImageGeomOriginScaling(SetImageGeomOriginScaling&&) noexcept = delete; + SetImageGeomOriginScaling& operator=(const SetImageGeomOriginScaling&) = delete; + SetImageGeomOriginScaling& operator=(SetImageGeomOriginScaling&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const SetImageGeomOriginScalingInputValues* 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/TriangleDihedralAngle.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/TriangleDihedralAngle.cpp new file mode 100644 index 0000000000..d249e38a72 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/TriangleDihedralAngle.cpp @@ -0,0 +1,26 @@ +#include "TriangleDihedralAngle.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +TriangleDihedralAngle::TriangleDihedralAngle(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + TriangleDihedralAngleInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +TriangleDihedralAngle::~TriangleDihedralAngle() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> TriangleDihedralAngle::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/TriangleDihedralAngle.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/TriangleDihedralAngle.hpp new file mode 100644 index 0000000000..2c1d522a38 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/TriangleDihedralAngle.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + TriangleDihedralAngleInputValues inputValues; + inputValues.InputTriangleGeometryPath = filterArgs.value(input_triangle_geometry_path); + inputValues.SurfaceMeshTriangleDihedralAnglesArrayName = filterArgs.value(surface_mesh_triangle_dihedral_angles_array_name); + return TriangleDihedralAngle(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT TriangleDihedralAngleInputValues +{ + GeometrySelectionParameter::ValueType InputTriangleGeometryPath; + DataObjectNameParameter::ValueType SurfaceMeshTriangleDihedralAnglesArrayName; +}; + +/** + * @class TriangleDihedralAngle + * @brief This algorithm implements support code for the TriangleDihedralAngleFilter + */ + +class SIMPLNXCORE_EXPORT TriangleDihedralAngle +{ +public: + TriangleDihedralAngle(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, TriangleDihedralAngleInputValues* inputValues); + ~TriangleDihedralAngle() noexcept; + + TriangleDihedralAngle(const TriangleDihedralAngle&) = delete; + TriangleDihedralAngle(TriangleDihedralAngle&&) noexcept = delete; + TriangleDihedralAngle& operator=(const TriangleDihedralAngle&) = delete; + TriangleDihedralAngle& operator=(TriangleDihedralAngle&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const TriangleDihedralAngleInputValues* 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/TriangleNormal.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/TriangleNormal.cpp new file mode 100644 index 0000000000..aa1edad686 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/TriangleNormal.cpp @@ -0,0 +1,25 @@ +#include "TriangleNormal.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +TriangleNormal::TriangleNormal(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, TriangleNormalInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +TriangleNormal::~TriangleNormal() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> TriangleNormal::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/TriangleNormal.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/TriangleNormal.hpp new file mode 100644 index 0000000000..c43974cb22 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/TriangleNormal.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + TriangleNormalInputValues inputValues; + inputValues.InputTriangleGeometryPath = filterArgs.value(input_triangle_geometry_path); + inputValues.OutputNormalsArrayName = filterArgs.value(output_normals_array_name); + return TriangleNormal(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT TriangleNormalInputValues +{ + GeometrySelectionParameter::ValueType InputTriangleGeometryPath; + DataObjectNameParameter::ValueType OutputNormalsArrayName; +}; + +/** + * @class TriangleNormal + * @brief This algorithm implements support code for the TriangleNormalFilter + */ + +class SIMPLNXCORE_EXPORT TriangleNormal +{ +public: + TriangleNormal(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, TriangleNormalInputValues* inputValues); + ~TriangleNormal() noexcept; + + TriangleNormal(const TriangleNormal&) = delete; + TriangleNormal(TriangleNormal&&) noexcept = delete; + TriangleNormal& operator=(const TriangleNormal&) = delete; + TriangleNormal& operator=(TriangleNormal&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const TriangleNormalInputValues* 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/WriteASCIIData.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteASCIIData.cpp new file mode 100644 index 0000000000..a278c81c8d --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteASCIIData.cpp @@ -0,0 +1,25 @@ +#include "WriteASCIIData.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +WriteASCIIData::WriteASCIIData(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, WriteASCIIDataInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +WriteASCIIData::~WriteASCIIData() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> WriteASCIIData::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteASCIIData.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteASCIIData.hpp new file mode 100644 index 0000000000..e316812496 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteASCIIData.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ChoicesParameter.hpp" +#include "simplnx/Parameters/FileSystemPathParameter.hpp" +#include "simplnx/Parameters/MultiArraySelectionParameter.hpp" +#include "simplnx/Parameters/NumberParameter.hpp" +#include "simplnx/Parameters/StringParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + WriteASCIIDataInputValues inputValues; + inputValues.DelimiterIndex = filterArgs.value(delimiter_index); + inputValues.FileExtension = filterArgs.value(file_extension); + inputValues.HeaderOptionIndex = filterArgs.value(header_option_index); + inputValues.InputDataArrayPaths = filterArgs.value(input_data_array_paths); + inputValues.MaxValPerLine = filterArgs.value(max_val_per_line); + inputValues.OutputDir = filterArgs.value(output_dir); + inputValues.OutputPath = filterArgs.value(output_path); + inputValues.OutputStyleIndex = filterArgs.value(output_style_index); + return WriteASCIIData(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT WriteASCIIDataInputValues +{ + ChoicesParameter::ValueType DelimiterIndex; + StringParameter::ValueType FileExtension; + ChoicesParameter::ValueType HeaderOptionIndex; + MultiArraySelectionParameter::ValueType InputDataArrayPaths; + Int32Parameter::ValueType MaxValPerLine; + FileSystemPathParameter::ValueType OutputDir; + FileSystemPathParameter::ValueType OutputPath; + ChoicesParameter::ValueType OutputStyleIndex; +}; + +/** + * @class WriteASCIIData + * @brief This algorithm implements support code for the WriteASCIIDataFilter + */ + +class SIMPLNXCORE_EXPORT WriteASCIIData +{ +public: + WriteASCIIData(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, WriteASCIIDataInputValues* inputValues); + ~WriteASCIIData() noexcept; + + WriteASCIIData(const WriteASCIIData&) = delete; + WriteASCIIData(WriteASCIIData&&) noexcept = delete; + WriteASCIIData& operator=(const WriteASCIIData&) = delete; + WriteASCIIData& operator=(WriteASCIIData&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const WriteASCIIDataInputValues* 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/WriteBinaryData.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteBinaryData.cpp new file mode 100644 index 0000000000..8e5488160c --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteBinaryData.cpp @@ -0,0 +1,25 @@ +#include "WriteBinaryData.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +WriteBinaryData::WriteBinaryData(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, WriteBinaryDataInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +WriteBinaryData::~WriteBinaryData() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> WriteBinaryData::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteBinaryData.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteBinaryData.hpp new file mode 100644 index 0000000000..741d9325f0 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteBinaryData.hpp @@ -0,0 +1,60 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ChoicesParameter.hpp" +#include "simplnx/Parameters/FileSystemPathParameter.hpp" +#include "simplnx/Parameters/MultiArraySelectionParameter.hpp" +#include "simplnx/Parameters/StringParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + WriteBinaryDataInputValues inputValues; + inputValues.EndianIndex = filterArgs.value(endian_index); + inputValues.FileExtension = filterArgs.value(file_extension); + inputValues.InputDataArrayPaths = filterArgs.value(input_data_array_paths); + inputValues.OutputPath = filterArgs.value(output_path); + return WriteBinaryData(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT WriteBinaryDataInputValues +{ + ChoicesParameter::ValueType EndianIndex; + StringParameter::ValueType FileExtension; + MultiArraySelectionParameter::ValueType InputDataArrayPaths; + FileSystemPathParameter::ValueType OutputPath; +}; + +/** + * @class WriteBinaryData + * @brief This algorithm implements support code for the WriteBinaryDataFilter + */ + +class SIMPLNXCORE_EXPORT WriteBinaryData +{ +public: + WriteBinaryData(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, WriteBinaryDataInputValues* inputValues); + ~WriteBinaryData() noexcept; + + WriteBinaryData(const WriteBinaryData&) = delete; + WriteBinaryData(WriteBinaryData&&) noexcept = delete; + WriteBinaryData& operator=(const WriteBinaryData&) = delete; + WriteBinaryData& operator=(WriteBinaryData&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const WriteBinaryDataInputValues* 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/WriteDREAM3D.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteDREAM3D.cpp new file mode 100644 index 0000000000..ea626df893 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteDREAM3D.cpp @@ -0,0 +1,25 @@ +#include "WriteDREAM3D.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +WriteDREAM3D::WriteDREAM3D(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, WriteDREAM3DInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +WriteDREAM3D::~WriteDREAM3D() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> WriteDREAM3D::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteDREAM3D.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteDREAM3D.hpp new file mode 100644 index 0000000000..427b9891f5 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteDREAM3D.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/FileSystemPathParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + WriteDREAM3DInputValues inputValues; + inputValues.ExportFilePath = filterArgs.value(export_file_path); + inputValues.WriteXdmfFile = filterArgs.value(write_xdmf_file); + return WriteDREAM3D(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT WriteDREAM3DInputValues +{ + FileSystemPathParameter::ValueType ExportFilePath; + BoolParameter::ValueType WriteXdmfFile; +}; + +/** + * @class WriteDREAM3D + * @brief This algorithm implements support code for the WriteDREAM3DFilter + */ + +class SIMPLNXCORE_EXPORT WriteDREAM3D +{ +public: + WriteDREAM3D(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, WriteDREAM3DInputValues* inputValues); + ~WriteDREAM3D() noexcept; + + WriteDREAM3D(const WriteDREAM3D&) = delete; + WriteDREAM3D(WriteDREAM3D&&) noexcept = delete; + WriteDREAM3D& operator=(const WriteDREAM3D&) = delete; + WriteDREAM3D& operator=(WriteDREAM3D&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const WriteDREAM3DInputValues* 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/WriteFeatureDataCSV.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteFeatureDataCSV.cpp new file mode 100644 index 0000000000..d46c6a8736 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteFeatureDataCSV.cpp @@ -0,0 +1,25 @@ +#include "WriteFeatureDataCSV.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +WriteFeatureDataCSV::WriteFeatureDataCSV(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, WriteFeatureDataCSVInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +WriteFeatureDataCSV::~WriteFeatureDataCSV() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> WriteFeatureDataCSV::operator()() +{ + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteFeatureDataCSV.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteFeatureDataCSV.hpp new file mode 100644 index 0000000000..e2b024dcb0 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteFeatureDataCSV.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/AttributeMatrixSelectionParameter.hpp" +#include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/ChoicesParameter.hpp" +#include "simplnx/Parameters/FileSystemPathParameter.hpp" + +/** +* This is example code to put in the Execute Method of the filter. + WriteFeatureDataCSVInputValues inputValues; + inputValues.CellFeatureAttributeMatrixPath = filterArgs.value(cell_feature_attribute_matrix_path); + inputValues.DelimiterIndex = filterArgs.value(delimiter_index); + inputValues.FeatureDataFile = filterArgs.value(feature_data_file); + inputValues.WriteNeighborlistData = filterArgs.value(write_neighborlist_data); + inputValues.WriteNumFeaturesLine = filterArgs.value(write_num_features_line); + return WriteFeatureDataCSV(dataStructure, messageHandler, shouldCancel, &inputValues)(); + +*/ + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT WriteFeatureDataCSVInputValues +{ + AttributeMatrixSelectionParameter::ValueType CellFeatureAttributeMatrixPath; + ChoicesParameter::ValueType DelimiterIndex; + FileSystemPathParameter::ValueType FeatureDataFile; + BoolParameter::ValueType WriteNeighborlistData; + BoolParameter::ValueType WriteNumFeaturesLine; +}; + +/** + * @class WriteFeatureDataCSV + * @brief This algorithm implements support code for the WriteFeatureDataCSVFilter + */ + +class SIMPLNXCORE_EXPORT WriteFeatureDataCSV +{ +public: + WriteFeatureDataCSV(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, WriteFeatureDataCSVInputValues* inputValues); + ~WriteFeatureDataCSV() noexcept; + + WriteFeatureDataCSV(const WriteFeatureDataCSV&) = delete; + WriteFeatureDataCSV(WriteFeatureDataCSV&&) noexcept = delete; + WriteFeatureDataCSV& operator=(const WriteFeatureDataCSV&) = delete; + WriteFeatureDataCSV& operator=(WriteFeatureDataCSV&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const WriteFeatureDataCSVInputValues* 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/AlignGeometriesFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/AlignGeometriesFilter.cpp index aace5cb1ef..e02ca19486 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/AlignGeometriesFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/AlignGeometriesFilter.cpp @@ -1,371 +1,17 @@ #include "AlignGeometriesFilter.hpp" -#include "simplnx/DataStructure/Geometry/EdgeGeom.hpp" -#include "simplnx/DataStructure/Geometry/INodeGeometry2D.hpp" -#include "simplnx/DataStructure/Geometry/INodeGeometry3D.hpp" -#include "simplnx/DataStructure/Geometry/ImageGeom.hpp" -#include "simplnx/DataStructure/Geometry/RectGridGeom.hpp" -#include "simplnx/DataStructure/Geometry/VertexGeom.hpp" +#include "Algorithms/AlignGeometries.hpp" + #include "simplnx/Filter/Actions/CreateArrayAction.hpp" #include "simplnx/Parameters/ChoicesParameter.hpp" #include "simplnx/Parameters/DataGroupSelectionParameter.hpp" #include "simplnx/Parameters/GeometrySelectionParameter.hpp" - #include "simplnx/Utilities/SIMPLConversion.hpp" #include using namespace nx::core; -namespace -{ -FloatVec3 extractOrigin(const IGeometry& geometry) -{ - auto geomType = geometry.getGeomType(); - switch(geomType) - { - case IGeometry::Type::Image: { - auto& image = dynamic_cast(geometry); - return image.getOrigin(); - } - case IGeometry::Type::RectGrid: { - auto& rectGrid = dynamic_cast(geometry); - const auto& xBounds = rectGrid.getXBounds()->getDataStoreRef(); - const auto& yBounds = rectGrid.getYBounds()->getDataStoreRef(); - const auto& zBounds = rectGrid.getZBounds()->getDataStoreRef(); - FloatVec3 origin(std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()); - for(size_t i = 0; i < xBounds.getNumberOfTuples(); i++) - { - if(xBounds[i] < origin[0]) - { - origin[0] = xBounds[i]; - } - } - for(size_t i = 0; i < yBounds.getNumberOfTuples(); i++) - { - if(yBounds[i] < origin[1]) - { - origin[1] = yBounds[i]; - } - } - for(size_t i = 0; i < zBounds.getNumberOfTuples(); i++) - { - if(zBounds[i] < origin[2]) - { - origin[2] = zBounds[i]; - } - } - return origin; - } - case IGeometry::Type::Vertex: { - auto& vertex = dynamic_cast(geometry); - const auto& vertices = vertex.getVertices()->getDataStoreRef(); - FloatVec3 origin(std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()); - - for(size_t i = 0; i < vertex.getNumberOfVertices(); i++) - { - for(size_t j = 0; j < 3; j++) - { - if(vertices[3 * i + j] < origin[j]) - { - origin[j] = vertices[3 * i + j]; - } - } - } - return origin; - } - case IGeometry::Type::Edge: { - const auto& edge = dynamic_cast(geometry); - const auto& vertices = edge.getVertices()->getDataStoreRef(); - FloatVec3 origin(std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()); - - for(size_t i = 0; i < edge.getNumberOfVertices(); i++) - { - for(size_t j = 0; j < 3; j++) - { - if(vertices[3 * i + j] < origin[j]) - { - origin[j] = vertices[3 * i + j]; - } - } - } - return origin; - } - // 2D - case IGeometry::Type::Triangle: - [[fallthrough]]; - case IGeometry::Type::Quad: { - const auto& geometry2d = dynamic_cast(geometry); - const auto& vertices = geometry2d.getVertices()->getDataStoreRef(); - FloatVec3 origin(std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()); - - for(size_t i = 0; i < geometry2d.getNumberOfVertices(); i++) - { - for(size_t j = 0; j < 3; j++) - { - if(vertices[3 * i + j] < origin[j]) - { - origin[j] = vertices[3 * i + j]; - } - } - } - return origin; - } - // 3D - case IGeometry::Type::Hexahedral: - [[fallthrough]]; - case IGeometry::Type::Tetrahedral: { - const auto& geometry3d = dynamic_cast(geometry); - const auto& vertices = geometry3d.getVertices()->getDataStoreRef(); - FloatVec3 origin(std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()); - - for(size_t i = 0; i < geometry3d.getNumberOfVertices(); i++) - { - for(size_t j = 0; j < 3; j++) - { - if(vertices[3 * i + j] < origin[j]) - { - origin[j] = vertices[3 * i + j]; - } - } - } - return origin; - } - default: - break; - } - - FloatVec3 origin(std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()); - return origin; -} - -FloatVec3 extractCentroid(const IGeometry& geometry) -{ - FloatVec3 centroid(0.0f, 0.0f, 0.0f); - switch(geometry.getGeomType()) - { - case IGeometry::Type::Image: { - const auto& image = dynamic_cast(geometry); - SizeVec3 dims = image.getDimensions(); - FloatVec3 origin = image.getOrigin(); - FloatVec3 res = image.getSpacing(); - - centroid[0] = (static_cast(dims[0]) * res[0] / 2.0f) + origin[0]; - centroid[1] = (static_cast(dims[1]) * res[1] / 2.0f) + origin[1]; - centroid[2] = (static_cast(dims[2]) * res[2] / 2.0f) + origin[2]; - return centroid; - } - case IGeometry::Type::RectGrid: { - const auto& rectGrid = dynamic_cast(geometry); - const auto& xBounds = rectGrid.getXBounds()->getDataStoreRef(); - const auto& yBounds = rectGrid.getYBounds()->getDataStoreRef(); - const auto& zBounds = rectGrid.getZBounds()->getDataStoreRef(); - float min[3] = {std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()}; - float max[3] = {std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min()}; - for(size_t i = 0; i < xBounds.getNumberOfTuples(); i++) - { - if(xBounds[i] < min[0]) - { - min[0] = xBounds[i]; - } - if(xBounds[i] > max[0]) - { - max[0] = xBounds[i]; - } - } - for(size_t i = 0; i < yBounds.getNumberOfTuples(); i++) - { - if(yBounds[i] < min[1]) - { - min[1] = yBounds[i]; - } - if(yBounds[i] > max[1]) - { - max[1] = yBounds[i]; - } - } - for(size_t i = 0; i < zBounds.getNumberOfTuples(); i++) - { - if(zBounds[i] < min[2]) - { - min[2] = zBounds[i]; - } - if(zBounds[i] > max[2]) - { - max[2] = zBounds[i]; - } - } - centroid[0] = (max[0] - min[0]) / 2.0f; - centroid[1] = (max[1] - min[1]) / 2.0f; - centroid[2] = (max[2] - min[2]) / 2.0f; - return centroid; - } - case IGeometry::Type::Vertex: { - const auto& vertex = dynamic_cast(geometry); - const auto& vertices = vertex.getVertices()->getDataStoreRef(); - centroid[0] = 0.0f; - centroid[1] = 0.0f; - centroid[2] = 0.0f; - for(size_t i = 0; i < vertex.getNumberOfVertices(); i++) - { - centroid[0] += vertices[3 * i + 0]; - centroid[1] += vertices[3 * i + 1]; - centroid[2] += vertices[3 * i + 2]; - } - centroid[0] /= static_cast(vertex.getNumberOfVertices()); - centroid[1] /= static_cast(vertex.getNumberOfVertices()); - centroid[2] /= static_cast(vertex.getNumberOfVertices()); - return centroid; - } - case IGeometry::Type::Edge: { - const auto& edge = dynamic_cast(geometry); - const auto& vertices = edge.getVertices()->getDataStoreRef(); - centroid[0] = 0.0f; - centroid[1] = 0.0f; - centroid[2] = 0.0f; - for(size_t i = 0; i < edge.getNumberOfVertices(); i++) - { - centroid[0] += vertices[3 * i + 0]; - centroid[1] += vertices[3 * i + 1]; - centroid[2] += vertices[3 * i + 2]; - } - centroid[0] /= static_cast(edge.getNumberOfVertices()); - centroid[1] /= static_cast(edge.getNumberOfVertices()); - centroid[2] /= static_cast(edge.getNumberOfVertices()); - return centroid; - } - // 2D Types - case IGeometry::Type::Triangle: - [[fallthrough]]; - case IGeometry::Type::Quad: { - auto& geometry2d = dynamic_cast(geometry); - const auto& vertices = geometry2d.getVertices()->getDataStoreRef(); - centroid[0] = 0.0f; - centroid[1] = 0.0f; - centroid[2] = 0.0f; - for(size_t i = 0; i < geometry2d.getNumberOfVertices(); i++) - { - centroid[0] += vertices[3 * i + 0]; - centroid[1] += vertices[3 * i + 1]; - centroid[2] += vertices[3 * i + 2]; - } - centroid[0] /= static_cast(geometry2d.getNumberOfVertices()); - centroid[1] /= static_cast(geometry2d.getNumberOfVertices()); - centroid[2] /= static_cast(geometry2d.getNumberOfVertices()); - return centroid; - } - // 3D Types - case IGeometry::Type::Hexahedral: - [[fallthrough]]; - case IGeometry::Type::Tetrahedral: { - const auto& geometry3d = dynamic_cast(geometry); - const auto& vertices = geometry3d.getVertices()->getDataStoreRef(); - centroid[0] = 0.0f; - centroid[1] = 0.0f; - centroid[2] = 0.0f; - for(size_t i = 0; i < geometry3d.getNumberOfVertices(); i++) - { - centroid[0] += vertices[3 * i + 0]; - centroid[1] += vertices[3 * i + 1]; - centroid[2] += vertices[3 * i + 2]; - } - centroid[0] /= static_cast(geometry3d.getNumberOfVertices()); - centroid[1] /= static_cast(geometry3d.getNumberOfVertices()); - centroid[2] /= static_cast(geometry3d.getNumberOfVertices()); - return centroid; - } - } - - return centroid; -} - -void translateGeometry(IGeometry& geometry, const FloatVec3& translation) -{ - switch(geometry.getGeomType()) - { - case IGeometry::Type::Image: { - auto& image = dynamic_cast(geometry); - FloatVec3 origin = image.getOrigin(); - origin[0] += translation[0]; - origin[1] += translation[1]; - origin[2] += translation[2]; - image.setOrigin(origin); - return; - } - case IGeometry::Type::RectGrid: { - auto& rectGrid = dynamic_cast(geometry); - auto& xBounds = rectGrid.getXBounds()->getDataStoreRef(); - auto& yBounds = rectGrid.getYBounds()->getDataStoreRef(); - auto& zBounds = rectGrid.getZBounds()->getDataStoreRef(); - for(size_t i = 0; i < rectGrid.getNumXCells(); i++) - { - xBounds[i] += translation[0]; - } - for(size_t i = 0; i < rectGrid.getNumYCells(); i++) - { - yBounds[i] += translation[1]; - } - for(size_t i = 0; i < rectGrid.getNumZCells(); i++) - { - zBounds[i] += translation[2]; - } - return; - } - case IGeometry::Type::Vertex: { - auto& vertex = dynamic_cast(geometry); - auto& vertices = vertex.getVertices()->getDataStoreRef(); - for(size_t i = 0; i < vertex.getNumberOfVertices(); i++) - { - vertices[3 * i + 0] += translation[0]; - vertices[3 * i + 1] += translation[1]; - vertices[3 * i + 2] += translation[2]; - } - return; - } - case IGeometry::Type::Edge: { - auto& edge = dynamic_cast(geometry); - auto& vertices = edge.getVertices()->getDataStoreRef(); - for(size_t i = 0; i < edge.getNumberOfVertices(); i++) - { - vertices[3 * i + 0] += translation[0]; - vertices[3 * i + 1] += translation[1]; - vertices[3 * i + 2] += translation[2]; - } - return; - } - // 2D Geometries - case IGeometry::Type::Quad: - [[fallthrough]]; - case IGeometry::Type::Triangle: { - auto& geometry2d = dynamic_cast(geometry); - auto& vertices = geometry2d.getVertices()->getDataStoreRef(); - for(size_t i = 0; i < geometry2d.getNumberOfVertices(); i++) - { - vertices[3 * i + 0] += translation[0]; - vertices[3 * i + 1] += translation[1]; - vertices[3 * i + 2] += translation[2]; - } - return; - } - // 3D Geometries - case IGeometry::Type::Hexahedral: - [[fallthrough]]; - case IGeometry::Type::Tetrahedral: { - auto& geometry3d = dynamic_cast(geometry); - auto& vertices = geometry3d.getVertices()->getDataStoreRef(); - for(size_t i = 0; i < geometry3d.getNumberOfVertices(); i++) - { - vertices[3 * i + 0] += translation[0]; - vertices[3 * i + 1] += translation[1]; - vertices[3 * i + 2] += translation[2]; - } - return; - } - } -} - -} // namespace - namespace nx::core { @@ -445,36 +91,12 @@ IFilter::PreflightResult AlignGeometriesFilter::preflightImpl(const DataStructur Result<> AlignGeometriesFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { - auto movingGeometryPath = filterArgs.value(k_MovingGeometry_Key); - auto targetGeometryPath = filterArgs.value(k_TargetGeometry_Key); - auto alignmentType = filterArgs.value(k_AlignmentType_Key); - - auto& moving = dataStructure.getDataRefAs(movingGeometryPath); - auto& target = dataStructure.getDataRefAs(targetGeometryPath); - - if(alignmentType == 0) - { - FloatVec3 movingOrigin = extractOrigin(moving); - FloatVec3 targetOrigin = extractOrigin(target); - - float translation[3] = {targetOrigin[0] - movingOrigin[0], targetOrigin[1] - movingOrigin[1], targetOrigin[2] - movingOrigin[2]}; - translateGeometry(moving, translation); - } - else if(alignmentType == 1) - { - FloatVec3 movingCentroid = extractCentroid(moving); - FloatVec3 targetCentroid = extractCentroid(target); - - float translation[3] = {targetCentroid[0] - movingCentroid[0], targetCentroid[0] - movingCentroid[0], targetCentroid[0] - movingCentroid[0]}; - translateGeometry(moving, translation); - } - else - { - std::string ss = fmt::format("Invalid selection for alignment type"); - return {MakeErrorResult<>(-1, ss)}; - } + AlignGeometriesInputValues inputValues; + inputValues.AlignmentTypeIndex = filterArgs.value(k_AlignmentType_Key); + inputValues.InputMovingGeometryPath = filterArgs.value(k_MovingGeometry_Key); + inputValues.InputTargetGeometryPath = filterArgs.value(k_TargetGeometry_Key); - return {}; + return AlignGeometries(dataStructure, messageHandler, shouldCancel, &inputValues)(); } namespace diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ApproximatePointCloudHullFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ApproximatePointCloudHullFilter.cpp index 8254bfe90e..39ede348d0 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ApproximatePointCloudHullFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ApproximatePointCloudHullFilter.cpp @@ -1,31 +1,19 @@ #include "ApproximatePointCloudHullFilter.hpp" -#include "simplnx/DataStructure/Geometry/ImageGeom.hpp" -#include "simplnx/DataStructure/Geometry/VertexGeom.hpp" +#include "SimplnxCore/Filters/Algorithms/ApproximatePointCloudHull.hpp" + #include "simplnx/Filter/Actions/CreateVertexGeometryAction.hpp" #include "simplnx/Parameters/DataGroupCreationParameter.hpp" #include "simplnx/Parameters/DataGroupSelectionParameter.hpp" #include "simplnx/Parameters/GeometrySelectionParameter.hpp" #include "simplnx/Parameters/NumberParameter.hpp" #include "simplnx/Parameters/VectorParameter.hpp" - #include "simplnx/Utilities/SIMPLConversion.hpp" #include namespace nx::core { -namespace -{ -bool validNeighbor(const SizeVec3& dims, const int64 neighborhood[78], usize index, int64 x, int64 y, int64 z) -{ - int64 modX = x + neighborhood[3 * index + 0]; - int64 modY = y + neighborhood[3 * index + 1]; - int64 modZ = z + neighborhood[3 * index + 2]; - - return (modX >= 0 && modX < dims[0]) && (modY >= 0 && modY < dims[1]) && (modZ >= 0 && modZ < dims[2]); -} -} // namespace //------------------------------------------------------------------------------ std::string ApproximatePointCloudHullFilter::name() const @@ -116,194 +104,13 @@ IFilter::PreflightResult ApproximatePointCloudHullFilter::preflightImpl(const Da Result<> ApproximatePointCloudHullFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { - auto gridResolution = filterArgs.value>(k_GridResolution_Key); - auto numberOfEmptyNeighbors = filterArgs.value(k_MinEmptyNeighbors_Key); - auto vertexGeomPath = filterArgs.value(k_VertexGeomPath_Key); - auto hullVertexGeomPath = filterArgs.value(k_HullVertexGeomPath_Key); - - float inverseResolution[3] = {1.0f / gridResolution[0], 1.0f / gridResolution[1], 1.0f / gridResolution[2]}; - - auto* source = dataStructure.getDataAs(vertexGeomPath); - auto* verts = source->getVertices(); - - DataStructure temp; - auto* samplingGrid = ImageGeom::Create(temp, "Image Geometry"); - samplingGrid->setSpacing(gridResolution[0], gridResolution[1], gridResolution[2]); - - usize numVerts = source->getNumberOfVertices(); - auto& vertex = source->getVertices()->getDataStoreRef(); - - std::vector meshMaxExtents; - std::vector meshMinExtents; - - for(usize i = 0; i < 3; i++) - { - meshMaxExtents.push_back(std::numeric_limits::lowest()); - meshMinExtents.push_back(std::numeric_limits::max()); - } - - for(int64 i = 0; i < numVerts; i++) - { - if(vertex[3 * i] > meshMaxExtents[0]) - { - meshMaxExtents[0] = vertex[3 * i]; - } - if(vertex[3 * i + 1] > meshMaxExtents[1]) - { - meshMaxExtents[1] = vertex[3 * i + 1]; - } - if(vertex[3 * i + 2] > meshMaxExtents[2]) - { - meshMaxExtents[2] = vertex[3 * i + 2]; - } - if(vertex[3 * i] < meshMinExtents[0]) - { - meshMinExtents[0] = vertex[3 * i]; - } - if(vertex[3 * i + 1] < meshMinExtents[1]) - { - meshMinExtents[1] = vertex[3 * i + 1]; - } - if(vertex[3 * i + 2] < meshMinExtents[2]) - { - meshMinExtents[2] = vertex[3 * i + 2]; - } - } - - for(auto i = 0; i < 3; i++) - { - meshMinExtents[i] -= (inverseResolution[i] / 2.0f); - meshMaxExtents[i] += (inverseResolution[i] / 2.0f); - } - - int64 bboxMin[3] = {0, 0, 0}; - int64 bboxMax[3] = {0, 0, 0}; - - bboxMin[0] = static_cast(std::floor(meshMinExtents[0] * inverseResolution[0])); - bboxMin[1] = static_cast(std::floor(meshMinExtents[1] * inverseResolution[1])); - bboxMin[2] = static_cast(std::floor(meshMinExtents[2] * inverseResolution[2])); - - bboxMax[0] = static_cast(std::floor(meshMaxExtents[0] * inverseResolution[0])); - bboxMax[1] = static_cast(std::floor(meshMaxExtents[1] * inverseResolution[1])); - bboxMax[2] = static_cast(std::floor(meshMaxExtents[2] * inverseResolution[2])); - - auto dims1 = static_cast(bboxMax[0] - bboxMin[0] + 1); - auto dims2 = static_cast(bboxMax[1] - bboxMin[1] + 1); - auto dims3 = static_cast(bboxMax[2] - bboxMin[2] + 1); - SizeVec3 dims(std::vector{dims1, dims2, dims3}); - samplingGrid->setDimensions(dims); - - int64 multiplier[3] = {1, static_cast(samplingGrid->getNumXCells()), static_cast(samplingGrid->getNumXCells() * samplingGrid->getNumYCells())}; - std::vector> vertsInVoxels(samplingGrid->getNumberOfCells()); - - int64 progIncrement = numVerts / 100; - int64 prog = 1; - int64 progressInt = 0; - - for(int64 v = 0; v < numVerts; v++) - { - auto i = static_cast(std::floor((*verts)[3 * v + 0] * inverseResolution[0]) - static_cast(bboxMin[0])); - auto j = static_cast(std::floor((*verts)[3 * v + 1] * inverseResolution[1]) - static_cast(bboxMin[1])); - auto k = static_cast(std::floor((*verts)[3 * v + 2] * inverseResolution[2]) - static_cast(bboxMin[2])); - int64 index = i * multiplier[0] + j * multiplier[1] + k * multiplier[2]; - vertsInVoxels[index].push_back(v); - - if(v > prog) - { - progressInt = static_cast((static_cast(v) / numVerts) * 100.0f); - std::string ss = fmt::format("Mapping Vertices to Voxels || {}% Complete", progressInt); - // notifyStatusMessage(ss); - prog = prog + progIncrement; - } - } - - std::vector tmpVerts; - int64 neighborhood[78] = {1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1, 1, 1, 0, -1, 1, 0, 1, -1, 0, -1, -1, 0, 1, 0, 1, 1, 0, -1, -1, 0, 1, - -1, 0, -1, 0, 1, 1, 0, 1, -1, 0, -1, 1, 0, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1}; - - progIncrement = (dims[0] * dims[1] * dims[2]) / 100; - prog = 1; - progressInt = 0; - int64 counter = 0; - int64 vertCounter = 0; - float xAvg = 0.0f; - float yAvg = 0.0f; - float zAvg = 0.0f; - - for(int64 z = 0; z < dims[2]; z++) - { - for(int64 y = 0; y < dims[1]; y++) - { - for(int64 x = 0; x < dims[0]; x++) - { - usize index = (z * dims[1] * dims[0]) + (y * dims[0]) + x; - if(vertsInVoxels[index].empty()) - { - counter++; - continue; - } - - usize emtpyNeighbors = 0; - - for(usize n = 0; n < 26; n++) - { - if(validNeighbor(dims, neighborhood, n, x, y, z)) - { - usize neighborIndex = ((z + neighborhood[3 * n + 2]) * dims[1] * dims[0]) + ((y + neighborhood[3 * n + 1]) * dims[0]) + (x + neighborhood[3 * n + 0]); - if(vertsInVoxels[neighborIndex].empty()) - { - emtpyNeighbors++; - } - } - } - - if(emtpyNeighbors > numberOfEmptyNeighbors) - { - for(auto vert : vertsInVoxels[index]) - { - vertCounter++; - xAvg += (*verts)[3 * vert + 0]; - yAvg += (*verts)[3 * vert + 1]; - zAvg += (*verts)[3 * vert + 2]; - } - xAvg /= static_cast(vertCounter); - yAvg /= static_cast(vertCounter); - zAvg /= static_cast(vertCounter); - tmpVerts.push_back(xAvg); - tmpVerts.push_back(yAvg); - tmpVerts.push_back(zAvg); - vertCounter = 0; - xAvg = 0.0f; - yAvg = 0.0f; - zAvg = 0.0f; - } - - if(counter > prog) - { - progressInt = static_cast((static_cast(counter) / (dims[0] * dims[1] * dims[2])) * 100.0f); - std::string ss = fmt::format("Trimming Interior Voxels || {}% Complete", progressInt); - // notifyStatusMessage(ss); - prog = prog + progIncrement; - } - counter++; - } - } - } - - auto* hull = dataStructure.getDataAs(hullVertexGeomPath); - hull->resizeVertexList(tmpVerts.size() / 3); - if(hull->getVertexAttributeMatrix() != nullptr) - { - hull->getVertexAttributeMatrix()->resizeTuples({tmpVerts.size() / 3}); - } - auto* hullVerts = hull->getVertices(); - auto tmpVertData = tmpVerts.data(); - for(usize i = 0; i < hull->getNumberOfVertices() * 3; i++) - { - (*hullVerts)[i] = tmpVertData[i]; - } + ApproximatePointCloudHullInputValues inputValues; + inputValues.GridResolution = filterArgs.value(k_GridResolution_Key); + inputValues.InputVertexGeometryPath = filterArgs.value(k_VertexGeomPath_Key); + inputValues.MinEmptyNeighbors = filterArgs.value(k_MinEmptyNeighbors_Key); + inputValues.OutputVertexGeometryPath = filterArgs.value(k_HullVertexGeomPath_Key); - return {}; + return ApproximatePointCloudHull(dataStructure, messageHandler, shouldCancel, &inputValues)(); } namespace diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeBoundaryElementFractionsFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeBoundaryElementFractionsFilter.cpp index 7cbd5b26d8..5cdd4631ec 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeBoundaryElementFractionsFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeBoundaryElementFractionsFilter.cpp @@ -1,15 +1,14 @@ #include "ComputeBoundaryElementFractionsFilter.hpp" +#include "SimplnxCore/Filters/Algorithms/ComputeBoundaryElementFractions.hpp" + #include "simplnx/DataStructure/AttributeMatrix.hpp" -#include "simplnx/DataStructure/DataArray.hpp" #include "simplnx/DataStructure/DataPath.hpp" #include "simplnx/Filter/Actions/CreateArrayAction.hpp" #include "simplnx/Parameters/ArraySelectionParameter.hpp" #include "simplnx/Parameters/AttributeMatrixSelectionParameter.hpp" - -#include "simplnx/Utilities/SIMPLConversion.hpp" - #include "simplnx/Parameters/DataObjectNameParameter.hpp" +#include "simplnx/Utilities/SIMPLConversion.hpp" using namespace nx::core; @@ -107,31 +106,14 @@ IFilter::PreflightResult ComputeBoundaryElementFractionsFilter::preflightImpl(co Result<> ComputeBoundaryElementFractionsFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { - auto& featureIds = dataStructure.getDataRefAs(filterArgs.value(k_FeatureIdsArrayPath_Key)); - auto& boundaryCells = dataStructure.getDataRefAs(filterArgs.value(k_BoundaryCellsArrayPath_Key)); - auto& boundaryCellFractions = - dataStructure.getDataRefAs(filterArgs.value(k_FeatureDataAMPath_Key).createChildPath(filterArgs.value(k_BoundaryCellFractionsArrayName_Key))); - - usize totalPoints = featureIds.getNumberOfTuples(); - usize numFeatures = boundaryCellFractions.getNumberOfTuples(); - - std::vector surfVoxCounts(numFeatures, 0); - std::vector voxCounts(numFeatures, 0); - - for(usize j = 0; j < totalPoints; j++) - { - int32 gnum = featureIds[j]; - voxCounts[gnum]++; - if(boundaryCells[j] > 0) - { - surfVoxCounts[gnum]++; - } - } - for(usize i = 1; i < numFeatures; i++) - { - boundaryCellFractions[i] = surfVoxCounts[i] / voxCounts[i]; - } - return {}; + ComputeBoundaryElementFractionsInputValues inputValues; + // Replace the keys below with the variables from the header. + inputValues.BoundaryCellFractionsArrayName = filterArgs.value(k_BoundaryCellFractionsArrayName_Key); + inputValues.BoundaryCellsArrayPath = filterArgs.value(k_BoundaryCellsArrayPath_Key); + inputValues.FeatureDataAttributeMatrixPath = filterArgs.value(k_FeatureDataAMPath_Key); + inputValues.FeatureIdsArrayPath = filterArgs.value(k_FeatureIdsArrayPath_Key); + + return ComputeBoundaryElementFractions(dataStructure, messageHandler, shouldCancel, &inputValues)(); } namespace diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeDifferencesMapFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeDifferencesMapFilter.cpp index 448c6a644c..ebab74c7a7 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeDifferencesMapFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeDifferencesMapFilter.cpp @@ -1,20 +1,20 @@ #include "ComputeDifferencesMapFilter.hpp" +#include "SimplnxCore/Filters/Algorithms/ComputeDifferencesMap.hpp" + #include "simplnx/DataStructure/AbstractDataStore.hpp" #include "simplnx/DataStructure/DataArray.hpp" #include "simplnx/Filter/Actions/CreateArrayAction.hpp" #include "simplnx/Parameters/ArrayCreationParameter.hpp" #include "simplnx/Parameters/ArraySelectionParameter.hpp" -#include "simplnx/Utilities/FilterUtilities.hpp" - -#include - #include "simplnx/Utilities/SIMPLConversion.hpp" +#include #include namespace nx::core { + namespace { constexpr int32 k_MissingInputArray = -567; @@ -76,32 +76,6 @@ WarningCollection warnOnUnsignedTypes(const DataStructure& dataStructure, const return results; } -struct ExecuteFindDifferenceMapFunctor -{ - template - void operator()(IDataArray* firstArrayPtr, IDataArray* secondArrayPtr, IDataArray* differenceMapPtr) - { - using store_type = AbstractDataStore; - - auto& firstArray = firstArrayPtr->template getIDataStoreRefAs(); - auto& secondArray = secondArrayPtr->template getIDataStoreRefAs(); - auto& differenceMap = differenceMapPtr->template getIDataStoreRefAs(); - - usize numTuples = firstArray.getNumberOfTuples(); - int32 numComps = firstArray.getNumberOfComponents(); - - for(usize i = 0; i < numTuples; i++) - { - for(int32 j = 0; j < numComps; j++) - { - auto firstVal = firstArray[numComps * i + j]; - auto secondVal = secondArray[numComps * i + j]; - auto diffVal = firstVal > secondVal ? firstVal - secondVal : secondVal - firstVal; - differenceMap[numComps * i + j] = diffVal; - } - } - } -}; } // namespace //------------------------------------------------------------------------------ @@ -233,11 +207,12 @@ IFilter::PreflightResult ComputeDifferencesMapFilter::preflightImpl(const DataSt Result<> ComputeDifferencesMapFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { - auto* firstInputArray = dataStructure.getDataAs(filterArgs.value(k_FirstInputArrayPath_Key)); - auto* secondInputArray = dataStructure.getDataAs(filterArgs.value(k_SecondInputArrayPath_Key)); - auto* differenceMapArray = dataStructure.getDataAs(filterArgs.value(k_DifferenceMapArrayPath_Key)); + ComputeDifferencesMapInputValues inputValues; - ExecuteDataFunction(ExecuteFindDifferenceMapFunctor{}, firstInputArray->getDataType(), firstInputArray, secondInputArray, differenceMapArray); + inputValues.DifferenceMapArrayPath = filterArgs.value(k_DifferenceMapArrayPath_Key); + inputValues.FirstInputArrayPath = filterArgs.value(k_FirstInputArrayPath_Key); + inputValues.SecondInputArrayPath = filterArgs.value(k_SecondInputArrayPath_Key); + return ComputeDifferencesMap(dataStructure, messageHandler, shouldCancel, &inputValues)(); return {}; } diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeFeatureSizesFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeFeatureSizesFilter.cpp index 874989f50c..1311cf5337 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeFeatureSizesFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeFeatureSizesFilter.cpp @@ -1,8 +1,8 @@ #include "ComputeFeatureSizesFilter.hpp" -#include "simplnx/Common/Numbers.hpp" +#include "SimplnxCore/Filters/Algorithms/ComputeFeatureSizes.hpp" + #include "simplnx/DataStructure/DataArray.hpp" -#include "simplnx/DataStructure/Geometry/ImageGeom.hpp" #include "simplnx/Filter/Actions/CreateArrayAction.hpp" #include "simplnx/Parameters/ArraySelectionParameter.hpp" #include "simplnx/Parameters/AttributeMatrixSelectionParameter.hpp" @@ -13,8 +13,6 @@ #include "simplnx/Utilities/DataArrayUtilities.hpp" #include "simplnx/Utilities/SIMPLConversion.hpp" -#include - namespace nx::core { namespace @@ -22,8 +20,6 @@ namespace constexpr nx::core::int32 k_MissingGeometry = -73225; 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 ComputeFeatureSizesFilter::name() const @@ -144,154 +140,15 @@ IFilter::PreflightResult ComputeFeatureSizesFilter::preflightImpl(const DataStru Result<> ComputeFeatureSizesFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { - auto saveElementSizes = filterArgs.value(k_SaveElementSizes_Key); - - auto featureIdsArrayPath = filterArgs.value(k_CellFeatureIdsArrayPath_Key); - auto featureIdsArrayPtr = dataStructure.getDataAs(featureIdsArrayPath); - const auto& featureIdsStoreRef = featureIdsArrayPtr->getDataStoreRef(); - { - auto featureAttributeMatrixPath = filterArgs.value(k_CellFeatureAttributeMatrixPath_Key); - auto validateNumFeatResult = ValidateFeatureIdsToFeatureAttributeMatrixIndexing(dataStructure, featureAttributeMatrixPath, *featureIdsArrayPtr, false, messageHandler); - if(validateNumFeatResult.invalid()) - { - return validateNumFeatResult; - } - } - usize totalPoints = featureIdsStoreRef.getNumberOfTuples(); - - auto geomPath = filterArgs.value(k_GeometryPath_Key); - auto* geom = dataStructure.getDataAs(geomPath); - - // If the geometry is an ImageGeometry or a RectilinearGeometry - auto* imageGeom = dynamic_cast(geom); - if(nullptr != imageGeom) - { - auto featureAttributeMatrixPath = filterArgs.value(k_CellFeatureAttributeMatrixPath_Key); - - auto& volumes = dataStructure.getDataAs(featureAttributeMatrixPath.createChildPath(filterArgs.value(k_VolumesName_Key)))->getDataStoreRef(); - auto& equivalentDiameters = dataStructure.getDataAs(featureAttributeMatrixPath.createChildPath(filterArgs.value(k_EquivalentDiametersName_Key)))->getDataStoreRef(); - auto& numElements = dataStructure.getDataAs(featureAttributeMatrixPath.createChildPath(filterArgs.value(k_NumElementsName_Key)))->getDataStoreRef(); - - usize featureIdsMaxIdx = std::distance(featureIdsStoreRef.begin(), std::max_element(featureIdsStoreRef.cbegin(), featureIdsStoreRef.cend())); - usize maxValue = featureIdsStoreRef[featureIdsMaxIdx]; - usize numFeatures = maxValue + 1; - - std::vector featureCounts(numFeatures, 0); - - for(size_t j = 0; j < totalPoints; j++) - { - int32_t gnum = featureIdsStoreRef[j]; - auto temp = featureCounts[gnum] + 1; - featureCounts[gnum] = temp; - } - - FloatVec3 spacing = imageGeom->getSpacing(); - - if(imageGeom->getNumXCells() == 1 || imageGeom->getNumYCells() == 1 || imageGeom->getNumZCells() == 1) - { - float res_scalar = 0.0f; - if(imageGeom->getNumXCells() == 1) - { - res_scalar = spacing[1] * spacing[2]; - } - else if(imageGeom->getNumYCells() == 1) - { - res_scalar = spacing[0] * spacing[2]; - } - else if(imageGeom->getNumZCells() == 1) - { - res_scalar = spacing[0] * spacing[1]; - } - - for(size_t i = 1; i < numFeatures; i++) - { - numElements[i] = static_cast(featureCounts[i]); - if(featureCounts[i] > 9007199254740992ULL) - { - std::string ss = fmt::format("Number of voxels belonging to feature {} ({}) is greater than 9007199254740992", i, featureCounts[i]); - return MakeErrorResult(k_BadFeatureCount, ss); - } - volumes[i] = static_cast(featureCounts[i]) * static_cast(res_scalar); - - float32 rad = volumes[i] / k_PI; - float32 diameter = (2 * sqrtf(rad)); - equivalentDiameters[i] = diameter; - } - } - else - { - float32 res_scalar = spacing[0] * spacing[1] * spacing[2]; - float vol_term = (4.0f / 3.0f) * k_PI; - for(usize i = 1; i < numFeatures; i++) - { - numElements[i] = static_cast(featureCounts[i]); - if(featureCounts[i] > 9007199254740992ULL) - { - std::string ss = fmt::format("Number of voxels belonging to feature {} ({}) is greater than 9007199254740992", i, featureCounts[i]); - return MakeErrorResult(k_BadFeatureCount, ss); - } - - volumes[i] = static_cast(featureCounts[i]) * static_cast(res_scalar); - - float32 rad = volumes[i] / vol_term; - float32 diameter = 2.0f * powf(rad, 0.3333333333f); - equivalentDiameters[i] = diameter; - } - } - - if(saveElementSizes) - { - int32 err = imageGeom->findElementSizes(false); - if(err < 0) - { - std::string ss = fmt::format("Error computing Element sizes for Geometry type {}", imageGeom->getTypeName()); - return MakeErrorResult(err, ss); - } - } - } - else - { - auto& volumes = dataStructure.getDataAs(filterArgs.value(k_VolumesName_Key))->getDataStoreRef(); - auto& equivalentDiameters = dataStructure.getDataAs(filterArgs.value(k_EquivalentDiametersName_Key))->getDataStoreRef(); - auto& numElements = dataStructure.getDataAs(filterArgs.value(k_NumElementsName_Key))->getDataStoreRef(); - - usize numFeatures = volumes.getNumberOfTuples(); - - int32_t err = geom->findElementSizes(false); - if(err < 0) - { - std::string ss = fmt::format("Error computing Element sizes for Geometry type {}", geom->getTypeName()); - return MakeErrorResult(err, ss); - } - - const Float32Array* elemSizes = geom->getElementSizes(); - - std::vector featureCounts(numFeatures, 1); - - for(size_t j = 0; j < totalPoints; j++) - { - int32 gnum = featureIdsStoreRef[j]; - auto temp = featureCounts[gnum] + 1; - featureCounts[gnum] = temp; - auto temp2 = volumes[gnum]; - volumes[gnum] = temp2 + (*elemSizes)[j]; - } - float vol_term = (4.0f / 3.0f) * k_PI; - for(size_t i = 1; i < numFeatures; i++) - { - numElements[i] = static_cast(featureCounts[i]); - float rad = volumes[i] / vol_term; - float diameter = 2.0f * powf(rad, 0.3333333333f); - equivalentDiameters[i] = diameter; - } - - if(!saveElementSizes) - { - geom->deleteElementSizes(); - } - } - - return {}; + ComputeFeatureSizesInputValues inputValues; + inputValues.EquivalentDiametersName = filterArgs.value(k_EquivalentDiametersName_Key); + inputValues.FeatureAttributeMatrixPath = filterArgs.value(k_CellFeatureAttributeMatrixPath_Key); + inputValues.FeatureIdsPath = filterArgs.value(k_CellFeatureIdsArrayPath_Key); + inputValues.InputImageGeometryPath = filterArgs.value(k_GeometryPath_Key); + inputValues.NumElementsName = filterArgs.value(k_NumElementsName_Key); + inputValues.SaveElementSizes = filterArgs.value(k_SaveElementSizes_Key); + inputValues.VolumesName = filterArgs.value(k_VolumesName_Key); + return ComputeFeatureSizes(dataStructure, messageHandler, shouldCancel, &inputValues)(); } namespace diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeSurfaceFeaturesFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeSurfaceFeaturesFilter.cpp index bb156ca67a..0ab8a52f62 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeSurfaceFeaturesFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ComputeSurfaceFeaturesFilter.cpp @@ -1,196 +1,21 @@ #include "ComputeSurfaceFeaturesFilter.hpp" -#include -#include "simplnx/Common/Array.hpp" +#include "SimplnxCore/Filters/Algorithms/ComputeSurfaceFeatures.hpp" + #include "simplnx/DataStructure/DataPath.hpp" #include "simplnx/DataStructure/Geometry/ImageGeom.hpp" #include "simplnx/Filter/Actions/CreateArrayAction.hpp" #include "simplnx/Parameters/ArraySelectionParameter.hpp" #include "simplnx/Parameters/AttributeMatrixSelectionParameter.hpp" #include "simplnx/Parameters/BoolParameter.hpp" +#include "simplnx/Parameters/DataGroupSelectionParameter.hpp" #include "simplnx/Parameters/DataObjectNameParameter.hpp" #include "simplnx/Parameters/GeometrySelectionParameter.hpp" - -#include "simplnx/Utilities/SIMPLConversion.hpp" - #include "simplnx/Utilities/DataArrayUtilities.hpp" +#include "simplnx/Utilities/SIMPLConversion.hpp" using namespace nx::core; -namespace -{ -bool IsPointASurfaceFeature(const Point2D& point, usize xPoints, usize yPoints, bool markFeature0Neighbors, const Int32AbstractDataStore& featureIds) -{ - const usize yStride = point.getY() * xPoints; - - if(point.getX() <= 0 || point.getX() >= xPoints - 1) - { - return true; - } - if(point.getY() <= 0 || point.getY() >= yPoints - 1) - { - return true; - } - - if(markFeature0Neighbors) - { - if(featureIds[yStride + point.getX() - 1] == 0) - { - return true; - } - if(featureIds[yStride + point.getX() + 1] == 0) - { - return true; - } - if(featureIds[yStride + point.getX() - xPoints] == 0) - { - return true; - } - if(featureIds[yStride + point.getX() + xPoints] == 0) - { - return true; - } - } - - return false; -} - -bool IsPointASurfaceFeature(const Point3D& point, usize xPoints, usize yPoints, usize zPoints, bool markFeature0Neighbors, const Int32AbstractDataStore& featureIds) -{ - usize yStride = point.getY() * xPoints; - usize zStride = point.getZ() * xPoints * yPoints; - - if(point.getX() <= 0 || point.getX() >= xPoints - 1) - { - return true; - } - if(point.getY() <= 0 || point.getY() >= yPoints - 1) - { - return true; - } - if(point.getZ() <= 0 || point.getZ() >= zPoints - 1) - { - return true; - } - - if(markFeature0Neighbors) - { - if(featureIds[zStride + yStride + point.getX() - 1] == 0) - { - return true; - } - if(featureIds[zStride + yStride + point.getX() + 1] == 0) - { - return true; - } - if(featureIds[zStride + yStride + point.getX() - xPoints] == 0) - { - return true; - } - if(featureIds[zStride + yStride + point.getX() + xPoints] == 0) - { - return true; - } - if(featureIds[zStride + yStride + point.getX() - (xPoints * yPoints)] == 0) - { - return true; - } - if(featureIds[zStride + yStride + point.getX() + (xPoints * yPoints)] == 0) - { - return true; - } - } - - return false; -} - -void findSurfaceFeatures3D(DataStructure& dataStructure, const DataPath& featureGeometryPathValue, const DataPath& featureIdsArrayPathValue, const DataPath& surfaceFeaturesArrayPathValue, - bool markFeature0Neighbors, const std::atomic_bool& shouldCancel) -{ - const auto& featureGeometry = dataStructure.getDataRefAs(featureGeometryPathValue); - const auto& featureIds = dataStructure.getDataAs(featureIdsArrayPathValue)->getDataStoreRef(); - auto& surfaceFeatures = dataStructure.getDataAs(surfaceFeaturesArrayPathValue)->getDataStoreRef(); - - const usize xPoints = featureGeometry.getNumXCells(); - const usize yPoints = featureGeometry.getNumYCells(); - const usize zPoints = featureGeometry.getNumZCells(); - - for(usize z = 0; z < zPoints; z++) - { - const usize zStride = z * xPoints * yPoints; - for(usize y = 0; y < yPoints; y++) - { - const usize yStride = y * xPoints; - for(usize x = 0; x < xPoints; x++) - { - if(shouldCancel) - { - return; - } - - const int32 gNum = featureIds[zStride + yStride + x]; - if(gNum != 0 && !surfaceFeatures[gNum]) - { - if(IsPointASurfaceFeature(Point3D{x, y, z}, xPoints, yPoints, zPoints, markFeature0Neighbors, featureIds)) - { - surfaceFeatures[gNum] = 1; - } - } - } - } - } -} - -void findSurfaceFeatures2D(DataStructure& dataStructure, const DataPath& featureGeometryPathValue, const DataPath& featureIdsArrayPathValue, const DataPath& surfaceFeaturesArrayPathValue, - bool markFeature0Neighbors, const std::atomic_bool& shouldCancel) -{ - const auto& featureGeometry = dataStructure.getDataRefAs(featureGeometryPathValue); - const auto& featureIds = dataStructure.getDataAs(featureIdsArrayPathValue)->getDataStoreRef(); - auto& surfaceFeatures = dataStructure.getDataAs(surfaceFeaturesArrayPathValue)->getDataStoreRef(); - - usize xPoints = 0; - usize yPoints = 0; - - if(featureGeometry.getNumXCells() == 1) - { - xPoints = featureGeometry.getNumYCells(); - yPoints = featureGeometry.getNumZCells(); - } - if(featureGeometry.getNumYCells() == 1) - { - xPoints = featureGeometry.getNumXCells(); - yPoints = featureGeometry.getNumZCells(); - } - if(featureGeometry.getNumZCells() == 1) - { - xPoints = featureGeometry.getNumXCells(); - yPoints = featureGeometry.getNumYCells(); - } - - for(usize y = 0; y < yPoints; y++) - { - const usize yStride = y * xPoints; - - for(usize x = 0; x < xPoints; x++) - { - if(shouldCancel) - { - return; - } - - const int32 gNum = featureIds[yStride + x]; - if(gNum != 0 && surfaceFeatures[gNum] == 0) - { - if(IsPointASurfaceFeature(Point2D{x, y}, xPoints, yPoints, markFeature0Neighbors, featureIds)) - { - surfaceFeatures[gNum] = 1; - } - } - } - } -} -} // namespace - namespace nx::core { //------------------------------------------------------------------------------ @@ -295,37 +120,13 @@ IFilter::PreflightResult ComputeSurfaceFeaturesFilter::preflightImpl(const DataS Result<> ComputeSurfaceFeaturesFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { - const auto pMarkFeature0NeighborsValue = filterArgs.value(k_MarkFeature0Neighbors); - const auto pFeatureGeometryPathValue = filterArgs.value(k_FeatureGeometryPath_Key); - const auto pFeatureIdsArrayPathValue = filterArgs.value(k_CellFeatureIdsArrayPath_Key); - const auto pFeaturesAttributeMatrixPathValue = filterArgs.value(k_CellFeatureAttributeMatrixPath_Key); - const auto pSurfaceFeaturesArrayPathValue = pFeaturesAttributeMatrixPathValue.createChildPath(filterArgs.value(k_SurfaceFeaturesArrayName_Key)); - - // Resize the surface features array to the proper size - const auto& featureIdsArray = dataStructure.getDataRefAs(pFeatureIdsArrayPathValue); - - auto validateNumFeatResult = ValidateFeatureIdsToFeatureAttributeMatrixIndexing(dataStructure, pFeaturesAttributeMatrixPathValue, featureIdsArray, false, messageHandler); - if(validateNumFeatResult.invalid()) - { - return validateNumFeatResult; - } - - // Find surface features - const auto& featureGeometry = dataStructure.getDataRefAs(pFeatureGeometryPathValue); - if(const usize geometryDimensionality = featureGeometry.getDimensionality(); geometryDimensionality == 3) - { - findSurfaceFeatures3D(dataStructure, pFeatureGeometryPathValue, pFeatureIdsArrayPathValue, pSurfaceFeaturesArrayPathValue, pMarkFeature0NeighborsValue, shouldCancel); - } - else if(geometryDimensionality == 2) - { - findSurfaceFeatures2D(dataStructure, pFeatureGeometryPathValue, pFeatureIdsArrayPathValue, pSurfaceFeaturesArrayPathValue, pMarkFeature0NeighborsValue, shouldCancel); - } - else - { - MakeErrorResult(-1000, fmt::format("Image Geometry at path '{}' must be either 3D or 2D", pFeatureGeometryPathValue.toString())); - } - - return {}; + ComputeSurfaceFeaturesInputValues inputValues; + inputValues.FeatureAttributeMatrixPath = filterArgs.value(k_CellFeatureAttributeMatrixPath_Key); + inputValues.FeatureIdsPath = filterArgs.value(k_CellFeatureIdsArrayPath_Key); + inputValues.InputImageGeometryPath = filterArgs.value(k_FeatureGeometryPath_Key); + inputValues.MarkFeature0Neighbors = filterArgs.value(k_MarkFeature0Neighbors); + inputValues.SurfaceFeaturesArrayName = filterArgs.value(k_SurfaceFeaturesArrayName_Key); + return ComputeSurfaceFeatures(dataStructure, messageHandler, shouldCancel, &inputValues)(); } namespace diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ConditionalSetValueFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ConditionalSetValueFilter.cpp index dc1c97f5d9..1ef79ca0ff 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ConditionalSetValueFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ConditionalSetValueFilter.cpp @@ -1,12 +1,12 @@ #include "ConditionalSetValueFilter.hpp" +#include "SimplnxCore/Filters/Algorithms/ConditionalSetValue.hpp" + #include "simplnx/DataStructure/DataArray.hpp" #include "simplnx/DataStructure/DataPath.hpp" #include "simplnx/Parameters/ArraySelectionParameter.hpp" #include "simplnx/Parameters/BoolParameter.hpp" #include "simplnx/Parameters/StringParameter.hpp" -#include "simplnx/Utilities/DataArrayUtilities.hpp" -#include "simplnx/Utilities/FilterUtilities.hpp" #include "simplnx/Utilities/SIMPLConversion.hpp" #include "simplnx/Utilities/StringInterpretationUtilities.hpp" @@ -18,29 +18,7 @@ constexpr int32 k_EmptyParameterValue = -123; constexpr int32 k_IncorrectInputArrayType = -124; constexpr int32 k_ConvertReplaceValueTypeError = -125; constexpr int32 k_ConvertRemoveValueTypeError = -126; - -struct ReplaceValueInArrayFunctor -{ - template - void operator()(IDataArray& workingArray, const std::string& removeValue, const std::string& replaceValue) - { - auto& dataStore = workingArray.template getIDataStoreRefAs>(); - - ScalarType removeVal = StringInterpretationUtilities::Convert(removeValue).value(); - ScalarType replaceVal = StringInterpretationUtilities::Convert(replaceValue).value(); - - const auto size = dataStore.getNumberOfTuples() * dataStore.getNumberOfComponents(); - - for(usize index = 0; index < size; index++) - { - if(dataStore[index] == removeVal) - { - dataStore[index] = replaceVal; - } - } - } -}; -} // namespace +}; // namespace namespace nx::core { @@ -160,29 +138,15 @@ IFilter::PreflightResult ConditionalSetValueFilter::preflightImpl(const DataStru Result<> ConditionalSetValueFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { - auto useConditionalValue = filterArgs.value(k_UseConditional_Key); - auto replaceValueString = filterArgs.value(k_ReplaceValue_Key); - auto conditionalArrayPath = filterArgs.value(k_ConditionalArrayPath_Key); - auto selectedArrayPath = filterArgs.value(k_SelectedArrayPath_Key); - auto invertMask = filterArgs.value(k_InvertMask_Key); - - if(useConditionalValue) - { - DataObject& inputDataObject = dataStructure.getDataRef(selectedArrayPath); - - const IDataArray& conditionalArray = dataStructure.getDataRefAs(conditionalArrayPath); - - Result<> result = ConditionalReplaceValueInArray(replaceValueString, inputDataObject, conditionalArray, invertMask); + ConditionalSetValueInputValues inputValues; + inputValues.ConditionalArrayPath = filterArgs.value(k_ConditionalArrayPath_Key); + inputValues.InvertMask = filterArgs.value(k_InvertMask_Key); + inputValues.RemoveValue = filterArgs.value(k_RemoveValue_Key); + inputValues.ReplaceValue = filterArgs.value(k_ReplaceValue_Key); + inputValues.SelectedArrayPath = filterArgs.value(k_SelectedArrayPath_Key); + inputValues.UseConditional = filterArgs.value(k_UseConditional_Key); - return result; - } - else - { - auto& inputDataArray = dataStructure.getDataRefAs(selectedArrayPath); - ExecuteDataFunction(ReplaceValueInArrayFunctor{}, inputDataArray.getDataType(), inputDataArray, filterArgs.value(k_RemoveValue_Key), replaceValueString); - } - - return {}; + return ConditionalSetValue(dataStructure, messageHandler, shouldCancel, &inputValues)(); } namespace diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ExtractInternalSurfacesFromTriangleGeometryFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ExtractInternalSurfacesFromTriangleGeometryFilter.cpp index 58da93b692..f2da11ac77 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ExtractInternalSurfacesFromTriangleGeometryFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ExtractInternalSurfacesFromTriangleGeometryFilter.cpp @@ -1,23 +1,15 @@ #include "ExtractInternalSurfacesFromTriangleGeometryFilter.hpp" +#include "SimplnxCore/Filters/Algorithms/ExtractInternalSurfacesFromTriangleGeometry.hpp" + #include "simplnx/DataStructure/Geometry/TriangleGeom.hpp" #include "simplnx/Filter/Actions/CreateArrayAction.hpp" #include "simplnx/Filter/Actions/CreateGeometry2DAction.hpp" -#include "simplnx/Parameters/ArraySelectionParameter.hpp" -#include "simplnx/Parameters/DataGroupCreationParameter.hpp" #include "simplnx/Parameters/DataGroupSelectionParameter.hpp" -#include "simplnx/Parameters/DataObjectNameParameter.hpp" -#include "simplnx/Parameters/GeometrySelectionParameter.hpp" -#include "simplnx/Parameters/MultiArraySelectionParameter.hpp" -#include "simplnx/Parameters/VectorParameter.hpp" -#include "simplnx/Utilities/FilterUtilities.hpp" #include "simplnx/Utilities/SIMPLConversion.hpp" #include -#include -#include - using namespace nx::core; namespace @@ -28,65 +20,6 @@ constexpr int32 k_NoNodeTypesArray = -353; constexpr int32 k_MissingVertexArray = -354; constexpr int32 k_MissingTriangleArray = -355; -template -void hashCombine(usize& seed, const T& obj) -{ - std::hash hasher; - seed ^= hasher(obj) + 0x9e3779b9 + (seed << 6) + (seed >> 2); -} - -struct CopyDataFunctor -{ - template - void operator()(IDataArray* inDataPtr, IDataArray* outDataPtr, std::unordered_map& elementMap) const - { - auto& inputData = inDataPtr->template getIDataStoreRefAs>(); - auto& outputData = outDataPtr->template getIDataStoreRefAs>(); - - usize nTuples = outDataPtr->getNumberOfTuples(); - usize nComps = inDataPtr->getNumberOfComponents(); - usize tmpIndex = 0; - usize ptrIndex = 0; - - for(usize i = 0; i < nTuples; i++) - { - for(usize d = 0; d < nComps; d++) - { - tmpIndex = nComps * i + d; - ptrIndex = nComps * elementMap[i] + d; - outputData[tmpIndex] = inputData[ptrIndex]; - } - } - } -}; - -struct RemoveFlaggedVerticesFunctor -{ - // copy data to masked geometry - template - void operator()(IDataArray* inputDataPtr, IDataArray* outputDataArray, const std::vector& indexMapping) const - { - auto& inputData = inputDataPtr->template getIDataStoreRefAs>(); - auto& outputData = outputDataArray->template getIDataStoreRefAs>(); - usize nComps = inputData.getNumberOfComponents(); - IGeometry::MeshIndexType notSeen = std::numeric_limits::max(); - - for(usize i = 0; i < indexMapping.size(); i++) - { - IGeometry::MeshIndexType newIndex = indexMapping[i]; - if(newIndex != notSeen) - { - for(usize compIdx = 0; compIdx < nComps; compIdx++) - { - usize destinationIndex = newIndex * nComps + compIdx; - usize sourceIndex = i * nComps + compIdx; - outputData[destinationIndex] = inputData[sourceIndex]; - } - } - } - } -}; - } // namespace namespace nx::core @@ -285,149 +218,16 @@ IFilter::PreflightResult ExtractInternalSurfacesFromTriangleGeometryFilter::pref Result<> ExtractInternalSurfacesFromTriangleGeometryFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { - auto nodeTypesArrayPath = filterArgs.value(k_NodeTypesPath_Key); - auto triangleGeomPath = filterArgs.value(k_SelectedTriangleGeometryPath_Key); - auto internalTrianglesPath = filterArgs.value(k_CreatedTriangleGeometryPath_Key); - auto copyVertexPaths = filterArgs.value>(k_CopyVertexPaths_Key); - auto copyTrianglePaths = filterArgs.value>(k_CopyTrianglePaths_Key); - auto vertexDataName = filterArgs.value(k_VertexAttributeMatrixName_Key); - auto faceDataName = filterArgs.value(k_TriangleAttributeMatrixName_Key); - - auto minMaxNodeValues = filterArgs.value(k_NodeTypeRange_Key); - - auto& triangleGeom = dataStructure.getDataRefAs(triangleGeomPath); - auto& internalTriangleGeom = dataStructure.getDataRefAs(internalTrianglesPath); - auto& vertices = *triangleGeom.getVertices(); - auto& triangles = *triangleGeom.getFaces(); - auto numVerts = triangleGeom.getNumberOfVertices(); - auto numTris = triangleGeom.getNumberOfFaces(); - - auto& nodeTypes = dataStructure.getDataRefAs(nodeTypesArrayPath); - - auto internalVerticesPath = internalTrianglesPath.createChildPath(TriangleGeom::k_SharedVertexListName); - internalTriangleGeom.setVertices(*dataStructure.getDataAs(internalVerticesPath)); - - auto internalFacesPath = internalTrianglesPath.createChildPath(TriangleGeom::k_SharedFacesListName); - internalTriangleGeom.setFaceList(*dataStructure.getDataAs(internalFacesPath)); - - // int64 progIncrement = numTris / 100; - // int64 prog = 1; - // int64 progressInt = 0; - // int64 counter = 0; - using MeshIndexType = IGeometry::MeshIndexType; - - const MeshIndexType notSeen = std::numeric_limits::max(); - - std::vector vertNewIndex(numVerts, notSeen); - std::vector triNewIndex(numTris, notSeen); - MeshIndexType currentNewTriIndex = 0; - MeshIndexType currentNewVertIndex = 0; - - // Loop over all the triangles mapping the triangle and the vertices to the new array locations - for(MeshIndexType triIndex = 0; triIndex < numTris; triIndex++) - { - MeshIndexType v0Index = triangles[3 * triIndex + 0]; - MeshIndexType v1Index = triangles[3 * triIndex + 1]; - MeshIndexType v2Index = triangles[3 * triIndex + 2]; - // Check if the NodeType is either 2, 3, 4 - if((nodeTypes[v0Index] >= minMaxNodeValues[0] && nodeTypes[v0Index] <= minMaxNodeValues[1]) && (nodeTypes[v1Index] >= minMaxNodeValues[0] && nodeTypes[v1Index] <= minMaxNodeValues[1]) && - (nodeTypes[v2Index] >= minMaxNodeValues[0] && nodeTypes[v2Index] <= minMaxNodeValues[1])) - { - // All Nodes are the correct type - triNewIndex[triIndex] = currentNewTriIndex; - currentNewTriIndex++; // increment the index into which this triangle would be place in the new triangle array - // Now figure out if we have seen each vertex - if(vertNewIndex[v0Index] == notSeen) - { - vertNewIndex[v0Index] = currentNewVertIndex; - currentNewVertIndex++; - } - if(vertNewIndex[v1Index] == notSeen) - { - vertNewIndex[v1Index] = currentNewVertIndex; - currentNewVertIndex++; - } - if(vertNewIndex[v2Index] == notSeen) - { - vertNewIndex[v2Index] = currentNewVertIndex; - currentNewVertIndex++; - } - } - - if(shouldCancel) - { - return {}; - } - } - - // Resize the vertex and triangle arrays - internalTriangleGeom.resizeVertexList(currentNewVertIndex); - internalTriangleGeom.resizeFaceList(currentNewTriIndex); - internalTriangleGeom.getVertexAttributeMatrix()->resizeTuples({currentNewVertIndex}); - internalTriangleGeom.getFaceAttributeMatrix()->resizeTuples({currentNewTriIndex}); - - IGeometry::SharedVertexList* internalVerts = internalTriangleGeom.getVertices(); - IGeometry::SharedFaceList* internalTriangles = internalTriangleGeom.getFaces(); - - // Transfer the data from the old SharedVertexList to the new VertexList - for(MeshIndexType vertIndex = 0; vertIndex < numVerts; vertIndex++) - { - MeshIndexType mappedIndex = vertNewIndex[vertIndex]; - if(mappedIndex != notSeen) - { - // Get the actual XYZ coordinate - float x = vertices[vertIndex * 3 + 0]; - float y = vertices[vertIndex * 3 + 1]; - float z = vertices[vertIndex * 3 + 2]; - - (*internalVerts)[mappedIndex * 3 + 0] = x; - (*internalVerts)[mappedIndex * 3 + 1] = y; - (*internalVerts)[mappedIndex * 3 + 2] = z; - } - } - - // Transfer the data from the old SharedTriangleList to the new TriangleList - for(MeshIndexType triIndex = 0; triIndex < numTris; triIndex++) - { - MeshIndexType mappedIndex = triNewIndex[triIndex]; - if(mappedIndex != notSeen) - { - // Get the 3 original vertex indices for this triangle - MeshIndexType v0 = triangles[triIndex * 3 + 0]; - MeshIndexType v1 = triangles[triIndex * 3 + 1]; - MeshIndexType v2 = triangles[triIndex * 3 + 2]; - - MeshIndexType v0New = vertNewIndex[v0]; - MeshIndexType v1New = vertNewIndex[v1]; - MeshIndexType v2New = vertNewIndex[v2]; - - (*internalTriangles)[mappedIndex * 3 + 0] = v0New; - (*internalTriangles)[mappedIndex * 3 + 1] = v1New; - (*internalTriangles)[mappedIndex * 3 + 2] = v2New; - } - } - - // Copy any Vertex and Triangle DataArrays to extracted surface mesh - for(const auto& targetArrayPath : copyVertexPaths) - { - DataPath destinationPath = internalTrianglesPath.createChildPath(vertexDataName).createChildPath(targetArrayPath.getTargetName()); - auto* src = dataStructure.getDataAs(targetArrayPath); - auto* dest = dataStructure.getDataAs(destinationPath); - - ExecuteDataFunction(RemoveFlaggedVerticesFunctor{}, src->getDataType(), src, dest, vertNewIndex); - } - - for(const auto& targetArrayPath : copyTrianglePaths) - { - DataPath destinationPath = internalTrianglesPath.createChildPath(faceDataName).createChildPath(targetArrayPath.getTargetName()); - auto* src = dataStructure.getDataAs(targetArrayPath); - auto* dest = dataStructure.getDataAs(destinationPath); - dest->resizeTuples({currentNewTriIndex}); - - ExecuteDataFunction(RemoveFlaggedVerticesFunctor{}, src->getDataType(), src, dest, triNewIndex); - } - - return {}; + ExtractInternalSurfacesFromTriangleGeometryInputValues inputValues; + inputValues.CopyTriangleArrayPaths = filterArgs.value(k_CopyTrianglePaths_Key); + inputValues.CopyVertexArrayPaths = filterArgs.value(k_CopyVertexPaths_Key); + inputValues.InputTriangleGeometryPath = filterArgs.value(k_SelectedTriangleGeometryPath_Key); + inputValues.NodeTypeRange = filterArgs.value(k_NodeTypeRange_Key); + inputValues.NodeTypesPath = filterArgs.value(k_NodeTypesPath_Key); + inputValues.OutputTriangleGeometryPath = filterArgs.value(k_CreatedTriangleGeometryPath_Key); + inputValues.TriangleAttributeMatrixName = filterArgs.value(k_TriangleAttributeMatrixName_Key); + inputValues.VertexAttributeMatrixName = filterArgs.value(k_VertexAttributeMatrixName_Key); + return ExtractInternalSurfacesFromTriangleGeometry(dataStructure, messageHandler, shouldCancel, &inputValues)(); } namespace diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/IdentifySampleFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/IdentifySampleFilter.cpp index 9bb62bd26b..80bbeef583 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/IdentifySampleFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/IdentifySampleFilter.cpp @@ -1,416 +1,17 @@ #include "IdentifySampleFilter.hpp" +#include "SimplnxCore/Filters/Algorithms/IdentifySample.hpp" + #include "simplnx/DataStructure/DataArray.hpp" -#include "simplnx/DataStructure/Geometry/ImageGeom.hpp" #include "simplnx/Parameters/ArraySelectionParameter.hpp" #include "simplnx/Parameters/BoolParameter.hpp" #include "simplnx/Parameters/ChoicesParameter.hpp" #include "simplnx/Parameters/DataGroupSelectionParameter.hpp" #include "simplnx/Parameters/GeometrySelectionParameter.hpp" -#include "simplnx/Utilities/FilterUtilities.hpp" #include "simplnx/Utilities/SIMPLConversion.hpp" namespace nx::core { -namespace -{ -struct IdentifySampleFunctor -{ - template - void operator()(const ImageGeom* imageGeom, IDataArray* goodVoxelsPtr, bool fillHoles) - { - ShapeType cDims = {1}; - auto& goodVoxels = goodVoxelsPtr->template getIDataStoreRefAs>(); - - const auto totalPoints = static_cast(goodVoxelsPtr->getNumberOfTuples()); - - SizeVec3 uDims = imageGeom->getDimensions(); - - const int64 dims[3] = { - static_cast(uDims[0]), - static_cast(uDims[1]), - static_cast(uDims[2]), - }; - - int64 neighborPoints[6] = {0, 0, 0, 0, 0, 0}; - const int64 xp = dims[0]; - const int64 yp = dims[1]; - const int64 zp = dims[2]; - - neighborPoints[0] = -(xp * yp); - neighborPoints[1] = -xp; - neighborPoints[2] = -1; - neighborPoints[3] = 1; - neighborPoints[4] = xp; - neighborPoints[5] = (xp * yp); - std::vector currentVList; - std::vector checked(totalPoints, false); - std::vector sample(totalPoints, false); - int64 biggestBlock = 0; - - int64 neighbor = 0; - - // In this loop over the data we are finding the biggest contiguous set of GoodVoxels and calling that the 'sample' All GoodVoxels that do not touch the 'sample' - // are flipped to be called 'bad' voxels or 'not sample' - float threshold = 0.0f; - for(int64 i = 0; i < totalPoints; i++) - { - const float percentIncrement = static_cast(i) / static_cast(totalPoints) * 100.0f; - if(percentIncrement > threshold) - { - threshold = threshold + 5.0f; - if(threshold < percentIncrement) - { - threshold = percentIncrement; - } - } - - if(!checked[i] && goodVoxels.getValue(i)) - { - currentVList.push_back(i); - usize count = 0; - while(count < currentVList.size()) - { - int64 index = currentVList[count]; - int64 column = index % xp; - int64 row = (index / xp) % yp; - int64 plane = index / (xp * yp); - for(int32 j = 0; j < 6; j++) - { - int32 good = 1; - neighbor = index + neighborPoints[j]; - if(j == 0 && plane == 0) - { - good = 0; - } - if(j == 5 && plane == (zp - 1)) - { - good = 0; - } - if(j == 1 && row == 0) - { - good = 0; - } - if(j == 4 && row == (yp - 1)) - { - good = 0; - } - if(j == 2 && column == 0) - { - good = 0; - } - if(j == 3 && column == (xp - 1)) - { - good = 0; - } - if(good == 1 && !checked[neighbor] && goodVoxels.getValue(neighbor)) - { - currentVList.push_back(neighbor); - checked[neighbor] = true; - } - } - count++; - } - if(static_cast(currentVList.size()) >= biggestBlock) - { - biggestBlock = currentVList.size(); - sample.assign(totalPoints, false); - for(int64 j = 0; j < biggestBlock; j++) - { - sample[currentVList[j]] = true; - } - } - currentVList.clear(); - } - } - for(int64 i = 0; i < totalPoints; i++) - { - if(!sample[i] && goodVoxels.getValue(i)) - { - goodVoxels.setValue(i, false); - } - } - sample.clear(); - checked.assign(totalPoints, false); - - // In this loop we are going to 'close' all the 'holes' inside the region already identified as the 'sample' if the user chose to do so. - // This is done by flipping all 'bad' voxel features that do not touch the outside of the sample (i.e. they are fully contained inside the 'sample'). - threshold = 0.0F; - if(fillHoles) - { - bool touchesBoundary = false; - for(int64 i = 0; i < totalPoints; i++) - { - const float percentIncrement = static_cast(i) / static_cast(totalPoints) * 100.0f; - if(percentIncrement > threshold) - { - threshold = threshold + 5.0f; - if(threshold < percentIncrement) - { - threshold = percentIncrement; - } - } - - if(!checked[i] && !goodVoxels.getValue(i)) - { - currentVList.push_back(i); - usize count = 0; - touchesBoundary = false; - while(count < currentVList.size()) - { - int64 index = currentVList[count]; - int64 column = index % xp; - int64 row = (index / xp) % yp; - int64 plane = index / (xp * yp); - if(column == 0 || column == (xp - 1) || row == 0 || row == (yp - 1) || plane == 0 || plane == (zp - 1)) - { - touchesBoundary = true; - } - for(int32 j = 0; j < 6; j++) - { - int32 good = 1; - neighbor = index + neighborPoints[j]; - if(j == 0 && plane == 0) - { - good = 0; - } - if(j == 5 && plane == (zp - 1)) - { - good = 0; - } - if(j == 1 && row == 0) - { - good = 0; - } - if(j == 4 && row == (yp - 1)) - { - good = 0; - } - if(j == 2 && column == 0) - { - good = 0; - } - if(j == 3 && column == (xp - 1)) - { - good = 0; - } - if(good == 1 && !checked[neighbor] && !goodVoxels.getValue(neighbor)) - { - currentVList.push_back(neighbor); - checked[neighbor] = true; - } - } - count++; - } - if(!touchesBoundary) - { - for(int64_t j : currentVList) - { - goodVoxels.setValue(j, true); - } - } - currentVList.clear(); - } - } - } - checked.clear(); - } -}; - -struct IdentifySampleSliceBySliceFunctor -{ - enum class Plane - { - XY, - XZ, - YZ - }; - - template - void operator()(const ImageGeom* imageGeom, IDataArray* goodVoxelsPtr, bool fillHoles, Plane plane) - { - auto& goodVoxels = goodVoxelsPtr->template getIDataStoreRefAs>(); - - SizeVec3 uDims = imageGeom->getDimensions(); - const int64 dimX = static_cast(uDims[0]); - const int64 dimY = static_cast(uDims[1]); - const int64 dimZ = static_cast(uDims[2]); - - int64 planeDim1, planeDim2, fixedDim; - int64 stride1, stride2, fixedStride; - - switch(plane) - { - case Plane::XY: - planeDim1 = dimX; - planeDim2 = dimY; - fixedDim = dimZ; - stride1 = 1; - stride2 = dimX; - fixedStride = dimX * dimY; - break; - - case Plane::XZ: - planeDim1 = dimX; - planeDim2 = dimZ; - fixedDim = dimY; - stride1 = 1; - stride2 = dimX * dimY; - fixedStride = dimX; - break; - - case Plane::YZ: - planeDim1 = dimY; - planeDim2 = dimZ; - fixedDim = dimX; - stride1 = dimX; - stride2 = dimX * dimY; - fixedStride = 1; - break; - } - - for(int64 fixedIdx = 0; fixedIdx < fixedDim; ++fixedIdx) // Process each slice - { - std::vector checked(planeDim1 * planeDim2, false); - std::vector sample(planeDim1 * planeDim2, false); - std::vector currentVList; - int64 biggestBlock = 0; - - // Identify the largest contiguous set of good voxels in the slice - for(int64 p2 = 0; p2 < planeDim2; ++p2) - { - for(int64 p1 = 0; p1 < planeDim1; ++p1) - { - int64 planeIndex = p2 * planeDim1 + p1; - int64 globalIndex = fixedIdx * fixedStride + p2 * stride2 + p1 * stride1; - - if(!checked[planeIndex] && goodVoxels.getValue(globalIndex)) - { - currentVList.push_back(planeIndex); - int64 count = 0; - - while(count < currentVList.size()) - { - int64 localIdx = currentVList[count]; - int64 localP1 = localIdx % planeDim1; - int64 localP2 = localIdx / planeDim1; - - for(int j = 0; j < 4; ++j) - { - int64 dp1[4] = {0, 0, -1, 1}; - int64 dp2[4] = {-1, 1, 0, 0}; - - int64 neighborP1 = localP1 + dp1[j]; - int64 neighborP2 = localP2 + dp2[j]; - - if(neighborP1 >= 0 && neighborP1 < planeDim1 && neighborP2 >= 0 && neighborP2 < planeDim2) - { - int64 neighborIdx = neighborP2 * planeDim1 + neighborP1; - int64 globalNeighborIdx = fixedIdx * fixedStride + neighborP2 * stride2 + neighborP1 * stride1; - - if(!checked[neighborIdx] && goodVoxels.getValue(globalNeighborIdx)) - { - currentVList.push_back(neighborIdx); - checked[neighborIdx] = true; - } - } - } - count++; - } - - if(static_cast(currentVList.size()) > biggestBlock) - { - biggestBlock = currentVList.size(); - sample.assign(planeDim1 * planeDim2, false); - for(int64 idx : currentVList) - { - sample[idx] = true; - } - } - currentVList.clear(); - } - } - } - - for(int64 p2 = 0; p2 < planeDim2; ++p2) - { - for(int64 p1 = 0; p1 < planeDim1; ++p1) - { - int64 planeIndex = p2 * planeDim1 + p1; - int64 globalIndex = fixedIdx * fixedStride + p2 * stride2 + p1 * stride1; - - if(!sample[planeIndex]) - { - goodVoxels.setValue(globalIndex, false); - } - } - } - - if(fillHoles) - { - for(int64 p2 = 0; p2 < planeDim2; ++p2) - { - for(int64 p1 = 0; p1 < planeDim1; ++p1) - { - int64 planeIndex = p2 * planeDim1 + p1; - int64 globalIndex = fixedIdx * fixedStride + p2 * stride2 + p1 * stride1; - - if(!checked[planeIndex] && !goodVoxels.getValue(globalIndex)) - { - currentVList.push_back(planeIndex); - int64 count = 0; - bool touchesBoundary = false; - - while(count < currentVList.size()) - { - int64 localIdx = currentVList[count]; - int64 localP1 = localIdx % planeDim1; - int64 localP2 = localIdx / planeDim1; - - if(localP1 == 0 || localP1 == planeDim1 - 1 || localP2 == 0 || localP2 == planeDim2 - 1) - { - touchesBoundary = true; - } - - for(int j = 0; j < 4; ++j) - { - int64 dp1[4] = {0, 0, -1, 1}; - int64 dp2[4] = {-1, 1, 0, 0}; - - int64 neighborP1 = localP1 + dp1[j]; - int64 neighborP2 = localP2 + dp2[j]; - - if(neighborP1 >= 0 && neighborP1 < planeDim1 && neighborP2 >= 0 && neighborP2 < planeDim2) - { - int64 neighborIdx = neighborP2 * planeDim1 + neighborP1; - int64 globalNeighborIdx = fixedIdx * fixedStride + neighborP2 * stride2 + neighborP1 * stride1; - - if(!checked[neighborIdx] && !goodVoxels.getValue(globalNeighborIdx)) - { - currentVList.push_back(neighborIdx); - checked[neighborIdx] = true; - } - } - } - count++; - } - - if(!touchesBoundary) - { - for(int64 idx : currentVList) - { - goodVoxels.setValue(fixedIdx * fixedStride + idx, true); - } - } - currentVList.clear(); - } - } - } - } - } - } -}; -} // namespace //------------------------------------------------------------------------------ std::string IdentifySampleFilter::name() const @@ -507,25 +108,13 @@ IFilter::PreflightResult IdentifySampleFilter::preflightImpl(const DataStructure Result<> IdentifySampleFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { - const auto fillHoles = filterArgs.value(k_FillHoles_Key); - const auto sliceBySlice = filterArgs.value(k_SliceBySlice_Key); - const auto sliceBySlicePlane = static_cast(filterArgs.value(k_SliceBySlicePlane_Key)); - const auto imageGeomPath = filterArgs.value(k_SelectedImageGeometryPath_Key); - const auto goodVoxelsArrayPath = filterArgs.value(k_MaskArrayPath_Key); - - auto* inputData = dataStructure.getDataAs(goodVoxelsArrayPath); - const auto* imageGeom = dataStructure.getDataAs(imageGeomPath); - - if(sliceBySlice) - { - ExecuteDataFunction(IdentifySampleSliceBySliceFunctor{}, inputData->getDataType(), imageGeom, inputData, fillHoles, sliceBySlicePlane); - } - else - { - ExecuteDataFunction(IdentifySampleFunctor{}, inputData->getDataType(), imageGeom, inputData, fillHoles); - } - - return {}; + IdentifySampleInputValues inputValues; + inputValues.FillHoles = filterArgs.value(k_FillHoles_Key); + inputValues.InputImageGeometryPath = filterArgs.value(k_SelectedImageGeometryPath_Key); + inputValues.MaskArrayPath = filterArgs.value(k_MaskArrayPath_Key); + inputValues.SliceBySlice = filterArgs.value(k_SliceBySlice_Key); + inputValues.SliceBySlicePlaneIndex = filterArgs.value(k_SliceBySlicePlane_Key); + return IdentifySample(dataStructure, messageHandler, shouldCancel, &inputValues)(); } namespace diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/IterativeClosestPointFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/IterativeClosestPointFilter.cpp index 8579235f66..694e88ca8e 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/IterativeClosestPointFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/IterativeClosestPointFilter.cpp @@ -1,8 +1,7 @@ #include "IterativeClosestPointFilter.hpp" -#include "SimplnxCore/utils/nanoflann.hpp" +#include "SimplnxCore/Filters/Algorithms/IterativeClosestPoint.hpp" -#include "simplnx/DataStructure/DataArray.hpp" #include "simplnx/DataStructure/Geometry/VertexGeom.hpp" #include "simplnx/Filter/Actions/CreateArrayAction.hpp" #include "simplnx/Parameters/ArrayCreationParameter.hpp" @@ -14,8 +13,6 @@ #include "simplnx/Utilities/MessageHelper.hpp" #include "simplnx/Utilities/SIMPLConversion.hpp" -#include - namespace nx::core { namespace @@ -23,48 +20,6 @@ namespace constexpr int32 k_MissingMovingVertex = -4500; constexpr int32 k_MissingTargetVertex = -4501; constexpr int32 k_BadNumIterations = -4502; -constexpr int32 k_MissingVertices = -4503; -constexpr int32 k_EmptyVertices = -4505; - -template -struct VertexGeomAdaptor -{ - const Derived& obj; - AbstractDataStore* verts; - size_t m_NumComponents = 0; - size_t m_NumTuples = 0; - - explicit VertexGeomAdaptor(const Derived& obj_) - : obj(obj_) - { - // These values never change for the lifetime of this object so cache them now. - verts = derived()->getVertices()->getDataStore(); - m_NumComponents = verts->getNumberOfComponents(); - m_NumTuples = verts->getNumberOfTuples(); - } - - [[nodiscard]] const Derived& derived() const - { - return obj; - } - - [[nodiscard]] usize kdtree_get_point_count() const - { - return m_NumTuples; - } - - [[nodiscard]] float kdtree_get_pt(const usize idx, const usize dim) const - { - auto offset = idx * m_NumComponents; - return verts->getValue(offset + dim); - } - - template - bool kdtree_get_bbox(BBOX& /*bb*/) const - { - return false; - } -}; } // namespace //------------------------------------------------------------------------------ @@ -167,130 +122,15 @@ IFilter::PreflightResult IterativeClosestPointFilter::preflightImpl(const DataSt Result<> IterativeClosestPointFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { - auto movingVertexPath = filterArgs.value(k_MovingVertexPath_Key); - auto targetVertexPath = filterArgs.value(k_TargetVertexPath_Key); - auto numIterations = filterArgs.value(k_NumIterations_Key); - auto applyTransformation = filterArgs.value(k_ApplyTransformation_Key); - auto transformArrayPath = filterArgs.value(k_TransformArrayPath_Key); - - auto movingVertexGeom = dataStructure.getDataAs(movingVertexPath); - auto targetVertexGeom = dataStructure.getDataAs(targetVertexPath); - - if(movingVertexGeom == nullptr) - { - return MakeErrorResult(k_MissingVertices, fmt::format("Moving Vertex Geometry not found at path '{}'", movingVertexPath.toString())); - } - if(targetVertexGeom == nullptr) - { - return MakeErrorResult(k_MissingVertices, fmt::format("Target Vertex Geometry not found at path '{}'", targetVertexPath.toString())); - } - - if(movingVertexGeom->getVertices() == nullptr) - { - return MakeErrorResult(k_MissingVertices, fmt::format("Moving Vertex Geometry does not contain a vertex array")); - } - if(targetVertexGeom->getVertices() == nullptr) - { - return MakeErrorResult(k_MissingVertices, fmt::format("Target Vertex Geometry does not contain a vertex array")); - } - - Float32AbstractDataStore& movingStore = movingVertexGeom->getVertices()->getDataStoreRef(); - if(movingStore.getNumberOfTuples() == 0) - { - return MakeErrorResult(k_EmptyVertices, fmt::format("Moving Vertex Geometry does not contain any vertices")); - } - Float32AbstractDataStore& targetStore = targetVertexGeom->getVertices()->getDataStoreRef(); - if(targetStore.getNumberOfTuples() == 0) - { - return MakeErrorResult(k_EmptyVertices, fmt::format("Target Vertex Geometry does not contain any vertices")); - } - - std::vector movingVector(movingStore.begin(), movingStore.end()); - float32* movingCopyPtr = movingVector.data(); - DataStructure tmp; - - usize numMovingVerts = movingVertexGeom->getNumberOfVertices(); - std::vector dynTarget(numMovingVerts * 3, 0.0F); - float* dynTargetPtr = dynTarget.data(); - - using Adaptor = VertexGeomAdaptor; - const Adaptor adaptor(targetVertexGeom); - - messageHandler("Building kd-tree index..."); - - using KDtree = nanoflann::KDTreeSingleIndexAdaptor, Adaptor, 3>; - KDtree index(3, adaptor, nanoflann::KDTreeSingleIndexAdaptorParams(30)); - index.buildIndex(); - - usize iters = numIterations; - const usize nn = 1; - - typedef Eigen::Matrix PointCloud; - typedef Eigen::Matrix UmeyamaTransform; + IterativeClosestPointInputValues inputValues; - UmeyamaTransform globalTransform; - globalTransform << 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1; - - MessageHelper messageHelper(messageHandler); - ThrottledMessenger throttledMessenger = messageHelper.createThrottledMessenger(); - for(usize i = 0; i < iters; i++) - { - if(shouldCancel) - { - return {}; - } - - for(usize j = 0; j < numMovingVerts; j++) - { - usize identifier; - float dist; - nanoflann::KNNResultSet results(nn); - results.init(&identifier, &dist); - index.findNeighbors(results, movingCopyPtr + (3 * j), nanoflann::SearchParams()); - dynTargetPtr[3 * j + 0] = targetStore[3 * identifier + 0]; - dynTargetPtr[3 * j + 1] = targetStore[3 * identifier + 1]; - dynTargetPtr[3 * j + 2] = targetStore[3 * identifier + 2]; - } - - Eigen::Map moving_(movingCopyPtr, 3, numMovingVerts); - Eigen::Map target_(dynTargetPtr, 3, numMovingVerts); - - UmeyamaTransform transform = Eigen::umeyama(moving_, target_, false); - - for(usize j = 0; j < numMovingVerts; j++) - { - Eigen::Vector4f position(movingCopyPtr[3 * j + 0], movingCopyPtr[3 * j + 1], movingCopyPtr[3 * j + 2], 1); - Eigen::Vector4f transformedPosition = transform * position; - std::memcpy(movingCopyPtr + (3 * j), transformedPosition.data(), sizeof(float) * 3); - } - // Update the global transform - globalTransform = transform * globalTransform; - - throttledMessenger.sendThrottledMessage([&]() { return fmt::format("Performing Registration Iterations || {:.2f}% Completed", CalculatePercentComplete(i, iters)); }); - } - - auto& transformStore = dataStructure.getDataAs(transformArrayPath)->getDataStoreRef(); - - if(applyTransformation) - { - for(usize j = 0; j < numMovingVerts; j++) - { - Eigen::Vector4f position(movingStore[3 * j + 0], movingStore[3 * j + 1], movingStore[3 * j + 2], 1); - Eigen::Vector4f transformedPosition = globalTransform * position; - for(usize k = 0; k < 3; k++) - { - movingStore[3 * j + k] = transformedPosition.data()[k]; - } - } - } - - globalTransform.transposeInPlace(); - for(usize j = 0; j < 16; j++) - { - transformStore[j] = globalTransform.data()[j]; - } + inputValues.ApplyTransformation = filterArgs.value(k_ApplyTransformation_Key); + inputValues.NumIterations = filterArgs.value(k_NumIterations_Key); + inputValues.MovingVertexPath = filterArgs.value(k_MovingVertexPath_Key); + inputValues.TargetVertexPath = filterArgs.value(k_TargetVertexPath_Key); + inputValues.TransformArrayPath = filterArgs.value(k_TransformArrayPath_Key); - return {}; + return IterativeClosestPoint(dataStructure, messageHandler, shouldCancel, &inputValues)(); } namespace diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/MapPointCloudToRegularGridFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/MapPointCloudToRegularGridFilter.cpp index a37bdf64b9..1670de824e 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/MapPointCloudToRegularGridFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/MapPointCloudToRegularGridFilter.cpp @@ -1,5 +1,7 @@ #include "MapPointCloudToRegularGridFilter.hpp" +#include "SimplnxCore/Filters/Algorithms/MapPointCloudToRegularGrid.hpp" + #include "simplnx/DataStructure/DataArray.hpp" #include "simplnx/DataStructure/Geometry/ImageGeom.hpp" #include "simplnx/DataStructure/Geometry/VertexGeom.hpp" @@ -15,8 +17,6 @@ #include "simplnx/Parameters/GeometrySelectionParameter.hpp" #include "simplnx/Parameters/NumberParameter.hpp" #include "simplnx/Parameters/VectorParameter.hpp" -#include "simplnx/Utilities/MaskCompareUtilities.hpp" -#include "simplnx/Utilities/MessageHelper.hpp" #include "simplnx/Utilities/SIMPLConversion.hpp" #include @@ -32,8 +32,6 @@ constexpr nx::core::StringLiteral k_WarningMode = "Warning with Count"; constexpr nx::core::StringLiteral k_ErrorMode = "Error at First Instance"; const nx::core::ChoicesParameter::Choices k_OutOfBoundsHandlingChoices = {k_SilentMode, k_WarningMode, k_ErrorMode}; const nx::core::ChoicesParameter::ValueType k_SilentModeIndex = 0; -const nx::core::ChoicesParameter::ValueType k_WarningModeIndex = 1; -const nx::core::ChoicesParameter::ValueType k_ErrorModeIndex = 2; constexpr int64 k_BadGridDimensions = -2601; constexpr int64 k_InvalidVertexGeometry = -2602; @@ -41,9 +39,6 @@ constexpr int64 k_IncompatibleMaskVoxelArrays = -2603; constexpr int64 k_MaskSelectedArrayInvalid = -2604; constexpr int64 k_MaskCompareInvalid = -2605; constexpr int64 k_InvalidImageGeometry = -2606; -constexpr int64 k_ErrorOutOfBounds = -2607; -constexpr int64 k_WarningOutOfBounds = -2608; -constexpr int64 k_InvalidHandlingValue = -2609; Result<> CreateRegularGrid(DataStructure& dataStructure, const Arguments& filterArgs) { @@ -76,8 +71,8 @@ Result<> CreateRegularGrid(DataStructure& dataStructure, const Arguments& filter std::vector meshMinExtents; for(size_t i = 0; i < 3; i++) { - meshMaxExtents.push_back(std::numeric_limits::lowest()); - meshMinExtents.push_back(std::numeric_limits::max()); + meshMaxExtents.push_back(std::numeric_limits::lowest()); + meshMinExtents.push_back(std::numeric_limits::max()); } for(int64_t i = 0; i < numVerts; i++) @@ -132,7 +127,7 @@ Result<> CreateRegularGrid(DataStructure& dataStructure, const Arguments& filter } else { - iRes[0] = 1.25f * (meshMaxExtents[0] - meshMinExtents[0]) / (static_cast(iDims[0])); + iRes[0] = 1.25f * (meshMaxExtents[0] - meshMinExtents[0]) / (static_cast(iDims[0])); if(iRes[0] == 0.0f) { iRes[0] = 1.0f; @@ -207,86 +202,6 @@ Result<> CreateRegularGrid(DataStructure& dataStructure, const Arguments& filter return {}; } - -template -struct OutOfBoundsType -{ - // Compile time checks for bounding, no runtime overhead - static_assert((UseSilent && !UseWarning && !UseError) || (!UseSilent && UseWarning && !UseError) || (!UseSilent && !UseWarning && UseError), - "struct `OutOfBoundsType` can only have one true bool in its instantiation"); - - static constexpr bool UsingSilent = UseSilent; - static constexpr bool UsingWarning = UseWarning; - static constexpr bool UsingError = UseError; -}; - -using SilentType = OutOfBoundsType; -using WarningType = OutOfBoundsType; -using ErrorType = OutOfBoundsType; - -template -Result<> ProcessVertices(MessageHelper& messageHelper, const VertexGeom& vertices, const ImageGeom* image, UInt64AbstractDataStore& voxelIndices, - const std::unique_ptr& maskCompare, uint64 outOfBoundsValue) -{ - // Validation - if(image == nullptr) - { - return MakeErrorResult(k_InvalidImageGeometry, fmt::format("{}({}): Function {}: Error. Supplied `image` is a nullptr", "::ProcessVertices", __FILE__, __LINE__)); - } - - // Out of Bounds Counter - usize count = 0; - - // Execution - usize numVerts = vertices.getNumberOfVertices(); - ThrottledMessenger throttledMessenger = messageHelper.createThrottledMessenger(); - for(int64 i = 0; i < numVerts; i++) - { - if constexpr(UseMask) - { - if(!maskCompare->isTrue(i)) - { - continue; - } - } - - auto coords = vertices.getVertexCoordinate(i); - const auto indexResult = image->getIndex(coords[0], coords[1], coords[2]); - if(indexResult.has_value()) - { - voxelIndices[i] = indexResult.value(); - } - else - { - if constexpr(OutOfBoundsType::UsingError) - { - BoundingBox3Df imageBounds = image->getBoundingBoxf(); - const Point3Df& minPoint = imageBounds.getMinPoint(); - const Point3Df& maxPoint = imageBounds.getMaxPoint(); - return MakeErrorResult( - k_ErrorOutOfBounds, - fmt::format("Out of bounds value encountered.\nVertex Index: {}\nVertex Coordinates [X,Y,Z]: [{},{},{}]\nImage Coordinate Bounds:\nX: {} to {}\nY: {} to {}\nZ: {} to {}", i, coords[0], - coords[1], coords[2], minPoint.getX(), maxPoint.getX(), minPoint.getY(), maxPoint.getY(), minPoint.getZ(), maxPoint.getZ())); - } - - // Out of bounds value - voxelIndices[i] = outOfBoundsValue; - count++; - } - - throttledMessenger.sendThrottledMessage([&]() { return fmt::format("Computing Point Cloud Voxel Indices || {:.2f}% Completed", CalculatePercentComplete(i, numVerts)); }); - } - - if constexpr(OutOfBoundsType::UsingWarning) - { - if(count > 0) - { - return MakeWarningVoidResult(k_WarningOutOfBounds, fmt::format("Mapping Complete. Number of value outside image bounds: {}", count)); - } - } - - return {}; -} } // namespace //------------------------------------------------------------------------------ @@ -453,9 +368,9 @@ IFilter::PreflightResult MapPointCloudToRegularGridFilter::preflightImpl(const D Result<> MapPointCloudToRegularGridFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { - // Get the target image as a pointer - const auto samplingGridType = filterArgs.value(k_SamplingGridType_Key); - const ImageGeom* image = nullptr; + MapPointCloudToRegularGridInputValues inputValues; + + auto samplingGridType = filterArgs.value(k_SamplingGridType_Key); if(samplingGridType == 0) { // Create the regular grid @@ -465,80 +380,30 @@ Result<> MapPointCloudToRegularGridFilter::executeImpl(DataStructure& dataStruct { return result; } - image = dataStructure.getDataAs(filterArgs.value(k_CreatedImageGeometryPath_Key)); + inputValues.ImageGeomPath = filterArgs.value(k_CreatedImageGeometryPath_Key); } else if(samplingGridType == 1) { - image = dataStructure.getDataAs(filterArgs.value(k_SelectedImageGeometryPath_Key)); + inputValues.ImageGeomPath = filterArgs.value(k_SelectedImageGeometryPath_Key); } - // Create the Mask - const auto useMask = filterArgs.value(k_UseMask_Key); - auto maskPath = filterArgs.value(k_InputMaskPath_Key); - if(!filterArgs.value(k_UseMask_Key)) + inputValues.UseMask = filterArgs.value(k_UseMask_Key); + inputValues.MaskArrayPath = filterArgs.value(k_InputMaskPath_Key); + if(!inputValues.UseMask) { - maskPath = DataPath({k_MaskName}); - } - std::unique_ptr maskCompare; - try - { - maskCompare = MaskCompareUtilities::InstantiateMaskCompare(dataStructure, maskPath); - } catch(const std::out_of_range& exception) - { - // This really should NOT be happening as the path was verified during preflight BUT we may be calling this from - // somewhere else that is NOT going through the normal nx::core::IFilter API of Preflight and Execute - std::string message = fmt::format("Mask Array DataPath does not exist or is not of the correct type (Bool | UInt8) {}", maskPath.toString()); - return MakeErrorResult(k_MaskCompareInvalid, message); + inputValues.MaskArrayPath = DataPath({k_MaskName}); } - // Cache all the needed objects for ::ProcessVertices - const auto vertexGeomPath = filterArgs.value(k_SelectedVertexGeometryPath_Key); - const auto& vertices = dataStructure.getDataRefAs(vertexGeomPath); - const DataPath voxelIndicesPath = vertexGeomPath.createChildPath(vertices.getVertexAttributeMatrix()->getName()).createChildPath(filterArgs.value(k_VoxelIndicesName_Key)); - auto& voxelIndices = dataStructure.getDataAs(voxelIndicesPath)->getDataStoreRef(); - auto outOfBoundsValue = filterArgs.value(k_OutOfBoundsValue_Key); + inputValues.VertexGeomPath = filterArgs.value(k_SelectedVertexGeometryPath_Key); + const auto& vertexGeom = dataStructure.getDataRefAs(inputValues.VertexGeomPath); + const AttributeMatrix* vertexData = vertexGeom.getVertexAttributeMatrix(); + const DataPath vertexDataPath = inputValues.VertexGeomPath.createChildPath(vertexData->getName()); + inputValues.VoxelIndicesPath = vertexDataPath.createChildPath(filterArgs.value(k_VoxelIndicesName_Key)); - MessageHelper messageHelper(messageHandler); + inputValues.OutOfBoundsHandling = filterArgs.value(k_OutOfBoundsHandlingType_Key); + inputValues.OutOfBoundsValue = filterArgs.value(k_OutOfBoundsValue_Key); - // Execute the correct ::ProcessVertices, else error out - switch(filterArgs.value(k_OutOfBoundsHandlingType_Key)) - { - case k_SilentModeIndex: { - if(useMask) - { - return ProcessVertices(messageHelper, vertices, image, voxelIndices, maskCompare, outOfBoundsValue); - } - else - { - return ProcessVertices(messageHelper, vertices, image, voxelIndices, maskCompare, outOfBoundsValue); - } - } - case k_WarningModeIndex: { - if(useMask) - { - return ProcessVertices(messageHelper, vertices, image, voxelIndices, maskCompare, outOfBoundsValue); - } - else - { - return ProcessVertices(messageHelper, vertices, image, voxelIndices, maskCompare, outOfBoundsValue); - } - } - case k_ErrorModeIndex: { - if(useMask) - { - return ProcessVertices(messageHelper, vertices, image, voxelIndices, maskCompare, outOfBoundsValue); - } - else - { - return ProcessVertices(messageHelper, vertices, image, voxelIndices, maskCompare, outOfBoundsValue); - } - } - default: { - return MakeErrorResult(k_InvalidHandlingValue, fmt::format("Unexpected Out of Bounds Handing Option. Received : {}. Expected: {} ({}), {} ({}), {} ({})", - filterArgs.value(k_OutOfBoundsHandlingType_Key), k_SilentMode, k_SilentModeIndex, k_WarningMode, - k_WarningModeIndex, k_ErrorMode, k_ErrorModeIndex)); - } - } + return MapPointCloudToRegularGrid(dataStructure, messageHandler, shouldCancel, &inputValues)(); } namespace diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RotateSampleRefFrameFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RotateSampleRefFrameFilter.cpp index fec6b5eabc..59af5f5372 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RotateSampleRefFrameFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RotateSampleRefFrameFilter.cpp @@ -1,7 +1,7 @@ #include "RotateSampleRefFrameFilter.hpp" -#include "simplnx/Common/Range.hpp" -#include "simplnx/Common/TypeTraits.hpp" +#include "SimplnxCore/Filters/Algorithms/RotateSampleRefFrame.hpp" + #include "simplnx/DataStructure/Geometry/ImageGeom.hpp" #include "simplnx/DataStructure/INeighborList.hpp" #include "simplnx/Filter/Actions/CopyDataObjectAction.hpp" @@ -18,7 +18,6 @@ #include "simplnx/Parameters/DynamicTableParameter.hpp" #include "simplnx/Parameters/GeometrySelectionParameter.hpp" #include "simplnx/Parameters/VectorParameter.hpp" -#include "simplnx/Utilities/DataArrayUtilities.hpp" #include "simplnx/Utilities/DataGroupUtilities.hpp" #include "simplnx/Utilities/GeometryHelpers.hpp" #include "simplnx/Utilities/ImageRotationUtilities.hpp" @@ -33,15 +32,15 @@ #include +#include "simplnx/Utilities/SIMPLConversion.hpp" +#include "simplnx/Utilities/StringUtilities.hpp" + using namespace nx::core; -using namespace nx::core::ImageRotationUtilities; namespace { const std::string k_TempGeometryName = ".rotated_image_geometry"; - -using RotationRepresentationType = RotateSampleRefFrameFilter::RotationRepresentation; - +using RotationRepresentationType = RotateSampleRefFrame::RotationRepresentation; } // namespace namespace nx::core @@ -85,7 +84,7 @@ Parameters RotateSampleRefFrameFilter::parameters() const params.insert(std::make_unique(k_RotateSliceBySlice_Key, "Perform Slice By Slice Transform", "This option is specific to EBSD Data and is not generally used.", false)); params.insertLinkableParameter(std::make_unique(k_RotationRepresentation_Key, "Rotation Representation", "Which form used to represent rotation (axis angle or rotation matrix)", - to_underlying(RotationRepresentation::AxisAngle), ChoicesParameter::Choices{"Axis Angle", "Rotation Matrix"})); + to_underlying(RotationRepresentationType::AxisAngle), ChoicesParameter::Choices{"Axis Angle", "Rotation Matrix"})); params.insert(std::make_unique(k_RotationAxisAngle_Key, "Rotation Axis-Angle [w]", "Axis-Angle in sample reference frame to rotate about.", VectorFloat32Parameter::ValueType{0.0f, 0.0f, 1.0f, 90.0F}, std::vector{"i", "j", "k", "w (Deg)"})); params.insertLinkableParameter(std::make_unique(k_RemoveOriginalGeometry_Key, "Perform In-Place Rotation", "Performs the rotation in-place for the given Image Geometry", true)); @@ -98,8 +97,8 @@ Parameters RotateSampleRefFrameFilter::parameters() const const DynamicTableInfo::TableDataType defaultTable{{{1.0F, 0.0F, 0.0F, 0.0F}, {0.0F, 1.0F, 0.0F, 0.0F}, {0.0F, 0.0F, 1.0F, 0.0F}, {0.0F, 0.0F, 0.0F, 1.0F}}}; params.insert(std::make_unique(k_RotationMatrix_Key, "Transformation Matrix", "The 4x4 Transformation Matrix", defaultTable, tableInfo)); - params.linkParameters(k_RotationRepresentation_Key, k_RotationAxisAngle_Key, std::make_any(to_underlying(RotationRepresentation::AxisAngle))); - params.linkParameters(k_RotationRepresentation_Key, k_RotationMatrix_Key, std::make_any(to_underlying(RotationRepresentation::RotationMatrix))); + params.linkParameters(k_RotationRepresentation_Key, k_RotationAxisAngle_Key, std::make_any(to_underlying(RotationRepresentationType::AxisAngle))); + params.linkParameters(k_RotationRepresentation_Key, k_RotationMatrix_Key, std::make_any(to_underlying(RotationRepresentationType::RotationMatrix))); params.insertSeparator(Parameters::Separator{"Input Image Geometry"}); params.insert(std::make_unique(k_SelectedImageGeometryPath_Key, "Selected Image Geometry", "The target geometry on which to perform the rotation", DataPath{}, @@ -265,79 +264,30 @@ IFilter::PreflightResult RotateSampleRefFrameFilter::preflightImpl(const DataStr Result<> RotateSampleRefFrameFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { - auto srcImagePath = filterArgs.value(k_SelectedImageGeometryPath_Key); - auto destImagePath = filterArgs.value(k_CreatedImageGeometryPath_Key); - auto sliceBySlice = filterArgs.value(k_RotateSliceBySlice_Key); + RotateSampleRefFrameInputValues inputValues; + + inputValues.SourceGeometryPath = filterArgs.value(k_SelectedImageGeometryPath_Key); + inputValues.DestGeometryPath = filterArgs.value(k_CreatedImageGeometryPath_Key); + auto removeOriginalGeometry = filterArgs.value(k_RemoveOriginalGeometry_Key); - auto keepInputGeometryOrigin = filterArgs.value(k_KeepInputGeometryOrigin_Key); + inputValues.KeepInputGeometryOrigin = filterArgs.value(k_KeepInputGeometryOrigin_Key); - auto& srcImageGeom = dataStructure.getDataRefAs(srcImagePath); + auto& srcImageGeom = dataStructure.getDataRefAs(inputValues.SourceGeometryPath); auto sourceImageGeomorigin = srcImageGeom.getOrigin(); if(removeOriginalGeometry) { - auto tempPathVector = srcImagePath.getPathVector(); + auto tempPathVector = inputValues.SourceGeometryPath.getPathVector(); std::string tempName = k_TempGeometryName; tempPathVector.back() = tempName; - destImagePath = DataPath({tempPathVector}); + inputValues.DestGeometryPath = DataPath({tempPathVector}); } - auto& destImageGeom = dataStructure.getDataRefAs(destImagePath); - - ImageRotationUtilities::Matrix4fR rotationMatrix; + inputValues.SliceBySlice = filterArgs.value(k_RotateSliceBySlice_Key); + inputValues.RotationRepresentationIndex = filterArgs.value(k_RotationRepresentation_Key); + inputValues.RotationAxisAngle = filterArgs.value(k_RotationAxisAngle_Key); + inputValues.RotationMatrixTable = filterArgs.value(k_RotationMatrix_Key); - auto rotationRepresentationIndex = filterArgs.value(RotateSampleRefFrameFilter::k_RotationRepresentation_Key); - switch(rotationRepresentationIndex) - { - case static_cast(RotationRepresentationType::AxisAngle): { - auto pRotationValue = filterArgs.value>(RotateSampleRefFrameFilter::k_RotationAxisAngle_Key); - rotationMatrix = ImageRotationUtilities::GenerateRotationTransformationMatrix(pRotationValue); - break; - } - case static_cast(RotationRepresentationType::RotationMatrix): { - auto rotationMatrixTable = filterArgs.value(RotateSampleRefFrameFilter::k_RotationMatrix_Key); - rotationMatrix = ImageRotationUtilities::GenerateManualTransformationMatrix(rotationMatrixTable); - break; - } - } - - ImageRotationUtilities::RotateArgs rotateArgs = ImageRotationUtilities::CreateRotationArgs(srcImageGeom, rotationMatrix); - - auto selectedCellDataChildren = GetAllChildArrayDataPaths(dataStructure, srcImageGeom.getCellDataPath()); - auto selectedCellArrays = selectedCellDataChildren.has_value() ? selectedCellDataChildren.value() : std::vector{}; - - ImageRotationUtilities::FilterProgressCallback filterProgressCallback(messageHandler, shouldCancel); - - // The actual rotating of the dataStructure arrays is done in parallel where parallel here - // refers to the cropping of each DataArray being done on a separate thread. - ParallelTaskAlgorithm taskRunner; - taskRunner.setParallelizationEnabled(true); - const DataPath srcCelLDataAMPath = srcImageGeom.getCellDataPath(); - const auto& srcCellDataAM = srcImageGeom.getCellDataRef(); - - const DataPath destCellDataAMPath = destImageGeom.getCellDataPath(); - - for(const auto& [dataId, srcDataObject] : srcCellDataAM) - { - if(shouldCancel) - { - return {}; - } - - const auto* srcDataArray = dataStructure.getDataAs(srcCelLDataAMPath.createChildPath(srcDataObject->getName())); - auto* destDataArray = dataStructure.getDataAs(destCellDataAMPath.createChildPath(srcDataObject->getName())); - messageHandler(fmt::format("Rotating Volume || Copying Data Array {}", srcDataObject->getName())); - - ExecuteParallelFunction(srcDataArray->getDataType(), taskRunner, srcDataArray, destDataArray, rotateArgs, rotationMatrix, - sliceBySlice, &filterProgressCallback); - } - - taskRunner.wait(); // This will spill over if the number of DataArrays to process does not divide evenly by the number of threads. - - if(keepInputGeometryOrigin) - { - destImageGeom.setOrigin(srcImageGeom.getOrigin()); - } - return {}; + return RotateSampleRefFrame(dataStructure, messageHandler, shouldCancel, &inputValues)(); } namespace diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RotateSampleRefFrameFilter.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RotateSampleRefFrameFilter.hpp index 3740f85aec..d80543db40 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RotateSampleRefFrameFilter.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RotateSampleRefFrameFilter.hpp @@ -24,12 +24,6 @@ class SIMPLNXCORE_EXPORT RotateSampleRefFrameFilter : public IFilter RotateSampleRefFrameFilter& operator=(const RotateSampleRefFrameFilter&) = delete; RotateSampleRefFrameFilter& operator=(RotateSampleRefFrameFilter&&) noexcept = delete; - enum class RotationRepresentation : uint64 - { - AxisAngle = 0, - RotationMatrix = 1 - }; - // Parameter Keys static constexpr StringLiteral k_RotationRepresentation_Key = "rotation_representation_index"; static constexpr StringLiteral k_RotationAxisAngle_Key = "rotation_axis_angle"; diff --git a/src/Plugins/SimplnxCore/test/RotateSampleRefFrameTest.cpp b/src/Plugins/SimplnxCore/test/RotateSampleRefFrameTest.cpp index e8d1aae842..0dd0a4f4f6 100644 --- a/src/Plugins/SimplnxCore/test/RotateSampleRefFrameTest.cpp +++ b/src/Plugins/SimplnxCore/test/RotateSampleRefFrameTest.cpp @@ -1,3 +1,4 @@ +#include "SimplnxCore/Filters/Algorithms/RotateSampleRefFrame.hpp" #include "SimplnxCore/Filters/RotateSampleRefFrameFilter.hpp" #include "SimplnxCore/SimplnxCore_test_dirs.hpp" @@ -108,8 +109,7 @@ TEST_CASE("SimplnxCore::RotateSampleRefFrame", "[Core][RotateSampleRefFrameFilte DataPath outputImageGeomPath = DataPath({fmt::format("{}_Test_AxisAngle", exemplaryGeomPath.getTargetName())}); - args.insertOrAssign(RotateSampleRefFrameFilter::k_RotationRepresentation_Key, - std::make_any(to_underlying(RotateSampleRefFrameFilter::RotationRepresentation::AxisAngle))); + args.insertOrAssign(RotateSampleRefFrameFilter::k_RotationRepresentation_Key, std::make_any(to_underlying(RotateSampleRefFrame::RotationRepresentation::AxisAngle))); args.insertOrAssign(RotateSampleRefFrameFilter::k_SelectedImageGeometryPath_Key, std::make_any(k_OriginalGeomPath)); args.insertOrAssign(RotateSampleRefFrameFilter::k_RemoveOriginalGeometry_Key, std::make_any(false)); // We need to keep the geometries around. args.insertOrAssign(RotateSampleRefFrameFilter::k_CreatedImageGeometryPath_Key, std::make_any(outputImageGeomPath)); @@ -145,7 +145,7 @@ TEST_CASE("SimplnxCore::RotateSampleRefFrame", "[Core][RotateSampleRefFrameFilte outputImageGeomPath = DataPath({fmt::format("{}_Test_RotationMatrix", exemplaryGeomPath.getTargetName())}); args.insertOrAssign(RotateSampleRefFrameFilter::k_RotationRepresentation_Key, - std::make_any(to_underlying(RotateSampleRefFrameFilter::RotationRepresentation::RotationMatrix))); + std::make_any(to_underlying(RotateSampleRefFrame::RotationRepresentation::RotationMatrix))); args.insertOrAssign(RotateSampleRefFrameFilter::k_RotationMatrix_Key, std::make_any(table)); args.insertOrAssign(RotateSampleRefFrameFilter::k_CreatedImageGeometryPath_Key, std::make_any(outputImageGeomPath)); diff --git a/wrapping/python/cmake/simplnx_algorithm.cpp.in b/wrapping/python/cmake/simplnx_algorithm.cpp.in new file mode 100644 index 0000000000..3c1a3920f6 --- /dev/null +++ b/wrapping/python/cmake/simplnx_algorithm.cpp.in @@ -0,0 +1,25 @@ +#include "@ALGO_NAME@.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +@ALGO_NAME@::@ALGO_NAME@(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, @ALGO_NAME@InputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +@ALGO_NAME@::~@ALGO_NAME@() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> @ALGO_NAME@::operator()() +{ + + return {}; +} diff --git a/wrapping/python/cmake/simplnx_algorithm.hpp.in b/wrapping/python/cmake/simplnx_algorithm.hpp.in new file mode 100644 index 0000000000..fa948f69c5 --- /dev/null +++ b/wrapping/python/cmake/simplnx_algorithm.hpp.in @@ -0,0 +1,47 @@ +#pragma once + +#include "@PLUGIN_NAME@/@PLUGIN_NAME@_export.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/Filter/IFilter.hpp" +@PARAMETER_INCLUDES@ + +/** +* This is example code to put in the Execute Method of the filter. +@EXECUTE_EXAMPLE_CODE@ +*/ + +namespace nx::core +{ + +struct @PLUGIN_NAME_UPPER@_EXPORT @ALGO_NAME@InputValues +{ +@INPUT_VALUE_STRUCT_DEF@}; + +/** + * @class @ALGO_NAME@ + * @brief This algorithm implements support code for the @ALGO_NAME@Filter + */ + +class @PLUGIN_NAME_UPPER@_EXPORT @ALGO_NAME@ +{ +public: + @ALGO_NAME@(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, @ALGO_NAME@InputValues* inputValues); + ~@ALGO_NAME@() noexcept; + + @ALGO_NAME@(const @ALGO_NAME@&) = delete; + @ALGO_NAME@(@ALGO_NAME@&&) noexcept = delete; + @ALGO_NAME@& operator=(const @ALGO_NAME@&) = delete; + @ALGO_NAME@& operator=(@ALGO_NAME@&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const @ALGO_NAME@InputValues* m_InputValues = nullptr; + const std::atomic_bool& m_ShouldCancel; + const IFilter::MessageHandler& m_MessageHandler; +}; + +} // namespace complex