我试图显示相交线的点,但是计算出的点在实际相交之间。
(https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection)
我已经多次检查了公式,并使用了另一个公式来计算相交点 x,y [x3+u*(x4-x3), y3+u*(y4-y3)]
而不是[x1+t*(x2-x1), y1+t*(y2-y1)]
,但这只是使这些点真正位于某处错误
(维基百科页面上未引用“ d”,而只是t和u公式的除数)
求交的函数
def checkcol(self, startObs, endObs):
x1, y1 = startObs
x2, y2 = endObs
x3, y3 = run.lamp
x4, y4 = self.endpoint
d = (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)
t = ((x1-x3)*(y3-y4)-(y1-y3)*(x3-x4))/d
u = ((x1-x2)*(y1-y3)-(y1-y2)*(x1-x3))/d
if 0 < t < 1 and 1 > u > 0:
pygame.draw.circle(run.screen, pygame.Color('green'), (round(x1+t*(x2-x1)), round(y1+t*(y2-y1))), 3)
整个代码
import pygame
import sys
import math
import random as rd
class Obs(object):
def __init__(self, startp, endp):
self.startp = startp
self.endp = endp
def drawww(self):
pygame.draw.line(run.screen, pygame.Color('red'), (self.startp), (self.endp))
for ray in run.lines:
ray.checkcol(self.startp, self.endp)
class rays(object):
def __init__(self, endpoint):
self.width = 2
self.endpoint = endpoint
def draww(self):
pygame.draw.line(run.screen, pygame.Color('white'), run.lamp, self.endpoint, 2)
def moveEnd(self, xoff, yoff):
self.endpoint[0] += xoff
self.endpoint[1] += yoff
def checkcol(self, startObs, endObs):
x1, y1 = startObs
x2, y2 = endObs
x3, y3 = run.lamp
x4, y4 = self.endpoint
d = (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)
t = ((x1-x3)*(y3-y4)-(y1-y3)*(x3-x4))/d
u = ((x1-x2)*(y1-y3)-(y1-y2)*(x1-x3))/d
if 0 < t < 1 and 1 > u > 0:
pygame.draw.circle(run.screen, pygame.Color('green'), (round(x1+t*(x2-x1)), round(y1+t*(y2-y1))), 3)
class Control(object):
def __init__(self):
self.winw = 800
self.winh = 800
self.screen = pygame.display.set_mode((self.winw, self.winh))
self.fps = 60
self.clock = pygame.time.Clock()
self.lamp = [400, 400]
self.lampr = 13
self.lines = []
self.r = 10
self.Obs = [Obs((rd.randint(0, self.winw), rd.randint(0, self.winh)),
(rd.randint(0, self.winw), rd.randint(0, self.winh))) for i in range(5)]
self.done = False
def event_loop(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_F5:
self.__init__()
if pygame.mouse.get_pressed() == (1, 0, 0):
self.lamp = (pygame.mouse.get_pos())
for line in self.lines:
line.moveEnd(pygame.mouse.get_rel()[0], pygame.mouse.get_rel()[1])
def draw(self):
self.screen.fill((pygame.Color('black')))
pygame.draw.circle(self.screen, pygame.Color('white'), self.lamp, self.lampr)
for line in self.lines:
line.draww()
for obs in self.Obs:
obs.drawww()
def createlines(self):
self.lines.clear()
for angle in range(0, 361, 9):
self.lines.append(rays([self.lamp[0] + 1200 * math.cos(angle), self.lamp[1] + 1200 * math.sin(angle)]))
def main_loop(self):
while not self.done:
self.event_loop()
self.createlines()
self.draw()
pygame.display.update()
self.clock.tick(self.fps)
pygame.display.set_caption(f"Draw FPS: {self.clock.get_fps()}")
if __name__ == '__main__':
run = Control()
run.main_loop()
pygame.quit()
sys.exit()
预计相交点将在实际相交点处。
答案 0 :(得分:3)
如果我计算两条线的交点,那么我将使用矢量算法和以下算法:
P ... point on the 1. line
R ... normalized direction of the 1. line
Q ... point on the 2. line
S ... normalized direction of the 2. line
alpha ... angle between Q-P and R
beta ... angle between R and S
gamma = 180° - alpha - beta
h = | Q - P | * sin(alpha)
u = h / sin(beta)
t = | Q - P | * sin(gamma) / sin(beta)
t = dot(Q-P, (S.y, -S.x)) / dot(R, (S.y, -S.x)) = determinant(mat2(Q-P, S)) / determinant(mat2(R, S))
u = dot(Q-P, (R.y, -R.x)) / dot(R, (S.y, -S.x)) = determinant(mat2(Q-P, R)) / determinant(mat2(R, S))
X = P + R * t = Q + S * u
在pygame中,可以使用pygame.math.Vector2
(甚至pygame.math.Vector3
)。
应用于您的代码,这意味着:
class rays(object):
# [...]
def checkcol(self, startObs, endObs):
P = pygame.Vector2(startObs)
R = (endObs - P).normalize()
Q = pygame.Vector2(run.lamp)
S = (self.endpoint - Q).normalize()
t = (Q-P).dot((S.y, -S.x)) / R.dot((S.y, -S.x))
u = (Q-P).dot((R.y, -R.x)) / R.dot((S.y, -S.x))
V = (endObs - P)
max_t = math.hypot(V.x, V.y)
if 0 < t < max_t and u > 0:
X = P + R * t
pygame.draw.circle(run.screen, pygame.Color('green'), (round(X.x), round(X.y)), 3)