package cz.urbangaming.galgs.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import android.util.Log;
import cz.urbangaming.galgs.GAlg;
import cz.urbangaming.galgs.Scene;
/**
* All kinds of mess.
* TODO: Debug, optimize, clean-up...
*
* @author Michal Karm Babacek
* @license GNU GPL 3.0
*
*/
public class Utils {
private static Random rand = new Random();
/**
* Generates random vertices
*
* @param howMany
* @param minX
* boundary
* @param minY
* boundary
* @param maxX
* boundary
* @param maxY
* boundary
* @return
*/
public static List<Point2D> generateSomeVertices(int howMany, int minX, int minY, int maxX, int maxY) {
List<Point2D> vertices = new ArrayList<Point2D>(howMany);
for (int i = 0; i < howMany; i++) {
vertices.add(new Point2D((float) randInt(minX, maxX), (float) randInt(minY, maxY)));
}
return vertices;
}
/**
* Random int within limits
*
* @param min
* @param max
* @return
*/
public static int randInt(int min, int max) {
return rand.nextInt((max - min) + 1) + min;
}
/**
* Determines whether the given x,y point lies within the rectangle determined by center and size.
*
* @param centerX
* @param centerY
* @param size
* @param x
* @param y
* @return
*/
public static boolean isInRectangle(Point2D centerPoint, float size, Point2D pointToTry) {
return pointToTry.x() >= centerPoint.x() - size && pointToTry.x() <= centerPoint.x() + size &&
pointToTry.y() >= centerPoint.y() - size && pointToTry.y() <= centerPoint.y() + size;
}
/**
* TODO: This is silly, let's merge it with the aforementioned one.
*
* @param pX
* @param pY
* @param x
* @param y
* @param width
* @param height
* @return
*/
public static boolean insideRect(float pX, float pY, float x, float y, float width, float height) {
return pX >= x && pX < x + width && pY >= y && pY < y + height;
}
/**
* Converts to our Point2D utility class
*
* @param scenePoints
* @return
*/
public static float[] pointVectorToArray(List<Point2D> scenePoints) {
float[] ret = new float[scenePoints.size() * Scene.COORDS_PER_VERTEX];
int i = 0;
for (Point2D point : scenePoints) {
ret[i] = point.x();
ret[i + 1] = point.y();
ret[i + 2] = 0f;
i += 3;
}
return ret;
}
/**
* Is a->b->c a counterclockwise turn?
*
* @param a
* first point
* @param b
* second point
* @param c
* third point
* @return { -1, 0, +1 } if a->b->c is a { clockwise, collinear; counterclocwise } turn.
*/
public static int ccw(Point2D a, Point2D b, Point2D c) {
double area2 = (b.x() - a.x()) * (c.y() - a.y()) - (b.y() - a.y()) * (c.x() - a.x());
if (area2 < 0) {
return -1;
}
else if (area2 > 0) {
return +1;
}
else {
return 0;
}
}
/**
* Are two points on the same chain?
* TODO: Does it really work? :-D
*
* @param a
* @param b
* @param orderedPolygon
* @return
*/
public static boolean areOnTheSameChain(Point2D a, Point2D b, List<Point2D> orderedPolygon) {
Point2D pivot = orderedPolygon.get(orderedPolygon.size() / 2);
boolean returnValue = false;
if ((b.x() < pivot.x() && a.x() < pivot.x()) || (b.x() > pivot.x() && a.x() > pivot.x())) {
returnValue = true;
}
Log.d(GAlg.DEBUG_TAG, "Are on the same chain? Pa:" + a + ", Pb:" + b + ", Are they:" + returnValue);
return returnValue;
}
/**
* This is a brutal force crap used only for some testing.
* TODO: Remove or improve with space partitioning in future.
*
* @param a
* @param b
* @param polygon
* @return
*/
public static boolean isItLegalDiagonal(Point2D a, Point2D b, List<Point2D> polygon) {
boolean isItLegal = true;
for (int i = 0; i < polygon.size(); i++) {
if (i < polygon.size() - 1) {
if (linesIntersect(a, b, polygon.get(i), polygon.get(i + 1)) != null) {
isItLegal = false;
Log.d(GAlg.DEBUG_TAG, "LINES:(" + a + ";" + b + ") and (" + polygon.get(i) + ";" + polygon.get(i + 1) + ") INTERSECT #A");
break;
}
} else {
if (linesIntersect(a, b, polygon.get(i), polygon.get(0)) != null) {
isItLegal = false;
Log.d(GAlg.DEBUG_TAG, "LINES:(" + a + ";" + b + ") and (" + polygon.get(i) + ";" + polygon.get(0) + ") INTERSECT #B");
break;
}
}
}
return isItLegal;
}
/**
* A suboptimal version of lines intersection.
* TODO: Enhance with deBerg's sweep line stuff.
*
* @param a
* @param b
* @param c
* @param d
* @return
*/
private static Point2D linesIntersect(Point2D a, Point2D b, Point2D c, Point2D d) {
// intersection point
double intersectX = 0d;
double intersectY = 0d;
double destS1X, destS1Y, destS2X, destS2Y;
destS1X = b.x() - a.x();
destS1Y = b.y() - a.y();
destS2X = d.x() - c.x();
destS2Y = d.y() - c.y();
double s, t;
s = (-destS1Y * (a.x() - c.x()) + destS1X * (a.y() - c.y())) / (-destS2X * destS1Y + destS1X * destS2Y);
t = (destS2X * (a.y() - c.y()) - destS2Y * (a.x() - c.x())) / (-destS2X * destS1Y + destS1X * destS2Y);
if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
// Collision detected
intersectX = a.x() + (t * destS1X);
intersectY = a.y() + (t * destS1Y);
Log.d(GAlg.DEBUG_TAG, "COLLISION ON POINT:[" + intersectX + "," + intersectY + "]");
if (((int) intersectX == (int) a.x() && (int) intersectY == (int) a.y()) || ((int) intersectX == (int) b.x() && (int) intersectY == (int) b.y()) || ((int) intersectX == (int) c.x() && (int) intersectY == (int) c.y())
|| ((int) intersectX == (int) d.x() && (int) intersectY == (int) d.y())) {
Log.d(GAlg.DEBUG_TAG, "COLLISION IGNORED...");
return null;
}
return new Point2D((float) intersectX, (float) intersectY);
}
return null; // No collision
}
public static Point2D getMiddlePoint(List<Point2D> points) {
points.get(points.size() / 2);
Point2D point = points.get(points.size() / 2);
return point;
}
public static List<Point2D> getLeftPoints(List<Point2D> points) {
return new ArrayList<Point2D>(points.subList(0, points.size() / 2));
}
public static List<Point2D> getRightPoints(List<Point2D> points) {
return new ArrayList<Point2D>(points.subList(points.size() / 2 + 1, points.size()));
}
}