package fr.octo.astroids.server.utils; import fr.octo.astroids.server.domain.Triangle; import fr.octo.astroids.server.domain.Vector2; public class Geometry { /** * Determines if p is inside the triangle made of pA, pB and pC. * @return */ public static boolean isInsideTriangle(Vector2 p, Vector2 pA, Vector2 pB, Vector2 pC) { // Move origin of coordinates to point A Vector2 pointB = new Vector2(pB.x - pA.x, pB.y - pA.y); Vector2 pointC = new Vector2(pC.x - pA.x, pC.y - pA.y); Vector2 point = new Vector2(p.x - pA.x, p.y - pA.y); // Calculate scalar Double scalar = pointB.x * pointC.y - pointC.x * pointB.y; // Calculate the 3 Barycentric weights Double weightA = ( point.x * ( pointB.y - pointC.y ) + point.y * ( pointC.x - pointB.x ) + pointB.x * pointC.y - pointC.x * pointB.y ) / scalar; Double weightB = ( point.x * pointC.y - point.y * pointC.x ) / scalar; Double weightC = ( point.y * pointB.x - point.x * pointB.y ) / scalar; // Point is inside triangle if and only if the 3 weights are between 0 and 1 return isBetweenZeroAndOne(weightA) && isBetweenZeroAndOne(weightB) && isBetweenZeroAndOne(weightC); } public static boolean isInsideTriangle(Vector2 p, Triangle triangle) { return isInsideTriangle(p, triangle.pointA, triangle.pointB, triangle.pointC); } private static boolean isBetweenZeroAndOne(Double d) { return d <= 1 && d >= 0; } public static boolean areTrianglesColliding(Triangle triangle1, Triangle triangle2) { return isInsideTriangle(triangle1.pointA, triangle2) || isInsideTriangle(triangle1.pointB, triangle2) || isInsideTriangle(triangle1.pointC, triangle2); } public static Vector2 coordinatesAfterRotation(Vector2 coordinates, Double rotation) { return new Vector2( coordinates.x * Math.cos(rotation) - coordinates.y * Math.sin(rotation), coordinates.x * Math.sin(rotation) - coordinates.y * Math.cos(rotation)); } }