Skip to content

Commit

Permalink
BUG: Fixes issue where any component shape was allowed for ComputeTri…
Browse files Browse the repository at this point in the history
…angleGeometrySizes (#1134)

* BUG: Fixes issue where any component shape were allowed for ComputeTriangleGeometrySizes.cpp
* Fix all instances of "Face Labels" are only allowed to use 2 component input arrays
* ComputeTriangleGeomVolumes - fix possible walking off the end of the array.
	A negative value for the face label when used as an index will cast into an unsigned value and bad things are going to happen.
* BUG: Fixes negative volumes produced from calculations

---------

Signed-off-by: Michael Jackson <[email protected]>
  • Loading branch information
imikejackson authored Nov 24, 2024
1 parent 0d00a5f commit 4f44d73
Show file tree
Hide file tree
Showing 19 changed files with 234 additions and 120 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Parameters ComputeTriangleGeomShapesFilter::parameters() const
GeometrySelectionParameter::AllowedTypes{IGeometry::Type::Triangle}));
params.insertSeparator(Parameters::Separator{"Input Triangle Face Data"});
params.insert(std::make_unique<ArraySelectionParameter>(k_FaceLabelsArrayPath_Key, "Face Labels", "The DataPath to the FaceLabels values.", DataPath{},
ArraySelectionParameter::AllowedTypes{nx::core::DataType::int32}));
ArraySelectionParameter::AllowedTypes{nx::core::DataType::int32}, ArraySelectionParameter::AllowedComponentShapes{{2}}));

params.insertSeparator(Parameters::Separator{"Input Face Feature Data"});
params.insert(std::make_unique<DataGroupSelectionParameter>(k_FeatureAttributeMatrixPath_Key, "Face Feature Attribute Matrix",
Expand Down
4 changes: 2 additions & 2 deletions src/Plugins/SimplnxCore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ set(FilterList
ComputeBiasedFeaturesFilter
ComputeBoundaryCellsFilter
ComputeBoundaryElementFractionsFilter
ComputeTriangleGeomSizesFilter
ComputeTriangleGeomVolumesFilter
FlyingEdges3DFilter
CreateColorMapFilter
IdentifySampleFilter
Expand Down Expand Up @@ -188,7 +188,7 @@ set(AlgorithmList
ComputeBiasedFeatures
ComputeBoundaryCells
FindNRingNeighbors
ComputeTriangleGeomSizes
ComputeTriangleGeomVolumes
FlyingEdges3D
CreateColorMap
InitializeData
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ Labels_ array. The volume of any generic polyhedron can be computed using the fo
4. Compute the signed volume of each tetrahedron
5. Sum the signed tetrahedra volumes to obtain the volume of the enclosing polyhedron

This computation is _not_ the same as the Find Feature Sizes for **Triangle Geometries**, which computes the sum of the
unit element sizes for a set of **Features** (thus, the Find Feature Sizes would compute the _area_
of **Features** in a **Triangle Geometry**, whereas this **Filter** is specialized to compute the enclosed volumes of **
Features** in a surface mesh).

% Auto generated parameter table will be inserted here

## Example Pipelines
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "ComputeTriangleGeomSizes.hpp"
#include "ComputeTriangleGeomVolumes.hpp"

#include "simplnx/DataStructure/DataArray.hpp"
#include "simplnx/DataStructure/DataGroup.hpp"
Expand Down Expand Up @@ -38,8 +38,8 @@ T FindTetrahedronVolume(const std::array<usize, 3>& vertIds, const AbstractDataS
} // namespace

// -----------------------------------------------------------------------------
ComputeTriangleGeomSizes::ComputeTriangleGeomSizes(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel,
ComputeTriangleGeomSizesInputValues* inputValues)
ComputeTriangleGeomVolumes::ComputeTriangleGeomVolumes(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel,
ComputeTriangleGeomVolumesInputValues* inputValues)
: m_DataStructure(dataStructure)
, m_InputValues(inputValues)
, m_ShouldCancel(shouldCancel)
Expand All @@ -48,16 +48,16 @@ ComputeTriangleGeomSizes::ComputeTriangleGeomSizes(DataStructure& dataStructure,
}

// -----------------------------------------------------------------------------
ComputeTriangleGeomSizes::~ComputeTriangleGeomSizes() noexcept = default;
ComputeTriangleGeomVolumes::~ComputeTriangleGeomVolumes() noexcept = default;

// -----------------------------------------------------------------------------
const std::atomic_bool& ComputeTriangleGeomSizes::getCancel()
const std::atomic_bool& ComputeTriangleGeomVolumes::getCancel()
{
return m_ShouldCancel;
}

// -----------------------------------------------------------------------------
Result<> ComputeTriangleGeomSizes::operator()()
Result<> ComputeTriangleGeomVolumes::operator()()
{
using MeshIndexType = IGeometry::MeshIndexType;
using SharedVertexListType = AbstractDataStore<IGeometry::SharedVertexList::value_type>;
Expand Down Expand Up @@ -85,28 +85,35 @@ Result<> ComputeTriangleGeomSizes::operator()()
auto& featAttrMat = m_DataStructure.getDataRefAs<AttributeMatrix>(m_InputValues->FeatureAttributeMatrixPath);
featAttrMat.resizeTuples(tDims);
auto& volumes = m_DataStructure.getDataAs<Float32Array>(m_InputValues->VolumesArrayPath)->getDataStoreRef();
volumes.fill(0.0f); // Initialize all volumes to ZERO

std::array<usize, 3> faceVertexIndices = {0, 0, 0};

for(MeshIndexType i = 0; i < numTriangles; i++)
{
triangleGeom.getFacePointIds(i, faceVertexIndices);
if(faceLabels[2 * i + 0] == -1)
int32 faceLabel0 = faceLabels[2 * i + 0];
int32 faceLabel1 = faceLabels[2 * i + 1];

if(faceLabel0 < 0 && faceLabel1 >= 0)
{
std::swap(faceVertexIndices[2], faceVertexIndices[1]);
volumes[faceLabels[2 * i + 1]] += FindTetrahedronVolume(faceVertexIndices, vertexCoords);
volumes[faceLabel1] += FindTetrahedronVolume(faceVertexIndices, vertexCoords);
}
else if(faceLabels[2 * i + 1] == -1)
else if(faceLabel1 < 0 && faceLabel0 >= 0)
{
volumes[faceLabels[2 * i + 0]] += FindTetrahedronVolume(faceVertexIndices, vertexCoords);
volumes[faceLabel0] += FindTetrahedronVolume(faceVertexIndices, vertexCoords);
}
else
{
volumes[faceLabels[2 * i + 0]] += FindTetrahedronVolume(faceVertexIndices, vertexCoords);
volumes[faceLabel0] += FindTetrahedronVolume(faceVertexIndices, vertexCoords);
std::swap(faceVertexIndices[2], faceVertexIndices[1]);
volumes[faceLabels[2 * i + 1]] += FindTetrahedronVolume(faceVertexIndices, vertexCoords);
volumes[faceLabel1] += FindTetrahedronVolume(faceVertexIndices, vertexCoords);
}
}

for(size_t i = 0; i < tDims[0]; i++)
{
volumes[i] = std::abs(volumes[i]);
}
return {};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#pragma once

#include "SimplnxCore/SimplnxCore_export.hpp"

#include "simplnx/DataStructure/DataPath.hpp"
#include "simplnx/DataStructure/DataStructure.hpp"
#include "simplnx/Filter/IFilter.hpp"

namespace nx::core
{

struct SIMPLNXCORE_EXPORT ComputeTriangleGeomVolumesInputValues
{
DataPath TriangleGeometryPath;
DataPath FaceLabelsArrayPath;
DataPath FeatureAttributeMatrixPath;
DataPath VolumesArrayPath;
};

/**
* @class
*/
class SIMPLNXCORE_EXPORT ComputeTriangleGeomVolumes
{
public:
ComputeTriangleGeomVolumes(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeTriangleGeomVolumesInputValues* inputValues);
~ComputeTriangleGeomVolumes() noexcept;

ComputeTriangleGeomVolumes(const ComputeTriangleGeomVolumes&) = delete;
ComputeTriangleGeomVolumes(ComputeTriangleGeomVolumes&&) noexcept = delete;
ComputeTriangleGeomVolumes& operator=(const ComputeTriangleGeomVolumes&) = delete;
ComputeTriangleGeomVolumes& operator=(ComputeTriangleGeomVolumes&&) noexcept = delete;

Result<> operator()();

const std::atomic_bool& getCancel();

private:
DataStructure& m_DataStructure;
const ComputeTriangleGeomVolumesInputValues* m_InputValues = nullptr;
const std::atomic_bool& m_ShouldCancel;
const IFilter::MessageHandler& m_MessageHandler;
};

} // namespace nx::core
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,64 @@
#include "simplnx/Parameters/DataGroupSelectionParameter.hpp"
#include "simplnx/Parameters/DataObjectNameParameter.hpp"
#include "simplnx/Parameters/GeometrySelectionParameter.hpp"
#include "simplnx/Utilities/GeometryUtilities.hpp"
#include "simplnx/Utilities/Math/MatrixMath.hpp"
#include "simplnx/Utilities/ParallelDataAlgorithm.hpp"

#include "simplnx/Utilities/SIMPLConversion.hpp"

#include "simplnx/Utilities/ParallelDataAlgorithm.hpp"

using namespace nx::core;

namespace
{
constexpr nx::core::int32 k_MissingFeatureAttributeMatrix = -75769;

/**
* @brief The CalculateAreasImpl class implements a threaded algorithm that computes the area of each
* triangle for a set of triangles
*/
class CalculateAreasImpl
{
public:
CalculateAreasImpl(const TriangleGeom* triangleGeom, Float64AbstractDataStore& areas, const std::atomic_bool& shouldCancel)
: m_TriangleGeom(triangleGeom)
, m_Areas(areas)
, m_ShouldCancel(shouldCancel)
{
}
virtual ~CalculateAreasImpl() = default;

void convert(size_t start, size_t end) const
{
std::array<float, 3> cross = {0.0f, 0.0f, 0.0f};
for(size_t triangleIndex = start; triangleIndex < end; triangleIndex++)
{
if(m_ShouldCancel)
{
break;
}
std::array<Point3Df, 3> vertCoords;
m_TriangleGeom->getFaceCoordinates(triangleIndex, vertCoords);

auto vecA = (vertCoords[0] - vertCoords[1]).toArray();
auto vecB = (vertCoords[0] - vertCoords[2]).toArray();

MatrixMath::CrossProduct(vecA.data(), vecB.data(), cross.data());

m_Areas[triangleIndex] = 0.5F * MatrixMath::Magnitude3x1(cross.data());
}
}

void operator()(const Range& range) const
{
convert(range.min(), range.max());
}

private:
const TriangleGeom* m_TriangleGeom = nullptr;
Float64AbstractDataStore& m_Areas;
const std::atomic_bool& m_ShouldCancel;
};
} // namespace

namespace nx::core
Expand Down Expand Up @@ -126,7 +173,12 @@ Result<> ComputeTriangleAreasFilter::executeImpl(DataStructure& dataStructure, c
DataPath pCalculatedAreasDataPath = pTriangleGeometryDataPath.createChildPath(faceAttributeMatrix->getName()).createChildPath(pCalculatedAreasName);
auto& faceAreas = dataStructure.getDataAs<Float64Array>(pCalculatedAreasDataPath)->getDataStoreRef();

return nx::core::GeometryUtilities::ComputeTriangleAreas(triangleGeom, faceAreas, shouldCancel);
// Parallel algorithm to find duplicate nodes
ParallelDataAlgorithm dataAlg;
dataAlg.setRange(0ULL, static_cast<size_t>(triangleGeom->getNumberOfFaces()));
dataAlg.execute(CalculateAreasImpl(triangleGeom, faceAreas, shouldCancel));

return {};
}

namespace
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Parameters ComputeTriangleGeomCentroidsFilter::parameters() const
GeometrySelectionParameter::AllowedTypes{IGeometry::Type::Triangle}));
params.insertSeparator(Parameters::Separator{"Input Triangle Face Data"});
params.insert(std::make_unique<ArraySelectionParameter>(k_FaceLabelsArrayPath_Key, "Face Labels", "The DataPath to the FaceLabels values.", DataPath{},
ArraySelectionParameter::AllowedTypes{nx::core::DataType::int32}));
ArraySelectionParameter::AllowedTypes{nx::core::DataType::int32}, ArraySelectionParameter::AllowedComponentShapes{{2}}));
params.insertSeparator(Parameters::Separator{"Input Face Feature Data"});
params.insert(std::make_unique<DataGroupSelectionParameter>(k_FeatureAttributeMatrixPath_Key, "Face Feature Attribute Matrix",
"The DataPath to the AttributeMatrix that holds feature data for the faces", DataPath({"TriangleDataContainer", "Face Feature Data"}),
Expand Down
Loading

0 comments on commit 4f44d73

Please sign in to comment.