如何判断圆和矩形在2D欧几里得空间中是否相交?(即经典的2D几何)
如何判断圆和矩形在2D欧几里得空间中是否相交?(即经典的2D几何)
Answers:
圆与矩形相交只有两种情况:
请注意,这不需要矩形与轴平行。
(一种查看方式:如果没有一条边在圆中有一个点(如果所有边都完全在圆的“外部”),那么圆仍然可以与多边形相交的唯一方法是如果它完全位于圆的内部多边形。)
有了这种洞察力,像下面的工作,其中圆的中心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)))
如果要编写任何几何图形,则库中可能已经具有上述功能。否则,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之后执行此步骤。
其余的线计算出圆形可能与矩形的角相交的困难情况。要解决该问题,请计算到圆心和角的距离,然后验证该距离不超过圆心的半径。对于中心在红色阴影区域内的所有圆,此计算均返回false;对于中心在白色阴影区域内的所有圆,此计算均返回true。
;)
circleDistance_x = abs(circle.x - (rect.x-rect.w/2)); circleDistance_y = abs(circle.y - (rect.y-rect.h/2));
这是另一个实现起来非常简单(也非常快)的解决方案。它会捕捉所有相交点,包括当球体完全进入矩形时。
// 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);
使用任何体面的数学库,可以将其缩短为3或4行。
您的球体和rect相交
,如果圆心与rect的一个顶点之间的距离小于球体的半径,
或者
圆心与rect的一个边缘之间的距离小于球体的半径( [ point-line distance ])
或
圆心在rect
point-point距离内:
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)
矩形内部的圆心:
采用单独的轴方法:如果在将矩形与该点分开的线上存在投影,则它们不相交
您可以将点投影在与矩形侧面平行的线上,然后可以轻松确定它们是否相交。如果它们不在所有四个投影上相交,则它们(点和矩形)不能相交。
您只需要内积(x = [x1,x2],y = [y1,y2],x * y = x1 * y1 + x2 * y2)
您的测试如下所示:
//矩形边缘:TL(左上),TR(右上),BL(左下),BR(右下) //要测试的点:POI 分隔=假 对于{{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) 分隔=真 中断//循环结束 万一 结束于 如果(分隔为true) 返回“无路口” 其他 返回“交集” 万一
这不假定轴对齐的矩形,并且可以很容易地扩展以测试凸集之间的相交。
这是最快的解决方案:
public static boolean intersect(Rectangle r, Circle c)
{
float cx = Math.abs(c.x - r.x - r.halfWidth);
float xDist = r.halfWidth + c.radius;
if (cx > xDist)
return false;
float cy = Math.abs(c.y - r.y - 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;
}
请注意执行顺序,并且宽度/高度的一半已预先计算。同样,平方是“手动”完成的,以节省一些时钟周期。
我想出的最简单的解决方案非常简单。
它的工作原理是在矩形中找到最接近圆的点,然后比较距离。
您可以通过一些操作来完成所有这些操作,甚至可以避免使用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;
}
就是这样!上面的解决方案假设x轴指向下在世界的左上方。
如果您想找到一种解决方案来处理移动的圆形和矩形之间的碰撞,则它要复杂得多,这也是我的另一个答案。
实际上,这要简单得多。您只需要两件事。
首先,您需要找到从圆心到矩形的每条线的四个正交距离。如果您的圆中的任何三个大于圆半径,则您的圆将不会与该矩形相交。
其次,您需要找到圆心和矩形中心之间的距离,然后如果该距离大于矩形对角线长度的一半,则您的圆将不在矩形内。
祝好运!
这是我的C代码,用于解决球体与无轴对齐框之间的碰撞。它依赖于我自己的几个库例程,但对某些人可能有用。我在游戏中使用它,效果很好。
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;
}
为了可视化,请使用键盘的小键盘。如果键“ 5”代表您的矩形,则所有键1-9代表9个象限的空间,除以构成矩形的线(其中5个是内部)。
1)如果圆心在第5象限内(即矩形内),则两个形状相交。
因此,有两种可能的情况:a)圆与矩形的两个或更多相邻边缘相交。b)圆与矩形的一条边相交。
第一种情况很简单。如果圆与矩形的两个相邻边相交,则它必须包含连接这两个边的角。(那个或它的中心位于我们已经覆盖的象限5中。另外请注意,也覆盖了圆仅与矩形的两个相对边缘相交的情况。)
2)如果矩形的任意角A,B,C,D位于圆内,则两个形状相交。
第二种情况比较棘手。我们应该注意,只有当圆心位于第2、4、6或8个象限之一时,才会发生这种情况。相应的角将是最接近它的点。)
现在,我们有了圆的中心位于“边缘”象限之一的情况,并且它仅与相应的边缘相交。然后,最靠近圆心的边上的点必须位于圆内。
3)对于AB,BC,CD,DA的每条线,通过圆心P构造垂直线p(AB,P),p(BC,P),p(CD,P),p(DA,P)。每条垂直线,如果与原始边缘的交点位于圆内,则两个形状相交。
这是最后一步的快捷方式。如果圆的中心在象限8中,并且边缘AB是上边缘,则交点将具有A和B的y坐标,以及中心P的x坐标。
您可以构造四个线相交,并检查它们是否位于其相应的边上,或者找出哪个象限P位于并检查相应的相交。两者都应简化为相同的布尔方程。请注意,上面的步骤2并不排除P在“角”象限之一中;它只是在寻找路口。
编辑:事实证明,我忽略了一个简单的事实,即#2是上面#3的子情况。毕竟,拐角也是边缘上的点。有关详细说明,请参见下面的@ShreevatsaR答案。同时,除非您想要快速但多余的检查,否则请忘记上面的#2。
此功能检测圆形和矩形之间的碰撞(相交)。他的回答类似于e.James方法,但是这一方法检测矩形所有角度(不仅是右上角)的碰撞。
注意:
aRect.origin.x和aRect.origin.y是矩形左下角的坐标!
aCircle.x和aCircle.y是圆心的坐标!
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;
}
我有一种避免不必要的昂贵毕达哥拉斯的方法-即。当矩形和圆形的边界框不相交时。
它也适用于非欧几里得:
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;
}
}
dLat=(lat-circleY); dLon=(lon-circleX); normed=dLat*dLat+dLon*dLon
。当然,如果您使用normDist方法,则需要normedDist = dist*dist;
为圆创建一个请参阅我的GraphHopper项目的完整BBox和Circle代码。
我开设了形状课,希望您喜欢
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;
}
}
这是修改后的代码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)
为我工作(仅当矩形角度为180时工作)
function intersects(circle, rect) {
let left = rect.x + rect.width > circle.x - circle.radius;
let right = rect.x < circle.x + circle.radius;
let top = rect.y < circle.y + circle.radius;
let bottom = rect.y + rect.height > circle.y - circle.radius;
return left && right && bottom && top;
}
改善e.James的答案:
double dx = abs(circle.x - rect.x) - rect.w / 2,
dy = abs(circle.y - rect.y) - rect.h / 2;
if (dx > circle.r || dy > circle.r) { return false; }
if (dx <= 0 || dy <= 0) { return true; }
return (dx * dx + dy * dy <= circle.r * circle.r);
该减去rect.w / 2
和rect.h / 2
一次,而不是三倍。
对于那些必须使用SQL在地理坐标中计算圆/矩形碰撞的人,
这是我在e.James建议算法的 oracle 11中的实现。
在输入中,它需要圆坐标,以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;
Works,一个星期前才发现,现在要进行测试。
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)));
def colision(rect, circle):
dx = rect.x - circle.x
dy = rect.y - circle.y
distance = (dy**2 + dx**2)**0.5
angle_to = (rect.angle + math.atan2(dx, dy)/3.1415*180.0) % 360
if((angle_to>135 and angle_to<225) or (angle_to>0 and angle_to<45) or (angle_to>315 and angle_to<360)):
if distance <= circle.rad/2.+((rect.height/2.0)*(1.+0.5*abs(math.sin(angle_to*math.pi/180.)))):
return True
else:
if distance <= circle.rad/2.+((rect.width/2.0)*(1.+0.5*abs(math.cos(angle_to*math.pi/180.)))):
return True
return False
假设您具有矩形的四个边缘,请检查从边缘到圆心的距离,如果圆角小于半径,则形状是相交的。
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