Рисование сплайнов размером 1 пиксель с алиасами и точным размером пикселя (в частности, Catmull-Rom)

Краткая предыстория: я работаю над веб-приложением для рисования, и мне нужно нарисовать сплайны толщиной 1 пиксель, проходящие через их контрольные точки.

Проблема, с которой я борюсь, заключается в том, что мне нужно нарисовать каждый пиксель между p1 и p2, как если бы я использовал инструмент карандаша 1px. Итак, без сглаживания и по одному пикселю за раз. Это нужно делать вручную без использования какого-либо кода библиотеки линий / кривых, поскольку моя система кистей зависит от наличия пиксельной координаты для нанесения кончика кисти на холст.

По сути, мне нужно объединить шаг на один пиксель из чего-то вроде алгоритма Брезенхема с координатами, возвращаемыми уравнением Катмалла-Рома. У меня проблемы, потому что точки Катмулла-Рома распределены неравномерно (поэтому я не могу просто сказать, что на кривой должно быть 100 пикселей, и запустить уравнение 100 раз). Я попытался использовать приблизительное начальное значение максимума дельт X и Y и заполнить пробелы с помощью Брезенхэма, но из-за округления я все еще получаю некоторые «грязные» участки (т.е. линия явно движется вверх и в сторону верно, но я все равно получаю два пикселя с одним и тем же компонентом Y, что приводит к «толстому» участку линии).

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

РЕДАКТИРОВАТЬ: Вот пример кривой, которую мне, возможно, придется визуализировать:

alt text

Ожидаемый результат может выглядеть так (обратите внимание, что это оценка):

alt text

Используя уравнение сплайна Катмулла-Рома, нам нужно четыре точки для создания сегмента. P0 и P3 используются как касательные для входящего и исходящего направления от сегмента P1-> P2. В сплайне Катмулла-Рома синяя часть - это все, что интерполируется, когда t перемещается от 0 до 1. P0 и P3 могут дублироваться, чтобы обеспечить визуализацию зеленой части, так что для меня это не проблема.

Для простоты мне нужно отрендерить пиксели на кривой между P1 и P2, учитывая, что у меня есть касательные в форме P0 и P3. Мне не обязательно использовать шлицы Катмулла-Рома, но они кажутся правильным инструментом для этой работы, так как контрольные точки должны быть пропущены через них. Неравномерное распределение точек интерполяции - вот что меня зациклило.

EDIT2: Вот пример того, что я имею в виду, когда говорю, что моя результирующая кривая грязная:

alt text

Красные стрелки указывают несколько мест, где не должно быть пикселя. Это происходит из-за того, что вычисляемые компоненты X и Y координаты не изменяются с одинаковой скоростью. Итак, когда каждый из компонентов округляется (так что у меня есть точное местоположение пикселя), может случиться так, что либо X, либо Y не будут увеличены, потому что вычисленная координата, скажем, (42.4999, 50.98). Замена раунда на пол или потолок не решает проблему, просто меняется место, где она возникает.


person Xenethyl    schedule 27.12.2010    source источник
comment
Было бы здорово, если бы вы могли добавить еще один рисунок, показывающий ожидаемый результат от P1 до P2.   -  person Dr. belisarius    schedule 28.12.2010
comment
@belisarius Я не вычислил, какие пиксели будут заполнены на основе уравнения Катмулла-Рома, но второе изображение должно дать вам представление о том, чего я пытаюсь достичь.   -  person Xenethyl    schedule 28.12.2010
comment
Я попросил об этом из-за вашего комментария: но я все еще получаю два пикселя с тем же компонентом Y   -  person Dr. belisarius    schedule 28.12.2010
comment
@belisarius Понятно. Я понимаю, что этот комментарий может сбивать с толку. Это сложно объяснить, не видя проблемы, с которой сталкивается моя текущая реализация, поэтому я прикрепил еще одно изображение. Третье изображение увеличено до 400% из моего приложения. Красные стрелки указывают пиксели, которых не должно быть (доля в компоненте Y была достаточно низкой, чтобы ее нельзя было округлить в большую сторону).   -  person Xenethyl    schedule 28.12.2010
comment
ААА, хорошо. Теперь все понятно. Спасибо!   -  person Dr. belisarius    schedule 28.12.2010


Ответы (1)


Здесь у вас есть документ, описывающий метод повторной параметризации сплайнов в чтобы получить равномерно расположенные точки по длине кривой. Я думаю, это может решить вашу проблему, если вы можете адаптировать ее к кривым Катмулла-Рома (я думаю, это не должно быть слишком сложно)

person Dr. belisarius    schedule 27.12.2010
comment
Спасибо за ссылку на статью. Я не включил длину дуги в свой поиск в Google. Я просто немного больше искал и получил гораздо лучшие результаты (см. ActionScript. org / forum / showthread.php3? t = 213252). Похоже, что принятое решение этой проблемы во многом зависит от приближения и предварительного расчета. Для меня это может вызвать проблемы с производительностью, поскольку это делается в JavaScript. Я мог бы повторно опубликовать свою проблему по-другому после того, как обдумал это, но на данный момент спасибо за помощь. Вы определенно указали мне правильное направление. - person Xenethyl; 28.12.2010
comment
@Xenethyl Рад помочь! Надеюсь, вы сможете оптимизировать его для своего сценария. - person Dr. belisarius; 28.12.2010