分离轴定理和 Python
这就是我目前正在做的事情:
创建垂直于 2 个矩形的 4 个边的 4 个轴。由于它们是矩形,我不需要为每个边生成一个轴(法线)。
然后我循环我的 4 个轴。
因此对于每个轴: 我得到了矩形每个角在轴上的投影。 有 2 个列表(数组)包含这些投影。每个矩形一个。 然后我得到每个投影和轴的点积。这返回一个标量值 可用于确定最小值和最大值。
现在这两个列表包含标量而不是向量。我对列表进行排序,以便可以轻松选择最小值和最大值。如果框 B 的最小值 >= 框 A 的最大值或框 B 的最大值 <= 框 A 的最小值,则该轴上不存在碰撞,并且对象之间也不存在碰撞。
此时函数结束并且循环中断。
如果所有轴都不满足这些条件,那么我们就会发生碰撞,
我希望这是正确的方法。
python 代码本身可以在这里找到 http://pastebin.com/vNFP3mAb
问题我的问题是上面的代码不起作用。即使没有碰撞,它也始终会检测到碰撞。我输入的正是代码正在做的事情。如果我遗漏了任何步骤或者只是不明白 SAT 的工作原理,请告诉我。
This is what I am currently doing:
Creating 4 axis that are perpendicular to 4 edges of 2 rectangles. Since they are rectangles I do not need to generate an axis (normal) per edge.
I then loop over my 4 axes.
So for each axis:
I get the projection of every corner of a rectangle on to the axis.
There are 2 lists (arrays) containing those projections. One for each rectangle.
I then get the dot product of each projection and the axis. This returns a scalar value
that can be used to to determine the min and max.
Now the 2 lists contain scalars and not vectors. I sort the lists so I can easily select the min and max values. If the min of box B >= the max of box A OR the max of box B <= the min of box A then there is no collision on that axis and no collision between the objects.
At this point the function finishes and the loop breaks.
If those conditions are never met for all the axis then we have a collision
I hope this was the correct way of doing it.
The python code itself can be found here http://pastebin.com/vNFP3mAb
The problem i was having is that the code above does not work. It always detects a a collision even where there is not a collision. What i typed out is exactly what the code is doing. If I am missing any steps or just not understanding how SAT works please let me know.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
一般来说,有必要执行问题中概述的步骤来确定矩形是否“碰撞”(相交),请注意,正如OP所做的那样,一旦分离轴我们就可以打破(得出不相交的结论)被发现。
有几种简单的方法可以“优化”,为提前退出提供机会。这些的实用价值取决于所检查的矩形的分布,但两者都很容易合并到现有框架中。
(1) 边界圆检查
证明不相交的一种快速方法是显示两个矩形的边界圆不相交。矩形的外接圆共享其中心,即任一对角线的中点,并且直径等于任一对角线的长度。如果两个圆心之间的距离超过两个圆的半径之和,则两个圆不相交。因此矩形也不能相交。如果目的是找到分离轴,那么我们还没有实现。但是,如果我们只想知道矩形是否“碰撞”,则可以提前退出。
(2) 一个矩形在另一个矩形内部的顶点
一个矩形的顶点在与另一个矩形边缘平行的轴上的投影提供了足够的信息来检测该顶点何时在另一个矩形内部。当后一个矩形已平移且未旋转到原点(边缘平行于普通轴)时,此检查尤其容易。如果一个矩形的顶点恰好在另一个矩形的内部,则这些矩形显然是相交的。当然,这是相交的充分条件,而不是必要条件。但它允许提前退出并得出交叉点(当然,无需找到分离轴,因为不存在任何分离轴)。
In general it is necessary to carry out the steps outlined in the Question to determine if the rectangles "collide" (intersect), noting as the OP does that we can break (with a conclusion of non-intersection) as soon as a separating axis is found.
There are a couple of simple ways to "optimize" in the sense of providing chances for earlier exits. The practical value of these depends on the distribution of rectangles being checked, but both are easily incorporated in the existing framework.
(1) Bounding Circle Check
One quick way to prove non-intersection is by showing the bounding circles of the two rectangles do not intersect. The bounding circle of a rectangle shares its center, the midpoint of either diagonal, and has diameter equal to the length of either diagonal. If the distance between the two centers exceeds the sum of the two circles' radii, then the circles do not intersect. Thus the rectangles also cannot intersect. If the purpose was to find an axis of separation, we haven't accomplished that yet. However if we only want to know if the rectangles "collide", this allows an early exit.
(2) Vertex of one rectangle inside the other
The projection of a vertex of one rectangle on axes parallel to the other rectangle's edges provides enough information to detect when that vertex is inside the other rectangle. This check is especially easy when the latter rectangle has been translated and unrotated to the origin (with edges parallel to the ordinary axes). If it happens that a vertex of one rectangle is inside the other, the rectangles obviously intersect. Of course this is a sufficient condition for intersection, not a necessary one. But it allows for an early exit with a conclusion of intersection (and of course without finding an axis of separation because none will exist).
我发现有两件事是错误的。首先,投影应该只是顶点与轴的点积。你正在做的事情太复杂了。其次,您获取轴的方式不正确。你写:
应该读到的地方:
区别在于坐标确实给了你一个向量,但要获得垂直线,你需要交换 x 和 y 值并对其中之一求负。
希望有帮助。
发现了另一个错误
编辑在这段代码中
:应该是:
排序为您提供了一个价值不断增加的列表。因此 [1,2,3,4] 和 [10,11,12,13] 不重叠,因为后者的最小值大于前者的最大值。第二个比较是交换输入集时的比较。
I see two things wrong. First, the projection should simply be the dot product of a vertex with the axis. What you're doing is way too complicated. Second, the way you get your axis is incorrect. You write:
Where it should read:
The difference is coordinates does give you a vector, but to get the perpendicular you need to exchange the x and y values and negate one of them.
Hope that helps.
EDIT Found another bug
In this code:
That should read:
Sort gives you a list increasing in value. So [1,2,3,4] and [10,11,12,13] do not overlap because the minimum of the later is greater than the maximum of the former. The second comparison is for when the input sets are swapped.