Mega Code Archive

 
Categories / Java / 2D Graphics GUI
 

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;   } }