Рисование линий N-ширины? - PullRequest
2 голосов
/ 06 июня 2010

Учитывая серию точек, как я могу вычислить вектор для этой линии на расстоянии 5 пикселей? Пример: Дано:

   \
    \
     \

Как я могу найти вектор для

   \  \
    \  \
     \  \

Те, что справа.

Я пытаюсь выяснить, как такие программы, как Flash, могут делать толстые контуры.

Спасибо

Ответы [ 4 ]

8 голосов
/ 06 июня 2010

Толстая линия - это многоугольник. (Давайте пока забудем о сглаживании)

картинка http://img39.imageshack.us/img39/863/linezi.png

start = начало строки = vector (x1, y1)
конец = строка конец = вектор (x2, y2)
dir = направление линии = конец - начало = вектор (x2-x1, y2-y1)
ndir = нормализованное направление = dir * 1.0 / длина (dir)
perp = перпендикулярно направлению = вектор (dir.x, -dir.y)
nperp = нормализованный перпендикуляр = perp * 1.0 / длина (perp)

perpoffset = nperp * w * 0.5
diroffset = ndir * w * 0.5

(Вы можете легко удалить одну нормализацию и рассчитать одно из смещений, взяв перпендикуляр из другого)

p0, p1, p2, p3 = точки многоугольника:
p0 = start + perpoffset - diroffset
p1 = начало - perpoffset - diroffset
p2 = end + perpoffset + diroffset
p3 = конец - perpoffset + diroffset

P.S. Ты последний человек, которому я собираюсь объяснить это. Подобные вещи следует понимать на интуитивном уровне.

1 голос
/ 06 июня 2010

Попробуйте этот непроверенный псевдокод:

# Calculate the "Rise" and "run" (slope) of your input line, then 
# call this function, which returns offsets of x- and y-intercept
# for the parallel line.  Obviously the slope of the parallel line
# is already known: rise/run.

# returns (delta_x, delta_y) to be added to intercepts.  
adjacent_parallel(rise, run, distance, other_side):
    negate = other_side ? -1 : 1
    if rise == 0:
        # horizontal line; parallel is vertically away
        return (0, negate * distance)
    elif run == 0:
        # vertical line; parallel is horizontally away
        return (negate * distance, 0)
    else:
        # a perpendicular radius is - run / rise slope with length
        # run^2 + rize^2 = length  ^ 2
        nrml = sqrt(run*run + rise*rise)
        return (negate * -1 * run / nrml, negate * rise/nrml)

Как показывает SigTerm на своей симпатичной диаграмме, вы захотите получить линии по обе стороны от намеченной линии: так что введите thickness/2 для расстояния и дважды позвоните, один раз с other_side=true, и нарисуйте толщину с центром «абстрактная линия».

1 голос
/ 06 июня 2010

Способ с прямой линией состоит в том, чтобы найти линию, перпендикулярную (N) к исходной линии, сделать шаг в 5 пикселей в этом направлении и затем найти перпендикуляр к перпендикуляру в этой точке

  |     |
--+-----+---N
  |     |
  |     |

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

0 голосов
/ 06 июня 2010

Вам понадобится математический фон.

Начните с понимания линии (линейные уравнения и линейные функции), что такое параллель , и извлеките выгоду из поиска геометрических преобразований .

После этого вы поймете ответ SigTerm ...

...