diff --git a/src/Plugins/SimplnxCore/CMakeLists.txt b/src/Plugins/SimplnxCore/CMakeLists.txt index c021538117..2dae27cb3b 100644 --- a/src/Plugins/SimplnxCore/CMakeLists.txt +++ b/src/Plugins/SimplnxCore/CMakeLists.txt @@ -78,6 +78,7 @@ set(FilterList IterativeClosestPointFilter KMeansFilter KMedoidsFilter + LabelTriangleGeometryFilter LaplacianSmoothingFilter MapPointCloudToRegularGridFilter MinNeighbors @@ -98,6 +99,7 @@ set(FilterList ReadVolumeGraphicsFileFilter RegularGridSampleSurfaceMeshFilter RemoveFlaggedFeaturesFilter + RemoveFlaggedTrianglesFilter RemoveFlaggedVertices RemoveMinimumSizeFeaturesFilter RenameDataObject @@ -173,6 +175,7 @@ set(AlgorithmList ImageContouring KMeans KMedoids + LabelTriangleGeometry LaplacianSmoothing NearestPointFuseRegularGrids PartitionGeometry @@ -185,6 +188,7 @@ set(AlgorithmList ReadVolumeGraphicsFile RegularGridSampleSurfaceMesh RemoveFlaggedFeatures + RemoveFlaggedTriangles ReplaceElementAttributesWithNeighborValues ResampleImageGeom ResampleRectGridToImageGeom @@ -428,7 +432,7 @@ if(EXISTS "${DREAM3D_DATA_DIR}" AND SIMPLNX_DOWNLOAD_TEST_FILES) download_test_data(DREAM3D_DATA_DIR ${DREAM3D_DATA_DIR} ARCHIVE_NAME STL_Models.tar.gz - SHA512 14d5bbb1dcc241a5ad9b17e7647144926f22fca9af5e426798c2ed423d8d3b5d89d8c66ce9e6854bfcdbaea7f72b69980477ab837498e3dca89b5cd2870e2cff + SHA512 6a17caa1c5b60740a18d30732b10139b5864e12abd5009ce482972f4070f86e1762a3bf2bbceb8f178187b4d70bedbde1516f32397c3d4424404557b320dde9d INSTALL COPY_DATA ) diff --git a/src/Plugins/SimplnxCore/docs/Images/LabelTriangleGeometry_1.png b/src/Plugins/SimplnxCore/docs/Images/LabelTriangleGeometry_1.png new file mode 100644 index 0000000000..80b6e11572 Binary files /dev/null and b/src/Plugins/SimplnxCore/docs/Images/LabelTriangleGeometry_1.png differ diff --git a/src/Plugins/SimplnxCore/docs/Images/RemoveFlaggedTriangles_1.png b/src/Plugins/SimplnxCore/docs/Images/RemoveFlaggedTriangles_1.png new file mode 100644 index 0000000000..5695ac729d Binary files /dev/null and b/src/Plugins/SimplnxCore/docs/Images/RemoveFlaggedTriangles_1.png differ diff --git a/src/Plugins/SimplnxCore/docs/Images/RemoveFlaggedTriangles_2.png b/src/Plugins/SimplnxCore/docs/Images/RemoveFlaggedTriangles_2.png new file mode 100644 index 0000000000..2e1b240e4a Binary files /dev/null and b/src/Plugins/SimplnxCore/docs/Images/RemoveFlaggedTriangles_2.png differ diff --git a/src/Plugins/SimplnxCore/docs/Images/connectivity_image.png b/src/Plugins/SimplnxCore/docs/Images/connectivity_image.png new file mode 100644 index 0000000000..cfbbc97538 Binary files /dev/null and b/src/Plugins/SimplnxCore/docs/Images/connectivity_image.png differ diff --git a/src/Plugins/SimplnxCore/docs/LabelTriangleGeometryFilter.md b/src/Plugins/SimplnxCore/docs/LabelTriangleGeometryFilter.md new file mode 100644 index 0000000000..fb9739fba7 --- /dev/null +++ b/src/Plugins/SimplnxCore/docs/LabelTriangleGeometryFilter.md @@ -0,0 +1,35 @@ +# Label Triangle Geometry + +## Group (Subgroup) + +Surface Meshing (Geometry) + +## Description + +This **Filter** accepts a **Triangle Geometry** and checks the connectivity of **Triangles** and assigns them **region ID**s in a mask accordingly as well as providing a count for the number of **Triangles** in each **Region**. + +Note: Our connectivity is different from other connectivity algorithms, in that it is dependent on the dimensionality of the geometry it is run on. A triangle geometry is two dimensional thus it must share one edge with another triangle to be considered connected. Only one shared vertex will not be enough to count triangles as connected. See the following image for reference: + +![Connectivity Image](Images/connectivity_image.png) + +The image in question demonstrates what geometric shapes would be considered connected according to matching color scheme. The colors are relative to the shapes dimensionality. Thus the fact there is a yellow triangle and a yellow cube does not mean they are related. + +- 1D Geometry: Two edges are considered connected if they share a vertex. +- 2D Geometry: Triangle and Quad Geometries are considered connected if they share an entire edge. As shown in the image above, Triangles 1 & 2 are connected while triangles 2 & 3 are **not** connected. +- 3D Geometry: Hexahedron/Tetrahedron: In the image above the hexahedrons 4,5, and 6 are **not** considered connected while 6 & 7 are considered connected. + +## Example Output + +The image below shows a single STL file that contains 12 different geometries. This filter labeled each geometry with a unique "Region ID" and the visualization is colored by those "Region Ids" + +![Filter Output](Images/LabelTriangleGeometry_1.png) + +% Auto generated parameter table will be inserted here + +## License & Copyright + +Please see the description file distributed with this plugin. + +## DREAM3D-NX Help + +If you need help, need to file a bug report or want to request a new feature, please head over to the [DREAM3DNX-Issues](https://github.com/BlueQuartzSoftware/DREAM3DNX-Issues) GItHub site where the community of DREAM3D-NX users can help answer your questions. diff --git a/src/Plugins/SimplnxCore/docs/RegularGridSampleSurfaceMesh.md b/src/Plugins/SimplnxCore/docs/RegularGridSampleSurfaceMesh.md index bdac2c49b0..f287e84b22 100644 --- a/src/Plugins/SimplnxCore/docs/RegularGridSampleSurfaceMesh.md +++ b/src/Plugins/SimplnxCore/docs/RegularGridSampleSurfaceMesh.md @@ -13,31 +13,7 @@ This **Filter** "samples" a triangulated surface mesh on a rectilinear grid. The 3. For each bounding box a **Cell** falls in, check against that **Feature's** **Triangle** list to determine if the **Cell** falls within that n-sided polyhedra (*Note:* if the surface mesh is conformal, then each **Cell** will only belong to one **Feature**, but if not, the last **Feature** the **Cell** is found to fall inside of will *own* the **Cell**) 4. Assign the **Feature** number that the **Cell** falls within to the *Feature Ids* array in the new rectilinear grid geometry -## Parameters - -| Name | Type | Description | -|------------|------| --------------------------------- | -| Dimensions | uint64 | Number of **Cells** along each axis | -| Resolution | float32 (3x) | The resolution values (dx, dy, dz) | -| Origin | float32 (3x) | The origin of the sampling volume | - -## Required Geometry - -Triangle - -## Required Objects - -| Type | Default Name | Type | Comp Dims | Description | -|------|--------------|-----|-----|-----------------------------------| -| Data Array | Face Labels | int32 | (2) | Specifies which **Features** are on either side of each **Face**. | - -## Created - -| Kind | Default Name | Type | Comp Dims | Description | -|---------------------------|--------------|----------|--------|---------------------------------------------| -| Image Geometry | Image Geometry | N/A | N/A | Created **Image Geometry** name and *DataPath* | -| Attribute Matrix | Cell Data | Cell | N/A | Created **Cell Attribute Matrix** name | -| Data Array | Feature Ids | int32 | (1) | Specifies to which **Feature** each **Cell** belongs | +% Auto generated parameter table will be inserted here ## License & Copyright diff --git a/src/Plugins/SimplnxCore/docs/RemoveFlaggedFeaturesFilter.md b/src/Plugins/SimplnxCore/docs/RemoveFlaggedFeaturesFilter.md index 19be24adac..9c7e728a83 100644 --- a/src/Plugins/SimplnxCore/docs/RemoveFlaggedFeaturesFilter.md +++ b/src/Plugins/SimplnxCore/docs/RemoveFlaggedFeaturesFilter.md @@ -6,11 +6,11 @@ Processing (Cleanup) ## Description -This **Filter** will remove **Features** that have been flagged by another **Filter** from the structure. The **Filter** -requires that the user point to a boolean array at the **Feature** level that tells the **Filter** whether the **Feature** -should remain in the structure. If the boolean array is *false* for a **Feature**, then all **Cells** that belong to that -**Feature** are temporarily *unassigned*. Optionally, after all *undesired* **Features** are removed, the remaining **Features** are -isotropically coarsened to fill in the gaps left by the removed **Features**. +This **Filter** will remove **Features** that have been flagged by another **Filter** from the structure. The **Filter** requires that the user point to a boolean array at the **Feature** level that tells the **Filter** whether the **Feature** should remain in the structure. If the boolean array is *false* for a **Feature**, then all **Cells** that belong to that **Feature** are temporarily *unassigned*. Optionally, after all *undesired* **Features** are removed, the remaining **Features** are isotropically coarsened to fill in the gaps left by the removed **Features**. + +## Caveats + +This filter will **ONLY** run on an Image Geometry. % Auto generated parameter table will be inserted here diff --git a/src/Plugins/SimplnxCore/docs/RemoveFlaggedTrianglesFilter.md b/src/Plugins/SimplnxCore/docs/RemoveFlaggedTrianglesFilter.md new file mode 100644 index 0000000000..d31c651fe7 --- /dev/null +++ b/src/Plugins/SimplnxCore/docs/RemoveFlaggedTrianglesFilter.md @@ -0,0 +1,38 @@ +# Remove Flagged Triangles + +## Group (Subgroup) + +Surface Meshing (Misc) + +## Description + +This **Filter** removes **Triangles** from the supplied **Triangle Geometry** that are flagged by a boolean mask array as **true**. A new reduced **Geometry** is created that contains all the remaining **Triangles**. It is unknown until run time how many **Triangles** will be removed from the **Geometry**. Therefore, this **Filter** requires that a new **TriangleGeom** be created to contain the reduced **Triangle Geometry**. This new **Geometry** will *NOT* contain copies of any **Feature Attribute Matrix** or **Ensemble Attribute Matrix** from the original **Geometry**. + +- Additionally, all **Vertex** data will be copied, with tuples *removed* for any **Vertices** removed by the **Filter**. The user must supply a name for the reduced **Geometry**. + +The mask is expected to be over the triangles themselves so it should be based on something from the ***Face Data*** **Attribute Matrix**, generally we suggest basing the mask on the created **Region Ids** array from the *Label Triangle Geometry Filter*. + +*Note:* Since it cannot be known before run time how many **Vertices** will be removed, the new **Vertex Geometry** and +all associated **Vertex** data to be copied will be initialized to have size 0. + +## Example Output + +- The next figure shows a triangle geometry that has had a mask generated. Yellow parts are flagged as true. + +![Masked triangle geometries for removal.](Images/RemoveFlaggedTriangles_1.png) + +- The next figure shows the result of running the filter. + +![Resulting triangle geometry](Images/RemoveFlaggedTriangles_2.png) + +% Auto generated parameter table will be inserted here + +## Example Pipelines + +## License & Copyright + +Please see the description file distributed with this plugin. + +## DREAM3D-NX Help + +If you need help, need to file a bug report or want to request a new feature, please head over to the [DREAM3DNX-Issues](https://github.com/BlueQuartzSoftware/DREAM3DNX-Issues) GItHub site where the community of DREAM3D-NX users can help answer your questions. diff --git a/src/Plugins/SimplnxCore/pipelines/Remove_Triangles.d3dpipeline b/src/Plugins/SimplnxCore/pipelines/Remove_Triangles.d3dpipeline new file mode 100644 index 0000000000..628b9c2f8e --- /dev/null +++ b/src/Plugins/SimplnxCore/pipelines/Remove_Triangles.d3dpipeline @@ -0,0 +1,113 @@ +{ + "isDisabled": false, + "name": "Untitled Pipeline", + "pipeline": [ + { + "args": { + "face_attribute_matrix": "Face Data", + "face_normals_data_path": "Face Normals", + "scale_factor": 1.0, + "scale_output": false, + "stl_file_path": "Data/STL_Models/Example_Triangle_Geometry.stl", + "triangle_geometry_name": "TriangleDataContainer", + "vertex_attribute_matrix": "Vertex Data" + }, + "comments": "", + "filter": { + "name": "nx::core::ReadStlFileFilter", + "uuid": "2f64bd45-9d28-4254-9e07-6aa7c6d3d015" + }, + "isDisabled": false + }, + { + "args": { + "created_region_ids_path": "TriangleDataContainer/Face Data/Region Ids", + "num_triangles_name": "NumTriangles", + "triangle_attribute_matrix_name": "CAD Part Data", + "triangle_geom_path": "TriangleDataContainer" + }, + "comments": "", + "filter": { + "name": "nx::core::LabelTriangleGeometryFilter", + "uuid": "7a7a2c6f-3b03-444d-8b8c-5976b0e5c82e" + }, + "isDisabled": false + }, + { + "args": { + "array_thresholds": { + "inverted": false, + "thresholds": [ + { + "array_path": "TriangleDataContainer/Face Data/Region Ids", + "comparison": 0, + "inverted": false, + "type": "array", + "union": 0, + "value": 9.0 + } + ], + "type": "collection", + "union": 0 + }, + "created_data_path": "Mask", + "created_mask_type": 1, + "custom_false_value": 0.0, + "custom_true_value": 1.0, + "use_custom_false_value": false, + "use_custom_true_value": false + }, + "comments": "", + "filter": { + "name": "nx::core::MultiThresholdObjects", + "uuid": "4246245e-1011-4add-8436-0af6bed19228" + }, + "isDisabled": false + }, + { + "args": { + "array_thresholds": { + "inverted": false, + "thresholds": [ + { + "array_path": "TriangleDataContainer/Face Data/Region Ids", + "comparison": 0, + "inverted": false, + "type": "array", + "union": 0, + "value": 9.0 + } + ], + "type": "collection", + "union": 0 + }, + "created_data_path": "Mask2", + "created_mask_type": 10, + "custom_false_value": 0.0, + "custom_true_value": 1.0, + "use_custom_false_value": false, + "use_custom_true_value": false + }, + "comments": "", + "filter": { + "name": "nx::core::MultiThresholdObjects", + "uuid": "4246245e-1011-4add-8436-0af6bed19228" + }, + "isDisabled": false + }, + { + "args": { + "input_geometry": "TriangleDataContainer", + "mask_array_path": "TriangleDataContainer/Face Data/Mask2", + "output_geometry": "Part 10" + }, + "comments": "", + "filter": { + "name": "nx::core::RemoveFlaggedTrianglesFilter", + "uuid": "38155c61-2709-4731-be95-43745bb3f8d8" + }, + "isDisabled": false + } + ], + "version": 1 +} \ No newline at end of file diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/LabelTriangleGeometry.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/LabelTriangleGeometry.cpp new file mode 100644 index 0000000000..51484dd467 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/LabelTriangleGeometry.cpp @@ -0,0 +1,111 @@ +#include "LabelTriangleGeometry.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" +#include "simplnx/DataStructure/Geometry/TriangleGeom.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +LabelTriangleGeometry::LabelTriangleGeometry(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + LabelTriangleGeometryInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +LabelTriangleGeometry::~LabelTriangleGeometry() noexcept = default; + +// ----------------------------------------------------------------------------- +const std::atomic_bool& LabelTriangleGeometry::getCancel() +{ + return m_ShouldCancel; +} + +// ----------------------------------------------------------------------------- +Result<> LabelTriangleGeometry::operator()() +{ + // Scope other values since underlying arrays will be changed by the time they are need again + std::vector triangleCounts = {0, 0}; + auto& triangle = m_DataStructure.getDataRefAs(m_InputValues->TriangleGeomPath); + + { + usize numTris = triangle.getNumberOfFaces(); + + auto check = triangle.findElementNeighbors(); // use auto since return time is a class declared typename + if(check < 0) + { + return MakeErrorResult(check, fmt::format("Error finding element neighbors for {} geometry", triangle.getName())); + } + + const TriangleGeom::ElementDynamicList* triangleNeighborsPtr = triangle.getElementNeighbors(); + + auto& regionIds = m_DataStructure.getDataRefAs(m_InputValues->RegionIdsPath); + + usize chunkSize = 1000; + std::vector triList(chunkSize, -1); + // first identify connected triangle sets as features + int32 regionCount = 1; + for(usize i = 0; i < numTris; i++) + { + if(regionIds[i] == 0) + { + regionIds[i] = regionCount; + triangleCounts[regionCount]++; + + usize size = 0; + triList[size] = static_cast(i); + size++; + while(size > 0) + { + TriangleGeom::MeshIndexType tri = triList[size - 1]; + size -= 1; + uint16_t tCount = triangleNeighborsPtr->getNumberOfElements(tri); + TriangleGeom::MeshIndexType* dataPtr = triangleNeighborsPtr->getElementListPointer(tri); + for(int j = 0; j < tCount; j++) + { + TriangleGeom::MeshIndexType neighTri = dataPtr[j]; + if(regionIds[neighTri] == 0) + { + regionIds[neighTri] = regionCount; + triangleCounts[regionCount]++; + triList[size] = static_cast(neighTri); + size++; + if(size >= triList.size()) + { + size = triList.size(); + triList.resize(size + chunkSize); + for(usize k = size; k < triList.size(); ++k) + { + triList[k] = -1; + } + } + } + } + } + regionCount++; + triangleCounts.push_back(0); + } + } + + // Resize the Triangle Region AttributeMatrix + m_DataStructure.getDataAs(m_InputValues->TriangleAMPath)->resizeTuples(std::vector{triangleCounts.size()}); + } + + // Clear ElementDynamicLists so write out is possible + triangle.deleteElementNeighbors(); + // Remove elements containing vertices, because Element neighbors created it quietly under the covers + triangle.deleteElementsContainingVert(); + + // copy triangleCounts into the proper DataArray "NumTriangles" in the Feature Attribute Matrix + auto& numTriangles = m_DataStructure.getDataRefAs(m_InputValues->NumTrianglesPath); + for(usize index = 0; index < numTriangles.getSize(); index++) + { + numTriangles[index] = static_cast(triangleCounts[index]); + } + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/LabelTriangleGeometry.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/LabelTriangleGeometry.hpp new file mode 100644 index 0000000000..61096d8024 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/LabelTriangleGeometry.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/ArrayCreationParameter.hpp" +#include "simplnx/Parameters/DataGroupSelectionParameter.hpp" + +namespace nx::core +{ + +struct SIMPLNXCORE_EXPORT LabelTriangleGeometryInputValues +{ + DataPath TriangleGeomPath; + DataPath RegionIdsPath; + DataPath TriangleAMPath; + DataPath NumTrianglesPath; +}; + +/** + * @class ConditionalSetValue + * @brief This filter replaces values in the target array with a user specified value + * where a bool mask array specifies. + */ + +class SIMPLNXCORE_EXPORT LabelTriangleGeometry +{ +public: + LabelTriangleGeometry(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, LabelTriangleGeometryInputValues* inputValues); + ~LabelTriangleGeometry() noexcept; + + LabelTriangleGeometry(const LabelTriangleGeometry&) = delete; + LabelTriangleGeometry(LabelTriangleGeometry&&) noexcept = delete; + LabelTriangleGeometry& operator=(const LabelTriangleGeometry&) = delete; + LabelTriangleGeometry& operator=(LabelTriangleGeometry&&) noexcept = delete; + + Result<> operator()(); + + const std::atomic_bool& getCancel(); + +private: + DataStructure& m_DataStructure; + const LabelTriangleGeometryInputValues* 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/RemoveFlaggedTriangles.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedTriangles.cpp new file mode 100644 index 0000000000..9529ebd230 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedTriangles.cpp @@ -0,0 +1,163 @@ +#include "RemoveFlaggedTriangles.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataGroup.hpp" +#include "simplnx/DataStructure/Geometry/TriangleGeom.hpp" +#include "simplnx/Utilities/ParallelDataAlgorithm.hpp" + +using namespace nx::core; + +namespace +{ +/** + * @brief The PopulateReducedGeometryTrianglesImpl pulls the vertices associated with a triangle then locates the indices in + * the new VertexList then assigns that "new" triangle to Reduced Geometry + */ +class PopulateReducedGeometryTrianglesImpl +{ +public: + PopulateReducedGeometryTrianglesImpl(const TriangleGeom& originalTriangle, TriangleGeom& reducedTriangle, const std::vector& newTrianglesIndex, const std::vector& newVerticesIndex) + : m_OriginalTriangle(originalTriangle) + , m_ReducedTriangle(reducedTriangle) + , m_NewTrianglesIndex(newTrianglesIndex) + , m_NewVerticesIndex(newVerticesIndex) + { + } + ~PopulateReducedGeometryTrianglesImpl() = default; + + void generate(usize start, usize end) const + { + for(usize index = start; index < end; index++) + { + // pull old vertices + usize oldVertexIndices[3] = {0, 0, 0}; + m_OriginalTriangle.getFacePointIds(m_NewTrianglesIndex[index], oldVertexIndices); + + // locate new vertex index for each vertex index + usize newVertexIndices[3] = {0, 0, 0}; + for(usize vertIndex = 0; vertIndex < 3; vertIndex++) + { + const auto& itr = lower_bound(m_NewVerticesIndex.cbegin(), m_NewVerticesIndex.cend(), oldVertexIndices[vertIndex]); // find first instance of value as iterator + usize indexOfTarget = std::distance(m_NewVerticesIndex.cbegin(), itr); + newVertexIndices[vertIndex] = indexOfTarget; + } + + // set the triangle in reduced + m_ReducedTriangle.setFacePointIds(index, newVertexIndices); + } + } + + void operator()(const Range& range) const + { + generate(range.min(), range.max()); + } + +private: + const TriangleGeom& m_OriginalTriangle; + TriangleGeom& m_ReducedTriangle; + const std::vector& m_NewTrianglesIndex; + const std::vector& m_NewVerticesIndex; +}; +} // namespace + +// ----------------------------------------------------------------------------- +RemoveFlaggedTriangles::RemoveFlaggedTriangles(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + RemoveFlaggedTrianglesInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +const std::atomic_bool& RemoveFlaggedTriangles::getCancel() +{ + return m_ShouldCancel; +} + +// ----------------------------------------------------------------------------- +Result<> RemoveFlaggedTriangles::operator()() +{ + // Remove Triangles from reduced according to removeTrianglesIndex + const auto& originalTriangle = m_DataStructure.getDataRefAs(m_InputValues->TriangleGeometry); + const auto& mask = m_DataStructure.getDataRefAs(m_InputValues->MaskArrayPath); + auto& reducedTriangle = m_DataStructure.getDataRefAs(m_InputValues->ReducedTriangleGeometry); + + // Set up allocated masks + usize size = originalTriangle.getNumberOfFaces(); + std::vector newTrianglesIndexList; + newTrianglesIndexList.reserve(size); + + // parse mask Triangles list and load a list of indices for triangles to keep + for(usize index = 0; index < size; index++) + { + if(!mask[index]) + { + newTrianglesIndexList.push_back(index); + } + } + newTrianglesIndexList.shrink_to_fit(); + + if(getCancel()) + { + return {}; + } + if(newTrianglesIndexList.empty()) + { + return MakeErrorResult(-67880, "Re-evaluate mask conditions - with current configuration all triangles will be stripped!"); + } + + // 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 + 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]); + } + if(getCancel()) + { + return {}; + } + + 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()); + + // define new sizing + size = VertexListIndices.size(); + reducedTriangle.resizeVertexList(size); // resize accordingly + + // 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); + } + + if(getCancel()) + { + return {}; + } + + // Set up preprocessing conditions (allocation for parallelization) + size = newTrianglesIndexList.size(); + reducedTriangle.resizeFaceList(size); // resize accordingly + + // parse triangles and reassign indexes to match new vertex list + ParallelDataAlgorithm dataAlg; + dataAlg.setRange(0, size); + dataAlg.execute(PopulateReducedGeometryTrianglesImpl(originalTriangle, reducedTriangle, newTrianglesIndexList, VertexListIndices)); + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedTriangles.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedTriangles.hpp new file mode 100644 index 0000000000..a4374de110 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedTriangles.hpp @@ -0,0 +1,47 @@ +#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/DataGroupSelectionParameter.hpp" +#include "simplnx/Parameters/StringParameter.hpp" + +namespace nx::core +{ +struct SIMPLNXCORE_EXPORT RemoveFlaggedTrianglesInputValues +{ + DataPath TriangleGeometry; + DataPath MaskArrayPath; + DataPath ReducedTriangleGeometry; +}; + +/** + * @class ConditionalSetValue + * @brief This filter replaces values in the target array with a user specified value + * where a bool mask array specifies. + */ +class SIMPLNXCORE_EXPORT RemoveFlaggedTriangles +{ +public: + RemoveFlaggedTriangles(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, RemoveFlaggedTrianglesInputValues* inputValues); + ~RemoveFlaggedTriangles() noexcept = default; + + RemoveFlaggedTriangles(const RemoveFlaggedTriangles&) = delete; + RemoveFlaggedTriangles(RemoveFlaggedTriangles&&) noexcept = delete; + RemoveFlaggedTriangles& operator=(const RemoveFlaggedTriangles&) = delete; + RemoveFlaggedTriangles& operator=(RemoveFlaggedTriangles&&) noexcept = delete; + + Result<> operator()(); + + const std::atomic_bool& getCancel(); + +private: + DataStructure& m_DataStructure; + const RemoveFlaggedTrianglesInputValues* 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/LabelTriangleGeometryFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/LabelTriangleGeometryFilter.cpp new file mode 100644 index 0000000000..728f983b8b --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/LabelTriangleGeometryFilter.cpp @@ -0,0 +1,156 @@ +#include "LabelTriangleGeometryFilter.hpp" + +#include "SimplnxCore/Filters/Algorithms/LabelTriangleGeometry.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/DataStructure/Geometry/TriangleGeom.hpp" +#include "simplnx/Filter/Actions/CreateArrayAction.hpp" +#include "simplnx/Filter/Actions/CreateAttributeMatrixAction.hpp" +#include "simplnx/Parameters/ArrayCreationParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" +#include "simplnx/Utilities/SIMPLConversion.hpp" + +using namespace nx::core; + +namespace nx::core +{ +//------------------------------------------------------------------------------ +std::string LabelTriangleGeometryFilter::name() const +{ + return FilterTraits::name.str(); +} + +//------------------------------------------------------------------------------ +std::string LabelTriangleGeometryFilter::className() const +{ + return FilterTraits::className; +} + +//------------------------------------------------------------------------------ +Uuid LabelTriangleGeometryFilter::uuid() const +{ + return FilterTraits::uuid; +} + +//------------------------------------------------------------------------------ +std::string LabelTriangleGeometryFilter::humanName() const +{ + return "Label CAD Geometry"; +} + +//------------------------------------------------------------------------------ +std::vector LabelTriangleGeometryFilter::defaultTags() const +{ + return {"Surface Meshing", "Mapping"}; +} + +//------------------------------------------------------------------------------ +Parameters LabelTriangleGeometryFilter::parameters() const +{ + Parameters params; + + // Create the parameter descriptors that are needed for this filter + params.insertSeparator(Parameters::Separator{"Required Data Objects"}); + params.insert(std::make_unique(k_TriangleGeomPath_Key, "Triangle Geometry", "The CAD Geometry to be labeled (TriangleGeom)", DataPath{}, + GeometrySelectionParameter::AllowedTypes{GeometrySelectionParameter::AllowedType::Triangle})); + + params.insertSeparator(Parameters::Separator{"Created Data Objects"}); + params.insert(std::make_unique(k_CreatedRegionIdsPath_Key, "Region Ids", "The triangle id array for indexing into triangle groupings", DataPath({"Region Ids"}))); + + params.insert(std::make_unique(k_TriangleAttributeMatrixName_Key, "Cell Feature Attribute Matrix Name", + "The name of the Cell Feature Attribute Matrix that will hold information arrays about each group; created in the CAD geometry", + "Cell Feature AM")); + params.insert(std::make_unique(k_NumTrianglesName_Key, "Number of Triangles Array Name", + "The name of array created in the new AM that stores the number of triangles per group", "NumTriangles")); + + return params; +} + +//------------------------------------------------------------------------------ +IFilter::UniquePointer LabelTriangleGeometryFilter::clone() const +{ + return std::make_unique(); +} + +//------------------------------------------------------------------------------ +IFilter::PreflightResult LabelTriangleGeometryFilter::preflightImpl(const DataStructure& dataStructure, const Arguments& filterArgs, const MessageHandler& messageHandler, + const std::atomic_bool& shouldCancel) const +{ + auto pTriangleGeomPathValue = filterArgs.value(k_TriangleGeomPath_Key); + auto pRegionIdsNameValue = filterArgs.value(k_CreatedRegionIdsPath_Key); + auto pTriangleAMNameValue = filterArgs.value(k_TriangleAttributeMatrixName_Key); + auto pNumTrianglesNameValue = filterArgs.value(k_NumTrianglesName_Key); + + Result resultOutputActions; + std::vector preflightUpdatedValues; + + { + const auto* triangleGeomPtr = dataStructure.getDataAs(pTriangleGeomPathValue); + if(triangleGeomPtr == nullptr) + { + return MakePreflightErrorResult(-34510, fmt::format("{} is not a valid Triangle Geometry", pTriangleGeomPathValue.toString())); + } + usize numTris = triangleGeomPtr->getNumberOfFaces(); + auto createArrayAction = std::make_unique(DataType::int32, std::vector{numTris}, std::vector{1}, pRegionIdsNameValue); + resultOutputActions.value().appendAction(std::move(createArrayAction)); + } + + DataPath triAMPath = pTriangleGeomPathValue.createChildPath(pTriangleAMNameValue); + std::vector tDims(1, 1); + { + auto createAMAction = std::make_unique(triAMPath, tDims); + resultOutputActions.value().appendAction(std::move(createAMAction)); + } + + { + DataPath numTrianglesPath = triAMPath.createChildPath(pNumTrianglesNameValue); + auto createArrayAction = std::make_unique(DataType::uint64, tDims, std::vector{1}, numTrianglesPath); + resultOutputActions.value().appendAction(std::move(createArrayAction)); + } + + // Return both the resultOutputActions and the preflightUpdatedValues via std::move() + return {std::move(resultOutputActions), std::move(preflightUpdatedValues)}; +} + +//------------------------------------------------------------------------------ +Result<> LabelTriangleGeometryFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, + const std::atomic_bool& shouldCancel) const +{ + LabelTriangleGeometryInputValues inputValues; + + inputValues.TriangleGeomPath = filterArgs.value(k_TriangleGeomPath_Key); + inputValues.RegionIdsPath = filterArgs.value(k_CreatedRegionIdsPath_Key); + inputValues.TriangleAMPath = inputValues.TriangleGeomPath.createChildPath(filterArgs.value(k_TriangleAttributeMatrixName_Key)); + inputValues.NumTrianglesPath = inputValues.TriangleAMPath.createChildPath(filterArgs.value(k_NumTrianglesName_Key)); + + return LabelTriangleGeometry(dataStructure, messageHandler, shouldCancel, &inputValues)(); +} + +namespace +{ +namespace SIMPL +{ +constexpr StringLiteral k_CADDataContainerPathKey = "CADDataContainerPath"; +constexpr StringLiteral k_RegionIdArrayNameKey = "RegionIdArrayName"; +constexpr StringLiteral k_TriangleAttributeMatrixNameKey = "TriangleAttributeMatrixName"; +constexpr StringLiteral k_NumTrianglesArrayNameKey = "NumTrianglesArrayName"; +} // namespace SIMPL +} // namespace + +Result LabelTriangleGeometryFilter::FromSIMPLJson(const nlohmann::json& json) +{ + Arguments args = LabelTriangleGeometryFilter().getDefaultArguments(); + + std::vector> results; + + results.push_back(SIMPLConversion::ConvertParameter(args, json, SIMPL::k_CADDataContainerPathKey, k_TriangleGeomPath_Key)); + results.push_back(SIMPLConversion::ConvertParameter(args, json, SIMPL::k_RegionIdArrayNameKey, k_CreatedRegionIdsPath_Key)); + results.push_back(SIMPLConversion::ConvertParameter(args, json, SIMPL::k_TriangleAttributeMatrixNameKey, k_TriangleAttributeMatrixName_Key)); + results.push_back(SIMPLConversion::ConvertParameter>(args, json, SIMPL::k_NumTrianglesArrayNameKey, k_NumTrianglesName_Key)); + + Result<> conversionResult = MergeResults(std::move(results)); + + return ConvertResultTo(std::move(conversionResult), std::move(args)); +} +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/LabelTriangleGeometryFilter.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/LabelTriangleGeometryFilter.hpp new file mode 100644 index 0000000000..e90ba2db5f --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/LabelTriangleGeometryFilter.hpp @@ -0,0 +1,106 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/Filter/FilterTraits.hpp" +#include "simplnx/Filter/IFilter.hpp" + +namespace nx::core +{ +/** + * @class LabelTriangleGeometryFilter + * @brief + */ +class SIMPLNXCORE_EXPORT LabelTriangleGeometryFilter : public IFilter +{ +public: + LabelTriangleGeometryFilter() = default; + ~LabelTriangleGeometryFilter() noexcept override = default; + + LabelTriangleGeometryFilter(const LabelTriangleGeometryFilter&) = delete; + LabelTriangleGeometryFilter(LabelTriangleGeometryFilter&&) noexcept = delete; + + LabelTriangleGeometryFilter& operator=(const LabelTriangleGeometryFilter&) = delete; + LabelTriangleGeometryFilter& operator=(LabelTriangleGeometryFilter&&) noexcept = delete; + + // Parameter Keys + static inline constexpr StringLiteral k_TriangleGeomPath_Key = "triangle_geom_path"; + static inline constexpr StringLiteral k_CreatedRegionIdsPath_Key = "created_region_ids_path"; + static inline constexpr StringLiteral k_TriangleAttributeMatrixName_Key = "triangle_attribute_matrix_name"; + static inline constexpr StringLiteral k_NumTrianglesName_Key = "num_triangles_name"; + + /** + * @brief Reads SIMPL json and converts it complex Arguments. + * @param json + * @return Result + */ + static Result FromSIMPLJson(const nlohmann::json& json); + + /** + * @brief Returns the name of the filter. + * @return + */ + std::string name() const override; + + /** + * @brief Returns the C++ classname of this filter. + * @return + */ + std::string className() const override; + + /** + * @brief Returns the uuid of the filter. + * @return + */ + Uuid uuid() const override; + + /** + * @brief Returns the human readable name of the filter. + * @return + */ + std::string humanName() const override; + + /** + * @brief Returns the default tags for this filter. + * @return + */ + std::vector defaultTags() const override; + + /** + * @brief Returns the parameters of the filter (i.e. its inputs) + * @return + */ + Parameters parameters() const override; + + /** + * @brief Returns a copy of the filter. + * @return + */ + UniquePointer clone() const override; + +protected: + /** + * @brief Takes in a DataStructure and checks that the filter can be run on it with the given arguments. + * Returns any warnings/errors. Also returns the changes that would be applied to the DataStructure. + * Some parts of the actions may not be completely filled out if all the required information is not available at preflight time. + * @param ds The input DataStructure instance + * @param filterArgs These are the input values for each parameter that is required for the filter + * @param messageHandler The MessageHandler object + * @return Returns a Result object with error or warning values if any of those occurred during execution of this function + */ + PreflightResult preflightImpl(const DataStructure& ds, const Arguments& filterArgs, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel) const override; + + /** + * @brief Applies the filter's algorithm to the DataStructure with the given arguments. Returns any warnings/errors. + * On failure, there is no guarantee that the DataStructure is in a correct state. + * @param ds The input DataStructure instance + * @param filterArgs These are the input values for each parameter that is required for the filter + * @param messageHandler The MessageHandler object + * @return Returns a Result object with error or warning values if any of those occurred during execution of this function + */ + Result<> executeImpl(DataStructure& data, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel) const override; +}; +} // namespace nx::core + +SIMPLNX_DEF_FILTER_TRAITS(nx::core, LabelTriangleGeometryFilter, "7a7a2c6f-3b03-444d-8b8c-5976b0e5c82e"); +/* LEGACY UUID FOR THIS FILTER a250a228-3b6b-5b37-a6e4-8687484f04c4 */ diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedTrianglesFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedTrianglesFilter.cpp new file mode 100644 index 0000000000..9aae7d45cf --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedTrianglesFilter.cpp @@ -0,0 +1,143 @@ +#include "RemoveFlaggedTrianglesFilter.hpp" + +#include "SimplnxCore/Filters/Algorithms/RemoveFlaggedTriangles.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/Filter/Actions/CreateGeometry2DAction.hpp" +#include "simplnx/Filter/Actions/EmptyAction.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/DataGroupCreationParameter.hpp" +#include "simplnx/Parameters/GeometrySelectionParameter.hpp" +#include "simplnx/Parameters/StringParameter.hpp" +#include "simplnx/Utilities/SIMPLConversion.hpp" + +using namespace nx::core; + +namespace nx::core +{ +//------------------------------------------------------------------------------ +std::string RemoveFlaggedTrianglesFilter::name() const +{ + return FilterTraits::name.str(); +} + +//------------------------------------------------------------------------------ +std::string RemoveFlaggedTrianglesFilter::className() const +{ + return FilterTraits::className; +} + +//------------------------------------------------------------------------------ +Uuid RemoveFlaggedTrianglesFilter::uuid() const +{ + return FilterTraits::uuid; +} + +//------------------------------------------------------------------------------ +std::string RemoveFlaggedTrianglesFilter::humanName() const +{ + return "Remove Flagged Triangles"; +} + +//------------------------------------------------------------------------------ +std::vector RemoveFlaggedTrianglesFilter::defaultTags() const +{ + return {"Surface Meshing", "Cleanup"}; +} + +//------------------------------------------------------------------------------ +Parameters RemoveFlaggedTrianglesFilter::parameters() const +{ + Parameters params; + + // Create the parameter descriptors that are needed for this filter + params.insertSeparator(Parameters::Separator{"Required Input Data Objects"}); + params.insert(std::make_unique(k_InputGeometry_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_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}, ArraySelectionParameter::AllowedComponentShapes{{1}})); + + params.insertSeparator(Parameters::Separator{"Created Geometry"}); + params.insert(std::make_unique(k_OutputGeometry_Key, "Created Geometry", "The name of the created Triangle Geometry", DataPath({"ReducedGeometry"}))); + return params; +} + +//------------------------------------------------------------------------------ +IFilter::UniquePointer RemoveFlaggedTrianglesFilter::clone() const +{ + return std::make_unique(); +} + +//------------------------------------------------------------------------------ +IFilter::PreflightResult RemoveFlaggedTrianglesFilter::preflightImpl(const DataStructure& dataStructure, const Arguments& filterArgs, const MessageHandler& messageHandler, + const std::atomic_bool& shouldCancel) const +{ + auto pInitialGeometryPathValue = filterArgs.value(k_InputGeometry_Key); + auto pReducedGeometryPathValue = filterArgs.value(k_OutputGeometry_Key); + + PreflightResult preflightResult; + Result resultOutputActions; + std::vector preflightUpdatedValues; + + const auto* initialGeom = dataStructure.getDataAs(pInitialGeometryPathValue); + + if(initialGeom->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()); + resultOutputActions.value().appendAction(std::move(createGeometryAction)); + } + + if(initialGeom->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()); + resultOutputActions.value().appendAction(std::move(createGeometryAction)); + } + + // Return both the resultOutputActions and the preflightUpdatedValues via std::move() + return {std::move(resultOutputActions), std::move(preflightUpdatedValues)}; +} + +//------------------------------------------------------------------------------ +Result<> RemoveFlaggedTrianglesFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, + const std::atomic_bool& shouldCancel) const +{ + RemoveFlaggedTrianglesInputValues inputValues; + + inputValues.TriangleGeometry = filterArgs.value(k_InputGeometry_Key); + inputValues.MaskArrayPath = filterArgs.value(k_MaskArrayPath_Key); + inputValues.ReducedTriangleGeometry = filterArgs.value(k_OutputGeometry_Key); + + return RemoveFlaggedTriangles(dataStructure, messageHandler, shouldCancel, &inputValues)(); +} + +namespace +{ +namespace SIMPL +{ +constexpr StringLiteral k_TriangleGeometryKey = "TriangleGeometry"; +constexpr StringLiteral k_MaskArrayPathKey = "MaskArrayPath"; +constexpr StringLiteral k_ReducedTriangleGeometryKey = "ReducedTriangleGeometry"; +} // namespace SIMPL +} // namespace + +Result RemoveFlaggedTrianglesFilter::FromSIMPLJson(const nlohmann::json& json) +{ + Arguments args = RemoveFlaggedTrianglesFilter().getDefaultArguments(); + + std::vector> results; + + results.push_back(SIMPLConversion::ConvertParameter(args, json, SIMPL::k_TriangleGeometryKey, k_InputGeometry_Key)); + results.push_back(SIMPLConversion::ConvertParameter(args, json, SIMPL::k_MaskArrayPathKey, k_MaskArrayPath_Key)); + results.push_back(SIMPLConversion::ConvertParameter(args, json, SIMPL::k_ReducedTriangleGeometryKey, k_OutputGeometry_Key)); + + Result<> conversionResult = MergeResults(std::move(results)); + + return ConvertResultTo(std::move(conversionResult), std::move(args)); +} +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedTrianglesFilter.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedTrianglesFilter.hpp new file mode 100644 index 0000000000..5b03c04202 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RemoveFlaggedTrianglesFilter.hpp @@ -0,0 +1,105 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/Filter/FilterTraits.hpp" +#include "simplnx/Filter/IFilter.hpp" + +namespace nx::core +{ +/** + * @class RemoveFlaggedTrianglesFilter + * @brief This filter will .... + */ +class SIMPLNXCORE_EXPORT RemoveFlaggedTrianglesFilter : public IFilter +{ +public: + RemoveFlaggedTrianglesFilter() = default; + ~RemoveFlaggedTrianglesFilter() noexcept override = default; + + RemoveFlaggedTrianglesFilter(const RemoveFlaggedTrianglesFilter&) = delete; + RemoveFlaggedTrianglesFilter(RemoveFlaggedTrianglesFilter&&) noexcept = delete; + + RemoveFlaggedTrianglesFilter& operator=(const RemoveFlaggedTrianglesFilter&) = delete; + RemoveFlaggedTrianglesFilter& operator=(RemoveFlaggedTrianglesFilter&&) noexcept = delete; + + // Parameter Keys + static inline constexpr StringLiteral k_InputGeometry_Key = "input_geometry"; + static inline constexpr StringLiteral k_MaskArrayPath_Key = "mask_array_path"; + static inline constexpr StringLiteral k_OutputGeometry_Key = "output_geometry"; + + /** + * @brief Reads SIMPL json and converts it complex Arguments. + * @param json + * @return Result + */ + static Result FromSIMPLJson(const nlohmann::json& json); + + /** + * @brief Returns the name of the filter. + * @return + */ + std::string name() const override; + + /** + * @brief Returns the C++ classname of this filter. + * @return + */ + std::string className() const override; + + /** + * @brief Returns the uuid of the filter. + * @return + */ + Uuid uuid() const override; + + /** + * @brief Returns the human readable name of the filter. + * @return + */ + std::string humanName() const override; + + /** + * @brief Returns the default tags for this filter. + * @return + */ + std::vector defaultTags() const override; + + /** + * @brief Returns the parameters of the filter (i.e. its inputs) + * @return + */ + Parameters parameters() const override; + + /** + * @brief Returns a copy of the filter. + * @return + */ + UniquePointer clone() const override; + +protected: + /** + * @brief Takes in a DataStructure and checks that the filter can be run on it with the given arguments. + * Returns any warnings/errors. Also returns the changes that would be applied to the DataStructure. + * Some parts of the actions may not be completely filled out if all the required information is not available at preflight time. + * @param ds The input DataStructure instance + * @param filterArgs These are the input values for each parameter that is required for the filter + * @param messageHandler The MessageHandler object + * @return Returns a Result object with error or warning values if any of those occurred during execution of this function + */ + PreflightResult preflightImpl(const DataStructure& ds, const Arguments& filterArgs, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel) const override; + + /** + * @brief Applies the filter's algorithm to the DataStructure with the given arguments. Returns any warnings/errors. + * On failure, there is no guarantee that the DataStructure is in a correct state. + * @param ds The input DataStructure instance + * @param filterArgs These are the input values for each parameter that is required for the filter + * @param messageHandler The MessageHandler object + * @return Returns a Result object with error or warning values if any of those occurred during execution of this function + */ + Result<> executeImpl(DataStructure& data, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel) const override; +}; +} // namespace nx::core + +SIMPLNX_DEF_FILTER_TRAITS(nx::core, RemoveFlaggedTrianglesFilter, "38155c61-2709-4731-be95-43745bb3f8d8"); +/* LEGACY UUID FOR THIS FILTER 379ccc67-16dd-530a-984f-177db9351bac */ diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/SimplnxCoreLegacyUUIDMapping.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/SimplnxCoreLegacyUUIDMapping.hpp index 1f9bd98fdf..c8b0d01396 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/SimplnxCoreLegacyUUIDMapping.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/SimplnxCoreLegacyUUIDMapping.hpp @@ -118,6 +118,8 @@ #include "SimplnxCore/Filters/KMedoidsFilter.hpp" #include "SimplnxCore/Filters/KMeansFilter.hpp" #include "SimplnxCore/Filters/SilhouetteFilter.hpp" +#include "SimplnxCore/Filters/LabelTriangleGeometryFilter.hpp" +#include "SimplnxCore/Filters/RemoveFlaggedTrianglesFilter.hpp" // @@__HEADER__TOKEN__DO__NOT__DELETE__@@ namespace nx::core @@ -241,6 +243,8 @@ namespace nx::core {nx::core::Uuid::FromString("f7486aa6-3049-5be7-8511-ae772b70c90b").value(), {nx::core::FilterTraits::uuid, &KMedoidsFilter::FromSIMPLJson}}, // KMedoids {nx::core::Uuid::FromString("b56a04de-0ca0-509d-809f-52219fca9c98").value(), {nx::core::FilterTraits::uuid, &KMeansFilter::FromSIMPLJson}}, // KMeans {nx::core::Uuid::FromString("f84d4d69-9ea5-54b6-a71c-df76d76d50cf").value(), {nx::core::FilterTraits::uuid, &SilhouetteFilter::FromSIMPLJson}}, // Silhouette + {nx::core::Uuid::FromString("a250a228-3b6b-5b37-a6e4-8687484f04c4").value(), {nx::core::FilterTraits::uuid, &LabelTriangleGeometryFilter::FromSIMPLJson}}, // LabelTriangleGeometry + {nx::core::Uuid::FromString("379ccc67-16dd-530a-984f-177db9351bac").value(), {nx::core::FilterTraits::uuid, &RemoveFlaggedTrianglesFilter::FromSIMPLJson}}, // RemoveFlaggedTriangles // @@__MAP__UPDATE__TOKEN__DO__NOT__DELETE__@@ }; diff --git a/src/Plugins/SimplnxCore/test/CMakeLists.txt b/src/Plugins/SimplnxCore/test/CMakeLists.txt index 67a3e9a4b9..69e8a24f66 100644 --- a/src/Plugins/SimplnxCore/test/CMakeLists.txt +++ b/src/Plugins/SimplnxCore/test/CMakeLists.txt @@ -79,6 +79,7 @@ set(${PLUGIN_NAME}UnitTest_SRCS IterativeClosestPointTest.cpp KMeansTest.cpp KMedoidsTest.cpp + LabelTriangleGeometryTest.cpp LaplacianSmoothingFilterTest.cpp MapPointCloudToRegularGridTest.cpp MinNeighborsTest.cpp @@ -99,6 +100,7 @@ set(${PLUGIN_NAME}UnitTest_SRCS ReadVolumeGraphicsFileTest.cpp RegularGridSampleSurfaceMeshTest.cpp RemoveFlaggedFeaturesTest.cpp + RemoveFlaggedTrianglesTest.cpp RemoveFlaggedVerticesTest.cpp RemoveMinimumSizeFeaturesTest.cpp RenameDataObjectTest.cpp @@ -206,7 +208,7 @@ if(EXISTS "${DREAM3D_DATA_DIR}" AND SIMPLNX_DOWNLOAD_TEST_FILES) download_test_data(DREAM3D_DATA_DIR ${DREAM3D_DATA_DIR} ARCHIVE_NAME 6_6_write_stl_test.tar.gz SHA512 d1e929246f73515b006d99392414a4b5a2afe6c96261a7cbccbcbb68cc0be1e43a987f6ab4a8fff21914fe3f15bf7f59b4387d8314cbdf8697f5c8cea40fa481) download_test_data(DREAM3D_DATA_DIR ${DREAM3D_DATA_DIR} ARCHIVE_NAME 6_6_interpolate_point_cloud_to_regular_grid.tar.gz SHA512 287500082913dfbf62c5f66ec5185c3db53cedc20a2c89c28b23a208ddfca47c377d557d2f509c1d72f3aff8aadc3058e6932159a6cef73f33227ad433f14752) download_test_data(DREAM3D_DATA_DIR ${DREAM3D_DATA_DIR} ARCHIVE_NAME 6_6_resample_rect_grid_to_image_geom.tar.gz SHA512 58cabfb83deeef7aff1252963a8cb378745ca00fc120a9623f699b4c9c618d216c4d3fa88e964772706a0096e979abc741be7ba6f96a2398162b3f6d4ec8ec13) - download_test_data(DREAM3D_DATA_DIR ${DREAM3D_DATA_DIR} ARCHIVE_NAME 6_6_combine_stl_files.tar.gz SHA512 109dfb39ac04213a7d8bc8ef3d852f112177ad1a1c624926e980c2a3e30af04ff3c48b8cf315d04fd2b8d0270b1defa33078511243d9ac2def37a8b43884120b) + download_test_data(DREAM3D_DATA_DIR ${DREAM3D_DATA_DIR} ARCHIVE_NAME 6_6_combine_stl_files_v2.tar.gz SHA512 40235976b9897365c338587056dc9ba90466b3eca58d6b310d59f7df16592b53647349daa1c7247cdcf01b5940596ad53d39eb734549dda4e829ae93a5928a4a) download_test_data(DREAM3D_DATA_DIR ${DREAM3D_DATA_DIR} ARCHIVE_NAME 6_6_avizo_writers.tar.gz SHA512 f776eb5c86e06bde0fb1ee76dbdf95e4fd1457697033b2c639cac376db3ba0b05410ed4074fb10a47dd26ef79c78a02b5bb77c04cfe1299e8a33d8b3bff09749) download_test_data(DREAM3D_DATA_DIR ${DREAM3D_DATA_DIR} ARCHIVE_NAME vtk_rectilinear_grid_writer.tar.gz SHA512 9fef02b5269609503d03dd0126cc635cc1c1156894cff18b0184b334d705b850ca1a06ae0d1c66a352a32dd9ad9fb74f24255c7de1399b06bbec7d2e2b41941b ) download_test_data(DREAM3D_DATA_DIR ${DREAM3D_DATA_DIR} ARCHIVE_NAME Small_IN100_dream3d.tar.gz SHA512 6dd8a3412532bdc7481f7781c7087b4477c6a1efbe6b214f997dad30c53c59714a751be522f084b98065fe75100c74df901bb8af2f512ef47344d8f7941575cf ) @@ -222,6 +224,8 @@ if(EXISTS "${DREAM3D_DATA_DIR}" AND SIMPLNX_DOWNLOAD_TEST_FILES) download_test_data(DREAM3D_DATA_DIR ${DREAM3D_DATA_DIR} ARCHIVE_NAME SurfaceMeshTest.tar.gz SHA512 a74e9fa40ccec78174dbbac90969bfa17367c3a7e14b7b84624032317c351de89957750803d7cb43c67dec19281ee4f647de022d474566fd43e25b8230cce6d6) download_test_data(DREAM3D_DATA_DIR ${DREAM3D_DATA_DIR} ARCHIVE_NAME initialize_data_test_files.tar.gz SHA512 f04fe76ef96add4b775111ae7fc95233a7748a25501d9f00a8b2a162c87782b8cd2813e6e46ba7892e721976693da06965e624335dbb28224c9c5b877a05aa49) download_test_data(DREAM3D_DATA_DIR ${DREAM3D_DATA_DIR} ARCHIVE_NAME 6_6_write_stl_file_test.tar.gz SHA512 05455dfb57724a14a3b2d92ad02ac335b5596ca4f353830ee60d84ffc858523136140328a1c95b6693331be9dc5c40a26e76f45ee54ab11e218f5efb6b2a4c38) + download_test_data(DREAM3D_DATA_DIR ${DREAM3D_DATA_DIR} ARCHIVE_NAME label_triangle_geometry_test.tar.gz SHA512 9281fa954c842ca1881ba932d6d96b9c43601b466b6b7ae33721d1c886629ba68986a3ccaf774f5be577e8bfce145612f77a2b98af319e6aa35a3e0aeb607597) + download_test_data(DREAM3D_DATA_DIR ${DREAM3D_DATA_DIR} ARCHIVE_NAME remove_flagged_triangles_test.tar.gz SHA512 cd5c6f3ea16a6d09e00e0c0bd0f941b27dca8a0beaeabb7262a2a6adaad83c829187c5d1aa433718123b628eaa839f016604c1134ced9f870723594b2df4be99) endif() @@ -243,7 +247,8 @@ set(PREBUILT_PIPELINE_NAMES "${${PLUGIN_NAME}_SOURCE_DIR}/pipelines/Import_CSV_Data.d3dpipeline" "${${PLUGIN_NAME}_SOURCE_DIR}/pipelines/Import_STL_Model.d3dpipeline" "${${PLUGIN_NAME}_SOURCE_DIR}/pipelines/Triangle_Face_Data_Demo.d3dpipeline" - + "${${PLUGIN_NAME}_SOURCE_DIR}/pipelines/Remove_Triangles.d3dpipeline" + # These are workflow files # "${${PLUGIN_NAME}_SOURCE_DIR}/pipelines/Import_ASCII_Data.d3dworkflow" diff --git a/src/Plugins/SimplnxCore/test/CombineStlFilesTest.cpp b/src/Plugins/SimplnxCore/test/CombineStlFilesTest.cpp index 1053bbee7f..5f51b1efb2 100644 --- a/src/Plugins/SimplnxCore/test/CombineStlFilesTest.cpp +++ b/src/Plugins/SimplnxCore/test/CombineStlFilesTest.cpp @@ -21,16 +21,14 @@ inline const DataPath k_ExemplarTriangleDataContainerName({k_TriangleDataContain TEST_CASE("SimplnxCore::CombineStlFilesFilter: Valid Filter Execution", "[SimplnxCore][CombineStlFilesFilter]") { - const nx::core::UnitTest::TestFileSentinel testDataSentinel(nx::core::unit_test::k_CMakeExecutable, nx::core::unit_test::k_TestFilesDir, "6_6_combine_stl_files.tar.gz", + const nx::core::UnitTest::TestFileSentinel testDataSentinel(nx::core::unit_test::k_CMakeExecutable, nx::core::unit_test::k_TestFilesDir, "6_6_combine_stl_files_v2.tar.gz", "6_6_combine_stl_files.dream3d"); - const nx::core::UnitTest::TestFileSentinel testDataSentinel1(nx::core::unit_test::k_CMakeExecutable, nx::core::unit_test::k_TestFilesDir, "STL_Models.tar.gz", "STL_Models"); - // Read Exemplar DREAM3D File Filter - auto exemplarFilePath = fs::path(fmt::format("{}/6_6_combine_stl_files.dream3d", unit_test::k_TestFilesDir)); + auto exemplarFilePath = fs::path(fmt::format("{}/6_6_combine_stl_files_v2/6_6_combine_stl_files.dream3d", unit_test::k_TestFilesDir)); DataStructure dataStructure = UnitTest::LoadDataStructure(exemplarFilePath); - std::string inputStlDir = fmt::format("{}/STL_Models", unit_test::k_TestFilesDir.view()); + std::string inputStlDir = fmt::format("{}/6_6_combine_stl_files_v2/STL_Models", unit_test::k_TestFilesDir.view()); // Instantiate the filter, a DataStructure object and an Arguments Object CombineStlFilesFilter filter; diff --git a/src/Plugins/SimplnxCore/test/LabelTriangleGeometryTest.cpp b/src/Plugins/SimplnxCore/test/LabelTriangleGeometryTest.cpp new file mode 100644 index 0000000000..e2ed39c087 --- /dev/null +++ b/src/Plugins/SimplnxCore/test/LabelTriangleGeometryTest.cpp @@ -0,0 +1,55 @@ +#include + +#include "SimplnxCore/Filters/LabelTriangleGeometryFilter.hpp" +#include "SimplnxCore/SimplnxCore_test_dirs.hpp" +#include "simplnx/UnitTest/UnitTestCommon.hpp" + +using namespace nx::core; + +namespace +{ +fs::path k_ExemplarDataFilePath = fs::path(fmt::format("{}/label_triangle_geometry_test/label_triangle_geometry_test.dream3d", nx::core::unit_test::k_TestFilesDir)); +fs::path k_BaseDataFilePath = fs::path(fmt::format("{}/label_triangle_geometry_test/data_to_generate_test/combined_stls.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"; + +const DataPath k_TriangleGeomPath({"TriangleGeometry"}); +const DataPath k_CreatedRegionIdsPath = k_TriangleGeomPath.createChildPath(Constants::k_Face_Data).createChildPath(k_RegionIdsName); +const DataPath k_CellFeatureAMPath = k_TriangleGeomPath.createChildPath(k_CreatedAMName); +const DataPath k_NumTrianglesPath = k_CellFeatureAMPath.createChildPath(k_NumTrianglesName); +} // namespace + +TEST_CASE("SimplnxCore::LabelTriangleGeometryFilter: Valid Filter Execution", "[SimplnxCore][LabelTriangleGeometryFilter]") +{ + const nx::core::UnitTest::TestFileSentinel testDataSentinel(nx::core::unit_test::k_CMakeExecutable, nx::core::unit_test::k_TestFilesDir, "label_triangle_geometry_test.tar.gz", + "label_triangle_geometry_test"); + + DataStructure dataStructure = UnitTest::LoadDataStructure(k_BaseDataFilePath); + + { + // Instantiate the filter, a DataStructure object and an Arguments Object + LabelTriangleGeometryFilter filter; + Arguments args; + + // Create default Parameters for the filter. + args.insertOrAssign(LabelTriangleGeometryFilter::k_TriangleGeomPath_Key, std::make_any(::k_TriangleGeomPath)); + args.insertOrAssign(LabelTriangleGeometryFilter::k_CreatedRegionIdsPath_Key, std::make_any(::k_CreatedRegionIdsPath)); + args.insertOrAssign(LabelTriangleGeometryFilter::k_TriangleAttributeMatrixName_Key, std::make_any(::k_CreatedAMName)); + args.insertOrAssign(LabelTriangleGeometryFilter::k_NumTrianglesName_Key, std::make_any(::k_NumTrianglesName)); + + // Preflight the filter and check result + auto preflightResult = filter.preflight(dataStructure, args); + REQUIRE(preflightResult.outputActions.valid()); + + // Execute the filter and check the result + auto executeResult = filter.execute(dataStructure, args); + REQUIRE(executeResult.result.valid()); + } + + DataStructure exemplarDataStructure = UnitTest::LoadDataStructure(k_ExemplarDataFilePath); + + UnitTest::CompareExemplarToGeneratedData(dataStructure, exemplarDataStructure, ::k_CellFeatureAMPath, ::k_TriangleGeomPath.toString()); + UnitTest::CompareExemplarToGeneratedData(dataStructure, exemplarDataStructure, ::k_TriangleGeomPath.createChildPath(Constants::k_Face_Data), ::k_TriangleGeomPath.toString()); +} diff --git a/src/Plugins/SimplnxCore/test/RemoveFlaggedTrianglesTest.cpp b/src/Plugins/SimplnxCore/test/RemoveFlaggedTrianglesTest.cpp new file mode 100644 index 0000000000..ab0f8b30bb --- /dev/null +++ b/src/Plugins/SimplnxCore/test/RemoveFlaggedTrianglesTest.cpp @@ -0,0 +1,58 @@ +#include + +#include "SimplnxCore/Filters/RemoveFlaggedTrianglesFilter.hpp" +#include "SimplnxCore/SimplnxCore_test_dirs.hpp" +#include "simplnx/UnitTest/UnitTestCommon.hpp" + +using namespace nx::core; + +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)); + +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_VertexListPath = k_ReducedGeomPath.createChildPath("SharedVertexList"); +const DataPath k_TriangleListPath = k_ReducedGeomPath.createChildPath("SharedTriList"); +} // namespace +} // namespace + +TEST_CASE("SimplnxCore::RemoveFlaggedTrianglesFilter: Valid Filter Execution", "[SimplnxCore][RemoveFlaggedTrianglesFilter]") +{ + const UnitTest::TestFileSentinel testDataSentinel(unit_test::k_CMakeExecutable, unit_test::k_TestFilesDir, "remove_flagged_triangles_test.tar.gz", "remove_flagged_triangles_test.dream3d"); + + // Load DataStructure containing the base geometry and an exemplar cleaned geometry + DataStructure dataStructure = UnitTest::LoadDataStructure(k_BaseDataFilePath); + { + // Instantiate the filter and an Arguments Object + RemoveFlaggedTrianglesFilter filter; + Arguments args; + + // Create default Parameters for the filter. + args.insertOrAssign(RemoveFlaggedTrianglesFilter::k_InputGeometry_Key, std::make_any(::k_TriangleGeomPath)); + args.insertOrAssign(RemoveFlaggedTrianglesFilter::k_MaskArrayPath_Key, std::make_any(::k_MaskPath)); + args.insertOrAssign(RemoveFlaggedTrianglesFilter::k_OutputGeometry_Key, std::make_any(::k_ReducedGeomPath)); + + // Preflight the filter and check result + auto preflightResult = filter.preflight(dataStructure, args); + REQUIRE(preflightResult.outputActions.valid()); + + // Execute the filter and check the result + auto executeResult = filter.execute(dataStructure, args); + REQUIRE(executeResult.result.valid()); + } + + DataStructure exemplarDataStructure = UnitTest::LoadDataStructure(k_ExemplarDataFilePath); + + UnitTest::CompareDataArrays(dataStructure.getDataRefAs(::k_TriangleListPath), exemplarDataStructure.getDataRefAs(::k_TriangleListPath)); + UnitTest::CompareDataArrays(dataStructure.getDataRefAs(::k_VertexListPath), exemplarDataStructure.getDataRefAs(::k_VertexListPath)); +} diff --git a/src/simplnx/DataStructure/DynamicListArray.hpp b/src/simplnx/DataStructure/DynamicListArray.hpp index 90e60148e5..d9c3b3ae29 100644 --- a/src/simplnx/DataStructure/DynamicListArray.hpp +++ b/src/simplnx/DataStructure/DynamicListArray.hpp @@ -85,9 +85,14 @@ class DynamicListArray : public DataObject */ DynamicListArray(const DynamicListArray& other) : DataObject(other) - , m_Array(other.m_Array) , m_Size(other.m_Size) { + allocate(other.m_Size); + + for(usize i = 0; i < other.m_Size; i++) + { + setElementList(i, other.m_Array[i]); + } } /** @@ -187,7 +192,7 @@ class DynamicListArray : public DataObject */ DataObject* shallowCopy() override { - throw std::runtime_error(""); + return new DynamicListArray(*this); } /** @@ -356,17 +361,18 @@ class DynamicListArray : public DataObject { static typename DynamicListArray::ElementList linkInit = {0, nullptr}; - // This makes sure we deallocate any lists that have been created - for(usize i = 0; i < this->m_Size; i++) + if(this->m_Array != nullptr) { - if(this->m_Array[i].cells != nullptr) + // This makes sure we deallocate any lists that have been created + for(usize i = 0; i < this->m_Size; i++) { - delete[] this->m_Array[i].cells; + if(this->m_Array[i].cells != nullptr) + { + delete[] this->m_Array[i].cells; + } } - } - // Now delete all the "ElementList" structures - if(this->m_Array != nullptr) - { + + // Now delete all the "ElementList" structures delete[] this->m_Array; } diff --git a/src/simplnx/DataStructure/Geometry/INodeGeometry1D.cpp b/src/simplnx/DataStructure/Geometry/INodeGeometry1D.cpp index 25af60551d..e5978f8a72 100644 --- a/src/simplnx/DataStructure/Geometry/INodeGeometry1D.cpp +++ b/src/simplnx/DataStructure/Geometry/INodeGeometry1D.cpp @@ -122,7 +122,10 @@ const INodeGeometry1D::ElementDynamicList* INodeGeometry1D::getElementNeighbors( void INodeGeometry1D::deleteElementNeighbors() { - getDataStructureRef().removeData(m_CellNeighborsDataArrayId); + if(!getDataStructureRef().removeData(m_CellNeighborsDataArrayId)) + { + throw std::runtime_error(fmt::format("{}({}): Function {}: Unable to remove Element Neighbors", "deleteElementNeighbors()", __FILE__, __LINE__)); + } m_CellNeighborsDataArrayId.reset(); } diff --git a/src/simplnx/DataStructure/Geometry/TriangleGeom.cpp b/src/simplnx/DataStructure/Geometry/TriangleGeom.cpp index 6edd32b351..9bec7aabeb 100644 --- a/src/simplnx/DataStructure/Geometry/TriangleGeom.cpp +++ b/src/simplnx/DataStructure/Geometry/TriangleGeom.cpp @@ -196,7 +196,7 @@ IGeometry::StatusCode TriangleGeom::findElementsContainingVert() IGeometry::StatusCode TriangleGeom::findElementNeighbors() { - StatusCode err = 0; + StatusCode err; if(getElementsContainingVert() == nullptr) { err = findElementsContainingVert(); @@ -205,7 +205,7 @@ IGeometry::StatusCode TriangleGeom::findElementNeighbors() return err; } } - auto triangleNeighbors = DynamicListArray::Create(*getDataStructure(), k_EltNeighbors, getId()); + auto triangleNeighbors = ElementDynamicList::Create(*getDataStructure(), k_EltNeighbors, getId()); err = GeometryHelpers::Connectivity::FindElementNeighbors(getFaces(), getElementsContainingVert(), triangleNeighbors, IGeometry::Type::Triangle); if(triangleNeighbors == nullptr) { diff --git a/src/simplnx/Utilities/GeometryHelpers.hpp b/src/simplnx/Utilities/GeometryHelpers.hpp index eaa0ceb83f..74bbc40b47 100644 --- a/src/simplnx/Utilities/GeometryHelpers.hpp +++ b/src/simplnx/Utilities/GeometryHelpers.hpp @@ -174,6 +174,7 @@ ErrorCode FindElementNeighbors(const DataArray* elemList, const DynamicListAr continue; } // We already added this element so loop again // qDebug() << " Comparing Element " << vertIdxs[vt] << "\n"; + auto vertCell = elemList->cbegin() + (vertIdxs[vt] * elemList->getNumberOfComponents()); usize vCount = 0; // Loop over all the vertex indices of this element and try to match numSharedVerts of them to the current loop element // If there is numSharedVerts match then that element is a neighbor of the source. If there are more than numVertsPerElem @@ -182,7 +183,7 @@ ErrorCode FindElementNeighbors(const DataArray* elemList, const DynamicListAr { for(usize j = 0; j < numVertsPerElem; j++) { - if(elems[offset + i] == elems[offset + j]) + if(elems[offset + i] == *(vertCell + j)) { vCount++; }