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





Вам необходимо вычислить единичный вектор, перпендикулярный отрезку линии. Избегайте вычисления наклона, потому что это может привести к делению на ноль ошибок.
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, возможно, используя линию Брезенхема, но я не могу думать об этом сразу.
Я думаю, у вас есть знаковая ошибка в ваших вычислениях или в пунктах 3 и 4. Используйте (+ - - +) или (- + + -) в последних четырех строках, не так ли?
Разве не dx вместо dy используется для вычисления x3?
Создайте визуализацию формулы на JSFiddle: jsfiddle.net/n2gqw8of Вы можете изменить значения ax, ay и bx, чтобы изменить линию и увидеть, как перпендикулярные линии корректируются соответствующим образом ...
@PaulTomblin приблизительное решение было бы перевернуть линию на 90 градусов, w / (dx,dy)->(-dy,dx); затем масштабируйте его примерно на N/L_aprx, где L_aprx = (|dx|+|dy|)*0.83. может быть достаточно хорошо. Длина двух тактов будет отключена от (10% (+-10%)).
Может ли кто-нибудь объяснить, что делает этот псевдокод, я понимаю, что он работает, но мой вопрос в том, как?
Вы просто оцениваете ортогональный вариант и умножаете на 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
Обычно я бы этого не делал, но я решил это на работе и подумал, что подробное объяснение поможет мне закрепить мои знания.
Для детально проработанного решения глянь сюда.