
org.jeometry.simple.math.SimpleQuaternion Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jeometry-simple Show documentation
Show all versions of jeometry-simple Show documentation
Jeometry, a Mathematic and Geometry library for Java
The newest version!
package org.jeometry.simple.math;
import org.jeometry.Jeometry;
import org.jeometry.factory.JeometryFactory;
import org.jeometry.math.Matrix;
import org.jeometry.math.Quaternion;
import org.jeometry.math.Vector;
/**
* This class is a simple implementation of the {@link Quaternion} interface.
* @author Julien Seinturier - COMEX S.A. - [email protected] - https://github.com/jorigin/jeometry
* @version {@value Jeometry#version} b{@value Jeometry#BUILD}
* @since 1.0.0
*
*/
public class SimpleQuaternion implements Quaternion {
/**
* The scalar component.
*/
private double scalar = Double.NaN;
/**
* The i component.
*/
private double i = Double.NaN;
/**
* The j component.
*/
private double j = Double.NaN;
/**
* The k component.
*/
private double k = Double.NaN;
/**
* Create a new simple quaternion equals to 0
*/
public SimpleQuaternion() {
this.scalar = 0.0d;
this.i = 0.0d;
this.j = 0.0d;
this.k = 0.0d;
}
/**
* Create a new simple quaternion with the given components.
* @param scalar the quaternion real part (or scalar) parameter, denoted a within the definition .
* @param i the i basis component of the quaternion vector part (or imaginary part) parameter.
* @param j the j basis component of the quaternion vector part (or imaginary part) parameter.
* @param k the k basis component of the quaternion vector part (or imaginary part) parameter.
*/
public SimpleQuaternion(double scalar, double i, double j, double k) {
this.scalar = scalar;
this.i = i;
this.j = j;
this.k = k;
}
/**
* Create a new simple quaternion that is a copy of the given one.
* @param quaternion the quaternion to copy.
*/
public SimpleQuaternion(Quaternion quaternion) {
if (quaternion != null) {
this.scalar = quaternion.getScalar();
this.i = quaternion.getI();
this.j = quaternion.getJ();
this.k = quaternion.getK();
}
}
@Override
public int getDimension() {
return 4;
}
@Override
public double getValue(int dimension) {
if ((dimension >= 0) && (dimension < 4)) {
if (dimension == Quaternion.QUATERNION_SCALAR_COMPONENT) {
return scalar;
} else if (dimension == Quaternion.QUATERNION_I_COMPONENT) {
return i;
} else if (dimension == Quaternion.QUATERNION_J_COMPONENT) {
return j;
} else if (dimension == Quaternion.QUATERNION_K_COMPONENT) {
return k;
} else {
throw new IllegalArgumentException("Invalid dimension "+dimension+". Expected 0 to 3");
}
} else {
throw new IllegalArgumentException("Invalid dimension "+dimension+". Expected 0 to 3");
}
}
@Override
public void setValue(int dimension, double value) {
if ((dimension >= 0) && (dimension < 4)) {
if (dimension == Quaternion.QUATERNION_SCALAR_COMPONENT) {
scalar = value;;
} else if (dimension == Quaternion.QUATERNION_I_COMPONENT) {
i = value;
} else if (dimension == Quaternion.QUATERNION_J_COMPONENT) {
j = value;
} else if (dimension == Quaternion.QUATERNION_K_COMPONENT) {
k = value;
} else {
throw new IllegalArgumentException("Invalid dimension "+dimension+". Expected 0 to 3");
}
} else {
throw new IllegalArgumentException("Invalid dimension "+dimension+". Expected 0 to 3");
}
}
@Override
public void setValues(Vector v) {
if (v == null) {
throw new IllegalArgumentException("Null input vector");
}
if (getDimension() != v.getDimension()) {
throw new IllegalArgumentException("Invalid input vector dimension "+v.getDimension()+", expected "+getDimension());
}
for(int dimension = 0; dimension < getDimension(); dimension++) {
setValue(dimension, v.getValue(dimension));
}
}
@Override
public void setValues(double[] components) {
if (components == null) {
throw new IllegalArgumentException("Null input array");
}
if (getDimension() != components.length) {
throw new IllegalArgumentException("Invalid input components length "+components.length+", expected "+getDimension());
}
for(int dimension = 0; dimension < getDimension(); dimension++) {
setValue(dimension, components[dimension]);
}
}
@Override
public Vector extract(int start, int length) {
Vector extracted = null;
if ((start < 0) || (start >= getDimension())) {
throw new IllegalArgumentException("Invalid first index "+start+", expected values within [0, "+(getDimension() - 1)+"]");
}
if ((length < 1) || (length > getDimension() - start)) {
throw new IllegalArgumentException("Invalid length "+start+", expected values within [0, "+(getDimension() - start)+"[");
}
extracted = JeometryFactory.createVector(length);
for(int dimension = 0; dimension < extracted.getDimension(); dimension++) {
extracted.setValue(dimension, getValue(dimension+start));
}
return extracted;
}
@Override
public double normSquare() {
return scalar*scalar + i*i + j*j + k*k;
}
@Override
public double norm() {
return Math.sqrt(normSquare());
}
@Override
public void normalize() {
double norm = norm();
scalar = scalar / norm;
i = i / norm;
j = j / norm;
k = k / norm;
}
@Override
public Vector orthogonal() {
// TODO implements SimpleQuaternion.orthogonal()
System.err.println("SimpleQuaternion.orthogonal() NOT YET IMPLEMENTED");
return null;
}
@Override
public Vector orthogonal(Vector result) {
// TODO implements SimpleQuaternion.orthogonal(Vector)
System.err.println("SimpleQuaternion.orthogonal(Vector) NOT YET IMPLEMENTED");
return null;
}
@Override
public double getScalar() {
return scalar;
}
@Override
public void setScalar(double value) {
this.scalar = value;
}
@Override
public double getI() {
return i;
}
@Override
public void setI(double value) {
this.i = value;
}
@Override
public double getJ() {
return j;
}
@Override
public void setJ(double value) {
j = value;
}
@Override
public double getK() {
return k;
}
@Override
public void setK(double value) {
this.k = value;
}
@Override
public double[] getValues() {
return new double[] {scalar, i, j, k};
}
@Override
public double[] getValues(double[] components) throws IllegalArgumentException {
if (components != null) {
if (components.length >= 4) {
components[org.jeometry.math.Quaternion.QUATERNION_SCALAR_COMPONENT] = scalar;
components[org.jeometry.math.Quaternion.QUATERNION_I_COMPONENT] = i;
components[org.jeometry.math.Quaternion.QUATERNION_J_COMPONENT] = j;
components[org.jeometry.math.Quaternion.QUATERNION_K_COMPONENT] = k;
} else {
throw new IllegalArgumentException("Invalid components length "+components.length+". Expected at least 4");
}
}
return components;
}
@Override
public void setComponents(double a, double b, double c, double d) {
scalar = a;
i = b;
j = c;
k = d;
}
@Override
public void setValues(double value) {
for(int dimension = 0; dimension < getDimension(); dimension++) {
setValue(dimension, value);
}
}
@Override
public void setValues(Matrix matrix) {
if (matrix == null) {
throw new IllegalArgumentException("Null input.");
}
int min = -1;
int max = -1;
boolean columnMatrix = false;
if (matrix.getRowsCount() < matrix.getColumnsCount()) {
min = matrix.getRowsCount();
max = matrix.getColumnsCount();
columnMatrix = true;
} else {
min = matrix.getColumnsCount();
max = matrix.getRowsCount();
columnMatrix = false;
}
if (min != 1) {
throw new IllegalArgumentException("Matrix "+matrix.getRowsCount()+"x"+ matrix.getColumnsCount()+" cannot be set to vector.");
}
if (max != getDimension()) {
throw new IllegalArgumentException("Matrix "+matrix.getRowsCount()+"x"+ matrix.getColumnsCount()+" cannot be set to a "+getDimension()+" vector");
}
if (columnMatrix) {
for(int dimension = 0; dimension < matrix.getColumnsCount(); dimension++) {
setValue(dimension, matrix.getValue(0, dimension));
}
} else {
for(int dimension = 0; dimension < matrix.getRowsCount(); dimension++) {
setValue(dimension, matrix.getValue(dimension, 0));
}
}
}
@Override
public Quaternion mult(Quaternion p) {
return mult(p, new SimpleQuaternion());
}
@Override
public Quaternion mult(Quaternion p, Quaternion result) {
if ((result != null) && (p != null)){
result.setComponents(scalar * p.getScalar() - i * p.getI() - j * p.getJ() - k * p.getK(),
scalar * p.getI() + i * p.getScalar() + j * p.getK() - k * p.getJ(),
scalar * p.getJ() - i * p.getK() + j * p.getScalar() + k * p.getI(),
scalar * p.getK() + i * p.getJ() - j * p.getI() + k * p.getScalar());
}
return result;
}
@Override
public Quaternion multAffect(Quaternion p) {
return mult(p, this);
}
@Override
public Quaternion invertQuaternion() throws IllegalStateException {
double normSquare = normSquare();
return new SimpleQuaternion( scalar / normSquare,
-1.0d * i / normSquare,
-1.0d * j / normSquare,
-1.0d * k / normSquare);
}
@Override
public Quaternion invertQuaternion(Quaternion result) throws IllegalStateException {
if (result != null) {
double normSquare = normSquare();
result.setComponents(scalar / normSquare,
-1.0d * i / normSquare,
-1.0d * j / normSquare,
-1.0d * k / normSquare);
}
return result;
}
@Override
public Quaternion invertQuaternionAffect() throws IllegalStateException {
double normSquare = normSquare();
scalar = scalar / normSquare;
i = -1.0d * i / normSquare;
j = -1.0d * j / normSquare;
k = -1.0d * k / normSquare;
return this;
}
@Override
public Quaternion conjugateQuaternion() {
return new SimpleQuaternion( scalar, -1.0d * i, -1.0d * j, -1.0d * k);
}
@Override
public Quaternion conjugateQuaternion(Quaternion result) {
if (result != null) {
result.setComponents(scalar, -1.0d * i, -1.0d * j, -1.0d * k);
}
return result;
}
@Override
public Quaternion conjugateQuaternionAffect() {
i = -1.0d * i;
j = -1.0d * j;
k = -1.0d * k;
return this;
}
@Override
public String toString() {
String str = "";
str += getScalar();
if (getI() > 0) {
str += " + "+getI();
} else if (getI() < 0){
str += " - "+Math.abs(getI());
}
if (getJ() > 0) {
str += " + "+getJ();
} else if (getJ() < 0){
str += " - "+Math.abs(getJ());
}
if (getK() > 0) {
str += " + "+getK();
} else if (getK() < 0){
str += " - "+Math.abs(getK());
}
return str;
}
@Override
public Quaternion plus(Vector v) {
return (Quaternion)plus(v, JeometryFactory.createQuaternion());
}
@Override
public Vector plus(Vector v, Vector result) {
if (v != null) {
if (v.getDimension() != getDimension()) {
throw new IllegalArgumentException("Invalid input vector dimension "+v.getDimension()+", expected "+getDimension());
}
if (result != null) {
if (result.getDimension() != getDimension()) {
throw new IllegalArgumentException("Invalid result vector dimension "+result.getDimension()+", expected "+getDimension());
}
for(int dimension = 0; dimension < getDimension(); dimension++) {
result.setValue(dimension, getValue(dimension) + v.getValue(dimension));
}
}
}
return result;
}
@Override
public Quaternion plusAffect(Vector v) {
return (Quaternion) plus(v, this);
}
@Override
public Vector plus(double scalar, Vector result) {
if (result != null) {
if (result.getDimension() != getDimension()) {
throw new IllegalArgumentException("Invalid result dimension "+result.getDimension()+", expected "+getDimension());
}
for(int dimension = 0; dimension < getDimension(); dimension++) {
result.setValue(dimension, getValue(dimension)+scalar);
}
}
return result;
}
@Override
public Quaternion plus(double scalar, Quaternion result) {
if (result != null) {
result.setI(getI()+scalar);
result.setJ(getI()+scalar);
result.setK(getI()+scalar);
result.setScalar(getScalar()+scalar);
}
return result;
}
@Override
public Quaternion plus(double scalar) {
return plus(scalar, JeometryFactory.createQuaternion());
}
@Override
public Quaternion plusAffect(double scalar) {
return plus(scalar, this);
}
@Override
public Vector minus(Vector v) {
return minus(v, JeometryFactory.createVector(getDimension()));
}
@Override
public Vector minus(Vector v, Vector result) {
if (v != null) {
if (v.getDimension() != getDimension()) {
throw new IllegalArgumentException("Invalid input vector dimension "+v.getDimension()+", expected "+getDimension());
}
if (result != null) {
if (result.getDimension() != getDimension()) {
throw new IllegalArgumentException("Invalid result vector dimension "+result.getDimension()+", expected "+getDimension());
}
for(int dimension = 0; dimension < getDimension(); dimension++) {
result.setValue(dimension, getValue(dimension) - v.getValue(dimension));
}
}
}
return result;
}
@Override
public Vector minus(double scalar, Vector result) {
if (result != null) {
if (result.getDimension() != getDimension()) {
throw new IllegalArgumentException("Invalid result dimension "+result.getDimension()+", expected "+getDimension());
}
for(int dimension = 0; dimension < getDimension(); dimension++) {
result.setValue(dimension, getValue(dimension) - scalar);
}
}
return result;
}
@Override
public Quaternion minus(double scalar, Quaternion result) {
if (result != null) {
result.setI(getI()-scalar);
result.setJ(getI()-scalar);
result.setK(getI()-scalar);
result.setScalar(getScalar()-scalar);
}
return result;
}
@Override
public Quaternion minus(double scalar) {
return minus(scalar, JeometryFactory.createQuaternion());
}
@Override
public Quaternion minusAffect(Vector v) {
return (Quaternion) minus(v, this);
}
@Override
public Quaternion minusAffect(double scalar) {
return minus(scalar, this);
}
@Override
public Vector multiply(Vector v) {
return multiply(v, JeometryFactory.createVector(getDimension()));
}
@Override
public Vector multiply(Vector v, Vector result) {
if (v != null) {
if (v.getDimension() != getDimension()) {
throw new IllegalArgumentException("Invalid input vector dimension "+v.getDimension()+", expected "+getDimension());
}
if (result != null) {
if (result.getDimension() != getDimension()) {
throw new IllegalArgumentException("Invalid result vector dimension "+result.getDimension()+", expected "+getDimension());
}
for(int dimension = 0; dimension < getDimension(); dimension++) {
result.setValue(dimension, getValue(dimension) * v.getValue(dimension));
}
}
}
return result;
}
@Override
public Quaternion multiply(double scalar, Quaternion result) {
if (result != null) {
result.setI(getI()*scalar);
result.setJ(getI()*scalar);
result.setK(getI()*scalar);
result.setScalar(getScalar()*scalar);
}
return result;
}
@Override
public Vector multiply(double scalar) {
return multiply(scalar, JeometryFactory.createVector(getDimension()));
}
@Override
public Vector multiply(double scalar, Vector result) throws IllegalArgumentException {
if (result != null) {
if (result.getDimension() >= getDimension()) {
for(int dimension = 0; dimension < getDimension(); dimension++) {
result.setValue(dimension, getValue(dimension)*scalar);
}
} else {
throw new IllegalArgumentException("Invalid result vector dimension ("+result.getDimension()+"), expected at least "+getDimension());
}
}
return result;
}
@Override
public Quaternion multiplyAffect(Vector v) {
return (Quaternion) multiply(v, this);
}
@Override
public Quaternion multiplyAffect(double scalar) {
for(int dimension = 0; dimension < getDimension(); dimension++) {
setValue(dimension, getValue(dimension)*scalar);
}
return this;
}
@Override
public Vector divide(Vector v) {
return divide(v, JeometryFactory.createVector(getDimension()));
}
@Override
public Vector divide(Vector v, Vector result) {
if (v != null) {
if (v.getDimension() != getDimension()) {
throw new IllegalArgumentException("Invalid input vector dimension "+v.getDimension()+", expected "+getDimension());
}
if (result != null) {
if (result.getDimension() != getDimension()) {
throw new IllegalArgumentException("Invalid result vector dimension "+result.getDimension()+", expected "+getDimension());
}
for(int dimension = 0; dimension < getDimension(); dimension++) {
result.setValue(dimension, getValue(dimension) / v.getValue(dimension));
}
}
}
return result;
}
@Override
public Quaternion divideAffect(Vector v) {
return (Quaternion) divide(v, this);
}
@Override
public Vector divide(double scalar, Vector result) throws IllegalArgumentException {
if (result != null) {
if (result.getDimension() != getDimension()) {
throw new IllegalArgumentException("Invalid result dimension "+result.getDimension()+", expected "+getDimension());
}
for(int dimension = 0; dimension < getDimension(); dimension++) {
result.setValue(dimension, getValue(dimension) / scalar);
}
}
return result;
}
@Override
public Quaternion divide(double scalar, Quaternion result) {
if (result != null) {
result.setI(getI()/scalar);
result.setJ(getI()/scalar);
result.setK(getI()/scalar);
result.setScalar(getScalar()/scalar);
}
return result;
}
@Override
public Quaternion divide(double scalar) {
return divide(scalar, JeometryFactory.createQuaternion());
}
@Override
public Quaternion divideAffect(double scalar) {
return divide(scalar, this);
}
@Override
public double dot(Vector v) {
if (v != null) {
if (v.getDimension() != getDimension()) {
throw new IllegalArgumentException("Invalid input vector dimension "+v.getDimension()+", expected "+getDimension());
}
double d = 0.0d;
for(int dimension = 0; dimension < getDimension(); dimension++) {
d = d + dimension + getValue(dimension) * v.getValue(dimension);
}
return d;
}
return Double.NaN;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy