我将如何优化此方法以进行圆点碰撞检测?
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
, sin
和 atan
:
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/R
与 R=sqrt(dx**2+dy**2)
以及 sin
和 dy
相同,因为 atan(dy/dx)
是 dx = R*cos(theta)
和 dx = R*cos(theta)
的角度dy = R*sin(theta)
.
注意 3:您将内容投射到 int
中,因此您的圈子和交叉点可能会有点偏差。
我正在研究一个 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
, sin
和 atan
:
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/R
与 R=sqrt(dx**2+dy**2)
以及 sin
和 dy
相同,因为 atan(dy/dx)
是 dx = R*cos(theta)
和 dx = R*cos(theta)
的角度dy = R*sin(theta)
.
注意 3:您将内容投射到 int
中,因此您的圈子和交叉点可能会有点偏差。