package com.momega.spacesimulator.utils; import org.apache.commons.math3.geometry.euclidean.threed.Rotation; import org.apache.commons.math3.geometry.euclidean.threed.RotationOrder; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.apache.commons.math3.util.FastMath; import org.springframework.util.Assert; import com.momega.spacesimulator.model.*; /** * The class contains set of the function to manipulate with the vectors * Created by martin on 6/22/14. */ public final class VectorUtils { public final static double SMALL_EPSILON = 0.00001; public static Vector3d transform(KeplerianOrbit keplerianOrbit, Vector3d vector) { Rotation r = new Rotation(RotationOrder.ZXZ, keplerianOrbit.getAscendingNode(), keplerianOrbit.getInclination(), keplerianOrbit.getArgumentOfPeriapsis()); Vector3D v = toVector3D(vector); Vector3D rv = r.applyInverseTo(v); Vector3d result = new Vector3d(rv.getX(), rv.getY(), rv.getZ()); return result; } public static CartesianState transformCoordinateSystem(MovingObject source, MovingObject target, CartesianState cartesianState) { CartesianState result = cartesianState.add(source.getCartesianState()).subtract(target.getCartesianState()); return result; } /** * Gets the relative cartesian state to the current center of the orbit * @param movingObject the moving object (typically spacecraft) * @return the new instance of the cartesian state */ public static CartesianState relativeCartesianState(MovingObject movingObject) { return movingObject.getCartesianState().subtract(movingObject.getKeplerianElements().getKeplerianOrbit().getReferenceFrame().getCartesianState()); } public static boolean equals(Vector3d v1, Vector3d v2, double precision) { return v1.subtract(v2).length()<precision; } /** * Rotates vector v anticlockwise about the specified axis by the specified angle (in radians). * @param v The vector to rotate about the axis * @param angle The angle by which to rotate it (in radians) * @param axis The axis about which to rotate it * @return A (new) vector containing the result of the rotation */ public static Vector3d rotateAboutAxis(final Vector3d v, final double angle, final Vector3d axis) { Assert.notNull(v); Assert.notNull(axis); Assert.isTrue(Math.abs(axis.length() - 1) < SMALL_EPSILON); // Main algorithm double cosAngle = FastMath.cos(angle); Vector3d cross = axis.cross(v); // ret = v cos radianAngle + (axis x v) sin radianAngle + axis(axis . v)(1 - cos radianAngle) // (See Mathematics for 3D Game Programming and Computer Graphics, P.62, for details of why this is (it's not very hard)). Vector3d ret = v.scale(cosAngle); ret = ret.scaleAdd(Math.sin(angle), cross); ret = ret.scaleAdd(axis.dot(v) * (1 - cosAngle), axis); return ret; } public static Orientation rotateByAngles(Orientation o, double alpha, double delta) { Orientation result = o.clone(); result.lookAroundV(alpha); result.lookUp(delta); return result; } /** * Creates the rotation transformation * @param alpha right ascension * @param delta declination of the north-pole * @return the transformation matrix */ public static Orientation createOrientation(double alpha, double delta, boolean toEcliptic) { Orientation o = Orientation.createUnit(); o.lookAroundV(alpha); o.lookUp(Math.PI / 2 - delta); if (toEcliptic) { o.rotate(new Vector3d(1, 0, 0), -VectorUtils.ECLIPTIC); } return o; } private static Vector3D toVector3D(Vector3d v) { return new Vector3D(v.getX(), v.getY(),v.getZ()); } /** * Get the angle of the ecliptic */ public static final double ECLIPTIC = Math.toRadians(23.439291); }