我将如何优化此方法以进行圆点碰撞检测?

How would I optimize this method for point of circle collision detection?

我正在研究一个 python 方法,应该 return 两个接触圆的截取坐标(碰撞点)。该方法按预期工作,但就其目的而言似乎过于昂贵。

应该只有一个拦截点,这些圆圈的大小可以变化。

def getPointOfContact(self, body):
    a1 = min(self.pos.x, body.pos.x) # The x value of the centre of the left-most circle
    b1 = min(self.pos.y, body.pos.y) # The y value of the up-most circle
    a2 = max(self.pos.x, body.pos.x) # The x value of the right-most circle
    b2 = max(self.pos.y, body.pos.y) # The y value of the down-most circle
    dx = a2-a1 # (Delta x) The difference in x positions
    dy = b2-b1 # (Delta y) The difference in y positions
    if dy == 0: # In case of no difference in y,
        m = 0 # Gradient is "zero"
    elif dx == 0: # In case of no difference in x,
        m = float("inf") # Gradient is "infinity"
    else:
        m = dy/dx # Gradient
    if a1 == self.pos.x: # Such that left-most circle's radius is used
        r1 = (self.size.x)/2
    else:
        r1 = (body.size.x)/2
    # Calculates the x position of intersection using trig
    x = a1+(r1*math.cos(math.atan(m))) 
    if b1 == self.pos.y: # Such that up-most circle's radius is used
        r1 = (self.size.x)/2
    else:
        r1 = (body.size.x)/2
    # Calculates the y position of intersection using trig
    y = b1+(r1*math.sin(math.atan(m)))
    return (int(x), int(y)) # Returns the coordinates as a tuple of integers

实际计算实际上相当简单。它只是将半径位移的 x 和 y 分量添加到圆心的坐标中。

问题是为了使计算有效,必须有很多准备就绪,即使用的圆必须具有最小的分量并且半径 (r1) 与圆非常匹配。

有没有办法简化这个方法,或者完全降低成本的技术?

提前致谢。

我不确定我明白了。你有第一个圆的半径,你假设它们正好相切,对吧?然后去掉你的 cos, sinatan:

d = sqrt(d1**2 + d2**2)
x = a1 + dx * r1 / d
y = b1 + dy * r1 / d

看看这个三角形,其中 + 是中心,* 是交点:

  0<-dx->|      
0 +
^  \ r1
|   \
|    *   d = r1+r2 = sqrt(dx**2 + dy**2)
dy    \ 
|      \ r2
v       \
-        +

注意 1:如果 m=dy/dx 并且您尝试计算 atan(m) 那么您最好直接使用 atan2(dy, dx) 来处理烦人的零和无穷大。

注释 2:cos(atan(dy/dx))==dx/RR=sqrt(dx**2+dy**2) 以及 sindy 相同,因为 atan(dy/dx)dx = R*cos(theta)dx = R*cos(theta) 的角度dy = R*sin(theta).

注意 3:您将内容投射到 int 中,因此您的圈子和交叉点可能会有点偏差。