Алгоритм рисования линий GDI + - PullRequest
3 голосов
/ 12 октября 2011

Я не могу понять, как GDI + рисует линию на поверхности, возможно, у нее есть какой-то алгоритм для этого.

Например Давайте возьмем поверхность 10х10 пикселей.

  Bitmap img = new Bitmap(10, 10);

Теперь нарисуем линию на этой поверхности шириной 5px и смещением сверху 5px.

  using (var g = Graphics.FromImage(img))
     {
        g.Clear(Color.White);
        var pen = new Pen(Color.Brown);
        pen.Width = 5;
        g.DrawLine(pen, 0F, 5F, 10F,  5F);
     }

Мы получим:

enter image description here

Рисование началось не с пикселя №5, оно началось с пикселя №4. Очевидно, что начальная точка рассчитывается отдельно. Но как?

Я пытался получить регулярность, и получил это:

  y = offset + width/2 - 1

где y - реальная начальная точка y, смещение - выбранная начальная точка y.

Но в некоторых случаях это не работает. Например, давайте возьмем width = 6, выбранное смещение вершины = 0, мы получим y = 2, и оно будет нарисовано так:

enter image description here

Должно отображаться 6 пикселей, но это не так.

Так что должен быть более общий алгоритм выбора начальной точки, но я действительно понятия не имею, что это может быть. Любая помощь приветствуется.

Ответы [ 3 ]

3 голосов
/ 12 октября 2011

На чертеже нет offset. Координаты, указанные вами в методе DrawLine, определяют центр линии. Верхний пиксель y - width / 2, а нижний y - width / 2 + width - 1. Эта вторая формула учитывает тот факт, что width / 2 округляется в меньшую сторону. Кроме того, верхняя строка - y = 0, а нижняя строка - y = 9. Итак, для вас первая строка:

top = 5 - (5 / 2) = 3
bottom = 5 - (5 / 2) + 5 - 1 = 7

и вторая строка:

top = 2 - (6 / 2) = -1
bottom = 2 - (6 / 2) + 6 - 1 = 4

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

1 голос
/ 12 октября 2011

В первом примере это выглядит как линия шириной 5 пикселей с центром в строке 5 (отсчет начинается с 0, а не с 1).Это кажется разумным результатом.

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

0 голосов
/ 12 октября 2011

Координаты в GDI + обозначают не сами пиксели, а (бесконечно малые) точки в их центре.Таким образом, (0f,5f) означает центр пикселя в первом столбце и 6-й строке (поскольку отсчет начинается с нуля).Поэтому теперь я буду различать координаты и строки пикселей .

При рисовании линии GDI + концептуально перемещает перо указанной ширины вдоль линии, определеннойпо этим координатам.Обратите внимание, что вы можете определить точную форму этого пера в начале и конце линии, указав Pen.StartCap и Pen.EndCap.

Поскольку вы указали ширину 5f и вы рисуете горизонтальлиния, линия продолжается 2.5 пикселей вверх и вниз, таким образом покрывая полные строки пикселей от # 3 до (и включая) # 7.Обратите внимание, что верхний край строки # 3 пикселей имеет y-координату 2.5, а нижний край строки # 7 имеет 7.5 в соответствии с приведенным выше определением, которое составляет 5f-2.5f и 5f+2.5f соответственно

Я не получаю тот же результат, что и вы для вашего второго примера (я пробовал в Попробуйте приложение GDI + ).Вместо этого я получаю строку, которая покрывает первые три строки пикселей.Теоретически, он должен даже охватывать первые 3,5 носа (поскольку координата обозначает центр первого ряда, верхняя часть просто обрезается).Но если сглаживание отключено, «половина строки» внизу усекается.

Это можно показать, установив g.SmoothingMode в SmoothingMode.AntiAlias, и в этом случае четвертый ряд будет отображен прозрачно.При использовании сглаживания вы также заметите, что первый и последний столбец не полностью закрашены, поскольку начальная координата снова находится в центре столбца.

...