Страницы

Поиск по вопросам

четверг, 9 января 2020 г.

Как отобразить точки пересечения прямой и границы коники

#python #numpy #геометрия #matplotlib #python_27


Пользуясь данный вопросом: https://stackoverflow.com/questions/57312462/how-to-find-and-draw-the-intersection-points-of-contour-shapes
В случае, когда коника представима в виде гиперболы (p,q,v,k,b=5,7,2,3,4 #hyperbole)
программа выдает точку пересечения между прямой, проходящей через точку V и коникой.
Результат работы программы для гиперболы: 

Однако, в случае, когда коника представлена в виде эллипса (p,q,v,k,b=5,0.7,2,3,4
# ellipse) кроме точек, находящихся на границе коники отображаются точки, находящиеся
внутри эллипса. Результат работы программы для эллипса: 

Мой код: 

import numpy as np
import matplotlib.pyplot as plt

def find_roots(x, y):
   s = np.abs(np.diff(np.sign(y))).astype(bool)
   return x[:-1][s] + np.diff(x)[s] / (np.abs(y[1:][s] / y[:-1][s]) + 1)

# p,q,v,k,b=5,7,2,3,4 #hyperbole

p,q,v,k,b=5,0.7,2,3,4 # ellipse

if(((2 * b * k * p) - (2 * b * k * q) + (k * k) - (b * b * q * q)) > 0):
   print("conic is an ellipse")
elif (((2 * b * k * p) - (2 * b * k * q) + (k * k) - (b * b * q * q)) == 0):
   print("conic is a parabola")
else:
   print("conic is a hyperbole")

X = np.arange(-50, 50, 0.05)

plt.plot(-v, 0)
plt.scatter(-v, 0, color='red', marker='o')
plt.text(-v, 0.8, "V", horizontalalignment="center")

xmin, xmax, ymin, ymax = -10, 10, -10, 10
ax = plt.gca()
ax.get_xlim()
ax.set_xlim([xmin, xmax])
ax.set_ylim([ymin, ymax])
ax.spines['left'].set_position('center')
ax.spines['bottom'].set_position('center')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

x, y = np.meshgrid(X, X)
l = b * x + b * v - v * y
vb = plt.contour(x, y, l, [0], colors='red')

conic = x * x * b * 2 * p * k - x * x * b * 2 * q * k + x * x * k * k + y * y - b
* 2 * y + 2 * b * q * x * y
cnc = plt.contour(x, y, (conic), [0], colors='blue')

c = cnc.collections[0].get_paths()[-1]
v0 = c.vertices
x1 = np.sort(v0[:, 0])
y1 = v0[np.argsort(v0[:, 0]), 1]

vb1 = vb.collections[0].get_paths()[0]
v1 = vb1.vertices
x2 = np.sort(v1[:, 0])
y2 = v1[np.argsort(v1[:, 0]), 1]

x = np.linspace(max(x1.min(), x2.min()), min(x1.max(), x2.max()), 1000)

y1i = np.interp(x, x1, y1)
y2i = np.interp(x, x2, y2) 

x_intersect = find_roots(x, y1i - y2i)
y_intersect = np.interp(x_intersect, x, y1i)

plt.plot(x_intersect, y_intersect, marker="X", ms=5, color="limegreen")

plt.show()


Как можно отобразить только точки пересечения прямой. проходящей через точку V и
 границы коники (эллипса)?
    


Ответы

Ответ 1



Задачу можно значительно упростить если работать с двумерными объектами: def graphs_intersection_pos(g1, g2): return np.argwhere(np.diff(np.sign(g1 - g2))).ravel() def line(x): return v*x + b X = np.arange(-50, 50, 0.05) plt.plot(-v, 0) plt.scatter(-v, 0, color='red', marker='o') plt.text(-v, 0.8, "V", horizontalalignment="center") xmin, xmax, ymin, ymax = -10, 10, -10, 10 ax = plt.gca() ax.get_xlim() ax.set_xlim([xmin, xmax]) ax.set_ylim([ymin, ymax]) ax.spines['left'].set_position('center') ax.spines['bottom'].set_position('center') ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) x, y = np.meshgrid(X, X) l = b * x + b * v - v * y vb = plt.contour(x, y, l, [0], colors='red') conic = x * x * b * 2 * p * k - x * x * b * 2 * q * k + x * x * k * k + y * y - b * 2 * y + 2 * b * q * x * y cnc = plt.contour(x, y, (conic), [0], colors='blue') plt.plot(X, line(X), color="red") # X,Y координаты коники / эллипса / контура coords = cnc.allsegs[0][0] # точки прямой должны соответствовать X значениям эллипса x_line = coords[:, 0] y_line = line(x_line) # находим индексы точек пересечения idx = graphs_intersection_pos(coords[:, 1], y_line) plt.scatter(x_line[idx], y_line[idx], color="green", s=50)

Комментариев нет:

Отправить комментарий