Skip to content

Commit 5c043f1

Browse files
committed
FILT: Compute Direction Vectors filter has been added.
No unit test has been created.
1 parent 4e58118 commit 5c043f1

6 files changed

Lines changed: 592 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ set(${PLUGIN_NAME}_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR})
2727
# These are all the filters in the plugin. All filters should be kept in the
2828
# SimplnxReview/src/SimplnxReview/Filters/ directory.
2929
set(FilterList
30+
ComputeDirectionVectorsFilter
3031
ComputeGroupingDensityFilter
3132
ComputeLocalAverageCAxisMisalignmentsFilter
3233
ComputeMicroTextureRegionsFilter
@@ -44,6 +45,7 @@ set(ActionList
4445
# This should be integrated with the `create_simplnx_plugin` function call
4546
# ------------------------------------------------------------------------------
4647
set(AlgorithmList
48+
ComputeDirectionVectors
4749
ComputeGroupingDensity
4850
ComputeLocalAverageCAxisMisalignments
4951
ComputeMicroTextureRegions
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Compute Direction Vectors
2+
3+
**THIS FILTER IS UNTESTED, UNVERIFIED AND UNVALIDATED. IT IS AN EXPERIMENTAL FILTER THAT IS UNDERGOING LONG TERM DEVELOPMENT
4+
AND TESTING. USE AT YOUR OWN RISK**
5+
6+
## Group (Subgroup)
7+
8+
Visualization Helpers
9+
10+
## Description
11+
12+
This **Filter** computes the crystallographic Z Axis in a cartesian coordinate system.
13+
14+
This results from this filter can then be used in various visualization applications to visually inspect the crystallographic system.
15+
16+
% Auto generated parameter table will be inserted here
17+
18+
## References
19+
20+
## Example Pipelines
21+
22+
## License & Copyright
23+
24+
Please see the description file distributed with this **Plugin**
25+
26+
## DREAM3D-NX Help
27+
28+
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.
Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
#include "ComputeDirectionVectors.hpp"
2+
3+
#include "EbsdLib/Core/Orientation.hpp"
4+
#include "EbsdLib/Orientation/AxisAngle.hpp"
5+
#include "EbsdLib/Orientation/Euler.hpp"
6+
#include "EbsdLib/Orientation/OrientationMatrix.hpp"
7+
#include "EbsdLib/Orientation/Quaternion.hpp"
8+
#include "EbsdLib/Orientation/Rodrigues.hpp"
9+
10+
#include <Eigen/Core>
11+
12+
13+
#include "simplnx/Common/Constants.hpp"
14+
#include "simplnx/DataStructure/DataArray.hpp"
15+
#include "simplnx/Utilities/DataArrayUtilities.hpp"
16+
#include "simplnx/Utilities/ParallelTaskAlgorithm.hpp"
17+
18+
using namespace nx::core;
19+
20+
namespace
21+
{
22+
/**
23+
*
24+
* @param latticeParameters The lattice Parameters in the order, a, b, c, alpha, beta, gamma. Note that alpha, beta, gamma are all stored as degrees.
25+
* @return
26+
*/
27+
template <typename T>
28+
ebsdlib::Matrix3X3<T> DirectStructureMatrix(const Vec3<float32>& latticeParametersLengths, const Vec3<float32>& latticeParametersAngles)
29+
{
30+
/* This code is taken from EMsoftOO/mod_crystallography.f90 - computeMatrices() function */
31+
32+
T a = latticeParametersLengths[0];
33+
T b = latticeParametersLengths[1];
34+
T c = latticeParametersLengths[2];
35+
T alpha = latticeParametersAngles[0];
36+
T beta = latticeParametersAngles[1];
37+
T gamma = latticeParametersAngles[2];
38+
39+
// auxiliary variables for the various tensors
40+
T pirad = Constants::k_PiOver180F;
41+
T ca = std::cos(pirad * alpha);
42+
T cb = std::cos(pirad * beta);
43+
T cg = std::cos(pirad * gamma);
44+
T sg = std::sin(pirad * gamma);
45+
46+
// cell volume via the determinant of dmt
47+
T det = (a * b * c) * (a * b * c) * (1.0f - ca * ca - cb * cb - cg * cg + 1.0f * ca * cb * cg);
48+
T vol = std::sqrt(det);
49+
50+
ebsdlib::Matrix3X3<T> dsm;
51+
dsm[0] = a;
52+
dsm[1] = b * cg;
53+
dsm[2] = c * cb;
54+
dsm[3] = 0.0;
55+
dsm[4] = b * sg;
56+
dsm[5] = -c * (cb * cg - ca) / sg;
57+
dsm[6] = 0.0;
58+
dsm[7] = 0.0;
59+
dsm[8] = vol / (a * b * sg);
60+
return dsm;
61+
}
62+
63+
template <typename T>
64+
class ComputeDirectionVectorsImpl
65+
{
66+
public:
67+
ComputeDirectionVectorsImpl(const DataArray<T>& inputOrientationsArray, ebsdlib::orientations::Type inputRepType, const ebsdlib::Matrix3X1<T>& cartesian, Float32Array& outputArray,
68+
const std::atomic_bool& shouldCancel)
69+
: m_InputOrientationsArray(inputOrientationsArray)
70+
, m_InputRepType(inputRepType)
71+
, m_Cartesian(cartesian)
72+
, m_OutputArray(outputArray)
73+
, m_ShouldCancel(shouldCancel)
74+
{
75+
}
76+
~ComputeDirectionVectorsImpl() = default;
77+
78+
ComputeDirectionVectorsImpl(const ComputeDirectionVectorsImpl&) = default;
79+
ComputeDirectionVectorsImpl(ComputeDirectionVectorsImpl&&) noexcept = default;
80+
ComputeDirectionVectorsImpl& operator=(const ComputeDirectionVectorsImpl&) = delete;
81+
ComputeDirectionVectorsImpl& operator=(ComputeDirectionVectorsImpl&&) noexcept = delete;
82+
83+
void convert(usize start, usize end) const
84+
{
85+
// For each orientation matrix, convert to gmatrix, transpose, and multiply by the cartesian point.
86+
// The result is the direction vector that will be stored in the output array.
87+
88+
const auto& inputOrientationsDataStore = m_InputOrientationsArray.template getIDataStoreRefAs<AbstractDataStore<T>>();
89+
auto& outputDataStore = m_OutputArray.template getIDataStoreRefAs<AbstractDataStore<float32>>();
90+
ebsdlib::OrientationMatrix<T> om;
91+
for(usize i = start; i < end; i++)
92+
{
93+
if(m_ShouldCancel)
94+
{
95+
return;
96+
}
97+
98+
switch(m_InputRepType)
99+
{
100+
case ebsdlib::orientations::Type::Euler: {
101+
// Euler has 3 components
102+
om = ebsdlib::Euler<T>(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2)).toOrientationMatrix();
103+
break;
104+
}
105+
case ebsdlib::orientations::Type::OrientationMatrix: {
106+
// OrientationMatrix has 9 components
107+
om = ebsdlib::OrientationMatrix<T>(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2),
108+
inputOrientationsDataStore.getValue(i * 3 + 3), inputOrientationsDataStore.getValue(i * 3 + 4), inputOrientationsDataStore.getValue(i * 3 + 5),
109+
inputOrientationsDataStore.getValue(i * 3 + 6), inputOrientationsDataStore.getValue(i * 3 + 7), inputOrientationsDataStore.getValue(i * 3 + 8));
110+
break;
111+
}
112+
case ebsdlib::orientations::Type::Rodrigues: {
113+
// Rodrigues has 4 components
114+
om = ebsdlib::Rodrigues<T>(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2),
115+
inputOrientationsDataStore.getValue(i * 3 + 3))
116+
.toOrientationMatrix();
117+
break;
118+
}
119+
case ebsdlib::orientations::Type::Quaternion: {
120+
// Quaternion has 4 components
121+
om = ebsdlib::Quaternion<T>(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2),
122+
inputOrientationsDataStore.getValue(i * 3 + 3))
123+
.toOrientationMatrix();
124+
break;
125+
}
126+
case ebsdlib::orientations::Type::AxisAngle: {
127+
// AxisAngle has 4 components
128+
om = ebsdlib::AxisAngle<T>(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2),
129+
inputOrientationsDataStore.getValue(i * 3 + 3))
130+
.toOrientationMatrix();
131+
break;
132+
}
133+
case ebsdlib::orientations::Type::Homochoric: {
134+
// Homochoric has 3 components
135+
om = ebsdlib::Homochoric<T>(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2)).toOrientationMatrix();
136+
break;
137+
}
138+
case ebsdlib::orientations::Type::Cubochoric: {
139+
// Cubochoric has 3 components
140+
om = ebsdlib::Cubochoric<T>(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2)).toOrientationMatrix();
141+
break;
142+
}
143+
case ebsdlib::orientations::Type::Stereographic: {
144+
// Stereographic has 3 components
145+
om =
146+
ebsdlib::Stereographic<T>(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2)).toOrientationMatrix();
147+
break;
148+
}
149+
case ebsdlib::orientations::Type::Unknown: {
150+
throw std::runtime_error("Unknown Orientation Representation Type. This should not happen, contact the developers.");
151+
}
152+
}
153+
154+
ebsdlib::Matrix3X1<T> point = om.toGMatrix().transpose() * m_Cartesian;
155+
std::copy(point.data(), point.data() + 3, outputDataStore.begin() + i * outputDataStore.getNumberOfComponents());
156+
157+
// std::cout << fmt::format("Cartesian: ({}, {}, {})", m_Cartesian[0], m_Cartesian[1], m_Cartesian[2]) << std::endl;
158+
// std::cout << fmt::format("Point: ({}, {}, {})", point[0], point[1], point[2]) << std::endl;
159+
}
160+
}
161+
162+
void operator()() const
163+
{
164+
convert(0, m_InputOrientationsArray.getNumberOfTuples());
165+
}
166+
167+
private:
168+
const DataArray<T>& m_InputOrientationsArray;
169+
Float32Array& m_OutputArray;
170+
const ebsdlib::Matrix3X1<T>& m_Cartesian;
171+
ebsdlib::orientations::Type m_InputRepType;
172+
const std::atomic_bool& m_ShouldCancel;
173+
};
174+
175+
template <typename T, typename = std::enable_if_t<std::is_same_v<T, float32> || std::is_same_v<T, float64>>>
176+
Result<> ExecuteComputeDirectionVectors(DataStructure& dataStructure, const DataPath& inputOrientationsArrayPath, const DataPath& outputArrayPath, ebsdlib::orientations::Type inputRepType,
177+
const Vec3<float32>& latticeParametersLengths, const Vec3<float32>& latticeParametersAngles, const IFilter::MessageHandler& msgHandler,
178+
const std::atomic_bool& shouldCancel)
179+
{
180+
msgHandler("Computing Direction Vectors...");
181+
182+
// Convert the lattice parameters to a direct structure matrix, and calculate the cartesian point
183+
ebsdlib::Matrix3X3<T> dsm = DirectStructureMatrix<T>(latticeParametersLengths, latticeParametersAngles);
184+
ebsdlib::Matrix3X1<T> latticePoint(0.0f, 0.0f, 1.0f);
185+
auto cartesian = dsm * latticePoint;
186+
187+
// Parallelize the implementation method
188+
ParallelTaskAlgorithm taskRunner;
189+
auto& inputOrientationsArray = dataStructure.getDataRefAs<DataArray<T>>(inputOrientationsArrayPath);
190+
auto& outputArray = dataStructure.getDataRefAs<Float32Array>(outputArrayPath);
191+
taskRunner.template execute<>(ComputeDirectionVectorsImpl<T>(inputOrientationsArray, inputRepType, cartesian, outputArray, shouldCancel));
192+
193+
return {};
194+
}
195+
} // namespace
196+
197+
// -----------------------------------------------------------------------------
198+
ComputeDirectionVectors::ComputeDirectionVectors(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel,
199+
ComputeDirectionVectorsInputValues* inputValues)
200+
: m_DataStructure(dataStructure)
201+
, m_InputValues(inputValues)
202+
, m_ShouldCancel(shouldCancel)
203+
, m_MessageHandler(mesgHandler)
204+
{
205+
}
206+
207+
// -----------------------------------------------------------------------------
208+
ComputeDirectionVectors::~ComputeDirectionVectors() noexcept = default;
209+
210+
// -----------------------------------------------------------------------------
211+
Result<> ComputeDirectionVectors::operator()()
212+
{
213+
Vec3<float32> latticeParametersLengths;
214+
Vec3<float32> latticeParametersAngles;
215+
switch(m_InputValues->LatticeConstantsInputType)
216+
{
217+
case LatticeConstantsInputType::DataArrayPath: {
218+
auto& latticeConstantsArray = m_DataStructure.getDataRefAs<Float32Array>(m_InputValues->LatticeConstantsArrayPath);
219+
latticeParametersLengths[0] = latticeConstantsArray[0];
220+
latticeParametersLengths[1] = latticeConstantsArray[1];
221+
latticeParametersLengths[2] = latticeConstantsArray[2];
222+
latticeParametersAngles[0] = latticeConstantsArray[3];
223+
latticeParametersAngles[1] = latticeConstantsArray[4];
224+
latticeParametersAngles[2] = latticeConstantsArray[5];
225+
break;
226+
}
227+
case LatticeConstantsInputType::Manual: {
228+
latticeParametersLengths = m_InputValues->ManualLatticeConstantsLengths;
229+
latticeParametersAngles = m_InputValues->ManualLatticeConstantsAngles;
230+
break;
231+
}
232+
}
233+
234+
DataPath orientationsParentPath = m_InputValues->InputOrientationsArrayPath.getParent();
235+
DataPath outputDirectionVectorsPath = orientationsParentPath.createChildPath(m_InputValues->OutputDirectionVectorsArrayName);
236+
237+
auto& inputOrientationsArray = m_DataStructure.getDataRefAs<IDataArray>(m_InputValues->InputOrientationsArrayPath);
238+
DataType inputDataType = inputOrientationsArray.getDataType();
239+
switch(inputDataType)
240+
{
241+
case DataType::float32: {
242+
return ExecuteComputeDirectionVectors<float32>(m_DataStructure, m_InputValues->InputOrientationsArrayPath, outputDirectionVectorsPath, m_InputValues->InputRepType, latticeParametersLengths,
243+
latticeParametersAngles, m_MessageHandler, m_ShouldCancel);
244+
}
245+
case DataType::float64: {
246+
return ExecuteComputeDirectionVectors<float64>(m_DataStructure, m_InputValues->InputOrientationsArrayPath, outputDirectionVectorsPath, m_InputValues->InputRepType, latticeParametersLengths,
247+
latticeParametersAngles, m_MessageHandler, m_ShouldCancel);
248+
}
249+
default: {
250+
return MakeErrorResult(
251+
-2300, fmt::format("Input Orientations array has incompatible data type: the data type is {} but this filter only supports float32 and float64 data types.", DataTypeToString(inputDataType)));
252+
}
253+
}
254+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#pragma once
2+
3+
#include "SimplnxReview/SimplnxReview_export.hpp"
4+
5+
#include "EbsdLib/Orientation/OrientationFwd.hpp"
6+
7+
#include "simplnx/Common/Array.hpp"
8+
#include "simplnx/DataStructure/DataPath.hpp"
9+
#include "simplnx/Filter/IFilter.hpp"
10+
#include "simplnx/Parameters/ChoicesParameter.hpp"
11+
12+
namespace nx::core
13+
{
14+
enum LatticeConstantsInputType : uint8
15+
{
16+
DataArrayPath = 0,
17+
Manual = 1
18+
};
19+
20+
struct SIMPLNXREVIEW_EXPORT ComputeDirectionVectorsInputValues
21+
{
22+
ebsdlib::orientations::Type InputRepType;
23+
DataPath InputOrientationsArrayPath;
24+
LatticeConstantsInputType LatticeConstantsInputType;
25+
DataPath LatticeConstantsArrayPath;
26+
FloatVec3 ManualLatticeConstantsLengths;
27+
FloatVec3 ManualLatticeConstantsAngles;
28+
std::string OutputDirectionVectorsArrayName;
29+
};
30+
31+
/**
32+
* @class
33+
*/
34+
class SIMPLNXREVIEW_EXPORT ComputeDirectionVectors
35+
{
36+
public:
37+
ComputeDirectionVectors(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeDirectionVectorsInputValues* inputValues);
38+
~ComputeDirectionVectors() noexcept;
39+
40+
ComputeDirectionVectors(const ComputeDirectionVectors&) = delete;
41+
ComputeDirectionVectors(ComputeDirectionVectors&&) noexcept = delete;
42+
ComputeDirectionVectors& operator=(const ComputeDirectionVectors&) = delete;
43+
ComputeDirectionVectors& operator=(ComputeDirectionVectors&&) noexcept = delete;
44+
45+
Result<> operator()();
46+
47+
private:
48+
DataStructure& m_DataStructure;
49+
const ComputeDirectionVectorsInputValues* m_InputValues = nullptr;
50+
const std::atomic_bool& m_ShouldCancel;
51+
const IFilter::MessageHandler& m_MessageHandler;
52+
};
53+
} // namespace nx::core

0 commit comments

Comments
 (0)