Вычислить местоположение спроецированной точки (x, y) на заданном начале линии (x, y) и конце (x, y) - PullRequest
2 голосов
/ 21 апреля 2020

Если у меня есть три точки P1, P2, P3 с их координатами (x, y)

P1 (x, y) и P3 (x, y) являются координатами линии (начало, конец) и P3 - это точка, которую необходимо спроецировать.

как я могу найти координату точки r (x, y), которая является проекцией P3 на P1 и P2 enter image description here

Ответы [ 2 ]

2 голосов
/ 21 апреля 2020

Это решение распространяется на точки с любой геометрией c размеров (2D, 3D, 4D, ...). Предполагается, что все точки являются одномерными numpy массивами (или двумерными с одной размерной формой 1). Я не уверен, что вам нужно, чтобы проекция попала на отрезок или расширение отрезка, поэтому я включаю оба. Вы можете выбрать то, что подходит для вашего вопроса лучше всего:

#distance between p1 and p2
l2 = np.sum((p1-p2)**2)
if l2 == 0:
  print('p1 and p2 are the same points')

#The line extending the segment is parameterized as p1 + t (p2 - p1).
#The projection falls where t = [(p3-p1) . (p2-p1)] / |p2-p1|^2

#if you need the point to project on line extention connecting p1 and p2
t = np.sum((p3 - p1) * (p2 - p1)) / l2

#if you need to ignore if p3 does not project onto line segment
if t > 1 or t < 0:
  print('p3 does not project onto p1-p2 line segment')

#if you need the point to project on line segment between p1 and p2 or closest point of the line segment
t = max(0, min(1, np.sum((p3 - p1) * (p2 - p1)) / l2))

projection = p1 + t * (p2 - p1)
1 голос
/ 21 апреля 2020

Numpy код, который работает как для 2D, так и для 3D (на основе https://gamedev.stackexchange.com/questions/72528/how-can-i-project-a-3d-point-onto-a-3d-line):

import numpy as np

def point_on_line(a, b, p):
    ap = p - a
    ab = b - a
    result = a + np.dot(ap, ab) / np.dot(ab, ab) * ab
    return result

A = np.array([2, 0])
B = np.array([4, 4])
P = np.array([1, 3])
projected = point_on_line(A, B, P)
print(projected)

Обновление

Сюжет:

A = np.array([ 10.5, 15.6 ])
B = np.array([ 2, 6 ])
P = np.array([ 18.561, -19.451])

projected = point_on_line(A, B, P) 
print(projected)
# [-3.35411076 -0.04699568]

plt.xlim(-20, 20)
plt.ylim(-20, 20)
plt.axis('equal')

x_values = [A[0], B[0]]
y_values = [A[1], B[1]]

plt.plot(B[0], B[1], 'ro')
plt.plot(A[0], A[1], 'ro')
plt.plot(P[0], P[1], 'ro')
plt.plot(x_values, y_values, 'b-')
plt.plot(projected[0], projected[1], 'rx')

Обновление 2

Если вам нужно, чтобы точка принадлежала сегменту, вам нужно внести небольшую поправку

def point_on_line(a, b, p):
    ap = p - a
    ab = b - a
    t = np.dot(ap, ab) / np.dot(ab, ab)
    # if you need the the closest point belonging to the segment
    t = max(0, min(1, t))
    result = a + t * ab
    return result
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...