我在确定此 python 代码中两条线的交点时遇到问题
I'm having a problem with determining the intersection of two lines in this python code
我尝试了解析几何的数学公式,但没有得到想要的结果。
正如您在代码中看到的那样,用户画了两条线并出现了一个绿色圆圈(交点)。
我已经尝试解决这个问题几个小时了,但我失败了。有时点不出现或出现但在错误的位置。
Source of the formula I used in the code
Docs of pygame the library I used
#!/usr/bin/env python
from pygame import *
from time import sleep
init();
win = display.set_mode((500,500));
lines = []
cords = []
preview = False
xi = -100
yi = -100
def drawlines(flines):
for fcords in flines:
draw.line(win,(0,0,0),fcords[0],fcords[1],4)
while True:
win.fill((255,255,255))
for ev in event.get():
if ev.type == QUIT:
quit();
exit();
elif ev.type == MOUSEBUTTONDOWN:
if ev.button == 1:
preview = True
a = mouse.get_pos()
cords.append(mouse.get_pos())
elif ev.type == MOUSEBUTTONUP:
if ev.button == 1:
cords.append(mouse.get_pos())
lines.append((cords))
cords = []
preview = False
######################################## THIS BROKEN PART #################################
if len(lines) == 2:
#line 1
points_line1 = lines[0]
point1_line1 = points_line1[0]
point2_line1 = points_line1[1]
line1_vector = (point2_line1[0]-point1_line1[0],point2_line1[1]-point1_line1[1])
a_line1 = line1_vector[1]
b_line1 = -line1_vector[0]
c_line1 = -((a_line1*point1_line1[0]) + (b_line1*point1_line1[1]))
#line2
points_line2 = lines[1]
point1_line2 = points_line2[0]
point2_line2 = points_line2[1]
line2_vector = (point2_line2[0]-point1_line2[0],point2_line2[1]-point1_line2[1])
a_line2 = line2_vector[1]
b_line2 = -line2_vector[0]
c_line2 = -((a_line2*point1_line2[0]) + (b_line2*point1_line2[1]))
if (a_line2 != 0 and b_line2 != 0):
if (a_line1 / a_line2) != ( b_line1/b_line2):
#intersection between line1 and line2
yi = ((((a_line1*c_line2) / a_line2) + c_line1) / -b_line1)
xi = (((-b_line1*yi)-c_line1) / a_line1)
###########################################################################################
elif preview:
draw.line(win,(0,0,0),a,mouse.get_pos(),4)
drawlines(lines)
draw.circle(win,(0,200,0),(int(xi),int(yi)),10)
display.flip()
很难挖掘您的代码。特别是 c_line1 = -((a_line1*point1_line1[0]) + (b_line1*point1_line1[1]))
看起来很奇怪,因为它计算的是向量和一个点的点积。
因此我不知道你的代码到底出了什么问题,但我知道如何交叉线。参见 and Collision and Intersection - Line and line。
编写可以加、减、缩放向量和将向量旋转 90° 的函数。编写一个函数来计算 Dot product:
def add(a, b):
return a[0]+b[0], a[1]+b[1]
def sub(a, b):
return a[0]-b[0], a[1]-b[1]
def rot90(v):
return -v[1], v[0]
def mul(v, s):
return v[0]*s, v[1]*s
def dot(a, b):
return a[0]*b[0] + a[1]*b[1]
计算从线的起点到线的终点的向量和线的法向量。将线向量旋转90°得到法向量:
#line 1
point1_line1, point2_line1 = lines[0]
line1_vector = sub(point2_line1, point1_line1)
line1_norml = rot90(line1_vector)
#line2
point1_line2, point2_line2 = lines[1]
line2_vector = sub(point2_line2, point1_line2)
line2_norml = rot90(line2_vector)
计算线段的交点。确保直线不平行且交点在线段上:
# vector from start point of line 2 to start point of line 1
l2p1_l1p1 = sub(point1_line1, point1_line2)
# intersection
d = dot(line2_vector, line1_norml)
if d != 0: # prallel lines
t = dot(l2p1_l1p1, line1_norml) / d
u = dot(l2p1_l1p1, line2_norml) / d
if 0 <= t <= 1 and 0 <= u <= 1: # intersection on line segments
xi, yi = add(point1_line2, mul(line2_vector, t))
最小示例:
from pygame import *
init()
win = display.set_mode((500,500))
lines = []
cords = []
preview = False
xi, yi = -100, -100
def drawlines(flines):
for fcords in flines:
draw.line(win,(0,0,0),fcords[0],fcords[1],4)
def add(a, b):
return a[0]+b[0], a[1]+b[1]
def sub(a, b):
return a[0]-b[0], a[1]-b[1]
def rot90(v):
return -v[1], v[0]
def mul(v, s):
return v[0]*s, v[1]*s
def dot(a, b):
return a[0]*b[0] + a[1]*b[1]
run = True
while run:
for ev in event.get():
if ev.type == QUIT:
run = False
elif ev.type == MOUSEBUTTONDOWN:
if ev.button == 1:
preview = True
a = ev.pos
cords.append(a)
elif ev.type == MOUSEBUTTONUP:
if ev.button == 1:
cords.append(ev.pos)
lines.append((cords))
cords = []
preview = False
intersections = []
for i, line1 in enumerate(lines):
for line2 in lines[i+1:]:
#line 1
point1_line1, point2_line1 = line1
line1_vector = sub(point2_line1, point1_line1)
line1_norml = rot90(line1_vector)
#line2
point1_line2, point2_line2 = line2
line2_vector = sub(point2_line2, point1_line2)
line2_norml = rot90(line2_vector)
# vector from start point of line 2 to start point of line 1
l2p1_l1p1 = sub(point1_line1, point1_line2)
# intersection
d = dot(line2_vector, line1_norml)
if d != 0: # prallel lines
t = dot(l2p1_l1p1, line1_norml) / d
u = dot(l2p1_l1p1, line2_norml) / d
if 0 <= t <= 1 and 0 <= u <= 1: # intersection on line segments
xi, yi = add(point1_line2, mul(line2_vector, t))
intersections.append((xi, yi))
win.fill((255,255,255))
if len(cords) % 2 == 1:
draw.line(win,(0,0,0), a, mouse.get_pos(), 4)
drawlines(lines)
for p in intersections:
draw.circle(win, (0,200,0), (round(p[0]), round(p[1])), 10)
display.flip()
quit()
exit()
我尝试了解析几何的数学公式,但没有得到想要的结果。
正如您在代码中看到的那样,用户画了两条线并出现了一个绿色圆圈(交点)。
我已经尝试解决这个问题几个小时了,但我失败了。有时点不出现或出现但在错误的位置。
Source of the formula I used in the code
Docs of pygame the library I used
#!/usr/bin/env python
from pygame import *
from time import sleep
init();
win = display.set_mode((500,500));
lines = []
cords = []
preview = False
xi = -100
yi = -100
def drawlines(flines):
for fcords in flines:
draw.line(win,(0,0,0),fcords[0],fcords[1],4)
while True:
win.fill((255,255,255))
for ev in event.get():
if ev.type == QUIT:
quit();
exit();
elif ev.type == MOUSEBUTTONDOWN:
if ev.button == 1:
preview = True
a = mouse.get_pos()
cords.append(mouse.get_pos())
elif ev.type == MOUSEBUTTONUP:
if ev.button == 1:
cords.append(mouse.get_pos())
lines.append((cords))
cords = []
preview = False
######################################## THIS BROKEN PART #################################
if len(lines) == 2:
#line 1
points_line1 = lines[0]
point1_line1 = points_line1[0]
point2_line1 = points_line1[1]
line1_vector = (point2_line1[0]-point1_line1[0],point2_line1[1]-point1_line1[1])
a_line1 = line1_vector[1]
b_line1 = -line1_vector[0]
c_line1 = -((a_line1*point1_line1[0]) + (b_line1*point1_line1[1]))
#line2
points_line2 = lines[1]
point1_line2 = points_line2[0]
point2_line2 = points_line2[1]
line2_vector = (point2_line2[0]-point1_line2[0],point2_line2[1]-point1_line2[1])
a_line2 = line2_vector[1]
b_line2 = -line2_vector[0]
c_line2 = -((a_line2*point1_line2[0]) + (b_line2*point1_line2[1]))
if (a_line2 != 0 and b_line2 != 0):
if (a_line1 / a_line2) != ( b_line1/b_line2):
#intersection between line1 and line2
yi = ((((a_line1*c_line2) / a_line2) + c_line1) / -b_line1)
xi = (((-b_line1*yi)-c_line1) / a_line1)
###########################################################################################
elif preview:
draw.line(win,(0,0,0),a,mouse.get_pos(),4)
drawlines(lines)
draw.circle(win,(0,200,0),(int(xi),int(yi)),10)
display.flip()
很难挖掘您的代码。特别是 c_line1 = -((a_line1*point1_line1[0]) + (b_line1*point1_line1[1]))
看起来很奇怪,因为它计算的是向量和一个点的点积。
因此我不知道你的代码到底出了什么问题,但我知道如何交叉线。参见
编写可以加、减、缩放向量和将向量旋转 90° 的函数。编写一个函数来计算 Dot product:
def add(a, b):
return a[0]+b[0], a[1]+b[1]
def sub(a, b):
return a[0]-b[0], a[1]-b[1]
def rot90(v):
return -v[1], v[0]
def mul(v, s):
return v[0]*s, v[1]*s
def dot(a, b):
return a[0]*b[0] + a[1]*b[1]
计算从线的起点到线的终点的向量和线的法向量。将线向量旋转90°得到法向量:
#line 1
point1_line1, point2_line1 = lines[0]
line1_vector = sub(point2_line1, point1_line1)
line1_norml = rot90(line1_vector)
#line2
point1_line2, point2_line2 = lines[1]
line2_vector = sub(point2_line2, point1_line2)
line2_norml = rot90(line2_vector)
计算线段的交点。确保直线不平行且交点在线段上:
# vector from start point of line 2 to start point of line 1
l2p1_l1p1 = sub(point1_line1, point1_line2)
# intersection
d = dot(line2_vector, line1_norml)
if d != 0: # prallel lines
t = dot(l2p1_l1p1, line1_norml) / d
u = dot(l2p1_l1p1, line2_norml) / d
if 0 <= t <= 1 and 0 <= u <= 1: # intersection on line segments
xi, yi = add(point1_line2, mul(line2_vector, t))
最小示例:
from pygame import *
init()
win = display.set_mode((500,500))
lines = []
cords = []
preview = False
xi, yi = -100, -100
def drawlines(flines):
for fcords in flines:
draw.line(win,(0,0,0),fcords[0],fcords[1],4)
def add(a, b):
return a[0]+b[0], a[1]+b[1]
def sub(a, b):
return a[0]-b[0], a[1]-b[1]
def rot90(v):
return -v[1], v[0]
def mul(v, s):
return v[0]*s, v[1]*s
def dot(a, b):
return a[0]*b[0] + a[1]*b[1]
run = True
while run:
for ev in event.get():
if ev.type == QUIT:
run = False
elif ev.type == MOUSEBUTTONDOWN:
if ev.button == 1:
preview = True
a = ev.pos
cords.append(a)
elif ev.type == MOUSEBUTTONUP:
if ev.button == 1:
cords.append(ev.pos)
lines.append((cords))
cords = []
preview = False
intersections = []
for i, line1 in enumerate(lines):
for line2 in lines[i+1:]:
#line 1
point1_line1, point2_line1 = line1
line1_vector = sub(point2_line1, point1_line1)
line1_norml = rot90(line1_vector)
#line2
point1_line2, point2_line2 = line2
line2_vector = sub(point2_line2, point1_line2)
line2_norml = rot90(line2_vector)
# vector from start point of line 2 to start point of line 1
l2p1_l1p1 = sub(point1_line1, point1_line2)
# intersection
d = dot(line2_vector, line1_norml)
if d != 0: # prallel lines
t = dot(l2p1_l1p1, line1_norml) / d
u = dot(l2p1_l1p1, line2_norml) / d
if 0 <= t <= 1 and 0 <= u <= 1: # intersection on line segments
xi, yi = add(point1_line2, mul(line2_vector, t))
intersections.append((xi, yi))
win.fill((255,255,255))
if len(cords) % 2 == 1:
draw.line(win,(0,0,0), a, mouse.get_pos(), 4)
drawlines(lines)
for p in intersections:
draw.circle(win, (0,200,0), (round(p[0]), round(p[1])), 10)
display.flip()
quit()
exit()