2008-09-25 2 views
36

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

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

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

+0

Подробное решение, [см. Здесь] (http://stackoverflow.com/a/17195324/183120). – legends2k 2013-10-19 05:58:15

ответ

72

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

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 
+1

Я продолжаю думать, что должен быть способ избежать этого неприятного sqrt там, возможно, используя линию Брешенема, но я не могу думать об этом. – 2008-09-25 15:29:04

5

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

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

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

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

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

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

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

Для определения знака, считают:

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

Known: точка 2: x2, y2

x21 = x1 - x2 
y21 = y1 - y2 

Известна: расстояние | 1 -> 3 | : Теорема Пифагора

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

Известно:: N/2

уравнение угол 2-1-3: под прямым углом

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

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

уравнение б: скалярное произведение = 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 

уравнения а: решена для 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 

уравнение а: решена для 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 

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

Смежные вопросы