From 43edc26ec721c6e23417260d9b8ad8a17194639d Mon Sep 17 00:00:00 2001 From: Michael Jackson Date: Mon, 3 Jun 2024 16:18:36 -0400 Subject: [PATCH] Implement a basic unit test. This should be more all encompassing. Signed-off-by: Michael Jackson --- .../Filters/Algorithms/RemoveFlaggedEdges.cpp | 89 +------ .../Filters/Algorithms/RemoveFlaggedEdges.hpp | 4 +- .../Algorithms/RemoveFlaggedTriangles.cpp | 69 ++++-- .../Algorithms/RemoveFlaggedTriangles.hpp | 29 +++ .../Filters/RemoveFlaggedEdgesFilter.cpp | 23 +- .../Filters/RemoveFlaggedEdgesFilter.hpp | 1 + .../Filters/RemoveFlaggedTrianglesFilter.cpp | 135 +++++++++-- .../Filters/RemoveFlaggedTrianglesFilter.hpp | 8 + .../test/RemoveFlaggedEdgesTest.cpp | 77 ++++-- src/simplnx/Utilities/DataArrayUtilities.cpp | 97 +++++--- src/simplnx/Utilities/DataArrayUtilities.hpp | 226 ++++++++++++------ 11 files changed, 496 insertions(+), 262 deletions(-) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedEdges.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedEdges.cpp index 695c39c98f..a574e75cc5 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedEdges.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedEdges.cpp @@ -7,7 +7,6 @@ #include "simplnx/Utilities/DataGroupUtilities.hpp" #include "simplnx/Utilities/ParallelAlgorithmUtilities.hpp" #include "simplnx/Utilities/ParallelDataAlgorithm.hpp" -#include "simplnx/Utilities/ParallelTaskAlgorithm.hpp" using namespace nx::core; @@ -15,61 +14,6 @@ namespace { constexpr usize k_NumVerts = 2; -/** - * @brief - * @tparam T - */ -template -class CopyCellDataArray -{ -public: - CopyCellDataArray(const IDataArray& oldCellArray, IDataArray& newCellArray, const std::vector& newEdgesIndex, const std::atomic_bool& shouldCancel) - : m_OldCellArray(dynamic_cast&>(oldCellArray)) - , m_NewCellArray(dynamic_cast&>(newCellArray)) - , m_NewEdgesIndex(newEdgesIndex) - , m_ShouldCancel(shouldCancel) - { - } - - ~CopyCellDataArray() = default; - - CopyCellDataArray(const CopyCellDataArray&) = default; - CopyCellDataArray(CopyCellDataArray&&) noexcept = default; - CopyCellDataArray& operator=(const CopyCellDataArray&) = delete; - CopyCellDataArray& operator=(CopyCellDataArray&&) noexcept = delete; - - void operator()() const - { - convert(); - } - -protected: - void convert() const - { - size_t numComps = m_OldCellArray.getNumberOfComponents(); - const auto& oldCellData = m_OldCellArray.getDataStoreRef(); - - auto& dataStore = m_NewCellArray.getDataStoreRef(); - std::fill(dataStore.begin(), dataStore.end(), static_cast(-1)); - - uint64 destTupleIndex = 0; - for(const auto& srcIndex : m_NewEdgesIndex) - { - for(size_t compIndex = 0; compIndex < numComps; compIndex++) - { - dataStore.setValue(destTupleIndex * numComps + compIndex, oldCellData.getValue(srcIndex * numComps + compIndex)); - } - destTupleIndex++; - } - } - -private: - const DataArray& m_OldCellArray; - DataArray& m_NewCellArray; - const std::vector& m_NewEdgesIndex; - const std::atomic_bool& m_ShouldCancel; -}; - /** * @brief The PopulateReducedGeometryEdgesImpl pulls the vertices associated with a triangle then locates the indices in * the new VertexList then assigns that "new" triangle to Reduced Geometry @@ -125,29 +69,6 @@ class PopulateReducedGeometryEdgesImpl const std::vector& m_NewVerticesIndex; }; -void transferElementData(DataStructure& m_DataStructure, AttributeMatrix& destCellDataAM, const std::vector& sourceDataPaths, const std::vector& newEdgesIndexList, - const std::atomic_bool& m_ShouldCancel, const IFilter::MessageHandler& m_MessageHandler) -{ - // The actual cropping 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; - for(const auto& edgeDataArrayPath : sourceDataPaths) - { - if(m_ShouldCancel) - { - return; - } - - const auto& oldDataArray = m_DataStructure.getDataRefAs(edgeDataArrayPath); - const std::string srcName = oldDataArray.getName(); - - auto& newDataArray = dynamic_cast(destCellDataAM.at(srcName)); - m_MessageHandler(fmt::format("Reducing Edge Geometry || Copying Data Array {}", srcName)); - ExecuteParallelFunction(oldDataArray.getDataType(), taskRunner, oldDataArray, newDataArray, newEdgesIndexList, m_ShouldCancel); - } - taskRunner.wait(); // This will spill over if the number of DataArrays to process does not divide evenly by the number of threads. -} - } // namespace // ----------------------------------------------------------------------------- @@ -263,7 +184,8 @@ Result<> RemoveFlaggedEdges::operator()() /** This section will copy any user defined Edge Data Arrays from the old to the reduced edge geometry **/ if(m_InputValues->EdgeDataHandling == k_CopySelectedEdgeArraysIdx) { - ::transferElementData(m_DataStructure, reducedEdgeGeom.getEdgeAttributeMatrixRef(), m_InputValues->SelectedEdgeData, newEdgesIndexList, m_ShouldCancel, m_MessageHandler); + TransferGeometryElementData::transferElementData(m_DataStructure, reducedEdgeGeom.getEdgeAttributeMatrixRef(), m_InputValues->SelectedEdgeData, newEdgesIndexList, m_ShouldCancel, + m_MessageHandler); } else if(m_InputValues->EdgeDataHandling == k_CopyAllEdgeArraysIdx) { @@ -271,14 +193,15 @@ Result<> RemoveFlaggedEdges::operator()() auto getChildrenResult = GetAllChildArrayDataPaths(m_DataStructure, m_InputValues->EdgeAttributeMatrixPath, ignorePaths); if(getChildrenResult.has_value()) { - ::transferElementData(m_DataStructure, reducedEdgeGeom.getEdgeAttributeMatrixRef(), getChildrenResult.value(), newEdgesIndexList, m_ShouldCancel, m_MessageHandler); + TransferGeometryElementData::transferElementData(m_DataStructure, reducedEdgeGeom.getEdgeAttributeMatrixRef(), getChildrenResult.value(), newEdgesIndexList, m_ShouldCancel, m_MessageHandler); } } /** This section will copy any user defined Vertex Data Arrays from the old to the reduced Vertex geometry **/ if(m_InputValues->VertexDataHandling == k_CopySelectedVertexArraysIdx) { - ::transferElementData(m_DataStructure, reducedEdgeGeom.getVertexAttributeMatrixRef(), m_InputValues->SelectedVertexData, vertexListIndices, m_ShouldCancel, m_MessageHandler); + TransferGeometryElementData::transferElementData(m_DataStructure, reducedEdgeGeom.getVertexAttributeMatrixRef(), m_InputValues->SelectedVertexData, vertexListIndices, m_ShouldCancel, + m_MessageHandler); } else if(m_InputValues->VertexDataHandling == k_CopyAllVertexArraysIdx) { @@ -286,7 +209,7 @@ Result<> RemoveFlaggedEdges::operator()() auto getChildrenResult = GetAllChildArrayDataPaths(m_DataStructure, m_InputValues->VertexAttributeMatrixPath, ignorePaths); if(getChildrenResult.has_value()) { - ::transferElementData(m_DataStructure, reducedEdgeGeom.getVertexAttributeMatrixRef(), getChildrenResult.value(), vertexListIndices, m_ShouldCancel, m_MessageHandler); + TransferGeometryElementData::transferElementData(m_DataStructure, reducedEdgeGeom.getVertexAttributeMatrixRef(), getChildrenResult.value(), vertexListIndices, m_ShouldCancel, m_MessageHandler); } } diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedEdges.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedEdges.hpp index 2369cdfb46..c0ce56bf47 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedEdges.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedEdges.hpp @@ -14,10 +14,10 @@ namespace { -const std::string k_CopySelectedEdgeData("Copy Selected Edge Data"); +const std::string k_CopySelectedTriangleData("Copy Selected Edge Data"); const std::string k_CopyAllEdgeData("Copy All Edge Data"); -const nx::core::ChoicesParameter::Choices k_EdgeDataHandlingChoices = {k_CopySelectedEdgeData, k_CopyAllEdgeData}; +const nx::core::ChoicesParameter::Choices k_EdgeDataHandlingChoices = {k_CopySelectedTriangleData, k_CopyAllEdgeData}; const nx::core::ChoicesParameter::ValueType k_CopySelectedEdgeArraysIdx = 0ULL; const nx::core::ChoicesParameter::ValueType k_CopyAllEdgeArraysIdx = 1ULL; diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedTriangles.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedTriangles.cpp index 410bffc40b..ec34cc9cc6 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedTriangles.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedTriangles.cpp @@ -4,6 +4,7 @@ #include "simplnx/DataStructure/DataGroup.hpp" #include "simplnx/DataStructure/Geometry/TriangleGeom.hpp" #include "simplnx/Utilities/DataArrayUtilities.hpp" +#include "simplnx/Utilities/DataGroupUtilities.hpp" #include "simplnx/Utilities/ParallelDataAlgorithm.hpp" using namespace nx::core; @@ -93,7 +94,7 @@ Result<> RemoveFlaggedTriangles::operator()() 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(-54070, message); } - auto& reducedTriangle = m_DataStructure.getDataRefAs(m_InputValues->ReducedTriangleGeometry); + auto& reducedTriangleGeom = m_DataStructure.getDataRefAs(m_InputValues->ReducedTriangleGeometry); // Set up allocated masks usize size = originalTriangle.getNumberOfFaces(); @@ -120,41 +121,41 @@ Result<> RemoveFlaggedTriangles::operator()() } // flatten a list of the indices of vertices used by the triangles - std::vector VertexListIndices; // also used as a pseudo look up table in PopulateReducedGeometryTrianglesImpl + std::vector vertexListIndices; // also used as a pseudo look up table in PopulateReducedGeometryTrianglesImpl for(usize& index : newTrianglesIndexList) { usize vertIDs[3] = {0, 0, 0}; originalTriangle.getFacePointIds(index, vertIDs); - VertexListIndices.push_back(vertIDs[0]); - VertexListIndices.push_back(vertIDs[1]); - VertexListIndices.push_back(vertIDs[2]); + vertexListIndices.push_back(vertIDs[0]); + vertexListIndices.push_back(vertIDs[1]); + vertexListIndices.push_back(vertIDs[2]); } if(getCancel()) { return {}; } - if(VertexListIndices.empty()) + if(vertexListIndices.empty()) { return MakeErrorResult(-67881, "Re-evaluate mask conditions - with current configuration all vertices will be dumped!"); } // clear duplicate values out of vector - std::sort(VertexListIndices.begin(), VertexListIndices.end()); // orders ascending !!!!! Basis for later search !!!!! - auto dupes = std::unique(VertexListIndices.begin(), VertexListIndices.end()); - VertexListIndices.erase(dupes, VertexListIndices.end()); + std::sort(vertexListIndices.begin(), vertexListIndices.end()); // orders ascending !!!!! Basis for later search !!!!! + auto dupes = std::unique(vertexListIndices.begin(), vertexListIndices.end()); + vertexListIndices.erase(dupes, vertexListIndices.end()); // define new sizing - size = VertexListIndices.size(); - reducedTriangle.resizeVertexList(size); // resize accordingly - reducedTriangle.getVertexAttributeMatrix()->resizeTuples({size}); + size = vertexListIndices.size(); + reducedTriangleGeom.resizeVertexList(size); // resize accordingly + reducedTriangleGeom.getVertexAttributeMatrix()->resizeTuples({size}); // load reduced Geometry Vertex list according to used vertices Point3Df coords = {0.0f, 0.0f, 0.0f}; for(usize i = 0; i < size; i++) { - coords = originalTriangle.getVertexCoordinate(VertexListIndices[i]); - reducedTriangle.setVertexCoordinate(i, coords); + coords = originalTriangle.getVertexCoordinate(vertexListIndices[i]); + reducedTriangleGeom.setVertexCoordinate(i, coords); } if(getCancel()) @@ -164,13 +165,47 @@ Result<> RemoveFlaggedTriangles::operator()() // Set up preprocessing conditions (allocation for parallelization) size = newTrianglesIndexList.size(); - reducedTriangle.resizeFaceList(size); // resize accordingly - reducedTriangle.getFaceAttributeMatrix()->resizeTuples({size}); + reducedTriangleGeom.resizeFaceList(size); // resize accordingly + reducedTriangleGeom.getFaceAttributeMatrix()->resizeTuples({size}); // parse triangles and reassign indexes to match new vertex list ParallelDataAlgorithm dataAlg; dataAlg.setRange(0, size); - dataAlg.execute(PopulateReducedGeometryTrianglesImpl(originalTriangle, reducedTriangle, newTrianglesIndexList, VertexListIndices)); + dataAlg.execute(PopulateReducedGeometryTrianglesImpl(originalTriangle, reducedTriangleGeom, newTrianglesIndexList, vertexListIndices)); + + /** This section will copy any user defined Triangle Data Arrays from the old to the reduced Triangle geometry **/ + if(m_InputValues->TriangleDataHandling == k_CopySelectedTriangleArraysIdx) + { + TransferGeometryElementData::transferElementData(m_DataStructure, reducedTriangleGeom.getFaceAttributeMatrixRef(), m_InputValues->SelectedTriangleData, newTrianglesIndexList, m_ShouldCancel, + m_MessageHandler); + } + else if(m_InputValues->TriangleDataHandling == k_CopyAllTriangleArraysIdx) + { + std::vector ignorePaths; + auto getChildrenResult = GetAllChildArrayDataPaths(m_DataStructure, m_InputValues->TriangleAttributeMatrixPath, ignorePaths); + if(getChildrenResult.has_value()) + { + TransferGeometryElementData::transferElementData(m_DataStructure, reducedTriangleGeom.getFaceAttributeMatrixRef(), getChildrenResult.value(), newTrianglesIndexList, m_ShouldCancel, + m_MessageHandler); + } + } + + /** This section will copy any user defined Vertex Data Arrays from the old to the reduced Vertex geometry **/ + if(m_InputValues->VertexDataHandling == k_CopySelectedVertexArraysIdx) + { + TransferGeometryElementData::transferElementData(m_DataStructure, reducedTriangleGeom.getVertexAttributeMatrixRef(), m_InputValues->SelectedVertexData, vertexListIndices, m_ShouldCancel, + m_MessageHandler); + } + else if(m_InputValues->VertexDataHandling == k_CopyAllVertexArraysIdx) + { + std::vector ignorePaths; + auto getChildrenResult = GetAllChildArrayDataPaths(m_DataStructure, m_InputValues->VertexAttributeMatrixPath, ignorePaths); + if(getChildrenResult.has_value()) + { + TransferGeometryElementData::transferElementData(m_DataStructure, reducedTriangleGeom.getVertexAttributeMatrixRef(), getChildrenResult.value(), vertexListIndices, m_ShouldCancel, + m_MessageHandler); + } + } return {}; } diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedTriangles.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedTriangles.hpp index 611551fd5b..873be2fd38 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedTriangles.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedTriangles.hpp @@ -6,9 +6,30 @@ #include "simplnx/DataStructure/DataStructure.hpp" #include "simplnx/Filter/IFilter.hpp" #include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/ChoicesParameter.hpp" #include "simplnx/Parameters/DataGroupSelectionParameter.hpp" +#include "simplnx/Parameters/MultiArraySelectionParameter.hpp" #include "simplnx/Parameters/StringParameter.hpp" +namespace +{ + +const std::string k_CopySelectedTriangleData("Copy Selected Triangle Data"); +const std::string k_CopyAllTriangleData("Copy All Triangle Data"); + +const nx::core::ChoicesParameter::Choices k_TriangleDataHandlingChoices = {k_CopySelectedTriangleData, k_CopyAllTriangleData}; +const nx::core::ChoicesParameter::ValueType k_CopySelectedTriangleArraysIdx = 0ULL; +const nx::core::ChoicesParameter::ValueType k_CopyAllTriangleArraysIdx = 1ULL; + +const std::string k_CopySelectedVertexData("Copy Selected Vertex Data"); +const std::string k_CopyAllVertexData("Copy All Vertex Data"); + +const nx::core::ChoicesParameter::Choices k_VertexDataHandlingChoices = {k_CopySelectedVertexData, k_CopyAllVertexData}; +const nx::core::ChoicesParameter::ValueType k_CopySelectedVertexArraysIdx = 0ULL; +const nx::core::ChoicesParameter::ValueType k_CopyAllVertexArraysIdx = 1ULL; + +} // namespace + namespace nx::core { struct SIMPLNXCORE_EXPORT RemoveFlaggedTrianglesInputValues @@ -16,6 +37,14 @@ struct SIMPLNXCORE_EXPORT RemoveFlaggedTrianglesInputValues DataPath TriangleGeometry; DataPath MaskArrayPath; DataPath ReducedTriangleGeometry; + // These variables are associated with the Edge Data Handling + nx::core::ChoicesParameter::ValueType TriangleDataHandling; + MultiArraySelectionParameter::ValueType SelectedTriangleData; + DataPath TriangleAttributeMatrixPath; + // These variables are associated with the Vertex Data Handling + nx::core::ChoicesParameter::ValueType VertexDataHandling; + MultiArraySelectionParameter::ValueType SelectedVertexData; + DataPath VertexAttributeMatrixPath; }; /** diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedEdgesFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedEdgesFilter.cpp index 80dd5fdd42..f40b2a3ece 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedEdgesFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedEdgesFilter.cpp @@ -18,21 +18,6 @@ using namespace nx::core; namespace { -template -void createDataArrayActions(const DataStructure& dataStructure, const AttributeMatrix* sourceAttrMatPtr, const MultiArraySelectionParameter::ValueType& selectedArrayPaths, - const DataPath& reducedGeometryPathAttrMatPath, Result& resultOutputActions) -{ - // Now loop over each array in selectedEdgeArrays and create the corresponding arrays - // in the destination geometry's attribute matrix - for(const auto& dataPath : selectedArrayPaths) - { - const auto& srcArray = dataStructure.getDataRefAs(dataPath); - DataType dataType = srcArray.getDataType(); - IDataStore::ShapeType componentShape = srcArray.getIDataStoreRef().getComponentShape(); - DataPath dataArrayPath = reducedGeometryPathAttrMatPath.createChildPath(srcArray.getName()); - resultOutputActions.value().appendAction(std::make_unique(dataType, sourceAttrMatPtr->getShape(), std::move(componentShape), dataArrayPath)); - } -} } // namespace @@ -164,7 +149,7 @@ IFilter::PreflightResult RemoveFlaggedEdgesFilter::preflightImpl(const DataStruc { return {MakeErrorResult(-5551, fmt::format("'{}' must have edge data attribute matrix", pInitialGeometryPathValue.toString()))}; } - createDataArrayActions(dataStructure, srcEdgeAttrMatPtr, selectedEdgeArrays, reducedEdgeAttributeMatrixPath, resultOutputActions); + TransferGeometryElementData::createDataArrayActions(dataStructure, srcEdgeAttrMatPtr, selectedEdgeArrays, reducedEdgeAttributeMatrixPath, resultOutputActions); } else if(pEdgeArrayHandling == k_CopyAllEdgeArraysIdx) { @@ -178,7 +163,7 @@ IFilter::PreflightResult RemoveFlaggedEdgesFilter::preflightImpl(const DataStruc if(getChildrenResult.has_value()) { selectedEdgeArrays = getChildrenResult.value(); - createDataArrayActions(dataStructure, srcEdgeAttrMatPtr, selectedEdgeArrays, reducedEdgeAttributeMatrixPath, resultOutputActions); + TransferGeometryElementData::createDataArrayActions(dataStructure, srcEdgeAttrMatPtr, selectedEdgeArrays, reducedEdgeAttributeMatrixPath, resultOutputActions); } } } @@ -194,7 +179,7 @@ IFilter::PreflightResult RemoveFlaggedEdgesFilter::preflightImpl(const DataStruc { return {MakeErrorResult(-5551, fmt::format("'{}' must have Vertex data attribute matrix", pInitialGeometryPathValue.toString()))}; } - createDataArrayActions(dataStructure, srcVertexAttrMatPtr, selectedVertexArrays, reducedVertexAttributeMatrixPath, resultOutputActions); + TransferGeometryElementData::createDataArrayActions(dataStructure, srcVertexAttrMatPtr, selectedVertexArrays, reducedVertexAttributeMatrixPath, resultOutputActions); } else if(pVertexArrayHandling == k_CopyAllVertexArraysIdx) { @@ -208,7 +193,7 @@ IFilter::PreflightResult RemoveFlaggedEdgesFilter::preflightImpl(const DataStruc if(getChildrenResult.has_value()) { selectedVertexArrays = getChildrenResult.value(); - createDataArrayActions(dataStructure, srcVertexAttrMatPtr, selectedVertexArrays, reducedVertexAttributeMatrixPath, resultOutputActions); + TransferGeometryElementData::createDataArrayActions(dataStructure, srcVertexAttrMatPtr, selectedVertexArrays, reducedVertexAttributeMatrixPath, resultOutputActions); } } } diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedEdgesFilter.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedEdgesFilter.hpp index 61ff93fdf8..f153405fcc 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedEdgesFilter.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedEdgesFilter.hpp @@ -27,6 +27,7 @@ class SIMPLNXCORE_EXPORT RemoveFlaggedEdgesFilter : public IFilter static inline constexpr StringLiteral k_SelectedTriangleGeometryPath_Key = "input_triangle_geometry_path"; static inline constexpr StringLiteral k_MaskArrayPath_Key = "mask_array_path"; static inline constexpr StringLiteral k_CreatedTriangleGeometryPath_Key = "output_triangle_geometry_path"; + static inline constexpr StringLiteral k_EdgeDataHandling_Key = "edge_data_handling_index"; static inline constexpr StringLiteral k_EdgeDataSelectedArrays_Key = "edge_data_selected_array_paths"; static inline constexpr StringLiteral k_EdgeDataSelectedAttributeMatrix_Key = "edge_data_selected_attribute_matrix_path"; diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedTrianglesFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedTrianglesFilter.cpp index c9764a4d7a..a04a2f83f7 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedTrianglesFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedTrianglesFilter.cpp @@ -9,6 +9,7 @@ #include "simplnx/Parameters/DataGroupCreationParameter.hpp" #include "simplnx/Parameters/GeometrySelectionParameter.hpp" #include "simplnx/Parameters/StringParameter.hpp" +#include "simplnx/Utilities/DataGroupUtilities.hpp" #include "simplnx/Utilities/SIMPLConversion.hpp" using namespace nx::core; @@ -42,7 +43,7 @@ std::string RemoveFlaggedTrianglesFilter::humanName() const //------------------------------------------------------------------------------ std::vector RemoveFlaggedTrianglesFilter::defaultTags() const { - return {"Surface Meshing", "Cleanup"}; + return {"Surface Meshing", "Cleanup", "Remove", "Delete"}; } //------------------------------------------------------------------------------ @@ -52,11 +53,35 @@ Parameters RemoveFlaggedTrianglesFilter::parameters() const // Create the parameter descriptors that are needed for this filter params.insertSeparator(Parameters::Separator{"Input Data Objects"}); - params.insert(std::make_unique(k_SelectedTriangleGeometryPath_Key, "Triangle|Quad Geometry", "The Triangle|Quad Geometry that will be processed.", DataPath(), - GeometrySelectionParameter::AllowedTypes{IGeometry::Type::Triangle, IGeometry::Type::Quad})); + params.insert(std::make_unique(k_SelectedTriangleGeometryPath_Key, "Triangle Geometry", "The Triangle Geometry that will be processed.", DataPath(), + GeometrySelectionParameter::AllowedTypes{IGeometry::Type::Triangle})); params.insert(std::make_unique(k_MaskArrayPath_Key, "Mask", "The DataArrayPath to the mask array that marks each face as either true (remove) or false(keep).", DataPath{}, ArraySelectionParameter::AllowedTypes{DataType::boolean, DataType::uint8}, ArraySelectionParameter::AllowedComponentShapes{{1}})); + // Vertex Data Handling + params.insertSeparator(Parameters::Separator{"Vertex Data Handling"}); + params.insertLinkableParameter(std::make_unique(k_VertexDataHandling_Key, "Vertex Data Handling", "How to handle Data that resides on the triangles", k_CopySelectedVertexArraysIdx, + k_VertexDataHandlingChoices)); + params.insert( + std::make_unique(k_VertexDataSelectedAttributeMatrix_Key, "Vertex Data", "Vertex Attribute Matrix that will be copied to the reduced geometry", DataPath{})); + params.insert(std::make_unique(k_VertexDataSelectedArrays_Key, "Vertex Attribute Arrays to Copy", "Vertex DataPaths to copy", std::vector(), + MultiArraySelectionParameter::AllowedTypes{IArray::ArrayType::DataArray}, GetAllNumericTypes())); + + params.linkParameters(k_VertexDataHandling_Key, k_VertexDataSelectedAttributeMatrix_Key, k_CopyAllVertexArraysIdx); + params.linkParameters(k_VertexDataHandling_Key, k_VertexDataSelectedArrays_Key, k_CopySelectedVertexArraysIdx); + + // Triangle Data Handling + params.insertSeparator(Parameters::Separator{"Triangle Data Handling"}); + params.insertLinkableParameter(std::make_unique(k_TriangleDataHandling_Key, "Triangle Data Handling", "How to handle Data that resides on the triangles", + k_CopySelectedTriangleArraysIdx, k_TriangleDataHandlingChoices)); + params.insert(std::make_unique(k_TriangleDataSelectedAttributeMatrix_Key, "Triangle Data", "Triangle Attribute Matrix that will be copied to the reduced geometry", + DataPath{})); + params.insert(std::make_unique(k_TriangleDataSelectedArrays_Key, "Triangle Attribute Arrays to Copy", "Triangle DataPaths to copy", std::vector(), + MultiArraySelectionParameter::AllowedTypes{IArray::ArrayType::DataArray}, GetAllNumericTypes())); + + params.linkParameters(k_TriangleDataHandling_Key, k_TriangleDataSelectedArrays_Key, k_CopySelectedTriangleArraysIdx); + params.linkParameters(k_TriangleDataHandling_Key, k_TriangleDataSelectedAttributeMatrix_Key, k_CopyAllTriangleArraysIdx); + params.insertSeparator(Parameters::Separator{"Output Geometry"}); params.insert(std::make_unique(k_CreatedTriangleGeometryPath_Key, "Created Geometry", "The name of the created Triangle Geometry", DataPath({"ReducedGeometry"}))); return params; @@ -74,31 +99,105 @@ IFilter::PreflightResult RemoveFlaggedTrianglesFilter::preflightImpl(const DataS { auto pInitialGeometryPathValue = filterArgs.value(k_SelectedTriangleGeometryPath_Key); auto pReducedGeometryPathValue = filterArgs.value(k_CreatedTriangleGeometryPath_Key); + auto pTriangleArrayHandling = filterArgs.value(k_TriangleDataHandling_Key); + auto selectedTriangleArrays = filterArgs.value(k_TriangleDataSelectedArrays_Key); + auto selectedTriangleAttrMatPath = filterArgs.value(k_TriangleDataSelectedAttributeMatrix_Key); + + auto pVertexArrayHandling = filterArgs.value(k_VertexDataHandling_Key); + auto selectedVertexArrays = filterArgs.value(k_VertexDataSelectedArrays_Key); + auto selectedVertexAttrMatPath = filterArgs.value(k_VertexDataSelectedAttributeMatrix_Key); PreflightResult preflightResult; Result resultOutputActions; std::vector preflightUpdatedValues; - const auto* initialGeom = dataStructure.getDataAs(pInitialGeometryPathValue); + const auto* initialGeomPtr = dataStructure.getDataAs(pInitialGeometryPathValue); + + std::string reducedVertexAttributeMatrixName = (initialGeomPtr->getVertexAttributeMatrix() == nullptr ? "Vertex Data" : initialGeomPtr->getVertexAttributeMatrix()->getName()); + std::string reducedFaceAttributeMatrixName = (initialGeomPtr->getEdgeAttributeMatrix() == nullptr ? "Face Data" : initialGeomPtr->getEdgeAttributeMatrix()->getName()); + + DataPath reducedVertexAttributeMatrixPath = pReducedGeometryPathValue.createChildPath(reducedVertexAttributeMatrixName); + DataPath reducedFaceAttributeMatrixPath = pReducedGeometryPathValue.createChildPath(reducedFaceAttributeMatrixName); - if(initialGeom->getGeomType() == IGeometry::Type::Triangle) + std::vector triangleDataShape = {initialGeomPtr->getNumberOfFaces()}; + std::vector vertexDataShape = {initialGeomPtr->getNumberOfVertices()}; + + if(initialGeomPtr->getGeomType() == IGeometry::Type::Triangle) { - auto createGeometryAction = std::make_unique>( - pReducedGeometryPathValue, initialGeom->getNumberOfFaces(), initialGeom->getNumberOfVertices(), - (initialGeom->getVertexAttributeMatrix() == nullptr ? "VertexAM" : initialGeom->getVertexAttributeMatrix()->getName()), - (initialGeom->getFaceAttributeMatrix() == nullptr ? "FaceAM" : initialGeom->getFaceAttributeMatrix()->getName()), initialGeom->getVertices()->getName(), initialGeom->getFaces()->getName()); + auto createGeometryAction = + std::make_unique>(pReducedGeometryPathValue, initialGeomPtr->getNumberOfFaces(), initialGeomPtr->getNumberOfVertices(), reducedVertexAttributeMatrixName, + reducedFaceAttributeMatrixName, initialGeomPtr->getVertices()->getName(), initialGeomPtr->getFaces()->getName()); resultOutputActions.value().appendAction(std::move(createGeometryAction)); } - if(initialGeom->getGeomType() == IGeometry::Type::Quad) + if(initialGeomPtr->getGeomType() == IGeometry::Type::Quad) { - auto createGeometryAction = std::make_unique>( - pReducedGeometryPathValue, initialGeom->getNumberOfFaces(), initialGeom->getNumberOfVertices(), - (initialGeom->getVertexAttributeMatrix() == nullptr ? "VertexAM" : initialGeom->getVertexAttributeMatrix()->getName()), - (initialGeom->getFaceAttributeMatrix() == nullptr ? "FaceAM" : initialGeom->getFaceAttributeMatrix()->getName()), initialGeom->getVertices()->getName(), initialGeom->getFaces()->getName()); + auto createGeometryAction = + std::make_unique>(pReducedGeometryPathValue, initialGeomPtr->getNumberOfFaces(), initialGeomPtr->getNumberOfVertices(), reducedVertexAttributeMatrixName, + reducedFaceAttributeMatrixName, initialGeomPtr->getVertices()->getName(), initialGeomPtr->getFaces()->getName()); resultOutputActions.value().appendAction(std::move(createGeometryAction)); } + /** This section is for copying the Face Data ***/ + // This _could_ be nullptr. We are going to hold off doing that check until inside each of the + // conditional blocks below. + { + const AttributeMatrix* srcTriangleAttrMatPtr = initialGeomPtr->getFaceAttributeMatrix(); + if(pTriangleArrayHandling == k_CopySelectedTriangleArraysIdx) + { + if(!selectedTriangleArrays.empty() && nullptr == srcTriangleAttrMatPtr) + { + return {MakeErrorResult(-5551, fmt::format("'{}' must have face data attribute matrix", pInitialGeometryPathValue.toString()))}; + } + TransferGeometryElementData::createDataArrayActions(dataStructure, srcTriangleAttrMatPtr, selectedTriangleArrays, reducedFaceAttributeMatrixPath, resultOutputActions); + } + else if(pTriangleArrayHandling == k_CopyAllTriangleArraysIdx) + { + if(nullptr == srcTriangleAttrMatPtr) + { + return {MakeErrorResult(-5551, fmt::format("'{}' must have face data attribute matrix", pInitialGeometryPathValue.toString()))}; + } + std::vector ignorePaths; + + auto getChildrenResult = GetAllChildArrayDataPaths(dataStructure, selectedTriangleAttrMatPath, ignorePaths); + if(getChildrenResult.has_value()) + { + selectedTriangleArrays = getChildrenResult.value(); + TransferGeometryElementData::createDataArrayActions(dataStructure, srcTriangleAttrMatPtr, selectedTriangleArrays, reducedFaceAttributeMatrixPath, resultOutputActions); + } + } + } + + /** This section is for copying the Vertex Data ***/ + // This _could_ be nullptr. We are going to hold off doing that check until inside each of the + // conditional blocks below. + { + const AttributeMatrix* srcVertexAttrMatPtr = initialGeomPtr->getVertexAttributeMatrix(); + if(pVertexArrayHandling == k_CopySelectedVertexArraysIdx) + { + if(!selectedVertexArrays.empty() && nullptr == srcVertexAttrMatPtr) + { + return {MakeErrorResult(-5551, fmt::format("'{}' must have Vertex data attribute matrix", pInitialGeometryPathValue.toString()))}; + } + TransferGeometryElementData::createDataArrayActions(dataStructure, srcVertexAttrMatPtr, selectedVertexArrays, reducedVertexAttributeMatrixPath, resultOutputActions); + } + else if(pVertexArrayHandling == k_CopyAllVertexArraysIdx) + { + if(nullptr == srcVertexAttrMatPtr) + { + return {MakeErrorResult(-5551, fmt::format("'{}' must have Vertex data attribute matrix", pInitialGeometryPathValue.toString()))}; + } + std::vector ignorePaths; + + auto getChildrenResult = GetAllChildArrayDataPaths(dataStructure, selectedVertexAttrMatPath, ignorePaths); + if(getChildrenResult.has_value()) + { + selectedVertexArrays = getChildrenResult.value(); + TransferGeometryElementData::createDataArrayActions(dataStructure, srcVertexAttrMatPtr, selectedVertexArrays, reducedVertexAttributeMatrixPath, resultOutputActions); + } + } + } + // Return both the resultOutputActions and the preflightUpdatedValues via std::move() return {std::move(resultOutputActions), std::move(preflightUpdatedValues)}; } @@ -113,6 +212,14 @@ Result<> RemoveFlaggedTrianglesFilter::executeImpl(DataStructure& dataStructure, inputValues.MaskArrayPath = filterArgs.value(k_MaskArrayPath_Key); inputValues.ReducedTriangleGeometry = filterArgs.value(k_CreatedTriangleGeometryPath_Key); + inputValues.TriangleDataHandling = filterArgs.value(k_TriangleDataHandling_Key); + inputValues.TriangleAttributeMatrixPath = filterArgs.value(k_TriangleDataSelectedAttributeMatrix_Key); + inputValues.SelectedTriangleData = filterArgs.value(k_TriangleDataSelectedArrays_Key); + + inputValues.VertexDataHandling = filterArgs.value(k_VertexDataHandling_Key); + inputValues.VertexAttributeMatrixPath = filterArgs.value(k_VertexDataSelectedAttributeMatrix_Key); + inputValues.SelectedVertexData = filterArgs.value(k_VertexDataSelectedArrays_Key); + return RemoveFlaggedTriangles(dataStructure, messageHandler, shouldCancel, &inputValues)(); } diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedTrianglesFilter.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedTrianglesFilter.hpp index fc38da088d..43403a06a8 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedTrianglesFilter.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedTrianglesFilter.hpp @@ -28,6 +28,14 @@ class SIMPLNXCORE_EXPORT RemoveFlaggedTrianglesFilter : public IFilter static inline constexpr StringLiteral k_MaskArrayPath_Key = "mask_array_path"; static inline constexpr StringLiteral k_CreatedTriangleGeometryPath_Key = "output_triangle_geometry_path"; + static inline constexpr StringLiteral k_TriangleDataHandling_Key = "triangle_data_handling_index"; + static inline constexpr StringLiteral k_TriangleDataSelectedArrays_Key = "triangle_data_selected_array_paths"; + static inline constexpr StringLiteral k_TriangleDataSelectedAttributeMatrix_Key = "triangle_data_selected_attribute_matrix_path"; + + static inline constexpr StringLiteral k_VertexDataHandling_Key = "vertex_data_handling_index"; + static inline constexpr StringLiteral k_VertexDataSelectedArrays_Key = "vertex_data_selected_array_paths"; + static inline constexpr StringLiteral k_VertexDataSelectedAttributeMatrix_Key = "vertex_data_selected_attribute_matrix_path"; + /** * @brief Reads SIMPL json and converts it complex Arguments. * @param json diff --git a/src/Plugins/SimplnxCore/test/RemoveFlaggedEdgesTest.cpp b/src/Plugins/SimplnxCore/test/RemoveFlaggedEdgesTest.cpp index 8755f804ea..3f22ef25e9 100644 --- a/src/Plugins/SimplnxCore/test/RemoveFlaggedEdgesTest.cpp +++ b/src/Plugins/SimplnxCore/test/RemoveFlaggedEdgesTest.cpp @@ -1,26 +1,29 @@ #include +#include "SimplnxCore/Filters/MultiThresholdObjectsFilter.hpp" #include "SimplnxCore/Filters/RemoveFlaggedEdgesFilter.hpp" #include "SimplnxCore/SimplnxCore_test_dirs.hpp" -#include "simplnx/DataStructure/Geometry/TriangleGeom.hpp" + +#include "simplnx/DataStructure/Geometry/EdgeGeom.hpp" #include "simplnx/UnitTest/UnitTestCommon.hpp" using namespace nx::core; +using namespace nx::core::UnitTest; namespace { namespace { -fs::path k_ExemplarDataFilePath = fs::path(fmt::format("{}/remove_flagged_triangles_test/remove_flagged_triangles_test.dream3d", nx::core::unit_test::k_TestFilesDir)); -fs::path k_BaseDataFilePath = fs::path(fmt::format("{}/remove_flagged_triangles_test/data_to_generate_test/masked_triangle_geometry.dream3d", nx::core::unit_test::k_TestFilesDir)); +// fs::path k_ExemplarDataFilePath = fs::path(fmt::format("{}/6_6_scan_path_test_data/6_6_scan_path_test_data.dream3d", nx::core::unit_test::k_TestFilesDir)); +// fs::path k_BaseDataFilePath = fs::path(fmt::format("{}/6_6_scan_path_test_data/masked_triangle_geometry.dream3d", nx::core::unit_test::k_TestFilesDir)); -static constexpr StringLiteral k_CreatedAMName = "Cell Feature AM"; -static constexpr StringLiteral k_NumTrianglesName = "NumTriangles"; -static constexpr StringLiteral k_RegionIdsName = "Region Ids"; +// static constexpr StringLiteral k_CreatedAMName = "Cell Feature AM"; +// static constexpr StringLiteral k_NumTrianglesName = "NumTriangles"; +// static constexpr StringLiteral k_RegionIdsName = "Region Ids"; -const DataPath k_TriangleGeomPath({"TriangleGeometry"}); -const DataPath k_MaskPath = k_TriangleGeomPath.createChildPath(Constants::k_Face_Data).createChildPath(Constants::k_Mask); -const DataPath k_ReducedGeomPath({"ReducedGeometry"}); +const DataPath k_TriangleGeomPath({"Exemplar Edge Geometry"}); +const DataPath k_MaskPath = k_TriangleGeomPath.createChildPath("Edge Data").createChildPath(Constants::k_Mask); +const DataPath k_ReducedGeomPath({"Reduced Geometry"}); const DataPath k_VertexListPath = k_ReducedGeomPath.createChildPath("SharedVertexList"); const DataPath k_TriangleListPath = k_ReducedGeomPath.createChildPath("SharedTriList"); @@ -29,10 +32,41 @@ const DataPath k_TriangleListPath = k_ReducedGeomPath.createChildPath("SharedTri TEST_CASE("SimplnxCore::RemoveFlaggedEdgesFilter: Valid Filter Execution", "[SimplnxCore][RemoveFlaggedEdgesFilter]") { - const UnitTest::TestFileSentinel testDataSentinel(unit_test::k_CMakeExecutable, unit_test::k_TestFilesDir, "remove_flagged_triangles_test.tar.gz", "remove_flagged_triangles_test.dream3d"); + const UnitTest::TestFileSentinel testDataSentinel(unit_test::k_CMakeExecutable, unit_test::k_TestFilesDir, "6_6_scan_path_test_data.tar.gz", "6_6_scan_path_test_data.dream3d"); // Load DataStructure containing the base geometry and an exemplar cleaned geometry - DataStructure dataStructure = UnitTest::LoadDataStructure(k_BaseDataFilePath); + auto baseDataFilePath = fs::path(fmt::format("{}/6_6_scan_path_test_data/6_6_scan_path_test_data.dream3d", nx::core::unit_test::k_TestFilesDir)); + DataStructure dataStructure = UnitTest::LoadDataStructure(baseDataFilePath); + + // Run a Multi-Threshold Filter + { + MultiThresholdObjectsFilter filter; + + Arguments args; + + ArrayThresholdSet arrayThresholdset; + ArrayThresholdSet::CollectionType thresholds; + + std::shared_ptr ciThreshold = std::make_shared(); + ciThreshold->setArrayPath(DataPath({"Exemplar Edge Geometry", "Edge Data", "RegionIds"})); + ciThreshold->setComparisonType(ArrayThreshold::ComparisonType::GreaterThan); + ciThreshold->setComparisonValue(4); + thresholds.push_back(ciThreshold); + + arrayThresholdset.setArrayThresholds(thresholds); + + args.insertOrAssign(MultiThresholdObjectsFilter::k_ArrayThresholdsObject_Key, std::make_any(arrayThresholdset)); + args.insertOrAssign(MultiThresholdObjectsFilter::k_CreatedDataName_Key, std::make_any(Constants::k_Mask)); + + // Preflight the filter and check result + auto preflightResult = filter.preflight(dataStructure, args); + SIMPLNX_RESULT_REQUIRE_VALID(preflightResult.outputActions) + + // Execute the filter and check the result + auto executeResult = filter.execute(dataStructure, args); + SIMPLNX_RESULT_REQUIRE_VALID(executeResult.result) + } + { // Instantiate the filter and an Arguments Object RemoveFlaggedEdgesFilter filter; @@ -47,19 +81,22 @@ TEST_CASE("SimplnxCore::RemoveFlaggedEdgesFilter: Valid Filter Execution", "[Sim auto preflightResult = filter.preflight(dataStructure, args); SIMPLNX_RESULT_REQUIRE_VALID(preflightResult.outputActions); - // This is in here because the exemplar face attribute matrix is not sized correctly. This will - // correct that value allowing the test to proceed normally. - auto& exemplarContourTriGeom = dataStructure.getDataRefAs(k_TriangleGeomPath); - exemplarContourTriGeom.getVertexAttributeMatrix()->resizeTuples({144}); - exemplarContourTriGeom.getFaceAttributeMatrix()->resizeTuples({276}); - // Execute the filter and check the result auto executeResult = filter.execute(dataStructure, args); SIMPLNX_RESULT_REQUIRE_VALID(executeResult.result); } - DataStructure exemplarDataStructure = UnitTest::LoadDataStructure(k_ExemplarDataFilePath); + // This filter did not exist in DREAM.3D Version 6 so there is nothing to compare against. + // Right now we are going to just check some basic attributes of the Edge Geometry and see + // if they are the expected value. + auto& reducedEdgeGeom = dataStructure.getDataRefAs(k_ReducedGeomPath); + REQUIRE(reducedEdgeGeom.getEdgeAttributeMatrixRef().getSize() == 0); + REQUIRE(reducedEdgeGeom.getVertexAttributeMatrixRef().getSize() == 0); + REQUIRE(reducedEdgeGeom.getNumberOfVertices() == 30800); + REQUIRE(reducedEdgeGeom.getNumberOfEdges() == 15400); - UnitTest::CompareDataArrays(dataStructure.getDataRefAs(::k_TriangleListPath), exemplarDataStructure.getDataRefAs(::k_TriangleListPath)); - UnitTest::CompareDataArrays(dataStructure.getDataRefAs(::k_VertexListPath), exemplarDataStructure.getDataRefAs(::k_VertexListPath)); + // Write the DataStructure out to the file system +#ifdef SIMPLNX_WRITE_TEST_OUTPUT + WriteTestDataStructure(dataStructure, fs::path(fmt::format("{}/remove_flagged_edges.dream3d", unit_test::k_BinaryTestOutputDir))); +#endif } diff --git a/src/simplnx/Utilities/DataArrayUtilities.cpp b/src/simplnx/Utilities/DataArrayUtilities.cpp index dfabfe6f33..74345055e9 100644 --- a/src/simplnx/Utilities/DataArrayUtilities.cpp +++ b/src/simplnx/Utilities/DataArrayUtilities.cpp @@ -24,8 +24,8 @@ struct InitializeNeighborListFunctor template void operator()(INeighborList* iNeighborList) { - auto* neighborList = dynamic_cast*>(iNeighborList); - neighborList->setList(neighborList->getNumberOfTuples() - 1, typename NeighborList::SharedVectorType(new typename NeighborList::VectorType)); + auto* neighborListPtr = dynamic_cast*>(iNeighborList); + neighborListPtr->setList(neighborListPtr->getNumberOfTuples() - 1, typename NeighborList::SharedVectorType(new typename NeighborList::VectorType)); } }; } // namespace @@ -124,8 +124,8 @@ bool CheckArraysAreSameType(const DataStructure& dataStructure, const std::vecto std::set types; for(const auto& dataPath : dataArrayPaths) { - const auto* dataArray = dataStructure.getDataAs(dataPath); - types.insert(dataArray->getDataType()); + const auto* dataArrayPtr = dataStructure.getDataAs(dataPath); + types.insert(dataArrayPtr->getDataType()); } return types.size() == 1; } @@ -153,11 +153,11 @@ bool CheckMemoryRequirement(DataStructure& dataStructure, uint64 requiredMemory, return true; } - Preferences* preferences = Application::GetOrCreateInstance()->getPreferences(); + Preferences* preferencesPtr = Application::GetOrCreateInstance()->getPreferences(); const uint64 memoryUsage = dataStructure.memoryUsage() + requiredMemory; - const uint64 largeDataStructureSize = preferences->largeDataStructureSize(); - std::string largeDataFormat = preferences->largeDataFormat(); + const uint64 largeDataStructureSize = preferencesPtr->largeDataStructureSize(); + std::string largeDataFormat = preferencesPtr->largeDataFormat(); if(memoryUsage >= largeDataStructureSize) { @@ -184,51 +184,51 @@ Result<> ConditionalReplaceValueInArray(const std::string& valueAsStr, DataObjec //----------------------------------------------------------------------------- Result<> ResizeAndReplaceDataArray(DataStructure& dataStructure, const DataPath& dataPath, std::vector& tupleShape, IDataAction::Mode mode) { - auto* inputDataArray = dataStructure.getDataAs(dataPath); + auto* inputDataArrayPtr = dataStructure.getDataAs(dataPath); - if(TemplateHelpers::CanDynamicCast()(inputDataArray)) + if(TemplateHelpers::CanDynamicCast()(inputDataArrayPtr)) { - return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArray); + return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArrayPtr); } - if(TemplateHelpers::CanDynamicCast()(inputDataArray)) + if(TemplateHelpers::CanDynamicCast()(inputDataArrayPtr)) { - return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArray); + return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArrayPtr); } - if(TemplateHelpers::CanDynamicCast()(inputDataArray)) + if(TemplateHelpers::CanDynamicCast()(inputDataArrayPtr)) { - return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArray); + return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArrayPtr); } - if(TemplateHelpers::CanDynamicCast()(inputDataArray)) + if(TemplateHelpers::CanDynamicCast()(inputDataArrayPtr)) { - return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArray); + return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArrayPtr); } - if(TemplateHelpers::CanDynamicCast()(inputDataArray)) + if(TemplateHelpers::CanDynamicCast()(inputDataArrayPtr)) { - return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArray); + return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArrayPtr); } - if(TemplateHelpers::CanDynamicCast()(inputDataArray)) + if(TemplateHelpers::CanDynamicCast()(inputDataArrayPtr)) { - return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArray); + return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArrayPtr); } - if(TemplateHelpers::CanDynamicCast()(inputDataArray)) + if(TemplateHelpers::CanDynamicCast()(inputDataArrayPtr)) { - return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArray); + return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArrayPtr); } - if(TemplateHelpers::CanDynamicCast()(inputDataArray)) + if(TemplateHelpers::CanDynamicCast()(inputDataArrayPtr)) { - return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArray); + return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArrayPtr); } - if(TemplateHelpers::CanDynamicCast()(inputDataArray)) + if(TemplateHelpers::CanDynamicCast()(inputDataArrayPtr)) { - return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArray); + return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArrayPtr); } - if(TemplateHelpers::CanDynamicCast()(inputDataArray)) + if(TemplateHelpers::CanDynamicCast()(inputDataArrayPtr)) { - return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArray); + return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArrayPtr); } - if(TemplateHelpers::CanDynamicCast()(inputDataArray)) + if(TemplateHelpers::CanDynamicCast()(inputDataArrayPtr)) { - return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArray); + return ReplaceArray(dataStructure, dataPath, tupleShape, mode, *inputDataArrayPtr); } return MakeErrorResult(-401, fmt::format("The input array at DataPath '{}' was of an unsupported type", dataPath.toString())); @@ -237,13 +237,13 @@ Result<> ResizeAndReplaceDataArray(DataStructure& dataStructure, const DataPath& //----------------------------------------------------------------------------- Result<> ValidateNumFeaturesInArray(const DataStructure& dataStructure, const DataPath& arrayPath, const Int32Array& featureIds) { - const auto* featureArray = dataStructure.getDataAs(arrayPath); - if(featureArray == nullptr) + const auto* featureArrayPtr = dataStructure.getDataAs(arrayPath); + if(featureArrayPtr == nullptr) { return MakeErrorResult(-5550, fmt::format("Could not find the input array path '{}' for validating number of features", arrayPath.toString())); } Result<> results = {}; - const usize numFeatures = featureArray->getNumberOfTuples(); + const usize numFeatures = featureArrayPtr->getNumberOfTuples(); for(const int32& featureId : featureIds) { @@ -267,8 +267,8 @@ Result<> ValidateNumFeaturesInArray(const DataStructure& dataStructure, const Da //----------------------------------------------------------------------------- void InitializeNeighborList(DataStructure& dataStructure, const DataPath& neighborListPath) { - auto* neighborList = dataStructure.getDataAs(neighborListPath); - ExecuteNeighborFunction(InitializeNeighborListFunctor{}, neighborList->getDataType(), neighborList); + auto* neighborListPtr = dataStructure.getDataAs(neighborListPath); + ExecuteNeighborFunction(InitializeNeighborListFunctor{}, neighborListPtr->getDataType(), neighborListPtr); } //----------------------------------------------------------------------------- @@ -327,4 +327,31 @@ bool ConvertIDataArray(const std::shared_ptr& dataArray, const std:: return false; } } + +namespace TransferGeometryElementData +{ +void transferElementData(DataStructure& m_DataStructure, AttributeMatrix& destCellDataAM, const std::vector& sourceDataPaths, const std::vector& newEdgesIndexList, + const std::atomic_bool& m_ShouldCancel, const IFilter::MessageHandler& m_MessageHandler) +{ + // The actual cropping 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; + for(const auto& edgeDataArrayPath : sourceDataPaths) + { + if(m_ShouldCancel) + { + return; + } + + const auto& oldDataArray = m_DataStructure.getDataRefAs(edgeDataArrayPath); + const std::string srcName = oldDataArray.getName(); + + auto& newDataArray = dynamic_cast(destCellDataAM.at(srcName)); + m_MessageHandler(fmt::format("Copying Data Array {}", srcName)); + ExecuteParallelFunction(oldDataArray.getDataType(), taskRunner, oldDataArray, newDataArray, newEdgesIndexList, m_ShouldCancel); + } + taskRunner.wait(); // This will spill over if the number of DataArrays to process does not divide evenly by the number of threads. +} +} // namespace TransferGeometryElementData + } // namespace nx::core diff --git a/src/simplnx/Utilities/DataArrayUtilities.hpp b/src/simplnx/Utilities/DataArrayUtilities.hpp index d128c909b7..a490c59942 100644 --- a/src/simplnx/Utilities/DataArrayUtilities.hpp +++ b/src/simplnx/Utilities/DataArrayUtilities.hpp @@ -11,9 +11,12 @@ #include "simplnx/DataStructure/IO/Generic/DataIOCollection.hpp" #include "simplnx/DataStructure/NeighborList.hpp" #include "simplnx/DataStructure/StringArray.hpp" +#include "simplnx/Filter/Actions/CreateArrayAction.hpp" #include "simplnx/Filter/Output.hpp" +#include "simplnx/Parameters/MultiArraySelectionParameter.hpp" #include "simplnx/Utilities/MemoryUtilities.hpp" #include "simplnx/Utilities/ParallelAlgorithmUtilities.hpp" +#include "simplnx/Utilities/ParallelTaskAlgorithm.hpp" #include "simplnx/Utilities/TemplateHelpers.hpp" #include "simplnx/simplnx_export.hpp" @@ -258,7 +261,6 @@ SIMPLNX_EXPORT Result<> CheckValueConvertsToArrayType(const std::string& value, template void ReplaceValue(DataArray& inputArrayPtr, const DataArray* condArrayPtr, T replaceValue, bool invertMask = false) { - T replaceVal = static_cast(replaceValue); usize numTuples = inputArrayPtr.getNumberOfTuples(); const DataArray& conditionalArray = *condArrayPtr; @@ -365,10 +367,10 @@ std::shared_ptr> CreateDataStore(const typename IDataStore: } case IDataAction::Mode::Execute: { uint64 dataSize = CalculateDataSize(tupleShape, componentShape); - auto* preferences = Application::GetOrCreateInstance()->getPreferences(); - if(preferences->forceOocData()) + auto* preferencesPtr = Application::GetOrCreateInstance()->getPreferences(); + if(preferencesPtr->forceOocData()) { - dataFormat = preferences->largeDataFormat(); + dataFormat = preferencesPtr->largeDataFormat(); } auto ioCollection = Application::GetOrCreateInstance()->getIOCollection(); ioCollection->checkStoreDataFormat(dataSize, dataFormat); @@ -399,16 +401,16 @@ Result<> CreateArray(DataStructure& dataStructure, const std::vector& tup std::optional dataObjectId; - DataObject* parentObject = nullptr; + DataObject* parentObjectPtr = nullptr; if(parentPath.getLength() != 0) { - parentObject = dataStructure.getData(parentPath); - if(parentObject == nullptr) + parentObjectPtr = dataStructure.getData(parentPath); + if(parentObjectPtr == nullptr) { return MakeErrorResult(-260, fmt::format("CreateArray: Parent object '{}' does not exist", parentPath.toString())); } - dataObjectId = parentObject->getId(); + dataObjectId = parentObjectPtr->getId(); } if(tupleShape.empty()) @@ -450,15 +452,15 @@ Result<> CreateArray(DataStructure& dataStructure, const std::vector& tup return MakeErrorResult(-264, fmt::format("CreateArray: Cannot create Data Array at path '{}' because it already exists. Choose a different name.", path.toString())); } - if(parentObject->getDataObjectType() == DataObject::Type::AttributeMatrix) + if(parentObjectPtr->getDataObjectType() == DataObject::Type::AttributeMatrix) { - auto* attrMatrix = dynamic_cast(parentObject); - std::string amShape = fmt::format("Attribute Matrix Tuple Dims: {}", fmt::join(attrMatrix->getShape(), " x ")); + auto* attrMatrixPtr = dynamic_cast(parentObjectPtr); + std::string amShape = fmt::format("Attribute Matrix Tuple Dims: {}", fmt::join(attrMatrixPtr->getShape(), " x ")); std::string arrayShape = fmt::format("Data Array Tuple Shape: {}", fmt::join(store->getTupleShape(), " x ")); return MakeErrorResult(-265, fmt::format("CreateArray: Unable to create Data Array '{}' inside Attribute matrix '{}'. Mismatch of tuple dimensions. The created Data Array must have the same tuple " "dimensions or the same total number of tuples.\n{}\n{}", - name, dataStructure.getDataPathsForId(parentObject->getId()).front().toString(), amShape, arrayShape)); + name, dataStructure.getDataPathsForId(parentObjectPtr->getId()).front().toString(), amShape, arrayShape)); } else { @@ -527,13 +529,13 @@ Result<> CreateNeighbors(DataStructure& dataStructure, usize numTuples, const Da if(parentPath.getLength() != 0) { - auto* parentObject = dataStructure.getData(parentPath); - if(parentObject == nullptr) + auto* parentObjectPtr = dataStructure.getData(parentPath); + if(parentObjectPtr == nullptr) { return MakeErrorResult(-5801, fmt::format("{}Parent object \"{}\" does not exist", prefix, parentPath.toString())); } - dataObjectId = parentObject->getId(); + dataObjectId = parentObjectPtr->getId(); } const usize last = path.getLength() - 1; @@ -560,12 +562,12 @@ template DataArray* ArrayFromPath(DataStructure& dataStructure, const DataPath& path) { using DataArrayType = DataArray; - DataObject* object = dataStructure.getData(path); - if(object == nullptr) + DataObject* objectPtr = dataStructure.getData(path); + if(objectPtr == nullptr) { throw std::runtime_error(fmt::format("DataArray does not exist at DataPath: '{}'", path.toString())); } - auto* dataArray = dynamic_cast(object); + auto* dataArray = dynamic_cast(objectPtr); if(dataArray == nullptr) { throw std::runtime_error(fmt::format("DataPath does not point to a DataArray. DataPath: '{}'", path.toString())); @@ -583,13 +585,13 @@ DataArray* ArrayFromPath(DataStructure& dataStructure, const DataPath& path) template DataArray& ArrayRefFromPath(DataStructure& dataStructure, const DataPath& path) { - DataObject* object = dataStructure.getData(path); - auto* dataArray = dynamic_cast*>(object); - if(dataArray == nullptr) + DataObject* objectPtr = dataStructure.getData(path); + auto* dataArrayPtr = dynamic_cast*>(objectPtr); + if(dataArrayPtr == nullptr) { throw std::runtime_error("Can't obtain DataArray"); } - return *dataArray; + return *dataArrayPtr; } /** @@ -604,8 +606,8 @@ DataArray& ArrayRefFromPath(DataStructure& dataStructure, const DataPath& pat template Result<> ImportFromBinaryFile(const fs::path& binaryFilePath, DataArray& outputDataArray, usize startByte = 0, usize defaultBufferSize = 1000000) { - FILE* inputFile = std::fopen(binaryFilePath.string().c_str(), "rb"); - if(inputFile == nullptr) + FILE* inputFilePtr = std::fopen(binaryFilePath.string().c_str(), "rb"); + if(inputFilePtr == nullptr) { return MakeErrorResult(-1000, fmt::format("Unable to open the specified file. '{}'", binaryFilePath.string())); } @@ -613,7 +615,7 @@ Result<> ImportFromBinaryFile(const fs::path& binaryFilePath, DataArray& outp // Skip some bytes if needed if(startByte > 0) { - FSEEK64(inputFile, static_cast(startByte), SEEK_SET); + FSEEK64(inputFilePtr, static_cast(startByte), SEEK_SET); } const usize numElements = outputDataArray.getSize(); @@ -624,14 +626,14 @@ Result<> ImportFromBinaryFile(const fs::path& binaryFilePath, DataArray& outp usize elementCounter = 0; while(elementCounter < numElements) { - usize elements_read = std::fread(buffer.data(), sizeof(T), chunkSize, inputFile); + usize elementsRead = std::fread(buffer.data(), sizeof(T), chunkSize, inputFilePtr); - for(usize i = 0; i < elements_read; i++) + for(usize i = 0; i < elementsRead; i++) { outputDataArray[i + elementCounter] = buffer[i]; } - elementCounter += elements_read; + elementCounter += elementsRead; usize elementsLeft = numElements - elementCounter; @@ -641,7 +643,7 @@ Result<> ImportFromBinaryFile(const fs::path& binaryFilePath, DataArray& outp } } - std::fclose(inputFile); + std::fclose(inputFilePtr); return {}; } @@ -667,28 +669,28 @@ DataArray* ImportFromBinaryFile(const std::string& filename, const std::strin if(!fs::exists(filename)) { - std::cout << "File Does Not Exist:'" << filename << "'" << std::endl; + std::cout << "File Does Not Exist:'" << filename << "'\n"; return nullptr; } std::shared_ptr dataStore = std::shared_ptr(new DataStoreType({tupleShape}, componentShape, static_cast(0))); - ArrayType* dataArray = ArrayType::Create(dataStructure, name, dataStore, parentId); + ArrayType* dataArrayPtr = ArrayType::Create(dataStructure, name, dataStore, parentId); const usize fileSize = fs::file_size(filename); - const usize numBytesToRead = dataArray->getSize() * sizeof(T); + const usize numBytesToRead = dataArrayPtr->getSize() * sizeof(T); if(numBytesToRead != fileSize) { - std::cout << "FileSize '" << fileSize << "' and Allocated Size '" << numBytesToRead << "' do not match" << std::endl; + std::cout << "FileSize '" << fileSize << "' and Allocated Size '" << numBytesToRead << "' do not match\n"; return nullptr; } - Result<> result = ImportFromBinaryFile(fs::path(filename), *dataArray); + Result<> result = ImportFromBinaryFile(fs::path(filename), *dataArrayPtr); if(result.invalid()) { return nullptr; } - return dataArray; + return dataArrayPtr; } /** @@ -772,12 +774,12 @@ SIMPLNX_EXPORT Result<> ValidateNumFeaturesInArray(const DataStructure& dataStru template Result<> ResizeDataArray(DataStructure& dataStructure, const DataPath& arrayPath, const std::vector& newShape) { - auto* dataArray = dataStructure.getDataAs>(arrayPath); - if(dataArray == nullptr) + auto* dataArrayPtr = dataStructure.getDataAs>(arrayPath); + if(dataArrayPtr == nullptr) { return MakeErrorResult(-4830, fmt::format("Could not find array path '{}' in the given data structure", arrayPath.toString())); } - if(dataArray->getTupleShape() == newShape) // array does not need to be reshaped + if(dataArrayPtr->getTupleShape() == newShape) // array does not need to be reshaped { return {}; } @@ -789,7 +791,7 @@ Result<> ResizeDataArray(DataStructure& dataStructure, const DataPath& arrayPath } // the array's parent is not in an Attribute Matrix so we can safely reshape to the new tuple shape - dataArray->template getIDataStoreRefAs>().resizeTuples(newShape); + dataArrayPtr->template getIDataStoreRefAs>().resizeTuples(newShape); return {}; } @@ -988,7 +990,7 @@ class CopyTupleUsingIndexList { if(newDataStore.copyFrom(i, oldDataStore, oldIndexI, 1).invalid()) { - std::cout << fmt::format("Array copy failed: Source Array Name: {} Source Tuple Index: {}\nDest Array Name: {} Dest. Tuple Index {}\n", m_OldCellArray.getName(), oldIndexI, i) << std::endl; + std::cout << fmt::format("Array copy failed: Source Array Name: {} Source Tuple Index: {}\nDest Array Name: {} Dest. Tuple Index {}\n\n", m_OldCellArray.getName(), oldIndexI, i); break; } } @@ -1103,19 +1105,19 @@ class AppendArray const usize offset = m_TupleOffset * m_DestCellArray->getNumberOfComponents(); if(m_ArrayType == IArray::ArrayType::NeighborListArray) { - using NeighborListT = NeighborList; - auto* destArray = dynamic_cast(m_DestCellArray); + using NeighborListType = NeighborList; + auto* destArrayPtr = dynamic_cast(m_DestCellArray); // Make sure the destination array is allocated AND each tuple list is initialized so we can use the [] operator to copy over the data - if(destArray->getValues().empty() || destArray->getList(0) == nullptr) + if(destArrayPtr->getValues().empty() || destArrayPtr->getList(0) == nullptr) { - destArray->addEntry(destArray->getNumberOfTuples() - 1, 0); + destArrayPtr->addEntry(destArrayPtr->getNumberOfTuples() - 1, 0); } - AppendData(*dynamic_cast(m_InputCellArray), *destArray, offset); + AppendData(*dynamic_cast(m_InputCellArray), *destArrayPtr, offset); } if(m_ArrayType == IArray::ArrayType::DataArray) { - using DataArrayT = DataArray; - AppendData(*dynamic_cast(m_InputCellArray), *dynamic_cast(m_DestCellArray), offset); + using DataArrayType = DataArray; + AppendData(*dynamic_cast(m_InputCellArray), *dynamic_cast(m_DestCellArray), offset); } if(m_ArrayType == IArray::ArrayType::StringArray) { @@ -1169,9 +1171,9 @@ class CombineArrays } if(m_ArrayType == IArray::ArrayType::DataArray) { - using DataArrayT = DataArray; - AppendData(*dynamic_cast(m_InputCellArray1), *dynamic_cast(m_DestCellArray), 0); - AppendData(*dynamic_cast(m_InputCellArray2), *dynamic_cast(m_DestCellArray), m_InputCellArray1->getSize()); + using DataArrayType = DataArray; + AppendData(*dynamic_cast(m_InputCellArray1), *dynamic_cast(m_DestCellArray), 0); + AppendData(*dynamic_cast(m_InputCellArray2), *dynamic_cast(m_DestCellArray), m_InputCellArray1->getSize()); } if(m_ArrayType == IArray::ArrayType::StringArray) { @@ -1231,11 +1233,11 @@ class CopyUsingIndexList } else if(m_ArrayType == IArray::ArrayType::DataArray) { - using DataArrayT = DataArray; - auto* destArray = dynamic_cast(m_DestCellArray); + using DataArrayType = DataArray; + auto* destArray = dynamic_cast(m_DestCellArray); if(oldIndexI >= 0) { - copySucceeded = CopyData(*dynamic_cast(m_InputCellArray), *destArray, i, oldIndexI, 1); + copySucceeded = CopyData(*dynamic_cast(m_InputCellArray), *destArray, i, oldIndexI, 1); } else { @@ -1359,21 +1361,21 @@ class MapRectGridDataToImageData if(m_ArrayType == IArray::ArrayType::NeighborListArray) { using NeighborListT = NeighborList; - auto* destArray = dynamic_cast(m_DestCellArray); + auto* destArrayPtr = dynamic_cast(m_DestCellArray); // Make sure the destination array is allocated AND each tuple list is initialized so we can use the [] operator to copy over the data - destArray->setList(imageIndex, typename NeighborListT::SharedVectorType(new typename NeighborListT::VectorType)); + destArrayPtr->setList(imageIndex, typename NeighborListT::SharedVectorType(new typename NeighborListT::VectorType)); if(rectGridIndex >= 0) { - copySucceeded = CopyData(*dynamic_cast(m_InputCellArray), *destArray, imageIndex, rectGridIndex, 1); + copySucceeded = CopyData(*dynamic_cast(m_InputCellArray), *destArrayPtr, imageIndex, rectGridIndex, 1); } } else if(m_ArrayType == IArray::ArrayType::DataArray) { - using DataArrayT = DataArray; - auto* destArray = dynamic_cast(m_DestCellArray); + using DataArrayType = DataArray; + auto* destArray = dynamic_cast(m_DestCellArray); if(rectGridIndex >= 0) { - copySucceeded = CopyData(*dynamic_cast(m_InputCellArray), *destArray, imageIndex, rectGridIndex, 1); + copySucceeded = CopyData(*dynamic_cast(m_InputCellArray), *destArray, imageIndex, rectGridIndex, 1); } else { @@ -1394,9 +1396,8 @@ class MapRectGridDataToImageData } if(!copySucceeded) { - std::cout << fmt::format("Array copy failed: Source Array Name: {} Source Tuple Index: {}\nDest Array Name: {} Dest. Tuple Index {}\n", m_InputCellArray->getName(), rectGridIndex, - imageIndex) - << std::endl; + std::cout << fmt::format("Array copy failed: Source Array Name: {} Source Tuple Index: {}\nDest Array Name: {} Dest. Tuple Index {}\n\n", m_InputCellArray->getName(), rectGridIndex, + imageIndex); break; } @@ -1426,9 +1427,9 @@ class MapRectGridDataToImageData */ inline void RunAppendBoolAppend(IArray& destCellArray, const IArray& inputCellArray, usize tupleOffset) { - using DataArrayT = DataArray; + using DataArrayType = DataArray; const usize offset = tupleOffset * destCellArray.getNumberOfComponents(); - AppendData(*dynamic_cast(&inputCellArray), *dynamic_cast(&destCellArray), offset); + AppendData(*dynamic_cast(&inputCellArray), *dynamic_cast(&destCellArray), offset); } /** @@ -1437,9 +1438,9 @@ inline void RunAppendBoolAppend(IArray& destCellArray, const IArray& inputCellAr */ inline void RunCombineBoolAppend(const IArray& inputCellArray1, const IArray& inputCellArray2, IArray& destCellArray) { - using DataArrayT = DataArray; - AppendData(*dynamic_cast(&inputCellArray1), *dynamic_cast(&destCellArray), 0); - AppendData(*dynamic_cast(&inputCellArray2), *dynamic_cast(&destCellArray), inputCellArray1.getSize()); + using DataArrayType = DataArray; + AppendData(*dynamic_cast(&inputCellArray1), *dynamic_cast(&destCellArray), 0); + AppendData(*dynamic_cast(&inputCellArray2), *dynamic_cast(&destCellArray), inputCellArray1.getSize()); } /** @@ -1448,8 +1449,8 @@ inline void RunCombineBoolAppend(const IArray& inputCellArray1, const IArray& in */ inline void RunBoolCopyUsingIndexList(IArray& destCellArray, const IArray& inputCellArray, const nonstd::span& newToOldIndices) { - using DataArrayT = DataArray; - CopyUsingIndexList(*dynamic_cast(&destCellArray), *dynamic_cast(&inputCellArray), newToOldIndices); + using DataArrayType = DataArray; + CopyUsingIndexList(*dynamic_cast(&destCellArray), *dynamic_cast(&inputCellArray), newToOldIndices); } /** @@ -1459,9 +1460,9 @@ inline void RunBoolCopyUsingIndexList(IArray& destCellArray, const IArray& input inline void RunBoolMapRectToImage(IArray& destCellArray, const IArray& inputCellArray, const FloatVec3& origin, const SizeVec3& imageGeoDims, const std::vector& imageGeoSpacing, const SizeVec3& rectGridDims, const Float32Array* xGridValues, const Float32Array* yGridValues, const Float32Array* zGridValues) { - using DataArrayT = DataArray; - MapRectGridDataToImageData(*dynamic_cast(&destCellArray), *dynamic_cast(&inputCellArray), origin, imageGeoDims, imageGeoSpacing, rectGridDims, - xGridValues, yGridValues, zGridValues); + using DataArrayType = DataArray; + MapRectGridDataToImageData(*dynamic_cast(&destCellArray), *dynamic_cast(&inputCellArray), origin, imageGeoDims, imageGeoSpacing, rectGridDims, + xGridValues, yGridValues, zGridValues); } template @@ -1553,4 +1554,85 @@ void RunParallelMapRectToImage(IArray& destArray, ParallelRunnerT&& runner, Args } // namespace CopyFromArray +namespace TransferGeometryElementData +{ + +/** + * @brief + * @tparam T + */ +template +class CopyCellDataArray +{ +public: + CopyCellDataArray(const IDataArray& oldCellArray, IDataArray& newCellArray, const std::vector& newEdgesIndex, const std::atomic_bool& shouldCancel) + : m_OldCellArray(dynamic_cast&>(oldCellArray)) + , m_NewCellArray(dynamic_cast&>(newCellArray)) + , m_NewEdgesIndex(newEdgesIndex) + , m_ShouldCancel(shouldCancel) + { + } + + ~CopyCellDataArray() = default; + + CopyCellDataArray(const CopyCellDataArray&) = default; + CopyCellDataArray(CopyCellDataArray&&) noexcept = default; + CopyCellDataArray& operator=(const CopyCellDataArray&) = delete; + CopyCellDataArray& operator=(CopyCellDataArray&&) noexcept = delete; + + void operator()() const + { + size_t numComps = m_OldCellArray.getNumberOfComponents(); + const auto& oldCellData = m_OldCellArray.getDataStoreRef(); + + auto& dataStore = m_NewCellArray.getDataStoreRef(); + std::fill(dataStore.begin(), dataStore.end(), static_cast(-1)); + + uint64 destTupleIndex = 0; + for(const auto& srcIndex : m_NewEdgesIndex) + { + for(size_t compIndex = 0; compIndex < numComps; compIndex++) + { + dataStore.setValue(destTupleIndex * numComps + compIndex, oldCellData.getValue(srcIndex * numComps + compIndex)); + } + destTupleIndex++; + } + } + +private: + const DataArray& m_OldCellArray; + DataArray& m_NewCellArray; + const std::vector& m_NewEdgesIndex; + const std::atomic_bool& m_ShouldCancel; +}; + +/** + * + * @param m_DataStructure + * @param destCellDataAM The destination Attribute Matrix + * @param sourceDataPaths The source data array paths that are to be copied + * @param newEdgesIndexList The index mapping + * @param m_ShouldCancel Should the algorithm be canceled + * @param m_MessageHandler The message handler to use for messages. + */ +SIMPLNX_EXPORT void transferElementData(DataStructure& m_DataStructure, AttributeMatrix& destCellDataAM, const std::vector& sourceDataPaths, const std::vector& newEdgesIndexList, + const std::atomic_bool& m_ShouldCancel, const IFilter::MessageHandler& m_MessageHandler); + +template +void createDataArrayActions(const DataStructure& dataStructure, const AttributeMatrix* sourceAttrMatPtr, const MultiArraySelectionParameter::ValueType& selectedArrayPaths, + const DataPath& reducedGeometryPathAttrMatPath, Result& resultOutputActions) +{ + // Now loop over each array in selectedEdgeArrays and create the corresponding arrays + // in the destination geometry's attribute matrix + for(const auto& dataPath : selectedArrayPaths) + { + const auto& srcArray = dataStructure.getDataRefAs(dataPath); + DataType dataType = srcArray.getDataType(); + IDataStore::ShapeType componentShape = srcArray.getIDataStoreRef().getComponentShape(); + DataPath dataArrayPath = reducedGeometryPathAttrMatPath.createChildPath(srcArray.getName()); + resultOutputActions.value().appendAction(std::make_unique(dataType, sourceAttrMatPtr->getShape(), std::move(componentShape), dataArrayPath)); + } +} + +} // namespace TransferGeometryElementData } // namespace nx::core