圆形 – 矩形碰撞检测(交叉)
如何判断一个圆和一个矩形在二维欧氏空间中是否相交? (即经典的2D几何)
当圆与矩形相交时只有两种情况:
- 圆的中心位于矩形内,或者
- 矩形的一个边在圆上有一个点。
请注意,这不需要矩形是轴平行的。
(一种方法是:如果没有一个边在圆上有一个点(如果所有的边都完全在圆的“外部”),那么这个圆仍然可以与多边形相交的唯一方法是,如果它完全位于多边形。)
有了这样的见解,类似下面的东西就可以工作,圆的中心P
和半径R
,矩形的顶点A
, B
, C
, D
按顺序排列(不是完整的代码):
def intersect(Circle(P, R), Rectangle(A, B, C, D)): S = Circle(P, R) return (pointInRectangle(P, Rectangle(A, B, C, D)) or intersectCircle(S, (A, B)) or intersectCircle(S, (B, C)) or intersectCircle(S, (C, D)) or intersectCircle(S, (D, A)))
如果您正在编写任何几何graphics,您的图书馆中可能已经具有上述function。 否则, pointInRectangle()
可以用几种方法实现; 多边形方法中的任何一般点都可以工作,但是对于一个矩形,您可以检查它是否工作:
0 ≤ AP·AB ≤ AB·AB and 0 ≤ AP·AD ≤ AD·AD
intersectCircle()
也很容易实现:一种方法是检查从P
到行的垂线的足够靠近并在端点之间,否则检查端点。
很酷的事情是, 相同的想法不仅适用于矩形,而且适用于与任何简单多边形相交的圆 – 甚至不必是凸的!
这是我将如何做到这一点:
bool intersects(CircleType circle, RectType rect) { circleDistance.x = abs(circle.x - rect.x); circleDistance.y = abs(circle.y - rect.y); if (circleDistance.x > (rect.width/2 + circle.r)) { return false; } if (circleDistance.y > (rect.height/2 + circle.r)) { return false; } if (circleDistance.x <= (rect.width/2)) { return true; } if (circleDistance.y <= (rect.height/2)) { return true; } cornerDistance_sq = (circleDistance.x - rect.width/2)^2 + (circleDistance.y - rect.height/2)^2; return (cornerDistance_sq <= (circle.r^2)); }
这是如何工作的:
-
第一对线计算圆的中心和矩形的中心之间的x和y差的绝对值。 这将四个象限分解为一个,所以计算不必四次。 图像显示了圆圈中心现在所在的区域。 请注意,只显示单个象限。 矩形是灰色区域,红色边框勾画出与矩形边缘正好相距一个半径的临界区域。 圆的中心必须在这个红色的边界内才能出现交叉点。
-
第二对线消除了圆形远离矩形(在任一方向)远离不可能交叉的简单情况。 这对应于图像中的绿色区域。
-
第三对线处理简单的情况,其中圆形足够接近矩形(在任一方向)确保交叉点。 这对应于图像中的橙色和灰色部分。 请注意,此步骤必须在步骤2后进行,以使逻辑合理。
-
其余的线计算圆形可能与矩形的拐angular相交的困难情况。 为了求解,计算从圆心和拐angular的距离,然后validation距离不大于圆的半径。 对于中心位于红色阴影区域内的所有圆圈,此计算结果为false,对于中心位于白色阴影区域内的所有圆圈,返回true。
这是另一个很容易实现的解决scheme(而且也很快)。 它将捕获所有交点,包括球完全进入矩形时。
// clamp(value, min, max) - limits value to the range min..max // Find the closest point to the circle within the rectangle float closestX = clamp(circle.X, rectangle.Left, rectangle.Right); float closestY = clamp(circle.Y, rectangle.Top, rectangle.Bottom); // Calculate the distance between the circle's center and this closest point float distanceX = circle.X - closestX; float distanceY = circle.Y - closestY; // If the distance is less than the circle's radius, an intersection occurs float distanceSquared = (distanceX * distanceX) + (distanceY * distanceY); return distanceSquared < (circle.Radius * circle.Radius);
有了任何体面的math图书馆,可以缩短到3或4行。
你的领域和直接相交IIF
圆心和你的矩形的一个顶点之间的距离小于你的球体的半径
要么
圆心和你的矩形的一个边缘之间的距离小于你的球体的半径([ 点线距离 ])
要么
圆心在里面
点到点距离:
P1 = [x1,y1] P2 = [x2,y2] 距离= sqrt(abs(x1-x2)+ abs(y1-y2))
点线距离:
L1 = [x1,y1],L2 = [x2,y2](你的线的两个点,即顶点) P1 = [px,py]某点 距离d = abs((x2-x1)(y1-py) - (x1-px)(y2-y1))/距离(L1,L2)
圆形中心矩形:
采取一个分离的轴线:如果在点上有一个将矩形分开的线上的投影,它们不会相交
你可以将点与线的两侧平行,然后可以很容易地确定它们是否相交。 如果它们不相交所有4个投影,它们(点和矩形)不能相交。
你只需要内积(x = [x1,x2],y = [y1,y2],x * y = x1 * y1 + x2 * y2)
你的testing看起来像这样:
//矩形边:TL(左上),TR(右上),BL(左下),BR(右下) //指向testing:POI 分开= false 对于{{TL,TR},{BL,BR},{TL,BL},{TR-BR}}中的egde://边 D =边缘[0] - 边缘[1] innerProd = D * POI Interval_min = min(D * edge [0],D * edge [1]) Interval_max = max(D * edge [0],D * edge [1]) 如果不是(Interval_min≤innerProd≤Interval_max) seperated = true rest//结束循环 万一 结束 如果(分开是真的) 返回“不交集” 其他 返回“十字路口” 万一
这不假定轴alignment的矩形,并且可以容易地扩展以testing凸集之间的交集。
这是最快的解决scheme:
public static boolean intersect(Rectangle r, Circle c) { float cx = Math.abs(cx - rx - r.halfWidth); float xDist = r.halfWidth + c.radius; if (cx > xDist) return false; float cy = Math.abs(cy - ry - r.halfHeight); float yDist = r.halfHeight + c.radius; if (cy > yDist) return false; if (cx <= r.halfWidth || cy <= r.halfHeight) return true; float xCornerDist = cx - r.halfWidth; float yCornerDist = cy - r.halfHeight; float xCornerDistSq = xCornerDist * xCornerDist; float yCornerDistSq = yCornerDist * yCornerDist; float maxCornerDistSq = c.radius * c.radius; return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; }
注意执行的顺序,宽度/高度的一半是预先计算的。 平方也是“手动”完成的,以节省一些时钟周期。
想象,拿你的键盘的数字键盘。 如果键“5”代表你的矩形,那么所有的键1-9代表空间的9象限除以组成你的矩形的线(其中5是内部)。
1)如果圆的中心在象限5(即在矩形内),那么这两个形状相交。
这样做有两种可能的情况:a)圆与矩形的两个或更多相邻边相交。 b)圆与矩形的一条边相交。
第一种情况很简单。 如果圆与矩形的两个相邻边相交,则它必须包含连接这两个边的angular。 (也就是说,它的中心位于我们已经覆盖的象限5中,还要注意圆圈仅与矩形的两个相对边相交的情况也被覆盖)。
2)如果矩形的任一angular落A,B,C,D位于圆内,则两个形状相交。
第二种情况更棘手。 我们应该注意到,只有当圆的中心位于象限2,4,6或8中的一个时才会发生。(事实上,如果中心位于象限1,3,7,8中的任何一个上,相应的angular落将是最接近的点)
现在我们有这样的情况:圆的中心位于“边”象限之一,并且只与相应的边交叉。 然后,边缘上最靠近圆心的点必须位于圆内。
3)对于每条线AB,BC,CD,DA,通过圆的中心Pbuild立垂直线p(AB,P),p(BC,P),p(CD,P),p(DA,P)每个垂直线,如果与原始边缘的交点位于圆内,则两个形状相交。
这是最后一步的捷径。 如果圆的中心在象限8中,边AB是顶边,则交点将具有A和B的y坐标以及中心P的x坐标。
您可以构build四条线的交点,并检查它们是否位于其相应的边缘,或找出哪个象限P在,并检查相应的交点。 两者都应简化为相同的布尔方程。 要小心,上面的步骤2并不排除P在“angular落”象限之一; 它只是找一个十字路口。
编辑:事实certificate,我忽略了一个简单的事实,即#2是上面#3的子表。 毕竟,angular落也是边缘点。 请参阅下面的@ ShreevatsaR的答案,以获得很好的解释。 与此同时,忘记#2,除非你想快速但多余的检查。
这是我的C代码来解决一个球体和一个非轴alignment框之间的碰撞。 它依赖于我自己的一些库函数,但对某些函数可能有用。 我在游戏中使用它,它完美的作品。
float physicsProcessCollisionBetweenSelfAndActorRect(SPhysics *self, SPhysics *actor) { float diff = 99999; SVector relative_position_of_circle = getDifference2DBetweenVectors(&self->worldPosition, &actor->worldPosition); rotateVector2DBy(&relative_position_of_circle, -actor->axis.angleZ); // This aligns the coord system so the rect becomes an AABB float x_clamped_within_rectangle = relative_position_of_circle.x; float y_clamped_within_rectangle = relative_position_of_circle.y; LIMIT(x_clamped_within_rectangle, actor->physicsRect.l, actor->physicsRect.r); LIMIT(y_clamped_within_rectangle, actor->physicsRect.b, actor->physicsRect.t); // Calculate the distance between the circle's center and this closest point float distance_to_nearest_edge_x = relative_position_of_circle.x - x_clamped_within_rectangle; float distance_to_nearest_edge_y = relative_position_of_circle.y - y_clamped_within_rectangle; // If the distance is less than the circle's radius, an intersection occurs float distance_sq_x = SQUARE(distance_to_nearest_edge_x); float distance_sq_y = SQUARE(distance_to_nearest_edge_y); float radius_sq = SQUARE(self->physicsRadius); if(distance_sq_x + distance_sq_y < radius_sq) { float half_rect_w = (actor->physicsRect.r - actor->physicsRect.l) * 0.5f; float half_rect_h = (actor->physicsRect.t - actor->physicsRect.b) * 0.5f; CREATE_VECTOR(push_vector); // If we're at one of the corners of this object, treat this as a circular/circular collision if(fabs(relative_position_of_circle.x) > half_rect_w && fabs(relative_position_of_circle.y) > half_rect_h) { SVector edges; if(relative_position_of_circle.x > 0) edges.x = half_rect_w; else edges.x = -half_rect_w; if(relative_position_of_circle.y > 0) edges.y = half_rect_h; else edges.y = -half_rect_h; push_vector = relative_position_of_circle; moveVectorByInverseVector2D(&push_vector, &edges); // We now have the vector from the corner of the rect to the point. float delta_length = getVector2DMagnitude(&push_vector); float diff = self->physicsRadius - delta_length; // Find out how far away we are from our ideal distance // Normalise the vector push_vector.x /= delta_length; push_vector.y /= delta_length; scaleVector2DBy(&push_vector, diff); // Now multiply it by the difference push_vector.z = 0; } else // Nope - just bouncing against one of the edges { if(relative_position_of_circle.x > 0) // Ball is to the right push_vector.x = (half_rect_w + self->physicsRadius) - relative_position_of_circle.x; else push_vector.x = -((half_rect_w + self->physicsRadius) + relative_position_of_circle.x); if(relative_position_of_circle.y > 0) // Ball is above push_vector.y = (half_rect_h + self->physicsRadius) - relative_position_of_circle.y; else push_vector.y = -((half_rect_h + self->physicsRadius) + relative_position_of_circle.y); if(fabs(push_vector.x) < fabs(push_vector.y)) push_vector.y = 0; else push_vector.x = 0; } diff = 0; // Cheat, since we don't do anything with the value anyway rotateVector2DBy(&push_vector, actor->axis.angleZ); SVector *from = &self->worldPosition; moveVectorBy2D(from, push_vector.x, push_vector.y); } return diff; }
这是模拟的代码100%的工作:
public static bool IsIntersected(PointF circle, float radius, RectangleF rectangle) { var rectangleCenter = new PointF((rectangle.X + rectangle.Width / 2), (rectangle.Y + rectangle.Height / 2)); var w = rectangle.Width / 2; var h = rectangle.Height / 2; var dx = Math.Abs(circle.X - rectangleCenter.X); var dy = Math.Abs(circle.Y - rectangleCenter.Y); if (dx > (radius + w) || dy > (radius + h)) return false; var circleDistance = new PointF { X = Math.Abs(circle.X - rectangle.X - w), Y = Math.Abs(circle.Y - rectangle.Y - h) }; if (circleDistance.X <= (w)) { return true; } if (circleDistance.Y <= (h)) { return true; } var cornerDistanceSq = Math.Pow(circleDistance.X - w, 2) + Math.Pow(circleDistance.Y - h, 2); return (cornerDistanceSq <= (Math.Pow(radius, 2))); }
Bassam Alugili
事实上,这更简单。 你只需要两件事情。
首先,你需要find从圆心到矩形每一行的四个正交距离。 那么如果它们中的任何三个都大于圆的半径,那么你的圆将不会与矩形相交。
其次,需要find圆心与矩形中心的距离,如果距离大于矩形对angular线长度的一半,则圆不在矩形内。
祝你好运!
我提出的最简单的解决scheme非常简单。
它通过find最接近圆的矩形中的点,然后比较距离来工作。
你可以用一些操作来完成所有这些,甚至可以避免使用sqrt函数。
public boolean intersects(float cx, float cy, float radius, float left, float top, float right, float bottom) { float closestX = (cx < left ? left : (cx > right ? right : cx)); float closestY = (cy < top ? top : (cy > bottom ? bottom : cy)); float dx = closestX - cx; float dy = closestY - cy; return ( dx * dx + dy * dy ) <= radius * radius; }
而就是这样! 上面的解决scheme假定世界左上angular的原点是x轴向下。
如果你想要一个解决scheme来处理一个移动的圆和矩形之间的碰撞,那就更加复杂了,并且在我的另一个答案中被覆盖了。
此function检测圆形和矩形之间的碰撞(相交)。 在他的回答中,他的工作方式类似于e.James方法,但是这个方法检测所有矩形angular度的碰撞(不仅在右上angular)。
注意:
aRect.origin.x和aRect.origin.y是矩形左下angular的坐标!
aCircle.x和aCircle.y是Circle Center的坐标!
static inline BOOL RectIntersectsCircle(CGRect aRect, Circle aCircle) { float testX = aCircle.x; float testY = aCircle.y; if (testX < aRect.origin.x) testX = aRect.origin.x; if (testX > (aRect.origin.x + aRect.size.width)) testX = (aRect.origin.x + aRect.size.width); if (testY < aRect.origin.y) testY = aRect.origin.y; if (testY > (aRect.origin.y + aRect.size.height)) testY = (aRect.origin.y + aRect.size.height); return ((aCircle.x - testX) * (aCircle.x - testX) + (aCircle.y - testY) * (aCircle.y - testY)) < aCircle.radius * aCircle.radius; }
我创造了希望你喜欢的形状的工作
public class Geomethry { public static boolean intersectionCircleAndRectangle(int circleX, int circleY, int circleR, int rectangleX, int rectangleY, int rectangleWidth, int rectangleHeight){ boolean result = false; float rectHalfWidth = rectangleWidth/2.0f; float rectHalfHeight = rectangleHeight/2.0f; float rectCenterX = rectangleX + rectHalfWidth; float rectCenterY = rectangleY + rectHalfHeight; float deltax = Math.abs(rectCenterX - circleX); float deltay = Math.abs(rectCenterY - circleY); float lengthHypotenuseSqure = deltax*deltax + deltay*deltay; do{ // check that distance between the centerse is more than the distance between the circumcircle of rectangle and circle if(lengthHypotenuseSqure > ((rectHalfWidth+circleR)*(rectHalfWidth+circleR) + (rectHalfHeight+circleR)*(rectHalfHeight+circleR))){ //System.out.println("distance between the centerse is more than the distance between the circumcircle of rectangle and circle"); break; } // check that distance between the centerse is less than the distance between the inscribed circle float rectMinHalfSide = Math.min(rectHalfWidth, rectHalfHeight); if(lengthHypotenuseSqure < ((rectMinHalfSide+circleR)*(rectMinHalfSide+circleR))){ //System.out.println("distance between the centerse is less than the distance between the inscribed circle"); result=true; break; } // check that the squares relate to angles if((deltax > (rectHalfWidth+circleR)*0.9) && (deltay > (rectHalfHeight+circleR)*0.9)){ //System.out.println("squares relate to angles"); result=true; } }while(false); return result; } public static boolean intersectionRectangleAndRectangle(int rectangleX, int rectangleY, int rectangleWidth, int rectangleHeight, int rectangleX2, int rectangleY2, int rectangleWidth2, int rectangleHeight2){ boolean result = false; float rectHalfWidth = rectangleWidth/2.0f; float rectHalfHeight = rectangleHeight/2.0f; float rectHalfWidth2 = rectangleWidth2/2.0f; float rectHalfHeight2 = rectangleHeight2/2.0f; float deltax = Math.abs((rectangleX + rectHalfWidth) - (rectangleX2 + rectHalfWidth2)); float deltay = Math.abs((rectangleY + rectHalfHeight) - (rectangleY2 + rectHalfHeight2)); float lengthHypotenuseSqure = deltax*deltax + deltay*deltay; do{ // check that distance between the centerse is more than the distance between the circumcircle if(lengthHypotenuseSqure > ((rectHalfWidth+rectHalfWidth2)*(rectHalfWidth+rectHalfWidth2) + (rectHalfHeight+rectHalfHeight2)*(rectHalfHeight+rectHalfHeight2))){ //System.out.println("distance between the centerse is more than the distance between the circumcircle"); break; } // check that distance between the centerse is less than the distance between the inscribed circle float rectMinHalfSide = Math.min(rectHalfWidth, rectHalfHeight); float rectMinHalfSide2 = Math.min(rectHalfWidth2, rectHalfHeight2); if(lengthHypotenuseSqure < ((rectMinHalfSide+rectMinHalfSide2)*(rectMinHalfSide+rectMinHalfSide2))){ //System.out.println("distance between the centerse is less than the distance between the inscribed circle"); result=true; break; } // check that the squares relate to angles if((deltax > (rectHalfWidth+rectHalfWidth2)*0.9) && (deltay > (rectHalfHeight+rectHalfHeight2)*0.9)){ //System.out.println("squares relate to angles"); result=true; } }while(false); return result; } }
这是一个快速的单行testing:
if (length(max(abs(center - rect_mid) - rect_halves, 0)) <= radius ) { // They intersect. }
这是轴alignment的情况,其中rect_halves
是从矩形中间指向angular的正向量。 length()
的expression式是从center
到矩形中最近点的delta向量。 这在任何维度上都有效。
- 首先检查矩形和圆的正切相切是否重叠(简单)。 如果它们不重叠,则不会相互碰撞。
- 检查圆的中心是否在矩形内(简单)。 如果它在里面,它们会相撞。
- 计算从矩形边到圆心的最小平方距离(很难)。 如果它的平方半径较低,那么它们相撞,否则它们不会。
这是有效的,因为:
- 首先它用廉价的algorithm检查最常见的情况,当它确定它们不会相互碰撞时,就结束了。
- 然后使用便宜的algorithm(不计算平方根,使用平方值)检查下一个最常见的情况,并确定它们碰撞时结束。
- 然后执行更昂贵的algorithm来检查与矩形边界的碰撞。
我有一种方法,避免昂贵的毕达哥拉斯如果没有必要 – 即。 当矩形的边界框与圆不相交时。
它也适用于非欧洲人:
class Circle { // create the bounding box of the circle only once BBox bbox; public boolean intersect(BBox b) { // test top intersect if (lat > b.maxLat) { if (lon < b.minLon) return normDist(b.maxLat, b.minLon) <= normedDist; if (lon > b.maxLon) return normDist(b.maxLat, b.maxLon) <= normedDist; return b.maxLat - bbox.minLat > 0; } // test bottom intersect if (lat < b.minLat) { if (lon < b.minLon) return normDist(b.minLat, b.minLon) <= normedDist; if (lon > b.maxLon) return normDist(b.minLat, b.maxLon) <= normedDist; return bbox.maxLat - b.minLat > 0; } // test middle intersect if (lon < b.minLon) return bbox.maxLon - b.minLon > 0; if (lon > b.maxLon) return b.maxLon - bbox.minLon > 0; return true; } }
- minLat,maxLat可以用minY,maxY代替,minLon,maxLon也一样:用minX,maxX代替
- normDist只是一个快一点的方法,然后全程计算。 例如没有欧几里德空间的平方根(或没有很多其他的东西),
dLat=(lat-circleY); dLon=(lon-circleX); normed=dLat*dLat+dLon*dLon
dLat=(lat-circleY); dLon=(lon-circleX); normed=dLat*dLat+dLon*dLon
dLat=(lat-circleY); dLon=(lon-circleX); normed=dLat*dLat+dLon*dLon
。 当然,如果你使用normDist方法,你需要创build一个normedDist = dist*dist;
为圆
查看GraphHopper项目的完整BBox和Circle代码。
对于那些必须使用SQL在地理坐标中计算圆/矩形碰撞的应用程序,
这是我在e.James推荐的 oracle 11中实现的algorithm 。
在input中需要圆的坐标,以km为单位的圆半径和矩形的两个顶点坐标:
CREATE OR REPLACE FUNCTION "DETECT_CIRC_RECT_COLLISION" ( circleCenterLat IN NUMBER, -- circle Center Latitude circleCenterLon IN NUMBER, -- circle Center Longitude circleRadius IN NUMBER, -- circle Radius in KM rectSWLat IN NUMBER, -- rectangle South West Latitude rectSWLon IN NUMBER, -- rectangle South West Longitude rectNELat IN NUMBER, -- rectangle North Est Latitude rectNELon IN NUMBER -- rectangle North Est Longitude ) RETURN NUMBER AS -- converts km to degrees (use 69 if miles) kmToDegreeConst NUMBER := 111.045; -- Remaining rectangle vertices rectNWLat NUMBER; rectNWLon NUMBER; rectSELat NUMBER; rectSELon NUMBER; rectHeight NUMBER; rectWIdth NUMBER; circleDistanceLat NUMBER; circleDistanceLon NUMBER; cornerDistanceSQ NUMBER; BEGIN -- Initialization of remaining rectangle vertices rectNWLat := rectNELat; rectNWLon := rectSWLon; rectSELat := rectSWLat; rectSELon := rectNELon; -- Rectangle sides length calculation rectHeight := calc_distance(rectSWLat, rectSWLon, rectNWLat, rectNWLon); rectWidth := calc_distance(rectSWLat, rectSWLon, rectSELat, rectSELon); circleDistanceLat := abs( (circleCenterLat * kmToDegreeConst) - ((rectSWLat * kmToDegreeConst) + (rectHeight/2)) ); circleDistanceLon := abs( (circleCenterLon * kmToDegreeConst) - ((rectSWLon * kmToDegreeConst) + (rectWidth/2)) ); IF circleDistanceLon > ((rectWidth/2) + circleRadius) THEN RETURN -1; -- -1 => NO Collision ; 0 => Collision Detected END IF; IF circleDistanceLat > ((rectHeight/2) + circleRadius) THEN RETURN -1; -- -1 => NO Collision ; 0 => Collision Detected END IF; IF circleDistanceLon <= (rectWidth/2) THEN RETURN 0; -- -1 => NO Collision ; 0 => Collision Detected END IF; IF circleDistanceLat <= (rectHeight/2) THEN RETURN 0; -- -1 => NO Collision ; 0 => Collision Detected END IF; cornerDistanceSQ := POWER(circleDistanceLon - (rectWidth/2), 2) + POWER(circleDistanceLat - (rectHeight/2), 2); IF cornerDistanceSQ <= POWER(circleRadius, 2) THEN RETURN 0; -- -1 => NO Collision ; 0 => Collision Detected ELSE RETURN -1; -- -1 => NO Collision ; 0 => Collision Detected END IF; RETURN -1; -- -1 => NO Collision ; 0 => Collision Detected END;
工作,一个星期前就明白了,现在才开始testing。
double theta = Math.atan2(cir.getX()-sqr.getX()*1.0, cir.getY()-sqr.getY()*1.0); //radians of the angle double dBox; //distance from box to edge of box in direction of the circle if((theta > Math.PI/4 && theta < 3*Math.PI / 4) || (theta < -Math.PI/4 && theta > -3*Math.PI / 4)) { dBox = sqr.getS() / (2*Math.sin(theta)); } else { dBox = sqr.getS() / (2*Math.cos(theta)); } boolean touching = (Math.abs(dBox) >= Math.sqrt(Math.pow(sqr.getX()-cir.getX(), 2) + Math.pow(sqr.getY()-cir.getY(), 2)));
假设矩形的四条边检查从边到圆的中心的距离,如果小于半径则形状相交。
if sqrt((rectangleRight.x - circleCenter.x)^2 + (rectangleBottom.y - circleCenter.y)^2) < radius // then they intersect if sqrt((rectangleRight.x - circleCenter.x)^2 + (rectangleTop.y - circleCenter.y)^2) < radius // then they intersect if sqrt((rectangleLeft.x - circleCenter.x)^2 + (rectangleTop.y - circleCenter.y)^2) < radius // then they intersect if sqrt((rectangleLeft.x - circleCenter.x)^2 + (rectangleBottom.y - circleCenter.y)^2) < radius // then they intersect