简体   繁体   English

如何确定两个圆形扇区是否相互重叠

[英]How to determine whether two circular sectors overlap with each other

Each sector can be represented as (x,y,r,a,d), where x,y is the location, r is the radius, d is the direction, and a is the angle. 每个扇区可以表示为(x,y,r,a,d),其中x,y是位置,r是半径,d是方向,a是角度。 Given these information of two circular sectors, how to determine whether they overlap with each other? 鉴于这两个循环扇区的信息,如何确定它们是否相互重叠? Is there any efficient algorithm for solving it? 有没有有效的算法来解决它? Thanks! 谢谢!

I know of one very quick way to discount the possibility, since I've used that for circle collisions before. 我知道一种非常快速的方法可以减少这种可能性,因为我以前用它来进行圆碰撞。

Work out the distance between the two centers and then, if that's greater than the sum of the radii, there can be no collision. 计算两个中心之间的距离,然后,如果大于半径之和,则不会发生碰撞。 For efficiency, don't use square root, just work directly on the squared values: 为了提高效率,不要使用平方根,只需直接处理平方值:

if (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) > (r1 + r2) * (r1 + r2):
    # No chance of collision.

Working it out for circle segments will be a little tougher. 对圆形段进行处理将会更加困难。


Your choice of method depends on how accurate you need it to be. 您选择的方法取决于您需要的准确程度。 If you're doing actual math, you probably need high accuracy. 如果您正在进行实际数学运算,则可能需要高精度。 But, for example, if you're doing this for something like a computer game, close enough may be good enough. 但是,例如,如果您正在为电脑游戏这样的事情做这件事,那么足够接近可能就足够了。

If that were the case, I'd look into transforming the arc into a series of straight lines (the number of which would probably depend on a , the "spread" of the arc - you could probably get away with a couple of lines for a spread of one degree of arc but that wouldn't work too well for 180 degrees). 如果真是那样的话,我会考虑转变弧形成一系列的直线(其数量很可能取决于a ,在弧形的“传播” -你很可能用了几行脱身一度弧度,但180度不会太好。

Straight line collision detection is a much better known method although you have to deal with the fact that the number of comparisons may rise quickly. 直线碰撞检测是一种更为人熟知的方法,尽管您必须处理比较次数可能快速增加的事实。


If you don't want to use line segments, then here's the process to follow. 如果您不想使用线段,那么这是要遵循的过程。 It uses a circle collision algorithm to find out the zero, one or two points of collisions for the full circles, then checks those points to see if they're within both arcs. 它使用圆碰撞算法找出整圆的零点,一点或两点碰撞,然后检查这些点以查看它们是否在两个弧内。

First, run that check above to detect the case where no collision is possible. 首先,运行上面的检查以检测不可能发生碰撞的情况。 If no collision is possible between the circles, then neither can the arcs collide. 如果圆圈之间不可能发生碰撞,那么弧线也不会发生碰撞。

Secondly, check if the circles have a single collision point. 其次,检查圆圈是否有单个碰撞点。 That's the case if: 如果是这样的情况:

(x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) == (r1 + r2) * (r1 + r2)

within a suitable error range, of course. 当然,在合适的误差范围内。 We should all know by now that comparing floating point numbers for equality should use some sort of delta comparison. 我们现在都应该知道,比较相等的浮点数应该使用某种delta比较。

If that's the case, you have one point to check and you can find out that point easily. 如果是这种情况,你有一点要检查,你可以很容易地找到这一点。 It's the point r1 units along the straight line leading from (x1,y1) to (x2,y2) or, looking at it as moving some fraction along that line: 它是从(x1,y1)(x2,y2)的直线上的点r1单位(x2,y2)或者看着它沿着该线移动一些分数:

(x1 + (x2-x1) * (r1+r2) / r1, y1 + (y2-y1) * (r1+r2) / r1)

Otherwise, there are two points to check and you can use the answers to a question like this one to establish what those two points are. 否则,有两点要检查,你可以使用像这样的问题的答案来确定这两点是什么。

Once you have some collision points, it's a much simpler method to find out if those points are on an arc, keeping in mind that the candidate point will need to be on both arcs for them to collide, not just on one. 一旦你有一些碰撞点,这是一个更简单的方法来确定这些点是否在弧上,记住候选点需要在两个弧上,以便它们碰撞,而不仅仅是在一个。

There's two steps. 有两个步骤。 First is to figure out if the two centres are close enough to each other to allow a collision, which can be done by comparing the distance between them to the sum of their radii: 首先要弄清楚两个中心是否足够接近以允许碰撞,这可以通过将它们之间的距离与它们的半径之和进行比较来完成:

if (((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) > ((r1 + r2) * (r1 + r2)))
    // No collision.

Then you need to check whether the line between the centres falls within the arcs defined by your various angles: 然后你需要检查中心之间的线是否落在由各种角度定义的弧内:

float angle1to2 = Math.atan2(y2 - y1, x2 - x1);
if (angle1to2 < (d1 - a1/2) || angle1to2 > (d1 + a1/2))
    // No collision
float angle2to1 = angle1to2 + Math.PI;
if (angle2to1 < (d2 - a2/2) || angle2to1 > (d2 + a2/2))
    // No collision

If you get through these checks without the possibility of a collision being excluded, then you have successfully detected a collision. 如果您通过这些检查而没有排除碰撞的可能性,那么您已成功检测到碰撞。

Caveat: this code isn't tested at all. 警告:此代码根本没有经过测试。 In particular, the atan2 calls may need some tweaking depending on your coordinate system. 特别是, atan2调用可能需要一些调整,具体取决于您的坐标系。

EDIT: just realised this misses an important corner case, where the arcs are not "pointing" at each other but still overlap. 编辑:刚刚意识到这错过了一个重要的角落情况,其中弧线不是“指向”彼此但仍然重叠。 Will ruminate upon this and return... 将反复思考并返回......

Since we have circular sectors, angle and direction do not matter if you are doing this in real time. 由于我们有圆形扇区,因此如果您实时执行此操作,则角度和方向无关紧要。 The following applies only to full circle sectors, or if both sectors are pointing to each other. 以下内容仅适用于整圆扇区,或两个扇区彼此指向的情况。

you can follow the next steps: 您可以按照以下步骤操作:

1) Find the distance between each sector, 2) Subtract both radius to that distance, 3) if the result is negative, there has been a collision between both sectors. 1)找到每个扇区之间的距离,2)将半径减去该距离,3)如果结果为负,则两个扇区之间发生冲突。 otherwise, its the distance to collision. 否则,它与碰撞的距离。

for example, we have two sectors, both with a 50 unit radius. 例如,我们有两个扇区,两个扇区的半径为50。 the distance between their center points is 80. subtract 80-50-50 = -20, so you know there has been a collision 20 units in distance. 它们的中心点之间的距离是80.减去80-50-50 = -20,所以你知道距离有20个单位。

otherwise, if the distance was 500, 500-50-50 = 400, a positive value, now you know that these two sectors are 400 units apart. 否则,如果距离为500,500-50-50 = 400,则为正值,现在您知道这两个扇区相距400个单位。

now, if the circles are too close, say, 1 unit apart, 1-50-50 = -99, which means they are almost totally overlapping. 现在,如果圆圈太近,比如相距1个单位,1-50-50 = -99,这意味着它们几乎完全重叠。

For true segmented circular sectors which is what you specified on the comments, you should use paxdiablos or Macs answers. 对于您在评论中指定的真正分段循环扇区 ,您应该使用paxdiablos或Macs答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM