Как вычислить точку пересечения двух линий?
У меня есть две линии, которые пересекаются в точке. Я знаю конечные точки двух линий. Как вычислить точку пересечения в Python?
# Given these endpoints
#line 1
A = [X, Y]
B = [X, Y]
#line 2
C = [X, Y]
D = [X, Y]
# Compute this:
point_of_intersection = [X, Y]
Ответы
Ответ 1
В отличие от других предложений, это краткое и не использует внешние библиотеки, такие как numpy
. (Не то чтобы использование других библиотек - это плохо... это не нужно, особенно для такой простой задачи.)
def line_intersection(line1, line2):
xdiff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])
ydiff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1])
def det(a, b):
return a[0] * b[1] - a[1] * b[0]
div = det(xdiff, ydiff)
if div == 0:
raise Exception('lines do not intersect')
d = (det(*line1), det(*line2))
x = det(d, xdiff) / div
y = det(d, ydiff) / div
return x, y
print line_intersection((A, B), (C, D))
И к вашему сведению, я бы использовал кортежи вместо списков для ваших очков. Например
A = (X, Y)
РЕДАКТИРОВАТЬ: Первоначально была опечатка. Это было исправлено в сентябре 2014 благодаря @zidik.
Это просто транслитерация Python следующей формулы, где линиями являются (a1, a2) и (b1, b2), а пересечение - p. (Если знаменатель равен нулю, линии не имеют уникального пересечения.)
![]()
Ответ 2
Нельзя стоять в стороне,
Итак, мы имеем линейную систему:
A 1 * x + B 1 * y = C 1
A 2 * x + B 2 * y = C 2
допустим это с правилом Крамера, поэтому решение можно найти в детерминантах:
x = D x/D
y = D y/D
где D - главный определитель системы:
A 1 B 1
A 2 B 2
и D x и D y могут быть найдены из матриц:
C 1 B 1
C 2 B 2
и
A 1 C 1
A 2 C 2
(обратите внимание, так как столбец C заменяет столбцы кодов x и y)
Итак, теперь, для ясности для python, чтобы не испортить вещи, пусть делает сопоставление между математикой и python. Мы будем использовать массив L
для хранения наших коэффициентов A, B, C линейных уравнений и intestead pretty x
, y
у нас будет [0]
, [1]
, но в любом случае. Таким образом, то, что я написал выше, будет иметь следующий код в коде:
при D
L1 [0] L1 [1]
L2 [0] L2 [1]
для D x
L1 [2] L1 [1]
L2 [2] L2 [1]
для D y
L1 [0] L1 [2]
L2 [0] L2 [2]
Теперь перейдите для кодирования:
line
- вырабатывает коэффициенты A, B, C линейного уравнения с помощью двух точек,
intersection
- находит точку пересечения (если она есть) двух строк, предоставленных коэффами.
from __future__ import division
def line(p1, p2):
A = (p1[1] - p2[1])
B = (p2[0] - p1[0])
C = (p1[0]*p2[1] - p2[0]*p1[1])
return A, B, -C
def intersection(L1, L2):
D = L1[0] * L2[1] - L1[1] * L2[0]
Dx = L1[2] * L2[1] - L1[1] * L2[2]
Dy = L1[0] * L2[2] - L1[2] * L2[0]
if D != 0:
x = Dx / D
y = Dy / D
return x,y
else:
return False
Пример использования:
L1 = line([0,1], [2,3])
L2 = line([2,3], [0,4])
R = intersection(L1, L2)
if R:
print "Intersection detected:", R
else:
print "No single intersection point detected"
Ответ 3
Используя формулу из: https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection
def findIntersection(x1,y1,x2,y2,x3,y3,x4,y4):
px= ( (x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4) ) / ( (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4) )
py= ( (x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4) ) / ( (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4) )
return [px, py]
Ответ 4
Вот решение с использованием библиотеки Shapely. Shapely часто используется для работы с ГИС, но создан для того, чтобы быть полезным для вычислительной геометрии. Я изменил ваши входы из списков на кортежи.
проблема
# Given these endpoints
#line 1
A = (X, Y)
B = (X, Y)
#line 2
C = (X, Y)
D = (X, Y)
# Compute this:
point_of_intersection = (X, Y)
Решение
import shapely
from shapely.geometry import LineString, Point
line1 = LineString([A, B])
line2 = LineString([C, D])
int_pt = line1.intersection(line2)
point_of_intersection = int_pt.x, int_pt.y
print(point_of_intersection)
Ответ 5
Я не нашел интуитивного объяснения в Интернете, так что теперь, когда я это обработал, вот мое решение. Это для бесконечных строк (что мне нужно), а не для сегментов.
Некоторые термины, которые вы, возможно, помните:
Линия определяется как y = mx + b OR y = наклон * x + y-перехват
Наклон = повышение над пробегом = dy/dx = высота/расстояние
Y-перехват - это где линия пересекает ось Y, где X = 0
Учитывая эти определения, вот некоторые функции:
def slope(P1, P2):
# dy/dx
# (y2 - y1) / (x2 - x1)
return(P2[1] - P1[1]) / (P2[0] - P1[0])
def y_intercept(P1, slope):
# y = mx + b
# b = y - mx
# b = P1[1] - slope * P1[0]
return P1[1] - slope * P1[0]
def line_intersect(m1, b1, m2, b2):
if m1 == m2:
print ("These lines are parallel!!!")
return None
# y = mx + b
# Set both lines equal to find the intersection point in the x direction
# m1 * x + b1 = m2 * x + b2
# m1 * x - m2 * x = b2 - b1
# x * (m1 - m2) = b2 - b1
# x = (b2 - b1) / (m1 - m2)
x = (b2 - b1) / (m1 - m2)
# Now solve for y -- use either line, because they are equal here
# y = mx + b
y = m1 * x + b1
return x,y
Здесь простой тест между двумя (бесконечными) строками:
A1 = [1,1]
A2 = [3,3]
B1 = [1,3]
B2 = [3,1]
slope_A = slope(A1, A2)
slope_B = slope(B1, B2)
y_int_A = y_intercept(A1, slope_A)
y_int_B = y_intercept(B1, slope_B)
print(line_intersect(slope_A, y_int_A, slope_B, y_int_B))
Вывод:
(2.0, 2.0)
Ответ 6
Если ваши линии вместо нескольких точек, вы можете использовать эту версию.
![enter image description here]()
import numpy as np
import matplotlib.pyplot as plt
"""
Sukhbinder
5 April 2017
Based on:
"""
def _rect_inter_inner(x1,x2):
n1=x1.shape[0]-1
n2=x2.shape[0]-1
X1=np.c_[x1[:-1],x1[1:]]
X2=np.c_[x2[:-1],x2[1:]]
S1=np.tile(X1.min(axis=1),(n2,1)).T
S2=np.tile(X2.max(axis=1),(n1,1))
S3=np.tile(X1.max(axis=1),(n2,1)).T
S4=np.tile(X2.min(axis=1),(n1,1))
return S1,S2,S3,S4
def _rectangle_intersection_(x1,y1,x2,y2):
S1,S2,S3,S4=_rect_inter_inner(x1,x2)
S5,S6,S7,S8=_rect_inter_inner(y1,y2)
C1=np.less_equal(S1,S2)
C2=np.greater_equal(S3,S4)
C3=np.less_equal(S5,S6)
C4=np.greater_equal(S7,S8)
ii,jj=np.nonzero(C1 & C2 & C3 & C4)
return ii,jj
def intersection(x1,y1,x2,y2):
"""
INTERSECTIONS Intersections of curves.
Computes the (x,y) locations where two curves intersect. The curves
can be broken with NaNs or have vertical segments.
usage:
x,y=intersection(x1,y1,x2,y2)
Example:
a, b = 1, 2
phi = np.linspace(3, 10, 100)
x1 = a*phi - b*np.sin(phi)
y1 = a - b*np.cos(phi)
x2=phi
y2=np.sin(phi)+2
x,y=intersection(x1,y1,x2,y2)
plt.plot(x1,y1,c='r')
plt.plot(x2,y2,c='g')
plt.plot(x,y,'*k')
plt.show()
"""
ii,jj=_rectangle_intersection_(x1,y1,x2,y2)
n=len(ii)
dxy1=np.diff(np.c_[x1,y1],axis=0)
dxy2=np.diff(np.c_[x2,y2],axis=0)
T=np.zeros((4,n))
AA=np.zeros((4,4,n))
AA[0:2,2,:]=-1
AA[2:4,3,:]=-1
AA[0::2,0,:]=dxy1[ii,:].T
AA[1::2,1,:]=dxy2[jj,:].T
BB=np.zeros((4,n))
BB[0,:]=-x1[ii].ravel()
BB[1,:]=-x2[jj].ravel()
BB[2,:]=-y1[ii].ravel()
BB[3,:]=-y2[jj].ravel()
for i in range(n):
try:
T[:,i]=np.linalg.solve(AA[:,:,i],BB[:,i])
except:
T[:,i]=np.NaN
in_range= (T[0,:] >=0) & (T[1,:] >=0) & (T[0,:] <=1) & (T[1,:] <=1)
xy0=T[2:,in_range]
xy0=xy0.T
return xy0[:,0],xy0[:,1]
if __name__ == '__main__':
# a piece of a prolate cycloid, and am going to find
a, b = 1, 2
phi = np.linspace(3, 10, 100)
x1 = a*phi - b*np.sin(phi)
y1 = a - b*np.cos(phi)
x2=phi
y2=np.sin(phi)+2
x,y=intersection(x1,y1,x2,y2)
plt.plot(x1,y1,c='r')
plt.plot(x2,y2,c='g')
plt.plot(x,y,'*k')
plt.show()