Created
March 14, 2020 02:21
-
-
Save sirisian/78196964265c385d81e1599391ebb249 to your computer and use it in GitHub Desktop.
IntersectionFunctions.hpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #include <vector> | |
| #include <cmath> | |
| #include "Vector2.hpp" | |
| namespace IntersectionFunctions | |
| { | |
| struct IntersectionObject | |
| { | |
| std::vector<Vector2> points; | |
| void InsertSolution(float x, float y) | |
| { | |
| points.push_back(Vector2(x, y)); | |
| } | |
| void InsertSolution(Vector2 v) | |
| { | |
| points.push_back(v); | |
| } | |
| int NumberOfSolutions() | |
| { | |
| return points.size(); | |
| } | |
| }; | |
| // Circle to Circle | |
| IntersectionObject CircleToCircleIntersection(Vector2 circlePosition1, float radius1, | |
| Vector2 circlePosition2, float radius2) | |
| { | |
| IntersectionObject result; | |
| float a, distSq, dist, h; | |
| Vector2 d, r, v2; | |
| // d is the vertical and horizontal distances between the circle centers | |
| d = circlePosition1 - circlePosition2; | |
| //distance squared between the circles | |
| distSq = d.LengthSq(); | |
| // Check for equality and infinite intersections exist | |
| if (distSq == 0 && radius1 == radius2) | |
| { | |
| return result; | |
| } | |
| //Check for solvability | |
| if (distSq > (radius1 + radius2) * (radius1 + radius2)) | |
| { | |
| // no solution. circles do not intersect | |
| return result; | |
| } | |
| if (distSq < abs(radius1 - radius2) * abs(radius1 - radius2)) | |
| { | |
| // no solution. one circle is contained in the other | |
| return result; | |
| } | |
| if (distSq == (radius1 + radius2) * (radius1 + radius2)) | |
| { | |
| //one solution | |
| result.InsertSolution((circlePosition1 - circlePosition2) / (radius1 + radius2) * radius1 + circlePosition1); | |
| return result; | |
| } | |
| dist = sqrt(distSq); | |
| // 'point 2' is the point where the line through the circle | |
| // intersection points crosses the line between the circle | |
| // centers. | |
| // Determine the distance from point 0 to point 2 | |
| a = ((radius1 * radius1) - (radius2 * radius2) + distSq) / (2.0f * dist); | |
| // Determine the coordinates of point 2 | |
| v2 = circlePosition1 + d * (a / dist); | |
| // Determine the distance from point 2 to either of the intersection points | |
| h = sqrt((radius1 * radius1) - (a * a)); | |
| // Now determine the offsets of the intersection points from point 2 | |
| r = d * (h / dist); | |
| r = r.Normal(); | |
| // Determine the absolute intersection points | |
| result.InsertSolution(v2 + r); | |
| result.InsertSolution(v2 - r); | |
| return result; | |
| } | |
| // Used only within this namespace | |
| int PrivateLineToCircleIntersection(Vector2 vertex1, Vector2 vertex2, | |
| Vector2 circlePosition, float radius, | |
| Vector2 & solution1, Vector2 & solution2) | |
| { | |
| // Vector from point 1 to point 2 | |
| Vector2 vertex1to2 = vertex2 - vertex1; | |
| // Vector from point 1 to the circle's center | |
| Vector2 circleToVertex1 = circlePosition - vertex1; | |
| float dot = vertex1to2.Dot(circleToVertex1); | |
| Vector2 proj1 = vertex1to2 * (dot / vertex1to2.LengthSq()); | |
| Vector2 midpt = vertex1 + proj1; | |
| Vector2 circleToMidpt = midpt - circlePosition; | |
| float distSqToCenter = circleToMidpt.LengthSq(); | |
| if (distSqToCenter > radius * radius) return 0; | |
| if (distSqToCenter == radius * radius) | |
| { | |
| solution1 = midpt; | |
| return 1; | |
| } | |
| float distToIntersection; | |
| if (distSqToCenter == 0) | |
| { | |
| distToIntersection = radius; | |
| } | |
| else | |
| { | |
| distToIntersection = sqrt(radius * radius - distSqToCenter); | |
| } | |
| vertex1to2 = vertex1to2.Normalize(); | |
| vertex1to2 *= distToIntersection; | |
| solution1 = midpt + vertex1to2; | |
| solution2 = midpt - vertex1to2; | |
| return 2; | |
| } | |
| //Line to Circle | |
| IntersectionObject LineToCircleIntersection(Vector2 vertex1, Vector2 vertex2, | |
| Vector2 circlePosition, float radius) | |
| { | |
| IntersectionObject result; | |
| Vector2 solution1, solution2; | |
| switch(PrivateLineToCircleIntersection(vertex1, vertex2, circlePosition, radius, solution1, solution2)) | |
| { | |
| case 2: | |
| result.InsertSolution(solution2); | |
| case 1: | |
| result.InsertSolution(solution1); | |
| break; | |
| } | |
| return result; | |
| } | |
| // Circle to Line | |
| IntersectionObject CircleToLineIntersection(Vector2 circlePosition, float radius, | |
| Vector2 vertex1, Vector2 vertex2) | |
| { | |
| return LineToCircleIntersection(vertex1, vertex2, circlePosition, radius); | |
| } | |
| // LineSegment to Circle | |
| IntersectionObject LineSegmentToCircleIntersection(Vector2 vertex1, Vector2 vertex2, | |
| Vector2 circlePosition, float radius) | |
| { | |
| IntersectionObject result; | |
| Vector2 solution1, solution2; | |
| Vector2 vertex1to2 = vertex2 - vertex1; | |
| Vector2 vertex1ToSolution1, vertex2ToSolution1, vertex1ToSolution2, vertex2ToSolution2; | |
| switch(PrivateLineToCircleIntersection(vertex1, vertex2, circlePosition, radius, solution1, solution2)) | |
| { | |
| case 2: | |
| vertex1ToSolution2 = solution2 - vertex1; | |
| vertex2ToSolution2 = solution2 - vertex2; | |
| if (vertex1ToSolution2.Dot(vertex1to2) > 0 && | |
| vertex2ToSolution2.Dot(vertex1to2) < 0) | |
| { | |
| result.InsertSolution(solution2); | |
| } | |
| case 1: | |
| vertex1ToSolution1 = solution1 - vertex1; | |
| vertex2ToSolution1 = solution1 - vertex2; | |
| if (vertex1ToSolution1.Dot(vertex1to2) > 0 && | |
| vertex2ToSolution1.Dot(vertex1to2) < 0) | |
| { | |
| result.InsertSolution(solution1); | |
| } | |
| break; | |
| } | |
| return result; | |
| } | |
| // Circle to LineSegment | |
| IntersectionObject CircleToLineSegmentIntersection(Vector2 circlePosition, float radius, | |
| Vector2 vertex1, Vector2 vertex2) | |
| { | |
| return LineSegmentToCircleIntersection(vertex1, vertex2, circlePosition, radius); | |
| } | |
| // Ray to Circle | |
| IntersectionObject RayToCircleIntersection(Vector2 vertex1, Vector2 vertex2, | |
| Vector2 circlePosition, float radius) | |
| { | |
| IntersectionObject result; | |
| Vector2 solution1, solution2; | |
| Vector2 vertex1to2 = vertex2 - vertex1; | |
| Vector2 vertex1ToSolution1, vertex1ToSolution2; | |
| switch(PrivateLineToCircleIntersection(vertex1, vertex2, circlePosition, radius, solution1, solution2)) | |
| { | |
| case 2: | |
| vertex1ToSolution2 = solution2 - vertex1; | |
| if (vertex1ToSolution2.Dot(vertex1to2) > 0) | |
| { | |
| result.InsertSolution(solution2); | |
| } | |
| case 1: | |
| vertex1ToSolution1 = solution1 - vertex1; | |
| if (vertex1ToSolution1.Dot(vertex1to2) > 0) | |
| { | |
| result.InsertSolution(solution1); | |
| } | |
| break; | |
| } | |
| return result; | |
| } | |
| // Circle to Ray | |
| IntersectionObject CircleToRayIntersection(Vector2 circlePosition, float radius, | |
| Vector2 vertex1, Vector2 vertex2) | |
| { | |
| return RayToCircleIntersection(vertex1, vertex2, circlePosition, radius); | |
| } | |
| // Used only within this namespace | |
| bool PrivateLineToLineIntersection(Vector2 vertex1, Vector2 vertex2, | |
| Vector2 vertex3, Vector2 vertex4, float & r, float & s) | |
| { | |
| float d; | |
| //Make sure the lines aren't parallel | |
| Vector2 vertex1to2 = vertex2 - vertex1; | |
| Vector2 vertex3to4 = vertex4 - vertex3; | |
| //if (vertex1to2.x * -vertex3to4.y + vertex1to2.y * vertex3to4.x != 0) | |
| //{ | |
| if(vertex1to2.y / vertex1to2.x != vertex3to4.y / vertex3to4.x) | |
| { | |
| d = vertex1to2.x * vertex3to4.y - vertex1to2.y * vertex3to4.x; | |
| if (d != 0) | |
| { | |
| Vector2 vertex3to1 = vertex1 - vertex3; | |
| r = (vertex3to1.y * vertex3to4.x - vertex3to1.x * vertex3to4.y) / d; | |
| s = (vertex3to1.y * vertex1to2.x - vertex3to1.x * vertex1to2.y) / d; | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| // Line to Line | |
| IntersectionObject LineToLineIntersection(Vector2 vertex1, Vector2 vertex2, | |
| Vector2 vertex3, Vector2 vertex4) | |
| { | |
| IntersectionObject result; | |
| float r, s; | |
| if(PrivateLineToLineIntersection(vertex1, vertex2, vertex3, vertex4, r, s)) | |
| { | |
| result.InsertSolution(vertex1 + (vertex2 - vertex1) * r); | |
| } | |
| return result; | |
| } | |
| // LineSegment to LineSegment | |
| IntersectionObject LineSegmentToLineSegmentIntersection(Vector2 vertex1, Vector2 vertex2, | |
| Vector2 vertex3, Vector2 vertex4) | |
| { | |
| IntersectionObject result; | |
| float r, s; | |
| if(PrivateLineToLineIntersection(vertex1, vertex2, vertex3, vertex4, r, s)) | |
| { | |
| if (r >= 0 && r <= 1) | |
| { | |
| if (s >= 0 && s <= 1) | |
| { | |
| result.InsertSolution(vertex1 + (vertex2 - vertex1) * r); | |
| } | |
| } | |
| } | |
| return result; | |
| } | |
| // LineSegment to Line | |
| IntersectionObject LineSegmentToLineIntersection(Vector2 vertex1, Vector2 vertex2, | |
| Vector2 vertex3, Vector2 vertex4) | |
| { | |
| IntersectionObject result; | |
| float r, s; | |
| if(PrivateLineToLineIntersection(vertex1, vertex2, vertex3, vertex4, r, s)) | |
| { | |
| if (r >= 0 && r <= 1) | |
| { | |
| result.InsertSolution(vertex1 + (vertex2 - vertex1) * r); | |
| } | |
| } | |
| return result; | |
| } | |
| // Line to LineSement | |
| IntersectionObject LineToLineSegmentIntersection(Vector2 vertex1, Vector2 vertex2, | |
| Vector2 vertex3, Vector2 vertex4) | |
| { | |
| return LineSegmentToLineIntersection(vertex3, vertex4, vertex1, vertex2); | |
| } | |
| // Ray to LineSegment | |
| IntersectionObject RayToLineSegmentIntersection(Vector2 vertex1, Vector2 vertex2, | |
| Vector2 vertex3, Vector2 vertex4) | |
| { | |
| IntersectionObject result; | |
| float r, s; | |
| if(PrivateLineToLineIntersection(vertex1, vertex2, vertex3, vertex4, r, s)) | |
| { | |
| if (r >= 0) | |
| { | |
| if (s >= 0 && s <= 1) | |
| { | |
| result.InsertSolution(vertex1 + (vertex2 - vertex1) * r); | |
| } | |
| } | |
| } | |
| return result; | |
| } | |
| // LineSegment to Ray | |
| IntersectionObject LineSegmentToRayIntersection(Vector2 vertex1, Vector2 vertex2, | |
| Vector2 vertex3, Vector2 vertex4) | |
| { | |
| return RayToLineSegmentIntersection(vertex3, vertex4, vertex1, vertex2); | |
| } | |
| // Ray to Line | |
| IntersectionObject RayToLineIntersection(Vector2 vertex1, Vector2 vertex2, | |
| Vector2 vertex3, Vector2 vertex4) | |
| { | |
| IntersectionObject result; | |
| float r, s; | |
| if(PrivateLineToLineIntersection(vertex1, vertex2, vertex3, vertex4, r, s)) | |
| { | |
| if (r >= 0) | |
| { | |
| result.InsertSolution(vertex1 + (vertex2 - vertex1) * r); | |
| } | |
| } | |
| return result; | |
| } | |
| // Line to Ray | |
| IntersectionObject LineToRayIntersection(Vector2 vertex1, Vector2 vertex2, | |
| Vector2 vertex3, Vector2 vertex4) | |
| { | |
| return RayToLineIntersection(vertex3, vertex4, vertex1, vertex2); | |
| } | |
| // Ray to Ray | |
| IntersectionObject RayToRayIntersection(Vector2 vertex1, Vector2 vertex2, | |
| Vector2 vertex3, Vector2 vertex4) | |
| { | |
| IntersectionObject result; | |
| float r, s; | |
| if(PrivateLineToLineIntersection(vertex1, vertex2, vertex3, vertex4, r, s)) | |
| { | |
| if (r >= 0) | |
| { | |
| if (s >= 0) | |
| { | |
| result.InsertSolution(vertex1 + (vertex2 - vertex1) * r); | |
| } | |
| } | |
| } | |
| return result; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment