Skip to content

Commit

Permalink
Implement a basic unit test. This should be more all encompassing.
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Jackson <[email protected]>
  • Loading branch information
imikejackson committed Jun 4, 2024
1 parent 6ee714b commit 43edc26
Show file tree
Hide file tree
Showing 11 changed files with 496 additions and 262 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,69 +7,13 @@
#include "simplnx/Utilities/DataGroupUtilities.hpp"
#include "simplnx/Utilities/ParallelAlgorithmUtilities.hpp"
#include "simplnx/Utilities/ParallelDataAlgorithm.hpp"
#include "simplnx/Utilities/ParallelTaskAlgorithm.hpp"

using namespace nx::core;

namespace
{
constexpr usize k_NumVerts = 2;

/**
* @brief
* @tparam T
*/
template <typename T>
class CopyCellDataArray
{
public:
CopyCellDataArray(const IDataArray& oldCellArray, IDataArray& newCellArray, const std::vector<usize>& newEdgesIndex, const std::atomic_bool& shouldCancel)
: m_OldCellArray(dynamic_cast<const DataArray<T>&>(oldCellArray))
, m_NewCellArray(dynamic_cast<DataArray<T>&>(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<T>(-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<T>& m_OldCellArray;
DataArray<T>& m_NewCellArray;
const std::vector<usize>& 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
Expand Down Expand Up @@ -125,29 +69,6 @@ class PopulateReducedGeometryEdgesImpl
const std::vector<usize>& m_NewVerticesIndex;
};

void transferElementData(DataStructure& m_DataStructure, AttributeMatrix& destCellDataAM, const std::vector<DataPath>& sourceDataPaths, const std::vector<usize>& 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<IDataArray>(edgeDataArrayPath);
const std::string srcName = oldDataArray.getName();

auto& newDataArray = dynamic_cast<IDataArray&>(destCellDataAM.at(srcName));
m_MessageHandler(fmt::format("Reducing Edge Geometry || Copying Data Array {}", srcName));
ExecuteParallelFunction<CopyCellDataArray>(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

// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -263,30 +184,32 @@ 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)
{
std::vector<DataPath> ignorePaths;
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)
{
std::vector<DataPath> ignorePaths;
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);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<TriangleGeom>(m_InputValues->ReducedTriangleGeometry);
auto& reducedTriangleGeom = m_DataStructure.getDataRefAs<TriangleGeom>(m_InputValues->ReducedTriangleGeometry);

// Set up allocated masks
usize size = originalTriangle.getNumberOfFaces();
Expand All @@ -120,41 +121,41 @@ Result<> RemoveFlaggedTriangles::operator()()
}

// flatten a list of the indices of vertices used by the triangles
std::vector<usize> VertexListIndices; // also used as a pseudo look up table in PopulateReducedGeometryTrianglesImpl
std::vector<usize> 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())
Expand All @@ -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<DataPath> 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<DataPath> 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 {};
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,45 @@
#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
{
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;
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,6 @@ using namespace nx::core;

namespace
{
template <typename GeometryType>
void createDataArrayActions(const DataStructure& dataStructure, const AttributeMatrix* sourceAttrMatPtr, const MultiArraySelectionParameter::ValueType& selectedArrayPaths,
const DataPath& reducedGeometryPathAttrMatPath, Result<OutputActions>& 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<IDataArray>(dataPath);
DataType dataType = srcArray.getDataType();
IDataStore::ShapeType componentShape = srcArray.getIDataStoreRef().getComponentShape();
DataPath dataArrayPath = reducedGeometryPathAttrMatPath.createChildPath(srcArray.getName());
resultOutputActions.value().appendAction(std::make_unique<CreateArrayAction>(dataType, sourceAttrMatPtr->getShape(), std::move(componentShape), dataArrayPath));
}
}

} // namespace

Expand Down Expand Up @@ -164,7 +149,7 @@ IFilter::PreflightResult RemoveFlaggedEdgesFilter::preflightImpl(const DataStruc
{
return {MakeErrorResult<OutputActions>(-5551, fmt::format("'{}' must have edge data attribute matrix", pInitialGeometryPathValue.toString()))};
}
createDataArrayActions<INodeGeometry1D>(dataStructure, srcEdgeAttrMatPtr, selectedEdgeArrays, reducedEdgeAttributeMatrixPath, resultOutputActions);
TransferGeometryElementData::createDataArrayActions<INodeGeometry1D>(dataStructure, srcEdgeAttrMatPtr, selectedEdgeArrays, reducedEdgeAttributeMatrixPath, resultOutputActions);
}
else if(pEdgeArrayHandling == k_CopyAllEdgeArraysIdx)
{
Expand All @@ -178,7 +163,7 @@ IFilter::PreflightResult RemoveFlaggedEdgesFilter::preflightImpl(const DataStruc
if(getChildrenResult.has_value())
{
selectedEdgeArrays = getChildrenResult.value();
createDataArrayActions<INodeGeometry1D>(dataStructure, srcEdgeAttrMatPtr, selectedEdgeArrays, reducedEdgeAttributeMatrixPath, resultOutputActions);
TransferGeometryElementData::createDataArrayActions<INodeGeometry1D>(dataStructure, srcEdgeAttrMatPtr, selectedEdgeArrays, reducedEdgeAttributeMatrixPath, resultOutputActions);
}
}
}
Expand All @@ -194,7 +179,7 @@ IFilter::PreflightResult RemoveFlaggedEdgesFilter::preflightImpl(const DataStruc
{
return {MakeErrorResult<OutputActions>(-5551, fmt::format("'{}' must have Vertex data attribute matrix", pInitialGeometryPathValue.toString()))};
}
createDataArrayActions<INodeGeometry1D>(dataStructure, srcVertexAttrMatPtr, selectedVertexArrays, reducedVertexAttributeMatrixPath, resultOutputActions);
TransferGeometryElementData::createDataArrayActions<INodeGeometry1D>(dataStructure, srcVertexAttrMatPtr, selectedVertexArrays, reducedVertexAttributeMatrixPath, resultOutputActions);
}
else if(pVertexArrayHandling == k_CopyAllVertexArraysIdx)
{
Expand All @@ -208,7 +193,7 @@ IFilter::PreflightResult RemoveFlaggedEdgesFilter::preflightImpl(const DataStruc
if(getChildrenResult.has_value())
{
selectedVertexArrays = getChildrenResult.value();
createDataArrayActions<INodeGeometry1D>(dataStructure, srcVertexAttrMatPtr, selectedVertexArrays, reducedVertexAttributeMatrixPath, resultOutputActions);
TransferGeometryElementData::createDataArrayActions<INodeGeometry1D>(dataStructure, srcVertexAttrMatPtr, selectedVertexArrays, reducedVertexAttributeMatrixPath, resultOutputActions);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
Loading

0 comments on commit 43edc26

Please sign in to comment.