Skip to content

Commit

Permalink
Merge 2f33d38 into 447ced4
Browse files Browse the repository at this point in the history
  • Loading branch information
stevebosman committed Nov 29, 2018
2 parents 447ced4 + 2f33d38 commit 50b1e4c
Show file tree
Hide file tree
Showing 2 changed files with 363 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,45 @@ public final class Quaternion implements Serializable {
* @param c Second vector component.
* @param d Third vector component.
*/
public Quaternion(final double a,
public static Quaternion of(final double a,
final double b,
final double c,
final double d) {
return new Quaternion(a, b, c, d);
}

/**
* Builds a quaternion from scalar and vector parts.
*
* @param scalar Scalar part of the quaternion.
* @param v Components of the vector part of the quaternion.
*
* @throws IllegalArgumentException if the array length is not 3.
*/
public static Quaternion of(final double scalar,
final double[] v) {
return new Quaternion(scalar, v);
}

/**
* Builds a pure quaternion from a vector (assuming that the scalar
* part is zero).
*
* @param v Components of the vector part of the pure quaternion.
*/
public static Quaternion of(final double[] v) {
return new Quaternion(0, v);
}

/**
* Builds a quaternion from its components.
*
* @param a Scalar component.
* @param b First vector component.
* @param c Second vector component.
* @param d Third vector component.
*/
private Quaternion(final double a,
final double b,
final double c,
final double d) {
Expand All @@ -79,7 +117,7 @@ public Quaternion(final double a,
*
* @throws IllegalArgumentException if the array length is not 3.
*/
public Quaternion(final double scalar,
private Quaternion(final double scalar,
final double[] v) {
if (v.length != 3) {
throw new IllegalArgumentException("Size of array must be 3");
Expand All @@ -92,21 +130,12 @@ public Quaternion(final double scalar,
}

/**
* Builds a pure quaternion from a vector (assuming that the scalar
* part is zero).
* Returns the conjugate of this quaternion number.
* The conjugate of {@code a + bi + cj + dk} is {@code a - bi -cj -dk}.
*
* @param v Components of the vector part of the pure quaternion.
* @return the conjugate of this quaternion object.
*/
public Quaternion(final double[] v) {
this(0, v);
}

/**
* Returns the conjugate quaternion of the instance.
*
* @return the conjugate quaternion
*/
public Quaternion getConjugate() {
public Quaternion conjugate() {
return new Quaternion(q0, -q1, -q2, -q3);
}

Expand Down Expand Up @@ -230,31 +259,37 @@ public double dotProduct(final Quaternion q) {
*
* @return the norm.
*/
public double getNorm() {
return Math.sqrt(q0 * q0 +
q1 * q1 +
q2 * q2 +
q3 * q3);
public double norm() {
return Math.sqrt(norm2());
}

/**
* Computes the square of the norm of the quaternion.
*
* @return the square of the norm.
*/
public double norm2() {
return q0 * q0 +
q1 * q1 +
q2 * q2 +
q3 * q3;
}

/**
* Computes the normalized quaternion (the versor of the instance).
* The norm of the quaternion must not be zero.
* The norm of the quaternion must not be near zero.
*
* @return a normalized quaternion.
* @throws IllegalStateException if the norm of the quaternion is zero.
* @throws IllegalStateException if the norm of the quaternion is near zero.
*/
public Quaternion normalize() {
final double norm = getNorm();
final double norm = norm();

if (norm < Precision.SAFE_MIN) {
throw new IllegalStateException(ZERO_NORM_MSG);
}

return new Quaternion(q0 / norm,
q1 / norm,
q2 / norm,
q3 / norm);
return this.divide(norm);
}

/**
Expand All @@ -267,10 +302,10 @@ public boolean equals(Object other) {
}
if (other instanceof Quaternion) {
final Quaternion q = (Quaternion) other;
return q0 == q.q0 &&
q1 == q.q1 &&
q2 == q.q2 &&
q3 == q.q3;
return ((Double)q0).equals(q.q0) &&
((Double)q1).equals(q.q1) &&
((Double)q2).equals(q.q2) &&
((Double)q3).equals(q.q3) ;
}

return false;
Expand Down Expand Up @@ -310,7 +345,7 @@ public boolean equals(final Quaternion q,
* {@code false} otherwise
*/
public boolean isUnitQuaternion(double eps) {
return Precision.equals(getNorm(), 1d, eps);
return Precision.equals(norm(), 1d, eps);
}

/**
Expand All @@ -329,7 +364,7 @@ public boolean isPureQuaternion(double eps) {
*
* @return the unit quaternion with positive scalar part.
*/
public Quaternion getPositivePolarForm() {
public Quaternion positivePolarForm() {
if (q0 < 0) {
final Quaternion unitQ = normalize();
// The quaternion of rotation (normalized quaternion) q and -q
Expand All @@ -350,8 +385,8 @@ public Quaternion getPositivePolarForm() {
* @return the inverse.
* @throws IllegalArgumentException if the norm (squared) of the quaternion is zero.
*/
public Quaternion getInverse() {
final double squareNorm = q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3;
public Quaternion inverse() {
final double squareNorm = norm2();
if (squareNorm < Precision.SAFE_MIN) {
throw new IllegalStateException(ZERO_NORM_MSG);
}
Expand Down Expand Up @@ -436,6 +471,71 @@ public Quaternion multiply(final double alpha) {
alpha * q3);
}

/**
* Divides the instance by a scalar.
*
* @param alpha Scalar factor.
* @return a scaled quaternion.
*/
public Quaternion divide(final double alpha) {
return new Quaternion(q0 / alpha,
q1 / alpha,
q2 / alpha,
q3 / alpha);
}

/**
* Parses a string that would be produced by {@link #toString()}
* and instantiates the corresponding object.
*
* @param s String representation.
* @return an instance.
* @throws QuaternionParsingException if the string does not
* conform to the specification.
*/
public static Quaternion parse(String s) {
final int len = s.length();
final int startBracket = s.indexOf("[");
if (startBracket != 0) {
throw new QuaternionParsingException("Missing opening square bracket");
}
final int endBracket = s.indexOf("]");
if (endBracket != len - 1) {
throw new QuaternionParsingException("Missing closing square bracket");
}
String[] elements = s.substring(1, s.length()-1).split(" ");
if (elements.length != 4) {
throw new QuaternionParsingException("Incorrect number of parts");
}

final double q1;
try {
q1 = Double.parseDouble(elements[0]);
} catch (Exception ex) {
throw new QuaternionParsingException("Could not parse scalar part" + elements[0]);
}
final double q2;
try {
q2 = Double.parseDouble(elements[1]);
} catch (Exception ex) {
throw new QuaternionParsingException("Could not parse i part" + elements[1]);
}
final double q3;
try {
q3 = Double.parseDouble(elements[2]);
} catch (Exception ex) {
throw new QuaternionParsingException("Could not parse j part" + elements[2]);
}
final double q4;
try {
q4 = Double.parseDouble(elements[3]);
} catch (Exception ex) {
throw new QuaternionParsingException("Could not parse k part" + elements[3]);
}

return of(q1, q2, q3, q4);
}

/**
* {@inheritDoc}
*/
Expand All @@ -452,4 +552,17 @@ public String toString() {

return s.toString();
}

/** See {@link #parse(String)}. */
static class QuaternionParsingException extends IllegalArgumentException {
/** Serializable version identifier. */
private static final long serialVersionUID = 20181128L;

/**
* @param msg Error message.
*/
QuaternionParsingException(String msg) {
super(msg);
}
}
}
Loading

0 comments on commit 50b1e4c

Please sign in to comment.