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

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

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

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

Для детально проработанного решения глянь сюда.

legends2k 19.10.2013 09:58
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
51
1
26 775
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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

Я продолжаю думать, что должен быть способ избежать этого неприятного sqrt, возможно, используя линию Брезенхема, но я не могу думать об этом сразу.

Paul Tomblin 25.09.2008 19:29

Я думаю, у вас есть знаковая ошибка в ваших вычислениях или в пунктах 3 и 4. Используйте (+ - - +) или (- + + -) в последних четырех строках, не так ли?

dmckee --- ex-moderator kitten 25.09.2008 19:29

Разве не dx вместо dy используется для вычисления x3?

jameswelle 03.09.2009 08:51

Создайте визуализацию формулы на JSFiddle: jsfiddle.net/n2gqw8of Вы можете изменить значения ax, ay и bx, чтобы изменить линию и увидеть, как перпендикулярные линии корректируются соответствующим образом ...

Kevin Jurkowski 09.04.2015 00:48

@PaulTomblin приблизительное решение было бы перевернуть линию на 90 градусов, w / (dx,dy)->(-dy,dx); затем масштабируйте его примерно на N/L_aprx, где L_aprx = (|dx|+|dy|)*0.83. может быть достаточно хорошо. Длина двух тактов будет отключена от (10% (+-10%)).

Will Ness 17.02.2016 13:31

Может ли кто-нибудь объяснить, что делает этот псевдокод, я понимаю, что он работает, но мой вопрос в том, как?

Santhosh 13.12.2017 12:30

Вы просто оцениваете ортогональный вариант и умножаете на 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

Если вы хотите избежать 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)

Поскольку векторы от 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

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

Другие вопросы по теме