Skip to content

Instantly share code, notes, and snippets.

@wtrebella
Created September 9, 2013 19:36
Show Gist options
  • Save wtrebella/6500405 to your computer and use it in GitHub Desktop.
Save wtrebella/6500405 to your computer and use it in GitHub Desktop.
Circle/Polygon Intersection from Pivvot's Code
using UnityEngine;
using System.Collections;
// Line segment intersection based on this: http://www.pdas.com/lineint.html
// Intersect circle/polygon algorithm based on this: http://gamedev.stackexchange.com/questions/7735/how-to-find-if-circle-and-concave-polygon-intersect
public static class WTUtils {
public static bool IntersectLineSegments(Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3) {
Vector2 s1 = p1 - p0;
Vector2 s2 = p3 - p2;
float s, t, denom;
denom = -s2.x * s1.y + s1.x * s2.y;
if (denom == 0) {
// divide by zero
return false;
}
s = (-s1.y * (p0.x - p2.x) + s1.x * (p0.y - p2.y)) / denom;
t = ( s2.x * (p0.y - p2.y) - s2.y * (p0.x - p2.x)) / denom;
if (s >= 0 && s <= 1 && t >= 0 && t <= 1) return true;
return false;
}
public static bool IntersectCircles(Vector2 circlePosA, float circleRadiusA, Vector2 circlePosB, float circleRadiusB) {
float dist = (circlePosB - circlePosA).magnitude;
if (dist < circleRadiusA + circleRadiusB) return true;
else return false;
}
public static bool IntersectCirclePolygon(Vector2 circlePos, float circleRadius, Vector2[] polygonVertices) {
float xPolygonMin = float.MaxValue;
float xPolygonMax = float.MinValue;
float yPolygonMin = float.MaxValue;
float yPolygonMax = float.MinValue;
for (int i = 0; i < polygonVertices.Length; i++) {
if (IntersectCircleLineSegment(circlePos, circleRadius, polygonVertices[i], polygonVertices[(i+1)%polygonVertices.Length])) {
return true;
}
Vector2 v = polygonVertices[i];
xPolygonMin = Mathf.Min(xPolygonMin, v.x);
xPolygonMax = Mathf.Max(xPolygonMax, v.x);
yPolygonMin = Mathf.Min(yPolygonMin, v.y);
yPolygonMax = Mathf.Max(yPolygonMax, v.y);
}
float extra = 5;
xPolygonMin -= extra;
xPolygonMax += extra;
yPolygonMin -= extra;
yPolygonMax += extra;
Vector2 circRayRight_p0 = circlePos;
Vector2 circRayRight_p1 = new Vector2(circlePos.x + 10000, circlePos.y);
float numIntersections = 0;
for (int i = 0; i < polygonVertices.Length; i++) {
Vector2 poly_p0 = polygonVertices[i];
Vector2 poly_p1 = polygonVertices[(i+1)%polygonVertices.Length];
if (poly_p0.y == poly_p1.y) continue;
if (IntersectLineSegments(circRayRight_p0, circRayRight_p1, poly_p0, poly_p1)) numIntersections++;
}
if (numIntersections % 2 == 1) return true;
else return false;
}
public static bool IntersectCircleLineSegment(Vector2 circlePos, float circleRadius, Vector2 segPointA, Vector2 segPointB) {
Vector2 upperPoint;
if (segPointA.y > segPointB.y) upperPoint = segPointA;
else upperPoint = segPointB;
Vector2 segVector = segPointB - segPointA;
Vector2 aToCircVector = circlePos - segPointA;
float closestSegPointMagnitude = Vector2.Dot(aToCircVector, segVector.normalized);
Vector2 closestSegPoint = Vector2.zero;
if (closestSegPointMagnitude < 0) closestSegPoint = segPointA;
else if (closestSegPointMagnitude > segVector.magnitude) closestSegPoint = segPointB;
else closestSegPoint = segPointA + closestSegPointMagnitude * segVector.normalized;
Vector2 closestToCircVector = circlePos - closestSegPoint;
if (upperPoint.Equals(closestSegPoint)) {
if (closestToCircVector.magnitude < circleRadius) return true;
}
else {
if (closestToCircVector.magnitude <= circleRadius) return true;
}
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment