package okj.easy.math; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.math.Line; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; public final class eMath { public static final int INFINITE = -10000; public static final Vector2 UNIT_VECTOR_Ox = new Vector2(1, 0); public static final Vector2 UNIT_VECTOR_0y = new Vector2(0, 1); public static final int COUNTER_CLOCKWISE = 1; public static final int CLOCKWISE = 2; static public final float PI = 3.1415927f; static public final float MAX_ANGLE = 36000000; /** Noone can instance this class */ public static float tmp; public static float tmp1; public static float tmp2; public static float tmp3; private eMath () { } /*************************************************************************** * ***************************************************************************/ /** Turn angle back to 0-360 form * * @param degrees * @return */ public static float claimAngle (float degrees) { tmp = degrees + MAX_ANGLE; tmp1 = tmp % 360; return tmp1; } public static int shortestPath (float originDegrees, float destDegrees) { originDegrees = claimAngle(originDegrees); destDegrees = claimAngle(destDegrees); // this algorithm is simple the smaller arc is the shortest path(which is smaller than 180) if (originDegrees < destDegrees) { tmp3 = destDegrees - originDegrees; if (tmp3 < 180) return 1; return -1; } else { tmp3 = originDegrees - destDegrees; if (tmp3 < 180) return -1; return 1; } } public static float calVectorAngle (Vector2 lineStart, Vector2 lineEnd) { if (lineEnd.x == lineStart.x) { if (lineEnd.y > lineStart.y) return 90; if (lineEnd.y < lineStart.y) return 270; } if (lineEnd.y == lineStart.y) { if (lineStart.x < lineEnd.x) return 360; if (lineStart.x > lineEnd.x) return 180; } if (lineEnd.x > lineStart.x) return (float)(180.0f / PI * Math.atan((lineEnd.y - lineStart.y) / (lineEnd.x - lineStart.x))); if (lineEnd.x < lineStart.x) return (float)(180.0f / PI * Math.atan((lineEnd.y - lineStart.y) / (lineEnd.x - lineStart.x))) - 180; return 0; } public static float calVectorAngle (float x, float y, float x1, float y1) { if (x1 == x) { if (y1 > y) return 90; if (y1 < y) return 270; } if (y1 == y) { if (x < x1) return 360; if (x > x1) return 180; } if (x1 > x) return (float)(180.0f / MathUtils.PI * Math.atan((y1 - y) / (x1 - x))); if (x1 < x) return (float)(180.0f / MathUtils.PI * Math.atan((y1 - y) / (x1 - x))) - 180; return 0; } public static float calModule (Vector2 src, Vector2 dst) { return (float)Math .sqrt((src.x - dst.x) * (src.x - dst.x) + (src.y - dst.y) * (src.y - dst.y)); } public static float calModule (float x1, float y1, float x2, float y2) { return (float)Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); } public static Vector2 calMiddle (Vector2 v1, Vector2 v2) { return new Vector2((v1.x + v2.x) / 2, (v1.y + v2.y) / 2); } public static void calCenterPoint (Vector2 result, float x, float y, float x1, float y1) { result.set((x + x1) / 2, (y + y1) / 2); } /************************************************************* * *************************************************************/ public static float getXinLine (int y, Vector2 src, Vector2 dst) { float delta = ((float)(src.x - dst.x) / (float)(src.y - dst.y)); return (float)(delta * (y - src.y) + src.x); } public static float getYinLine (float x, Vector2 src, Vector2 dst) { float delta = ((float)(src.y - dst.y) / (float)(src.x - dst.x)); return (float)(delta * (x - src.x) + src.y); } public static float getXinLine (float y, Vector2 src, Vector2 dst) { float delta = ((float)(src.x - dst.x) / (float)(src.y - dst.y)); return (int)(delta * (y - src.y) + src.x); } /** Calculate angle between two line, (x,y)-(x1-y1) and (x,y)-(x2,y2) * * @param x * @param y * @param x1 * @param y1 * @param x2 * @param y2 * @return the angle in degree */ public static float calAngle (float x, float y, float x1, float y1, float x2, float y2) { float a; float b; float c; Vector2 BASE = new Vector2(x, y); Vector2 FP = new Vector2(x1, y1); Vector2 SP = new Vector2(x2, y2); a = calModule(BASE, FP); b = calModule(BASE, SP); c = calModule(FP, SP); float cos; cos = (a * a + b * b - c * c) / (2 * a * b); return (float)(Math.acos(cos) * 180 / Math.PI); } public static Vector2 getCrossPointOf2Line (Line line, Line line1) { Vector2 n = line.getNormalVector(); float a = n.x; float b = n.y; float c = line.getConstantOfLine(); Vector2 n1 = line1.getNormalVector(); float a1 = n1.x; float b1 = n1.y; float c1 = line1.getConstantOfLine(); Gdx.app.log("shit", "" + a + " " + b + " " + c + " " + a1 + " " + b1 + " " + c1); if (a * b1 == b * a1) return null; else return new Vector2((b * c1 - c * b1) / (b1 * a - b * a1), (a1 * c - c1 * a) / (b1 * a - b * a1)); } /*************************************************************************** * ***************************************************************************/ public static Vector2 solveTheQuadricFunction (float a, float b, float c) { if (a == 0) return new Vector2(-c / b, -c / b); else { return new Vector2((float)(-b + Math.sqrt(b * b - 4 * a * c)) / (2 * a), (float)(-b - Math.sqrt(b * b - 4 * a * c)) / (2 * a)); } } /** Return 1 if the srcAngle should increase to reach dstAngle, otherwise -1 * * @param srcANGLE * @param dstANGLE * @return */ public static int calShortestPathBetweenTwoAngle (float srcANGLE, float dstANGLE) { if (dstANGLE <= 180) { if (srcANGLE > 180) { float x1 = 360 - srcANGLE; float y1 = dstANGLE; float x2 = srcANGLE - 180; float y2 = 180 - dstANGLE; if ((x1 + y1) >= (x2 + y2)) { return -1; } else return 1; } else { if (srcANGLE < dstANGLE) return 1; else return -1; } } else { if (srcANGLE > 180) { if (srcANGLE < dstANGLE) return 1; else return -1; } else { float x1 = 360 - dstANGLE; float y1 = srcANGLE; float x2 = dstANGLE - 180; float y2 = 180 - srcANGLE; if ((x1 + y1) >= (x2 + y2)) { return 1; } else return -1; } } } public static float minDivisibleNumber (float yourDividend, float divisor) { return yourDividend - (yourDividend % divisor); } public static float maxDivisibleNumber (float yourDividend, float divisor) { return yourDividend + (divisor - (yourDividend % divisor)); } /** This method is more special if your number is power of two it will return a number >= 0 ,otherwise it will return < 0 * * @param number * @return */ public static int isPowerOfTwo (int number) { if (!MathUtils.isPowerOfTwo(number)) return -1; for (int i = 0; i < 32; i++) { if ((number >> i) == 0) return i - 1; } return 0; } /******************** vector and matrix helper ********************/ public final static float[] tmpVec3 = new float[3]; public final static float[] tmpVec2 = new float[3]; public final static float[] tmpVec1 = new float[3]; public static void ToFloatVector (Vector3 v, float[] tmp) { tmp[0] = v.x; tmp[1] = v.y; tmp[2] = v.z; } public static void ToFloatVector (float x, float y, float z, float[] tmp) { tmp[0] = x; tmp[1] = y; tmp[2] = z; } public static void ToObjectVector (Vector3 v, float[] tmp) { v.x = tmp[0]; v.y = tmp[1]; v.z = tmp[2]; } }