21 double SignForCrossProduct(MillerIndexOrientation::QComponent q1,
22 MillerIndexOrientation::QComponent q2);
23 MillerIndexOrientation::QComponent ThirdQComponent(MillerIndexOrientation::QComponent q1,
24 MillerIndexOrientation::QComponent q2);
25 void FillVectorInRow(Eigen::Matrix3d& matrix,
kvector_t vec,
26 MillerIndexOrientation::QComponent row);
29 ILatticeOrientation::~ILatticeOrientation() =
default;
31 MillerIndex::MillerIndex(
double h_,
double k_,
double l_) : h(h_), k(k_), l(l_) {}
35 MillerIndexOrientation::QComponent q2,
37 : m_prim_lattice(), m_q1(q1), m_q2(q2), m_ind1{index1}, m_ind2{index2}
39 if (!checkAlignment())
40 throw std::runtime_error(
"MillerIndexOrientation constructor: "
41 "invalid alignment parameters");
47 result->usePrimitiveLattice(m_prim_lattice);
51 MillerIndexOrientation::~MillerIndexOrientation() =
default;
53 void MillerIndexOrientation::usePrimitiveLattice(
const Lattice& lattice)
59 Transform3D MillerIndexOrientation::transformationMatrix()
const
63 auto dir_2_parallel = dir_2.
project(dir_1);
64 dir_2 = (dir_2 - dir_2_parallel).unit();
65 auto dir_3 = SignForCrossProduct(m_q1, m_q2) * dir_1.
cross(dir_2);
66 auto q3 = ThirdQComponent(m_q1, m_q2);
67 Eigen::Matrix3d rot_matrix;
68 FillVectorInRow(rot_matrix, dir_1, m_q1);
69 FillVectorInRow(rot_matrix, dir_2, m_q2);
70 FillVectorInRow(rot_matrix, dir_3, q3);
74 bool MillerIndexOrientation::checkAlignment()
const
78 if (!ValidMillerIndex(m_ind1) || !ValidMillerIndex(m_ind2))
80 if (ParallelMillerIndices(m_ind1, m_ind2))
89 return (index.h != 0.0 || index.k != 0.0 || index.l != 0.0);
94 if (index2.h != 0.0) {
95 ratio = index1.h / index2.h;
96 }
else if (index2.k != 0.0) {
97 ratio = index1.k / index2.k;
98 }
else if (index2.l != 0.0) {
99 ratio = index1.l / index2.l;
103 return (index1.h == ratio * index2.h && index1.k == ratio * index2.k
104 && index1.l == ratio * index2.l);
106 double SignForCrossProduct(MillerIndexOrientation::QComponent q1,
107 MillerIndexOrientation::QComponent q2)
109 if ((q1 == MillerIndexOrientation::QX && q2 == MillerIndexOrientation::QY)
110 || (q1 == MillerIndexOrientation::QY && q2 == MillerIndexOrientation::QZ)
111 || (q1 == MillerIndexOrientation::QZ && q2 == MillerIndexOrientation::QX))
115 MillerIndexOrientation::QComponent ThirdQComponent(MillerIndexOrientation::QComponent q1,
116 MillerIndexOrientation::QComponent q2)
118 if (q1 != MillerIndexOrientation::QX && q2 != MillerIndexOrientation::QX)
119 return MillerIndexOrientation::QX;
120 if (q1 != MillerIndexOrientation::QY && q2 != MillerIndexOrientation::QY)
121 return MillerIndexOrientation::QY;
122 return MillerIndexOrientation::QZ;
124 void FillVectorInRow(Eigen::Matrix3d& mat,
kvector_t vec, MillerIndexOrientation::QComponent row)
126 int i = row == MillerIndexOrientation::QX ? 0 : row == MillerIndexOrientation::QY ? 1 : 2;
127 for (
int j = 0; j < 3; ++j)
Defines interface ILatticeOrientation and subclasses.
BasicVector3D< T > project(const BasicVector3D< T > &v) const
Returns projection of this onto other vector: (this*v)*v/|v|^2.
auto cross(const BasicVector3D< U > &v) const
Returns cross product of vectors (linear in both arguments).
A lattice with three basis vectors.
void resetBasis(const kvector_t a1, const kvector_t a2, const kvector_t a3)
Resets the basis vectors.
kvector_t getMillerDirection(double h, double k, double l) const
Returns normalized direction corresponding to the given Miller indices.
kvector_t getBasisVectorB() const
Returns basis vector b.
kvector_t getBasisVectorC() const
Returns basis vector c.
kvector_t getBasisVectorA() const
Returns basis vector a.
Specifies a rotation of a lattice through the Miller indices of two coordinate axes.
MillerIndexOrientation(QComponent q1, MillerIndex index1, QComponent q2, MillerIndex index2)
This constructor is best explained by an example.
A direction in reciprocal space, specified by double-valued indices hkl.