Fast trigonometric operations
//package com.ryanm.droid.rugl.util; /** * Fast trigonometric operations * * @author Riven */ public class Trig { /** * I'm sick of casting to float */ public static final float PI = (float) Math.PI; /** * I'm also sick of multiplying by two */ public static final float TWO_PI = 2 * PI; /** * Honestly, who has the time to divide by two? */ public static final float HALF_PI = PI / 2; private static final int ATAN2_BITS = 7; private static final int ATAN2_BITS2 = ATAN2_BITS << 1; private static final int ATAN2_MASK = ~(-1 << ATAN2_BITS2); private static final int ATAN2_COUNT = ATAN2_MASK + 1; private static final int ATAN2_DIM = (int) Math.sqrt(ATAN2_COUNT); private static final float ATAN2_DIM_MINUS_1 = ATAN2_DIM - 1; private static final float[] atan2 = new float[ATAN2_COUNT]; private static final int SIN_BITS, SIN_MASK, SIN_COUNT; private static final float radFull, radToIndex; private static final float[] sin, cos; static { for (int i = 0; i < ATAN2_DIM; i++) { for (int j = 0; j < ATAN2_DIM; j++) { float x0 = (float) i / ATAN2_DIM; float y0 = (float) j / ATAN2_DIM; atan2[j * ATAN2_DIM + i] = (float) Math.atan2(y0, x0); } } SIN_BITS = 12; SIN_MASK = ~(-1 << SIN_BITS); SIN_COUNT = SIN_MASK + 1; radFull = (float) (Math.PI * 2.0); radToIndex = SIN_COUNT / radFull; sin = new float[SIN_COUNT]; cos = new float[SIN_COUNT]; for (int i = 0; i < SIN_COUNT; i++) { sin[i] = (float) Math.sin((i + 0.5f) / SIN_COUNT * radFull); cos[i] = (float) Math.cos((i + 0.5f) / SIN_COUNT * radFull); } } /** * Like {@link Math#sin(double)}, but a lot faster and a bit less accurate * * @param rad * @return sin( rad ) */ public static final float sin(float rad) { return sin[(int) (rad * radToIndex) & SIN_MASK]; } /** * Like {@link Math#cos(double)}, but a lot faster and a bit less accurate * * @param rad * @return cos( rad ) */ public static final float cos(float rad) { return cos[(int) (rad * radToIndex) & SIN_MASK]; } /** * @param y * @param x * @return the angle to (x,y) */ public static final float atan2(float y, float x) { float add, mul; if (x < 0.0f) { if (y < 0.0f) { x = -x; y = -y; mul = 1.0f; } else { x = -x; mul = -1.0f; } add = -3.141592653f; } else { if (y < 0.0f) { y = -y; mul = -1.0f; } else { mul = 1.0f; } add = 0.0f; } float invDiv = ATAN2_DIM_MINUS_1 / (x < y ? y : x); int xi = (int) (x * invDiv); int yi = (int) (y * invDiv); return (atan2[yi * ATAN2_DIM + xi] + add) * mul; } /** * @param degrees * @return the radians value */ public static float toRadians(float degrees) { return degrees / 180.0f * Trig.PI; } /** * @param radians * @return the degrees value */ public static float toDegrees(float radians) { return radians * 180.0f / Trig.PI; } }