Skip to content

Instantly share code, notes, and snippets.

@pkclsoft
Last active January 2, 2016 10:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pkclsoft/8293496 to your computer and use it in GitHub Desktop.
Save pkclsoft/8293496 to your computer and use it in GitHub Desktop.
Circle and Rotated Rectangle Collision Detection in Objective-C This code was ported from some code at: http://www.migapro.com/circle-and-rotated-rectangle-collision-detection/ I've changed the code to assume that it is the centre of the rectangle, not the top-left corner of the rectangle that is passed in. This makes it simpler to use from Coco…
@interface Cocosutil : NSObject
typedef struct {
float overlapSize;
BOOL intersects;
} ccIntersection;
+ (ccIntersection) intersectionOfCircleWithRadius:(float)radius
atPoint:(CGPoint)circlePt
andRectangle:(CGRect)rect
withRotation:(float)rotation;
@end
@implementation CocosUtil
#define CC_DEGREES_TO_RADIANS(__ANGLE__) ((__ANGLE__) * 0.01745329252f) // PI / 180
// Original code is from:
//
// http://www.migapro.com/circle-and-rotated-rectangle-collision-detection/
//
+ (ccIntersection) intersectionOfCircleWithRadius:(float)radius atPoint:(CGPoint)circlePt andRectangle:(CGRect)rect withRotation:(float)rotation {
ccIntersection result;
// Rotate circle's center point back
float unrotatedCircleX =
cosf(CC_DEGREES_TO_RADIANS(rotation)) * (circlePt.x - rect.origin.x) -
sinf(CC_DEGREES_TO_RADIANS(rotation)) * (circlePt.y - rect.origin.y) + rect.origin.x;
float unrotatedCircleY =
sinf(CC_DEGREES_TO_RADIANS(rotation)) * (circlePt.x - rect.origin.x) +
cosf(CC_DEGREES_TO_RADIANS(rotation)) * (circlePt.y - rect.origin.y) + rect.origin.y;
// Closest point in the rectangle to the center of circle rotated backwards(unrotated)
float closestX, closestY;
// Find the unrotated closest x point from center of unrotated circle
if (unrotatedCircleX < (rect.origin.x - (rect.size.width/2.0f))) {
closestX = rect.origin.x - (rect.size.width/2.0f);
} else if (unrotatedCircleX > rect.origin.x + (rect.size.width+rect.size.width/2.0f)) {
closestX = rect.origin.x + (rect.size.width/2.0f);
} else {
closestX = unrotatedCircleX ;
}
// Find the unrotated closest y point from center of unrotated circle
if (unrotatedCircleY < (rect.origin.y - (rect.size.height/2.0f))) {
closestY = rect.origin.y - (rect.size.height/2.0f);
} else if (unrotatedCircleY > (rect.origin.y + (rect.size.height/2.0f))) {
closestY = rect.origin.y + (rect.size.height/2.0f);
} else {
closestY = unrotatedCircleY;
}
// Determine collision
float distance = [CocosUtil distanceFrom:CGPointMake(unrotatedCircleX , unrotatedCircleY) to:CGPointMake(closestX, closestY)];
if (distance < radius) {
result.intersects = YES; // Collision
result.overlapSize = radius - distance;
} else {
result.intersects = NO;
result.overlapSize = 0.0f;
}
return result;
}
+ (float) distanceFrom:(CGPoint)from to:(CGPoint)to {
float a = abs(from.x - to.x);
float b = abs(from.y - to.y);
return sqrt((a * a) + (b * b));
}
@end
@gyfis
Copy link

gyfis commented Mar 12, 2014

If the rectangle is already rotated with the angle, I think that the calculations should take that in account and use "-rotation", because leaving it to the user to input the negative angle in the method could be a bit misleading. Thanks a lot though, it's perfect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment