Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ set(${PLUGIN_NAME}_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR})
# These are all the filters in the plugin. All filters should be kept in the
# SimplnxReview/src/SimplnxReview/Filters/ directory.
set(FilterList
ComputeEquivalentDiameterCirclesFilter
ComputeGroupingDensityFilter
ComputeLocalAverageCAxisMisalignmentsFilter
ComputeMicroTextureRegionsFilter
Expand All @@ -44,6 +45,7 @@ set(ActionList
# This should be integrated with the `create_simplnx_plugin` function call
# ------------------------------------------------------------------------------
set(AlgorithmList
ComputeEquivalentDiameterCircles
ComputeGroupingDensity
ComputeLocalAverageCAxisMisalignments
ComputeMicroTextureRegions
Expand Down
28 changes: 28 additions & 0 deletions docs/ComputeEquivalentDiameterCirclesFilter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Compute Equivalent Diameter Circles

**THIS FILTER IS UNTESTED, UNVERIFIED AND UNVALIDATED. IT IS AN EXPERIMENTAL FILTER THAT IS UNDERGOING LONG TERM DEVELOPMENT
AND TESTING. USE AT YOUR OWN RISK**

## Group (Subgroup)

Visualization Helpers

## Description

This filter will generate an Edge Geometry that holds N number of circles where each circle is centered at a given centroid and the radius of the circle is based on the Equivalent Spherical Diameter(ESD) values that are also provided by the user.

This filter was meant to generate 2D circles in the XY plane. This filter will not work well with 3D centroids or centroids that have differing Z Values.

% Auto generated parameter table will be inserted here

## References

## 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/discussions) GitHub site where the community of DREAM3D-NX users can help answer your questions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include "ComputeEquivalentDiameterCircles.hpp"

#include "simplnx/Common/Constants.hpp"
#include "simplnx/Common/Result.hpp"
#include "simplnx/Common/Types.hpp"
#include "simplnx/DataStructure/DataArray.hpp"
#include "simplnx/DataStructure/DataPath.hpp"
#include "simplnx/DataStructure/DataStructure.hpp"
#include "simplnx/DataStructure/Geometry/EdgeGeom.hpp"
#include "simplnx/Filter/IFilter.hpp"

#include <atomic>
#include <cmath>

using namespace nx::core;

// -----------------------------------------------------------------------------
ComputeEquivalentDiameterCircles::ComputeEquivalentDiameterCircles(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel,
ComputeEquivalentDiameterCirclesInputValues* inputValues)
: m_DataStructure(dataStructure)
, m_InputValues(inputValues)
, m_ShouldCancel(shouldCancel)
, m_MessageHandler(mesgHandler)
{
}

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

// -----------------------------------------------------------------------------
Result<> ComputeEquivalentDiameterCircles::operator()()
{
auto& centroidsArray = m_DataStructure.getDataRefAs<Float32Array>(m_InputValues->CentroidsArrayPath);
auto& equivalentDiametersArray = m_DataStructure.getDataRefAs<Float32Array>(m_InputValues->EquivalentDiametersArrayPath);
const DataPath featureIdsPath = m_InputValues->OutputEdgeGeometryPath.createChildPath(m_InputValues->EdgeAttributeMatrixName).createChildPath(m_InputValues->FeatureIdsArrayName);
auto& featureIdsArray = m_DataStructure.getDataRefAs<Int32Array>(featureIdsPath);
auto& outputEdgeGeom = m_DataStructure.getDataRefAs<EdgeGeom>(m_InputValues->OutputEdgeGeometryPath);
Float32Array& verticesArray = outputEdgeGeom.getVerticesRef();
UInt64Array& edgesArray = outputEdgeGeom.getEdgesRef();

const usize circleResolution = m_InputValues->CircleResolution;
const usize verticesPerCircle = circleResolution + 1;
usize edgeIdx = 0;

for(usize i = 1; i < centroidsArray.getNumberOfTuples(); ++i)
{
const float32 r = equivalentDiametersArray[i] / 2.0f;
const float32 cx = centroidsArray.getComponent(i, 0);
const float32 cy = centroidsArray.getComponent(i, 1);

const usize circleVertexStart = (i - 1) * verticesPerCircle;

for(usize v = 0; v < verticesPerCircle; ++v)
{
const usize vertexIdx = circleVertexStart + v;

const float32 theta = 2.0f * nx::core::Constants::k_PiF * static_cast<float32>(v) / static_cast<float32>(circleResolution);

const float32 x = cx + r * std::cos(theta);
const float32 y = cy + r * std::sin(theta);

verticesArray.setComponent(vertexIdx, 0, x);
verticesArray.setComponent(vertexIdx, 1, y);
verticesArray.setComponent(vertexIdx, 2, static_cast<float32>(m_InputValues->ZPlane));
}

for(usize e = 0; e < circleResolution; ++e)
{
const usize v0 = circleVertexStart + e;
const usize v1 = circleVertexStart + e + 1;

featureIdsArray.setValue(edgeIdx, static_cast<int32>(i));

edgesArray.setComponent(edgeIdx, 0, v0);
edgesArray.setComponent(edgeIdx, 1, v1);
edgeIdx++;
}
}

return {};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#pragma once

#include "SimplnxReview/SimplnxReview_export.hpp"

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

namespace nx::core
{

struct SIMPLNXREVIEW_EXPORT ComputeEquivalentDiameterCirclesInputValues
{
DataPath CentroidsArrayPath;
DataPath EquivalentDiametersArrayPath;
uint64 CircleResolution;
int64 ZPlane;
DataPath OutputEdgeGeometryPath;
std::string EdgeAttributeMatrixName;
std::string FeatureIdsArrayName;
};

/**
* @class ComputeEquivalentDiameterCircles
* @brief This filter determines the average C-axis location of each Feature.
*/

class SIMPLNXREVIEW_EXPORT ComputeEquivalentDiameterCircles
{
public:
ComputeEquivalentDiameterCircles(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel,
ComputeEquivalentDiameterCirclesInputValues* inputValues);
~ComputeEquivalentDiameterCircles() noexcept = default;

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

Result<> operator()();

const std::atomic_bool& getCancel();

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

} // namespace nx::core
134 changes: 134 additions & 0 deletions src/SimplnxReview/Filters/ComputeEquivalentDiameterCirclesFilter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#include "ComputeEquivalentDiameterCirclesFilter.hpp"

#include "SimplnxReview/Filters/Algorithms/ComputeEquivalentDiameterCircles.hpp"

#include "simplnx/DataStructure/DataArray.hpp"
#include "simplnx/Filter/Actions/CreateArrayAction.hpp"
#include "simplnx/Filter/Actions/CreateGeometry1DAction.hpp"
#include "simplnx/Parameters/ArraySelectionParameter.hpp"
#include "simplnx/Parameters/DataGroupCreationParameter.hpp"
#include "simplnx/Parameters/DataObjectNameParameter.hpp"
#include "simplnx/Parameters/NumberParameter.hpp"

using namespace nx::core;

namespace nx::core
{
//------------------------------------------------------------------------------
std::string ComputeEquivalentDiameterCirclesFilter::name() const
{
return FilterTraits<ComputeEquivalentDiameterCirclesFilter>::name.str();
}

//------------------------------------------------------------------------------
std::string ComputeEquivalentDiameterCirclesFilter::className() const
{
return FilterTraits<ComputeEquivalentDiameterCirclesFilter>::className;
}

//------------------------------------------------------------------------------
Uuid ComputeEquivalentDiameterCirclesFilter::uuid() const
{
return FilterTraits<ComputeEquivalentDiameterCirclesFilter>::uuid;
}

//------------------------------------------------------------------------------
std::string ComputeEquivalentDiameterCirclesFilter::humanName() const
{
return "Compute Equivalent Diameter Circles";
}

//------------------------------------------------------------------------------
std::vector<std::string> ComputeEquivalentDiameterCirclesFilter::defaultTags() const
{
return {className()};
}

//------------------------------------------------------------------------------
Parameters ComputeEquivalentDiameterCirclesFilter::parameters() const
{
Parameters params;
// Create the parameter descriptors that are needed for this filter
params.insertSeparator(Parameters::Separator{"Input Parameter(s)"});
params.insert(std::make_unique<ArraySelectionParameter>(k_CentroidsArrayPath_Key, "Feature Centroids", "X, Y, Z coordinates of Feature center of mass", DataPath{},
ArraySelectionParameter::AllowedTypes{DataType::float32}, ArraySelectionParameter::AllowedComponentShapes{{3}}));
params.insert(std::make_unique<ArraySelectionParameter>(k_EquivalentDiametersArrayPath_Key, "Equivalent Diameters", "Input feature based Equivalent Diameters", DataPath{},
ArraySelectionParameter::AllowedTypes{DataType::float32}, ArraySelectionParameter::AllowedComponentShapes{{1}}));
params.insert(std::make_unique<NumberParameter<uint64>>(k_CircleResolution_Key, "Circle Resolution", "The number of edges that each circle will have", 100));
params.insert(std::make_unique<NumberParameter<int64>>(k_ZPlane_Key, "Z Plane", "The Z plane that the circles will be calculated on.", 0));

params.insertSeparator(Parameters::Separator{"Output Edge Geometry"});
params.insert(std::make_unique<DataGroupCreationParameter>(k_OutputEdgeGeometryPath_Key, "Created Edge Geometry", "The name of the created Edge Geometry", DataPath({"Circles"})));
params.insert(std::make_unique<DataObjectNameParameter>(k_EdgeAttributeMatrixName_Key, "Edge Attribute Matrix", "Attribute Matrix to store information about the created edges", "Edge Data"));
params.insert(std::make_unique<DataObjectNameParameter>(k_CreatedFeatureIdsArrayName_Key, "Edge Feature Ids", "Identifies the Feature Id to which each edge belongs", "Feature Ids"));

return params;
}

//------------------------------------------------------------------------------
IFilter::UniquePointer ComputeEquivalentDiameterCirclesFilter::clone() const
{
return std::make_unique<ComputeEquivalentDiameterCirclesFilter>();
}

//------------------------------------------------------------------------------
IFilter::VersionType ComputeEquivalentDiameterCirclesFilter::parametersVersion() const
{
return 1;
}

//------------------------------------------------------------------------------
IFilter::PreflightResult ComputeEquivalentDiameterCirclesFilter::preflightImpl(const DataStructure& dataStructure, const Arguments& filterArgs, const MessageHandler& messageHandler,
const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const
{
auto pCentroidsArrayPath = filterArgs.value<DataPath>(k_CentroidsArrayPath_Key);
auto pEquivalentDiametersArrayPath = filterArgs.value<DataPath>(k_EquivalentDiametersArrayPath_Key);
auto pCircleResolution = filterArgs.value<uint64>(k_CircleResolution_Key);
auto pOutputEdgeGeometryPath = filterArgs.value<DataGroupCreationParameter::ValueType>(k_OutputEdgeGeometryPath_Key);
auto pEdgeAttributeMatrixName = filterArgs.value<DataObjectNameParameter::ValueType>(k_EdgeAttributeMatrixName_Key);
auto pFeatureIdsArrayName = filterArgs.value<DataObjectNameParameter::ValueType>(k_CreatedFeatureIdsArrayName_Key);

Result<OutputActions> resultOutputActions;
std::vector<PreflightValue> preflightUpdatedValues;

auto& centroidsArray = dataStructure.getDataRefAs<Float32Array>(pCentroidsArrayPath);
auto& equivalentDiametersArray = dataStructure.getDataRefAs<Float32Array>(pEquivalentDiametersArrayPath);
usize numberOfCentroids = centroidsArray.getNumberOfTuples();
if(numberOfCentroids != equivalentDiametersArray.getNumberOfTuples())
{
return MakePreflightErrorResult(-13860, fmt::format("Centroids array has {} centroids, and the equivalent diameters array has {} diameters. These must be equal.", numberOfCentroids,
equivalentDiametersArray.getNumberOfTuples()));
}

auto createGeometryAction =
std::make_unique<CreateEdgeGeometryAction>(pOutputEdgeGeometryPath, pCircleResolution * (numberOfCentroids - 1), (pCircleResolution + 1) * (numberOfCentroids - 1),
INodeGeometry0D::k_VertexAttributeMatrixName, pEdgeAttributeMatrixName, EdgeGeom::k_SharedVertexListName, EdgeGeom::k_SharedEdgeListName);
resultOutputActions.value().appendAction(std::move(createGeometryAction));

DataPath path = pOutputEdgeGeometryPath.createChildPath(pEdgeAttributeMatrixName).createChildPath(pFeatureIdsArrayName);
auto createArray = std::make_unique<CreateArrayAction>(DataType::int32, std::vector<usize>{pCircleResolution * (numberOfCentroids - 1)}, std::vector<usize>{1}, path);
resultOutputActions.value().appendAction(std::move(createArray));

preflightUpdatedValues.push_back({"WARNING: This filter is experimental in nature and has not had any testing, validation or verification. Use at your own risk"});
resultOutputActions.warnings().push_back({-65432, "WARNING: This filter is experimental in nature and has not had any testing, validation or verification. Use at your own risk"});

return {std::move(resultOutputActions), std::move(preflightUpdatedValues)};
}

//------------------------------------------------------------------------------
Result<> ComputeEquivalentDiameterCirclesFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler,
const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const
{
ComputeEquivalentDiameterCirclesInputValues inputValues;

inputValues.CentroidsArrayPath = filterArgs.value<DataPath>(k_CentroidsArrayPath_Key);
inputValues.EquivalentDiametersArrayPath = filterArgs.value<DataPath>(k_EquivalentDiametersArrayPath_Key);
inputValues.CircleResolution = filterArgs.value<uint64>(k_CircleResolution_Key);
inputValues.ZPlane = filterArgs.value<int64>(k_ZPlane_Key);
inputValues.OutputEdgeGeometryPath = filterArgs.value<DataGroupCreationParameter::ValueType>(k_OutputEdgeGeometryPath_Key);
inputValues.EdgeAttributeMatrixName = filterArgs.value<DataObjectNameParameter::ValueType>(k_EdgeAttributeMatrixName_Key);
inputValues.FeatureIdsArrayName = filterArgs.value<DataObjectNameParameter::ValueType>(k_CreatedFeatureIdsArrayName_Key);

return ComputeEquivalentDiameterCircles(dataStructure, messageHandler, shouldCancel, &inputValues)();
}
} // namespace nx::core
Loading
Loading