Как найти точку на заданном перпендикулярном расстоянии от линии?

У меня есть линия, которую я рисую в окне, и я позволяю пользователю перетаскивать ее. Итак, моя линия определяется двумя точками: (x1, y1) и (x2, y2). Но теперь я хотел бы нарисовать «заглушки» в конце моей линии, то есть короткие перпендикулярные линии в каждой из моих конечных точек. Заглавные буквы должны быть длиной N пикселей.

Таким образом, чтобы нарисовать мою «верхнюю» линию в конечной точке (x1, y1), мне нужно найти две точки, которые образуют перпендикулярную линию, каждая из которых находится на расстоянии N / 2 пикселей от точки (x1, y1).

Итак, как вы вычисляете точку (x3, y3), учитывая, что она должна находиться на перпендикулярном расстоянии N / 2 от конечной точки (x1, y1) известной линии, то есть линии, определяемой (x1, y1) и (x2, y2)?


person AZDean    schedule 25.09.2008    source источник
comment
Подробное разработанное решение см. здесь.   -  person legends2k    schedule 19.10.2013


Ответы (4)


Вам необходимо вычислить единичный вектор, перпендикулярный отрезку линии. Избегайте вычисления наклона, потому что это может привести к делению на ноль ошибок.

dx = x1-x2
dy = y1-y2
dist = sqrt(dx*dx + dy*dy)
dx /= dist
dy /= dist
x3 = x1 + (N/2)*dy
y3 = y1 - (N/2)*dx
x4 = x1 - (N/2)*dy
y4 = y1 + (N/2)*dx
person David Nehme    schedule 25.09.2008
comment
Я продолжаю думать, что должен быть способ избежать этого неприятного sqrt, возможно, используя линию Брешенхема, но я не могу думать об этом сразу. - person Paul Tomblin; 25.09.2008
comment
Я думаю, у вас есть знаковая ошибка в ваших вычислениях или в пунктах 3 и 4. Используйте (+ - - +) или (- + + -) в последних четырех строках, не так ли? - person dmckee --- ex-moderator kitten; 25.09.2008
comment
Разве не dx вместо dy используется для вычисления x3? - person jameswelle; 03.09.2009
comment
Создайте визуализацию формулы на JSFiddle: jsfiddle.net/n2gqw8of Вы можете изменить значения ax, ay и bx, чтобы изменить линию и увидеть, как перпендикулярные линии корректируются соответствующим образом ... - person Kevin Jurkowski; 09.04.2015
comment
@PaulTomblin приблизительное решение - перевернуть линию на 90 градусов, w / (dx,dy)->(-dy,dx); затем масштабируйте его приблизительно на N/L_aprx, где L_aprx = (|dx|+|dy|)*0.83. может быть достаточно хорошо. Длины двух тактов будут (10% (+-10%)) выключены. - person Will Ness; 17.02.2016
comment
Может ли кто-нибудь объяснить, что делает этот псевдокод, я понимаю, что он работает, но мой вопрос в том, как? - person Santhosh; 13.12.2017

Вы просто оцениваете ортогональный вариант и умножаете на N / 2

vx = x2-x1
vy = y2-y1
len = sqrt( vx*vx + vy*vy )
ux = -vy/len
uy = vx/len

x3 = x1 + N/2 * ux
Y3 = y1 + N/2 * uy

x4 = x1 - N/2 * ux
Y4 = y1 - N/2 * uy
person Giacomo Degli Esposti    schedule 25.09.2008

Поскольку векторы от 2 до 1 и от 1 до 3 перпендикулярны, их скалярное произведение равно 0.

Это оставляет вам два неизвестных: x от 1 до 3 (x13) и y от 1 до 3 (y13).

Используйте теорему Пифагора, чтобы получить другое уравнение для этих неизвестных.

Решите для каждого неизвестного путем подстановки ...

Это требует возведения в квадрат и без квадрата, поэтому вы теряете знак, связанный с вашими уравнениями.

Чтобы определить признак, рассмотрите:

while x21 is negative, y13 will be positive
while x21 is positive, y13 will be negative
while y21 is positive, x13 will be positive
while y21 is negative, x13 will be negative

Известно: точка 1: x1, y1

Известно: точка 2: x2, y2

x21 = x1 - x2
y21 = y1 - y2

Известно: расстояние | 1-> 3 | : N / 2

уравнение а: теорема Пифагора

x13^2 + y13^2 = |1->3|^2
x13^2 + y13^2 = (N/2)^2

Известно: угол 2-1-3: прямой угол

векторы 2-> 1 и 1-> 3 перпендикулярны

2-> 1 точка 1-> 3 - 0

уравнение b: скалярное произведение = 0

x21*x13 + y21*y13 = 2->1 dot 1->3
x21*x13 + y21*y13 = 0

соотношение ч / б x13 и y13:

x21*x13 = -y21*y13
x13 = -(y21/x21)y13

x13 = -phi*y13

уравнение a: решено относительно y13 с соотношением

  plug x13 into a
phi^2*y13^2 + y13^2 = |1->3|^2

  factor out y13
y13^2 * (phi^2 + 1) = 

  plug in phi
y13^2 * (y21^2/x21^2 + 1) = 

  multiply both sides by x21^2
y13^2 * (y21^2 + x21^2) = |1->3|^2 * x21^2

  plug in Pythagorean theorem of 2->1
y13^2 * |2->1|^2 = |1->3|^2 * x21^2

  take square root of both sides
y13 * |2->1| = |1->3| * x21

  divide both sides by the length of 1->2
y13 = (|1->3|/|2->1|) *x21

  lets call the ratio of 1->3 to 2->1 lengths psi
y13 = psi * x21

  check the signs
    when x21 is negative, y13 will be positive
    when x21 is positive, y13 will be negative

y13 = -psi * x21

уравнение a: решено относительно x13 с соотношением

  plug y13 into a
x13^2 + x13^2/phi^2 = |1->3|^2

  factor out x13
x13^2 * (1 + 1/phi^2) = 

  plug in phi
x13^2 * (1 + x21^2/y21^2) = 

  multiply both sides by y21^2
x13^2 * (y21^2 + x21^2) = |1->3|^2 * y21^2

  plug in Pythagorean theorem of 2->1
x13^2 * |2->1|^2 = |1->3|^2 * y21^2

  take square root of both sides
x13 * |2->1| = |1->3| * y21

  divide both sides by the length of 2->1
x13 = (|1->3|/|2->1|) *y21

  lets call the ratio of |1->3| to |2->1| psi
x13 = psi * y21

  check the signs
    when y21 is negative, x13 will be negative
    when y21 is positive, x13 will be negative

x13 = psi * y21

уплотнять

x21 = x1 - x2
y21 = y1 - y2

|2->1| = sqrt( x21^2 + y^21^2 )
|1->3| = N/2

psi = |1->3|/|2->1|

y13 = -psi * x21
x13 =  psi * y21

Обычно я бы этого не делал, но я решил это на работе и подумал, что подробное объяснение поможет мне закрепить мои знания.

person user677616    schedule 26.03.2011

Если вы хотите избежать sqrt, сделайте следующее:

in: line_length, cap_length, rotation, position of line centre

define points:
  tl (-line_length/2, cap_length)
  tr (line_length/2, cap_length)
  bl (-line_length/2, -cap_length)
  br (line_length/2, -cap_length)

rotate the four points by 'rotation'
offset four points by 'position'

drawline (midpoint tl,bl to midpoint tr,br)
drawline (tl to bl)
drawline (tr to br)
person Skizz    schedule 25.09.2008