package com.momega.spacesimulator.model; import com.momega.spacesimulator.utils.VectorUtils; import org.apache.commons.math3.util.FastMath; /** * Orientation class is used to define 3D orientation. It is defined with * the three mutually-orthogonal axes, namely {@link #n} (points in the * direction faced by the object), {@link #u} (points to the left of the object) * and {@link #v} (points to the top of the object). * Created by martin on 9.5.2014. */ public class Orientation { private Vector3d n; private Vector3d u; private Vector3d v; public Orientation(Vector3d nVector, Vector3d vVector) { setN(nVector.normalize()); setV(vVector.normalize()); setU(getV().cross(getN())); } public static Orientation createUnit() { return new Orientation(Vector3d.ONE_X, Vector3d.ONE_Z); } /** * Returns the n vector of the object3d. */ public Vector3d getN() { return n; } /** * Returns the u vector of the object3d. */ public Vector3d getU() { return u; } /** * Returns the v vector of the object3d. */ public Vector3d getV() { return v; } public void setN(Vector3d nVector) { this.n = nVector; } public void setU(Vector3d uVector) { this.u = uVector; } public void setV(Vector3d vVector) { this.v = vVector; } /** * Rotates the orientation up * @param step the angle in radians */ public void lookUp(double step) { rotate(this.u, step); } public void lookLeft(double step) { rotate(new Vector3d(0,0,1), step); } public void lookAroundV(double step) { rotate(this.v, step); } public void twist(double step) { rotate(this.n, step); } public Orientation clone() { Orientation o = new Orientation(getN().clone(), getV().clone()); return o; } /** * Rotates the orientation object anticlockwise by the specified angle about the specified axis. * @param axis The axis about which to rotate * @param angle The angle by which to rotate (in radians) */ public void rotate(Vector3d axis, double angle) { // Note: We try and optimise things a little by observing that there's no point rotating // an axis about itself and that generally when we rotate about an axis, we'll be passing // it in as the parameter axis, e.g. object3d.rotate(object3d.getN(), Math.PI/2). if(axis != getN()) { setN(VectorUtils.rotateAboutAxis(getN(), angle, axis)); } if(axis != getU()) { setU(VectorUtils.rotateAboutAxis(getU(), angle, axis)); } if(axis != getV()) { setV(VectorUtils.rotateAboutAxis(getV(), angle, axis)); } } /** * Gets the spherical coordinates defined by the vector and the orientation object (3 axis). * The radius parameter will be used only for radius in result spherical coordinates * @param point the given point * @param radius * @return */ public SphericalCoordinates getCoordinatesOfVector(Vector3d point, double radius) { double theta = FastMath.abs(getV().angle(point)); Plane xy = new Plane(Vector3d.ZERO, getV()); Vector3d projectionV = xy.projection(point); double phi = getN().angle(projectionV); return new SphericalCoordinates(radius, theta, phi); } }