Java tutorial
/** * Copyright 2013 Robin Stumm (serverkorken@googlemail.com, http://dermetfan.bplaced.net) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.indignado.games.smariano.utils.dermetfan.math; import com.badlogic.gdx.math.Polygon; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; /** * contains some useful methods for geometric calculations * @author dermetfan */ public abstract class GeometryUtils { /** a temporary variable used by some methods * warning not safe to use as it may change any time */ public static Vector2 tmpVec = new Vector2(); /** @see #tmpVec */ public static Vector2[] tmpVecArr; /** @see #tmpVec */ public static float[] tmpFloatArr; /** @return a Vector2 representing the size of a rectangle containing all given vertices */ public static Vector2 size(Vector2[] vertices, Vector2 output) { return output.set(amplitude(filterX(vertices)), amplitude(filterY(vertices))); } /** @see #size(com.badlogic.gdx.math.Vector2[], com.badlogic.gdx.math.Vector2) */ public static Vector2 size(Vector2[] vertices) { return size(vertices, tmpVec); } /** @return the peak-to-peak amplitude of the given array */ public static float amplitude(float[] f) { return Math.abs(max(f) - min(f)); } /** @return the largest element of the given array */ public static float max(float[] floats) { float max = Float.NEGATIVE_INFINITY; for (float f : floats) max = f > max ? f : max; return max; } /** @return the smallest element of the given array */ public static float min(float[] floats) { float min = Float.POSITIVE_INFINITY; for (float f : floats) min = f < min ? f : min; return min; } /** @return the x values of the given vertices */ public static float[] filterX(Vector2[] vertices, float[] output) { output = new float[vertices.length]; for (int i = 0; i < output.length; i++) output[i] = vertices[i].x; return output; } /** @see #filterX(com.badlogic.gdx.math.Vector2[], float[]) */ public static float[] filterX(Vector2[] vertices) { return filterX(vertices, tmpFloatArr); } /** @return the y values of the given vertices */ public static float[] filterY(Vector2[] vertices, float[] output) { output = new float[vertices.length]; for (int i = 0; i < output.length; i++) output[i] = vertices[i].y; return output; } /** @see #filterY(com.badlogic.gdx.math.Vector2[], float[]) */ public static float[] filterY(Vector2[] vertices) { return filterY(vertices, tmpFloatArr); } /** * scales the given float array to have the given min and max values * @param values the values to scale * @param min the desired minimal value in the array * @param max the desired maximal value in the array * @return the rescaled array */ public static float[] scale(float[] values, float min, float max) { float tmp = amplitude(values) / (max - min); for (int i = 0; i < values.length; i++) values[i] /= tmp; tmp = min - min(values); for (int i = 0; i < values.length; i++) values[i] += tmp; return values; } /** * @param vector2s the Vector2[] to convert to a float[] * @return the float[] converted from the given Vector2[] */ public static float[] toFloatArray(Vector2[] vector2s, float[] output) { output = new float[vector2s.length * 2]; int vi = -1; for (int i = 0; i < output.length; i++) if (i % 2 == 0) output[i] = vector2s[++vi].x; else output[i] = vector2s[vi].y; return output; } /** @see #toFloatArray(com.badlogic.gdx.math.Vector2[], float[]) */ public static float[] toFloatArray(Vector2[] vector2s) { return toFloatArray(vector2s, tmpFloatArr); } /** * @param floats the float[] to convert to a Vector2[] * @return the Vector2[] converted from the given float[] */ public static Vector2[] toVector2Array(float[] floats, Vector2[] output) { if (floats.length % 2 != 0) throw new IllegalArgumentException( "the float array's length is not dividable by two, so it won't make up a Vector2 array: " + floats.length); output = new Vector2[floats.length / 2]; int fi = -1; for (int i = 0; i < output.length; i++) output[i] = new Vector2(floats[++fi], floats[++fi]); return output; } /** @see #toVector2Array(float[], com.badlogic.gdx.math.Vector2[]) */ public static Vector2[] toVector2Array(float[] floats) { return toVector2Array(floats, tmpVecArr); } public static Vector2[] toVector2Array(short[] shorts) { float[] floats = new float[shorts.length]; for (int i = 0; i < shorts.length; i++) { floats[i] = (float) shorts[i]; } return toVector2Array(floats, tmpVecArr); } /** * @param vertexCount the number of vertices for each {@link com.badlogic.gdx.math.Polygon} * @see #toPolygonArray(com.badlogic.gdx.math.Vector2[], int[]) */ public static Polygon[] toPolygonArray(Vector2[] vertices, int vertexCount) { int[] vertexCounts = new int[vertices.length / vertexCount]; for (int i = 0; i < vertexCounts.length; i++) vertexCounts[i] = vertexCount; return toPolygonArray(vertices, vertexCounts); } /** * @param vertices the vertices which should be split into a {@link com.badlogic.gdx.math.Polygon} array * @param vertexCounts the number of vertices of each {@link com.badlogic.gdx.math.Polygon} * @return the {@link com.badlogic.gdx.math.Polygon} array extracted from the vertices */ public static Polygon[] toPolygonArray(Vector2[] vertices, int[] vertexCounts) { Polygon[] polygons = new Polygon[vertexCounts.length]; int vertice = -1; for (int i = 0; i < polygons.length; i++) { tmpVecArr = new Vector2[vertexCounts[i]]; for (int i2 = 0; i2 < tmpVecArr.length; i2++) tmpVecArr[i2] = vertices[++vertice]; polygons[i] = new Polygon(toFloatArray(tmpVecArr)); } return polygons; } /** @see com.badlogic.gdx.math.Polygon#area() */ public static float area(float[] vertices) { // from com.badlogic.gdx.math.Polygon#area() float area = 0; int x1, y1, x2, y2; for (int i = 0; i < vertices.length; i += 2) { x1 = i; y1 = i + 1; x2 = (i + 2) % vertices.length; y2 = (i + 3) % vertices.length; area += vertices[x1] * vertices[y2]; area -= vertices[x2] * vertices[y1]; } return area /= 2; } /** * @param polygon the polygon, assumed to be simple * @return if the vertices are in clockwise order */ public static boolean areVerticesClockwise(Polygon polygon) { return polygon.area() < 0; } /** @see #areVerticesClockwise(com.badlogic.gdx.math.Polygon) */ public static boolean areVerticesClockwise(float[] vertices) { if (vertices.length <= 4) return true; return area(vertices) < 0; } /** @see #isConvex(com.badlogic.gdx.math.Vector2[]) */ public static boolean isConvex(float[] vertices) { return isConvex(toVector2Array(vertices)); } /** @see #isConvex(com.badlogic.gdx.math.Vector2[]) */ public static boolean isConvex(Polygon polygon) { return isConvex(polygon.getVertices()); } /** * @param vertices the vertices of the polygon to examine for convexity * @return if the polygon is convex */ public static boolean isConvex(Vector2[] vertices) { // http://www.sunshine2k.de/coding/java/Polygon/Convex/polygon.htm Vector2 p, v, u; float res = 0; for (int i = 0; i < vertices.length; i++) { p = vertices[i]; tmpVec = vertices[(i + 1) % vertices.length]; v = new Vector2(); v.x = tmpVec.x - p.x; v.y = tmpVec.y - p.y; u = vertices[(i + 2) % vertices.length]; if (i == 0) // in first loop direction is unknown, so save it in res res = u.x * v.y - u.y * v.x + v.x * p.y - v.y * p.x; else { float newres = u.x * v.y - u.y * v.x + v.x * p.y - v.y * p.x; if (newres > 0 && res < 0 || newres < 0 && res > 0) return false; } } return true; } /** * converts point to its coordinates on an isometric grid * @param point the point to convert * @param cellWidth the width of the grid cells * @param cellHeight the height of the grid cells * @return the given point converted to its coordinates on an isometric grid */ public static Vector2 toIsometricGridPoint(Vector2 point, float cellWidth, float cellHeight) { point.x = (point.x /= cellWidth) - ((point.y = (point.y - cellHeight / 2) / cellHeight + point.x) - point.x); return point; } /** @see #toIsometricGridPoint(com.badlogic.gdx.math.Vector2, float, float) */ public static Vector3 toIsometricGridPoint(Vector3 point, float cellWidth, float cellHeight) { point.x = (point.x /= cellWidth) - ((point.y = (point.y - cellHeight / 2) / cellHeight + point.x) - point.x); return point; } }