13#include <boost/algorithm/string.hpp>
52 double norm =
a *
a +
b *
b +
c *
c +
w *
w;
53 if (
fabs(norm - 1) > FLT_EPSILON) {
65Quat::Quat(
const double _w,
const double _a,
const double _b,
const double _c) : w(_w), a(_a), b(_b), c(_c) {}
99void Quat::set(
const double ww,
const double aa,
const double bb,
const double cc) {
117 double s = sin(0.5 * _deg *
deg2rad);
126 double pw =
fabs(
w) - 1;
147 double s = sin(_deg);
149 _deg *= 360.0 / M_PI;
159 double _deg, ax0, ax1, ax2;
170void Quat::operator()(
const double ww,
const double aa,
const double bb,
const double cc) { this->
set(ww, aa, bb, cc); }
204 constexpr V3D oX =
V3D(1., 0., 0.);
205 constexpr V3D oY =
V3D(0., 1., 0.);
213 const double angle1 = oX.
angle(rX);
223 const double angle2 = roY.
angle(rY);
228 const Quat final = Q2 * Q1;
286 double w1, a1, b1, c1;
287 w1 =
w * _q.
w -
a * _q.
a -
b * _q.
b -
c * _q.
c;
288 a1 =
w * _q.
a + _q.
w *
a +
b * _q.
c - _q.
b *
c;
289 b1 =
w * _q.
b + _q.
w *
b -
a * _q.
c +
c * _q.
a;
290 c1 =
w * _q.
c + _q.
w *
c +
a * _q.
b - _q.
a *
b;
291 return Quat(w1, a1, b1, c1);
299 double w1, a1, b1, c1;
300 w1 =
w * _q.
w -
a * _q.
a -
b * _q.
b -
c * _q.
c;
301 a1 =
w * _q.
a + _q.
w *
a +
b * _q.
c - _q.
b *
c;
302 b1 =
w * _q.
b + _q.
w *
b -
a * _q.
c +
c * _q.
a;
303 c1 =
w * _q.
c + _q.
w *
c +
a * _q.
b - _q.
a *
b;
345 overnorm = 1.0 /
len();
378 double overnorm =
len2();
382 overnorm = 1.0 / overnorm;
400 Quat pos(0.0, v[0], v[1], v[2]);
423 *mat = 1.0 - 2.0 * (bb + cc);
425 *mat = 2.0 * (ab + cw);
427 *mat = 2.0 * (ac - bw);
431 *mat = 2.0 * (ab - cw);
433 *mat = 1.0 - 2.0 * (aa + cc);
435 *mat = 2.0 * (bc + aw);
439 *mat = 2.0 * (ac + bw);
441 *mat = 2.0 * (bc - aw);
443 *mat = 1.0 - 2.0 * (aa + bb);
445 for (
int i = 0; i < 4; ++i) {
463 if (check_normalisation) {
464 double normSq = aa + bb + cc +
w *
w;
465 if (
fabs(normSq - 1) > FLT_EPSILON) {
466 if (throw_on_errors) {
467 g_log.
error() <<
" A non-unit quaternion used to obtain a rotation "
468 "matrix; need to notmalize it first\n";
469 throw(std::invalid_argument(
"Attempt to use non-normalized quaternion "
470 "to define rotation matrix; need to "
471 "notmalize it first"));
474 "the rotation matrix; using normalized quat\n";
487 std::vector<double> out(9);
489 out[0] = (1.0 - 2.0 * (bb + cc));
490 out[1] = 2.0 * (ab - cw);
491 out[2] = 2.0 * (ac + bw);
493 out[3] = 2.0 * (ab + cw);
494 out[4] = (1.0 - 2.0 * (aa + cc));
495 out[5] = 2.0 * (bc - aw);
497 out[6] = 2.0 * (ac - bw);
498 out[7] = 2.0 * (bc + aw);
499 out[8] = (1.0 - 2.0 * (aa + bb));
508 int nxt[3] = {1, 2, 0};
509 tr = mat[0] + mat[5] + mat[10];
514 a = (mat[6] - mat[9]) * s;
515 b = (mat[8] - mat[2]) * s;
516 c = (mat[1] - mat[4]) * s;
521 if (mat[10] > mat[i * 5])
525 s = sqrt(mat[i * 5] - (mat[j * 5] + mat[k * 5]) + 1.0);
529 q[3] = (mat[j * 4 + k] - mat[k * 4 + j]) * s;
530 q[j] = (mat[i * 4 + j] + mat[j * 4 + i]) * s;
531 q[k] = (mat[i * 4 + k] + mat[k * 4 + i]) * s;
542 if (rMat[1][1] > rMat[0][0])
544 if (rMat[2][2] > rMat[1][1])
548 double r = sqrt(1. + rMat[i][i] - rMat[j][j] - rMat[k][k]);
555 double q[4], f = 0.5 / r;
557 q[j] = f * (rMat[i][j] + rMat[j][i]);
558 q[k] = f * (rMat[k][i] + rMat[i][k]);
559 q[3] = f * (rMat[k][j] - rMat[j][k]);
582 throw std::runtime_error(
"Quat::operator[] range error");
602 throw std::runtime_error(
"Quat::operator[] range error");
609void Quat::printSelf(std::ostream &os)
const { os <<
"[" <<
w <<
"," <<
a <<
"," <<
b <<
"," <<
c <<
"]"; }
617 std::getline(IX, in);
618 size_t i = in.find_first_of(
'[');
619 if (i == std::string::npos)
620 throw std::runtime_error(
"Wrong format for Quat input: " + in);
621 size_t j = in.find_last_of(
']');
622 if (j == std::string::npos || j < i + 8)
623 throw std::runtime_error(
"Wrong format for Quat input: " + in);
625 size_t c1 = in.find_first_of(
',');
626 size_t c2 = in.find_first_of(
',', c1 + 1);
627 size_t c3 = in.find_first_of(
',', c2 + 1);
628 if (c1 == std::string::npos || c2 == std::string::npos || c3 == std::string::npos)
629 throw std::runtime_error(
"Wrong format for Quat input: [" + in +
"]");
631 w = std::stod(in.substr(i + 1, c1 - i - 1));
632 a = std::stod(in.substr(c1 + 1, c2 - c1 - 1));
633 b = std::stod(in.substr(c2 + 1, c3 - c2 - 1));
634 c = std::stod(in.substr(c3 + 1, j - c3 - 1));
658 std::ostringstream mess;
666 std::istringstream mess(str);
670void Quat::rotateBB(
double &xmin,
double &ymin,
double &zmin,
double &xmax,
double &ymax,
double &zmax)
const {
673 std::swap(xmin, xmax);
675 std::swap(ymin, ymax);
677 std::swap(zmin, zmax);
690 for (
int i = 0; i < 3; i++) {
691 for (
int j = 0; j < 3; j++) {
695 minV[j] += (rotMatr[
index] > 0) ? rotMatr[
index] * minT[i] : rotMatr[
index] * maxT[i];
696 maxV[j] += (rotMatr[
index] > 0) ? rotMatr[
index] * maxT[i] : rotMatr[
index] * minT[i];
730 std::string conv(convention);
732 if (conv.length() != 3)
733 throw std::invalid_argument(
"Wrong convention name (string length not 3)");
735 boost::to_upper(conv);
738 if (conv.find_first_not_of(
"XYZ") != std::string::npos)
739 throw std::invalid_argument(
"Wrong convention name (characters other than XYZ)");
742 if ((conv[0] == conv[1]) || (conv[2] == conv[1]))
743 throw std::invalid_argument(
"Wrong convention name (repeated indices)");
745 boost::replace_all(conv,
"X",
"0");
746 boost::replace_all(conv,
"Y",
"1");
747 boost::replace_all(conv,
"Z",
"2");
750 s << conv[0] <<
" " << conv[1] <<
" " << conv[2];
752 int first, second, last;
753 s >> first >> second >> last;
756 const int TB = (first * second * last == 0 && first + second + last == 3) ? 1 : 0;
758 const int par01 = ((second - first + 9) % 3 == 1) ? 1 : -1;
759 const int par12 = ((last - second + 9) % 3 == 1) ? 1 : -1;
761 std::vector<double> angles(3);
765 const int i = (last + TB * par12 + 9) % 3;
766 const int j1 = (last - par12 + 9) % 3;
767 const int j2 = (last + par12 + 9) % 3;
769 const double s3 = (1.0 - TB - TB * par12) * R[i][j1];
770 const double c3 = (TB - (1.0 - TB) * par12) * R[i][j2];
775 constexpr double rad2deg = 180.0 / M_PI;
777 angles[2] = atan2(s3, c3) *
rad2deg;
782 const double s1 = par01 * Rp[(first - par01 + 9) % 3][(first + par01 + 9) % 3];
783 const double c1 = Rp[second][second];
784 const double s2 = par01 * Rp[first][3 - first - second];
785 const double c2 = Rp[first][first];
787 angles[0] = atan2(s1, c1) *
rad2deg;
788 angles[1] = atan2(s2, c2) *
rad2deg;
std::map< DeltaEMode::Type, std::string > index
void error(const std::string &msg)
Logs at error level.
void information(const std::string &msg)
Logs at information level.
void readPrinted(std::istream &)
Read data from a stream in the format returned by printSelf ("[w,a,b,c]").
void init()
Re-initialize to identity.
void normalize()
Normalize.
bool operator!=(const Quat &) const
Quaternion non-equal operator.
Quat operator-(const Quat &) const
Quaternion subtraction operator.
Quat()
Null Constructor Initialize the quaternion with the identity q=1.0+0i+0j+0k;.
Quat operator+(const Quat &) const
Overload operators.
void inverse()
Inverse a quaternion (in the sense of rotation inversion)
Quat & operator+=(const Quat &)
Quaternion self-addition operator.
double len() const
Norm of a quaternion.
Quat & operator-=(const Quat &)
Quaternion self-substraction operator.
bool operator==(const Quat &) const
Quaternion equal operator.
void getAngleAxis(double &_deg, double &_ax0, double &_ax1, double &ax2) const
Extracts the angle of roatation and axis.
void setQuat(double mat[16])
Convert GL Matrix into Quat.
void fromString(const std::string &str)
Sets the Quat using a string.
double len2() const
Norm squared.
void GLMatrix(double *mat) const
Convert quaternion rotation to an OpenGL matrix [4x4] matrix stored as an linear array of 16 double T...
void set(const double ww, const double aa, const double bb, const double cc)
Sets the quat values from four doubles.
Quat operator*(const Quat &) const
Quaternion multiplication operator.
void rotate(V3D &) const
Rotate a vector.
void printSelf(std::ostream &) const
Prints a string representation of itself.
Quat & operator*=(const Quat &)
Quaternion self-multiplication operator.
std::string toString() const
void rotateBB(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax) const
Taking two points defining a cuboid bounding box (xmin,ymin,zmin) and.
std::vector< double > getEulerAngles(const std::string &convention) const
Calculate the Euler angles that are equivalent to this Quaternion.
bool isNull(const double tolerance=0.001) const
Is the quaternion representing a null rotation.
std::vector< double > getRotation(bool check_normalisation=false, bool throw_on_errors=false) const
returns the rotation matrix defined by this quaternion as an 9-point
void setAngleAxis(const double _deg, const V3D &_axis)
Constructor from an angle and axis.
void setRotation(const double deg)
Set the rotation (both don't change rotation axis)
void conjugate()
Take the complex conjugate.
double operator[](int) const
Bracket operator overload returns the internal representation values based on an index.
void operator()(const Quat &)
Sets the quat values from another Quat.
constexpr double scalar_prod(const V3D &v) const noexcept
Calculates the cross product.
constexpr V3D cross_prod(const V3D &v) const noexcept
Cross product (this * argument)
double angle(const V3D &) const
Angle between this and another vector.
bool nullVector(const double tolerance=1e-3) const noexcept
Determine if the point is null.
constexpr double deg2rad
Defines units/enum for Crystal work.
Logger g_log("DateAndTime")
MANTID_KERNEL_DLL std::ostream & operator<<(std::ostream &, CPUTimer &)
Convenience function to provide for easier debug printing.
MANTID_KERNEL_DLL std::istream & operator>>(std::istream &, Interpolation &)
Reads in parameter value.
constexpr double Tolerance
Standard tolerance value.
MANTID_KERNEL_DLL V3D normalize(V3D v)
Normalizes a V3D.
Mantid::Kernel::Matrix< double > DblMatrix