Skip to content

Commit 05cded2

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

6 files changed

Lines changed: 593 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: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
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+
#include "OrientationAnalysis/Filters/Algorithms/ConvertOrientations.hpp"
13+
14+
#include "simplnx/Common/Constants.hpp"
15+
#include "simplnx/DataStructure/DataArray.hpp"
16+
#include "simplnx/Utilities/DataArrayUtilities.hpp"
17+
#include "simplnx/Utilities/ParallelTaskAlgorithm.hpp"
18+
19+
using namespace nx::core;
20+
21+
namespace
22+
{
23+
/**
24+
*
25+
* @param latticeParameters The lattice Parameters in the order, a, b, c, alpha, beta, gamma. Note that alpha, beta, gamma are all stored as degrees.
26+
* @return
27+
*/
28+
template <typename T>
29+
ebsdlib::Matrix3X3<T> DirectStructureMatrix(const Vec3<float32>& latticeParametersLengths, const Vec3<float32>& latticeParametersAngles)
30+
{
31+
/* This code is taken from EMsoftOO/mod_crystallography.f90 - computeMatrices() function */
32+
33+
T a = latticeParametersLengths[0];
34+
T b = latticeParametersLengths[1];
35+
T c = latticeParametersLengths[2];
36+
T alpha = latticeParametersAngles[0];
37+
T beta = latticeParametersAngles[1];
38+
T gamma = latticeParametersAngles[2];
39+
40+
// auxiliary variables for the various tensors
41+
T pirad = Constants::k_PiOver180F;
42+
T ca = std::cos(pirad * alpha);
43+
T cb = std::cos(pirad * beta);
44+
T cg = std::cos(pirad * gamma);
45+
T sg = std::sin(pirad * gamma);
46+
47+
// cell volume via the determinant of dmt
48+
T det = (a * b * c) * (a * b * c) * (1.0f - ca * ca - cb * cb - cg * cg + 1.0f * ca * cb * cg);
49+
T vol = std::sqrt(det);
50+
51+
ebsdlib::Matrix3X3<T> dsm;
52+
dsm[0] = a;
53+
dsm[1] = b * cg;
54+
dsm[2] = c * cb;
55+
dsm[3] = 0.0;
56+
dsm[4] = b * sg;
57+
dsm[5] = -c * (cb * cg - ca) / sg;
58+
dsm[6] = 0.0;
59+
dsm[7] = 0.0;
60+
dsm[8] = vol / (a * b * sg);
61+
return dsm;
62+
}
63+
64+
template <typename T>
65+
class ComputeDirectionVectorsImpl
66+
{
67+
public:
68+
ComputeDirectionVectorsImpl(const DataArray<T>& inputOrientationsArray, ebsdlib::orientations::Type inputRepType, const ebsdlib::Matrix3X1<T>& cartesian, Float32Array& outputArray,
69+
const std::atomic_bool& shouldCancel)
70+
: m_InputOrientationsArray(inputOrientationsArray)
71+
, m_InputRepType(inputRepType)
72+
, m_Cartesian(cartesian)
73+
, m_OutputArray(outputArray)
74+
, m_ShouldCancel(shouldCancel)
75+
{
76+
}
77+
~ComputeDirectionVectorsImpl() = default;
78+
79+
ComputeDirectionVectorsImpl(const ComputeDirectionVectorsImpl&) = default;
80+
ComputeDirectionVectorsImpl(ComputeDirectionVectorsImpl&&) noexcept = default;
81+
ComputeDirectionVectorsImpl& operator=(const ComputeDirectionVectorsImpl&) = delete;
82+
ComputeDirectionVectorsImpl& operator=(ComputeDirectionVectorsImpl&&) noexcept = delete;
83+
84+
void convert(usize start, usize end) const
85+
{
86+
// For each orientation matrix, convert to gmatrix, transpose, and multiply by the cartesian point.
87+
// The result is the direction vector that will be stored in the output array.
88+
89+
const auto& inputOrientationsDataStore = m_InputOrientationsArray.template getIDataStoreRefAs<AbstractDataStore<T>>();
90+
auto& outputDataStore = m_OutputArray.template getIDataStoreRefAs<AbstractDataStore<float32>>();
91+
ebsdlib::OrientationMatrix<T> om;
92+
for(usize i = start; i < end; i++)
93+
{
94+
if(m_ShouldCancel)
95+
{
96+
return;
97+
}
98+
99+
switch(m_InputRepType)
100+
{
101+
case ebsdlib::orientations::Type::Euler: {
102+
// Euler has 3 components
103+
om = ebsdlib::Euler<T>(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2)).toOrientationMatrix();
104+
break;
105+
}
106+
case ebsdlib::orientations::Type::OrientationMatrix: {
107+
// OrientationMatrix has 9 components
108+
om = ebsdlib::OrientationMatrix<T>(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2),
109+
inputOrientationsDataStore.getValue(i * 3 + 3), inputOrientationsDataStore.getValue(i * 3 + 4), inputOrientationsDataStore.getValue(i * 3 + 5),
110+
inputOrientationsDataStore.getValue(i * 3 + 6), inputOrientationsDataStore.getValue(i * 3 + 7), inputOrientationsDataStore.getValue(i * 3 + 8));
111+
break;
112+
}
113+
case ebsdlib::orientations::Type::Rodrigues: {
114+
// Rodrigues has 4 components
115+
om = ebsdlib::Rodrigues<T>(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2),
116+
inputOrientationsDataStore.getValue(i * 3 + 3))
117+
.toOrientationMatrix();
118+
break;
119+
}
120+
case ebsdlib::orientations::Type::Quaternion: {
121+
// Quaternion has 4 components
122+
om = ebsdlib::Quaternion<T>(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2),
123+
inputOrientationsDataStore.getValue(i * 3 + 3))
124+
.toOrientationMatrix();
125+
break;
126+
}
127+
case ebsdlib::orientations::Type::AxisAngle: {
128+
// AxisAngle has 4 components
129+
om = ebsdlib::AxisAngle<T>(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2),
130+
inputOrientationsDataStore.getValue(i * 3 + 3))
131+
.toOrientationMatrix();
132+
break;
133+
}
134+
case ebsdlib::orientations::Type::Homochoric: {
135+
// Homochoric has 3 components
136+
om = ebsdlib::Homochoric<T>(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2)).toOrientationMatrix();
137+
break;
138+
}
139+
case ebsdlib::orientations::Type::Cubochoric: {
140+
// Cubochoric has 3 components
141+
om = ebsdlib::Cubochoric<T>(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2)).toOrientationMatrix();
142+
break;
143+
}
144+
case ebsdlib::orientations::Type::Stereographic: {
145+
// Stereographic has 3 components
146+
om =
147+
ebsdlib::Stereographic<T>(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2)).toOrientationMatrix();
148+
break;
149+
}
150+
case ebsdlib::orientations::Type::Unknown: {
151+
throw std::runtime_error("Unknown Orientation Representation Type. This should not happen, contact the developers.");
152+
}
153+
}
154+
155+
ebsdlib::Matrix3X1<T> point = om.toGMatrix().transpose() * m_Cartesian;
156+
std::copy(point.data(), point.data() + 3, outputDataStore.begin() + i * outputDataStore.getNumberOfComponents());
157+
158+
std::cout << fmt::format("Cartesian: ({}, {}, {})", m_Cartesian[0], m_Cartesian[1], m_Cartesian[2]) << std::endl;
159+
std::cout << fmt::format("Point: ({}, {}, {})", point[0], point[1], point[2]) << std::endl;
160+
}
161+
}
162+
163+
void operator()() const
164+
{
165+
convert(0, m_InputOrientationsArray.getNumberOfTuples());
166+
}
167+
168+
private:
169+
const DataArray<T>& m_InputOrientationsArray;
170+
Float32Array& m_OutputArray;
171+
const ebsdlib::Matrix3X1<T>& m_Cartesian;
172+
ebsdlib::orientations::Type m_InputRepType;
173+
const std::atomic_bool& m_ShouldCancel;
174+
};
175+
176+
template <typename T, typename = std::enable_if_t<std::is_same_v<T, float32> || std::is_same_v<T, float64>>>
177+
Result<> ExecuteComputeDirectionVectors(DataStructure& dataStructure, const DataPath& inputOrientationsArrayPath, const DataPath& outputArrayPath, ebsdlib::orientations::Type inputRepType,
178+
const Vec3<float32>& latticeParametersLengths, const Vec3<float32>& latticeParametersAngles, const IFilter::MessageHandler& msgHandler,
179+
const std::atomic_bool& shouldCancel)
180+
{
181+
msgHandler("Computing Direction Vectors...");
182+
183+
// Convert the lattice parameters to a direct structure matrix, and calculate the cartesian point
184+
ebsdlib::Matrix3X3<T> dsm = DirectStructureMatrix<T>(latticeParametersLengths, latticeParametersAngles);
185+
ebsdlib::Matrix3X1<T> latticePoint(0.0f, 0.0f, 1.0f);
186+
auto cartesian = dsm * latticePoint;
187+
188+
// Parallelize the implementation method
189+
ParallelTaskAlgorithm taskRunner;
190+
auto& inputOrientationsArray = dataStructure.getDataRefAs<DataArray<T>>(inputOrientationsArrayPath);
191+
auto& outputArray = dataStructure.getDataRefAs<Float32Array>(outputArrayPath);
192+
taskRunner.template execute<>(ComputeDirectionVectorsImpl<T>(inputOrientationsArray, inputRepType, cartesian, outputArray, shouldCancel));
193+
194+
return {};
195+
}
196+
} // namespace
197+
198+
// -----------------------------------------------------------------------------
199+
ComputeDirectionVectors::ComputeDirectionVectors(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel,
200+
ComputeDirectionVectorsInputValues* inputValues)
201+
: m_DataStructure(dataStructure)
202+
, m_InputValues(inputValues)
203+
, m_ShouldCancel(shouldCancel)
204+
, m_MessageHandler(mesgHandler)
205+
{
206+
}
207+
208+
// -----------------------------------------------------------------------------
209+
ComputeDirectionVectors::~ComputeDirectionVectors() noexcept = default;
210+
211+
// -----------------------------------------------------------------------------
212+
Result<> ComputeDirectionVectors::operator()()
213+
{
214+
Vec3<float32> latticeParametersLengths;
215+
Vec3<float32> latticeParametersAngles;
216+
switch(m_InputValues->LatticeConstantsInputType)
217+
{
218+
case LatticeConstantsInputType::DataArrayPath: {
219+
auto& latticeConstantsArray = m_DataStructure.getDataRefAs<Float32Array>(m_InputValues->LatticeConstantsArrayPath);
220+
latticeParametersLengths[0] = latticeConstantsArray[0];
221+
latticeParametersLengths[1] = latticeConstantsArray[1];
222+
latticeParametersLengths[2] = latticeConstantsArray[2];
223+
latticeParametersAngles[0] = latticeConstantsArray[3];
224+
latticeParametersAngles[1] = latticeConstantsArray[4];
225+
latticeParametersAngles[2] = latticeConstantsArray[5];
226+
break;
227+
}
228+
case LatticeConstantsInputType::Manual: {
229+
latticeParametersLengths = m_InputValues->ManualLatticeConstantsLengths;
230+
latticeParametersAngles = m_InputValues->ManualLatticeConstantsAngles;
231+
break;
232+
}
233+
}
234+
235+
DataPath orientationsParentPath = m_InputValues->InputOrientationsArrayPath.getParent();
236+
DataPath outputDirectionVectorsPath = orientationsParentPath.createChildPath(m_InputValues->OutputDirectionVectorsArrayName);
237+
238+
auto& inputOrientationsArray = m_DataStructure.getDataRefAs<IDataArray>(m_InputValues->InputOrientationsArrayPath);
239+
DataType inputDataType = inputOrientationsArray.getDataType();
240+
switch(inputDataType)
241+
{
242+
case DataType::float32: {
243+
return ExecuteComputeDirectionVectors<float32>(m_DataStructure, m_InputValues->InputOrientationsArrayPath, outputDirectionVectorsPath, m_InputValues->InputRepType, latticeParametersLengths,
244+
latticeParametersAngles, m_MessageHandler, m_ShouldCancel);
245+
}
246+
case DataType::float64: {
247+
return ExecuteComputeDirectionVectors<float64>(m_DataStructure, m_InputValues->InputOrientationsArrayPath, outputDirectionVectorsPath, m_InputValues->InputRepType, latticeParametersLengths,
248+
latticeParametersAngles, m_MessageHandler, m_ShouldCancel);
249+
}
250+
default: {
251+
return MakeErrorResult(
252+
-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)));
253+
}
254+
}
255+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#pragma once
2+
3+
#include "OrientationAnalysis/OrientationAnalysis_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 ORIENTATIONANALYSIS_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 ORIENTATIONANALYSIS_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)