diff --git a/src/raylib.h b/src/raylib.h index d693f026b..84e5991bc 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1130,6 +1130,7 @@ RLAPI bool CheckCollisionPointRec(Vector2 point, Rectangle rec); RLAPI bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius); // Check if point is inside circle RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3); // Check if point is inside a triangle RLAPI bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, Vector2 endPos2, Vector2 *collisionPoint); // Check the collision between two lines defined by two points each, returns collision point by reference +RLAPI bool CheckCollisionPointPolygon(Vector2 polygon[], int vertexCount, Vector2 point); // Check if point is inside a polygon RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2); // Get collision rectangle for two rectangles collision //------------------------------------------------------------------------------------ diff --git a/src/shapes.c b/src/shapes.c index fc4bddc02..cc877e786 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -68,6 +68,9 @@ // Module specific Functions Declaration //---------------------------------------------------------------------------------- static float EaseCubicInOut(float t, float b, float c, float d); // Cubic easing +static bool OnSegment(Vector2 p, Vector2 q, Vector2 r); +static int Orientation(Vector2 p, Vector2 q, Vector2 r); +static bool DoIntersect(Vector2 p1, Vector2 q1, Vector2 p2, Vector2 q2); //---------------------------------------------------------------------------------- // Module Functions Definition @@ -1521,6 +1524,40 @@ bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, return true; } +// Another function from GeeksForGeeks +// Returns true if the point p lies inside the polygon[] with n vertices +bool CheckCollisionPointPolygon(Vector2 polygon[], int vertexCount, Vector2 point) +{ + // There must be at least 3 vertices in polygon[] + if (vertexCount < 3) return false; + + // Create a point for line segment from p to infinite + Vector2 extreme = {10000, point.y}; + + // Count intersections of the above line with sides of polygon + int count = 0, i = 0; + do + { + int next = (i+1)%vertexCount; + + // Check if the line segment from 'p' to 'extreme' intersects + // with the line segment from 'polygon[i]' to 'polygon[next]' + if (DoIntersect(polygon[i], polygon[next], point, extreme)) + { + // If the point 'p' is colinear with line segment 'i-next', + // then check if it lies on segment. If it lies, return true, + // otherwise false + if (Orientation(polygon[i], point, polygon[next]) == 0) return OnSegment(polygon[i], point, polygon[next]); + + count++; + } + i = next; + } while (i != 0); + + // Return true if count is odd, false otherwise + return count&1; // Same as (count%2 == 1) +} + // Get collision rectangle for two rectangles collision Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2) { @@ -1602,3 +1639,64 @@ static float EaseCubicInOut(float t, float b, float c, float d) return 0.5f*c*(t*t*t + 2.0f) + b; } + +// Point inside polygon checking code +// Credit to https://www.geeksforgeeks.org/how-to-check-if-a-given-point-lies-inside-a-polygon/ + +#define INF 10000 +// Given three colinear points p, q, r, the function checks if +// point q lies on line segment 'pr' +static bool OnSegment(Vector2 p, Vector2 q, Vector2 r) +{ + if (q.x <= fmaxf(p.x, r.x) && q.x >= fminf(p.x, r.x) && + q.y <= fmaxf(p.y, r.y) && q.y >= fminf(p.y, r.y)) + return true; + return false; +} + +// To find orientation of ordered triplet (p, q, r). +// The function returns following values +// 0 --> p, q and r are colinear +// 1 --> Clockwise +// 2 --> Counterclockwise +static int Orientation(Vector2 p, Vector2 q, Vector2 r) +{ + int val = (q.y - p.y) * (r.x - q.x) - + (q.x - p.x) * (r.y - q.y); + + if (val == 0) return 0; // colinear + return (val > 0)? 1: 2; // clock or counterclock wise +} + +// The function that returns true if line segment 'p1q1' +// and 'p2q2' intersect. +static bool DoIntersect(Vector2 p1, Vector2 q1, Vector2 p2, Vector2 q2) +{ + // Find the four orientations needed for general and + // special cases + int o1 = Orientation(p1, q1, p2); + int o2 = Orientation(p1, q1, q2); + int o3 = Orientation(p2, q2, p1); + int o4 = Orientation(p2, q2, q1); + + // General case + if (o1 != o2 && o3 != o4) + return true; + + // Special Cases + // p1, q1 and p2 are colinear and p2 lies on segment p1q1 + if (o1 == 0 && OnSegment(p1, p2, q1)) return true; + + // p1, q1 and p2 are colinear and q2 lies on segment p1q1 + if (o2 == 0 && OnSegment(p1, q2, q1)) return true; + + // p2, q2 and p1 are colinear and p1 lies on segment p2q2 + if (o3 == 0 && OnSegment(p2, p1, q2)) return true; + + // p2, q2 and q1 are colinear and q1 lies on segment p2q2 + if (o4 == 0 && OnSegment(p2, q1, q2)) return true; + + return false; // Doesn't fall in any of the above cases +} + +// End of GeeksForGeeks code