Last active
January 2, 2016 10:59
-
-
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…
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
@interface Cocosutil : NSObject | |
typedef struct { | |
float overlapSize; | |
BOOL intersects; | |
} ccIntersection; | |
+ (ccIntersection) intersectionOfCircleWithRadius:(float)radius | |
atPoint:(CGPoint)circlePt | |
andRectangle:(CGRect)rect | |
withRotation:(float)rotation; | |
@end |
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
@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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.