检测矩形交叉圆

Detect rectangle crossing circle

提问人:Danijel 提问时间:12/19/2018 最后编辑:YksisarvinenDanijel 更新时间:12/19/2018 访问量:262

问:

**enter image description here**

如何检测矩形是出圈还是穿过圆圈?矩形是一个自由流动的内圆。我知道圆的确切位置和矩形的确切位置。

几何 图形与语言无关的 检测

评论

1赞 Scheff's Cat 12/19/2018
在CG和游戏中有一个相当简单的技巧:将矩形放大圆半径,然后你可以简单地检查圆中心点是否在里面。 (后者是中心x和y对立rect [xmin, xmax]和[ymin, ymax]的范围检查。
0赞 Scheff's Cat 12/19/2018
如果您想找到更多,请尝试谷歌“交叉矩形圆”。
0赞 HolyBlackCat 12/19/2018
矩形轴是否对齐?
0赞 MBo 12/19/2018
@Scheff 这不能正常工作:想象正方形 (-1-1)(-1,1)(1,1)(1,-1) 和半径为 1 且中心为 *(.9, 1,9) 的圆
1赞 Reblochon Masque 12/19/2018
如果矩形的每个角到圆心的距离是圆的半径,则矩形不交叉。<=

答:

4赞 MBo 12/19/2018 #1

从圆心到矩形最近点的平方距离可以计算为(零表示圆心在矩形内):

 dx = Max(Abs(cx - rect.center.x) - rect.width / 2, 0)
 dy = Max(Abs(cy - rect.center.y) - rect.height / 2, 0)
 SquaredDistance = dx * dx + dy * dy

然后将其与平方半径进行比较

2赞 Nima 12/19/2018 #2

矩形有 4 个角,您应该检查这 4 个角中是否有一个不圆。 如果你有圆心和它的半径,每个矩形角到圆心的距离必须小于圆半径。

enter image description here

评论

1赞 MBo 12/19/2018
不适用于正方形 (-1-1)(-1,1)(1,1)(1,-1) 和中心为 (0,0) 且半径为 1.2 的圆形 - 所有角都在外面,但交点确实存在。
1赞 Nima 12/19/2018
@MBo问题希望确保矩形在圆圈内,因此矩形在圆圈外或与圆圈交叉没有区别。
1赞 ALX23z 12/19/2018 #3

我还没有完全理解你的问题,我将回答两个可能的问题:

1)检查矩形是否与圆相交:首先找到矩形离圆心最近的点,然后检查该点是否在圆到圆心的半径范围内。“仅检查角”或“检查矩形的段”等方法不起作用,并且有反例。

下面是一个代码示例:

struct Rect
{
    double minX, maxX;
    double minY, maxY;
};

struct Circle
{
    double cX, cY, Radius;
};

double Clamp(double val, double lo, double hi) // use std::clamp if you have C++17
{
    if(val < lo) return lo;
    if(val > hi) return hi;
    return val;
}

double Sqr(double val) {return val*val;}

bool RectangleIntersectsCircle(Rect R, Circle C)
{
    double closestX = Clamp(C.cX, R.minX, R.maxX);
    double closestY = Clamp(C.cY, R.minY, R.maxY);

    return Sqr(closestX - C.cX) + Sqr(closestY - C.cY) < Sqr(C.Radius);
}

2)检查矩形是否完全在圆内:只需检查矩形的所有4个角是否都在圆内即可。

bool RectangleInsideCircle(Rect R, Circle C)
{
    double fartherstX = max(fabs(R.minX - C.cX), fabs(R.maxX - C.cX));
    double fartherstY = max(fabs(R.minY - C.cY), fabs(R.maxY - C.cY));

    return Sqr(fartherstX) + Sqr(fartherstY) < Sqr(C.Radius);
}