Автор вопроса: Victor | Web-сайт:vt-dbnz.narod.ru | ICQ: 345743490
subject=Круг с Antialiasing'ом. Производительность. Sqr()
Пишу все тот же движок для линий напряженности. Решил сделать точки не
пикселями, а кружочками. И притом с антиалиасингом.
И получилось что-то вроде
...
DrawCircle:
maxD = 3.14 * pr * pr
If maxD > 1 Then maxD = 1
If maxD < 0.001 Then Return 'точку не видно будет - не надо рисовать
For ty = Max(0, Int(py + 0.5 - pr)) To Min(-Int(-(py - 0.5 + pr)), h -
1)
For tx = Max(Int(px + 0.5 - pr), 0) To Min(-Int(-(px - 0.5 + pr)),
w - 1)
d = pr - Sqr((tx - px) * (tx - px) + (ty - py) * (ty - py)) +
0.5
If d < 0 Then d = 0
If d > maxD Then d = maxD
Data(tx, ty).rgbBlue = Data(tx, ty).rgbBlue * (1# - d) +
Points(i).Color.rgbBlue * d
Data(tx, ty).rgbGreen = Data(tx, ty).rgbGreen * (1# - d) +
Points(i).Color.rgbGreen * d
Data(tx, ty).rgbRed = Data(tx, ty).rgbRed * (1# - d) +
Points(i).Color.rgbRed * d
Next tx
Next ty
Return
...
, где
Data - массив RGBQUAD'ов, содержащий рисунок на PictureBox
px,py,pr - параметры кружка, в пикселях. тип = Double
Points(i).Color - цвет рисования кружка, типа RGBQUAD.
w,h - ширина, высота рисунка, в пикселях. Тип=long
Переменные:
tx,ty - координаты очередного пикселя в кружке (а иногда и вне него). Типа
Long.
d - прозрачность, с которой рисовать данный пиксель. Типа Double.
MaxD - максимальная прозрачность, которая введена для того, чтобы кружки
маленького радиуса рисовались корректно. Типа Double.
Прошу не осуждать меня за использование устаревшей конструкции GoSub ...
Label ... Return. Просто удобно было написать все это прямо в процедуре
обработки, чтобы быстрее было и чтобы не передавать кучу параметров.
Проблема
Работает медленно, если окружность большого радиуса (почти на весь экран к
примеру). Предположительно из-за использования Sqr.
Как обойти проблему? Подскажите, как сделать вычисление Sqr быстрее или как
вообще от него избавиться.
Попробуй замораживать PictureBox на время рисования.
Кстати, на каком это Васе?!
Если на шестом, то поздравьте меня - я не знал, что он поддерживает Return. Да и способ рисования я что-то не понял - нельзя ли банально circle'ами?
For ty = Max(0, Int(py + 0.5 - pr)) To Min(-Int(-(py - 0.5 + pr)), h -
1)
For tx = Max(Int(px + 0.5 - pr), 0) To Min(-Int(-(px - 0.5 + pr)),
w - 1)
Вынеси из циклов функции Min и Max. Это кончно не панацея, но должно работать побыстрее.
При каждом проходе цикла функции вызыватся, а это очень значительные издержки.
Т.е. сделай оценку перед входом в цикл.
Попробуй замораживать PictureBox на время рисования.
Это как?
При каждом проходе цикла функции вызыватся, а это очень значительные издержки.
Не правда. Точнее, не совсем. Для каждой инициализации цикла они вызываются ровно один раз, во время работы цикла они уже не вызываются. Но действительно, границы чикла по x считаются заново при каждом y, в чем нет необходимости. Я, правда, уверен, что это ни капли не ускорит рисование больших кругов, а именно с ними у меня тормоза.
Да и способ рисования я что-то не понял - нельзя ли банально circle'ами?
У них анти-алиасинга нет. И вообще, когда их много и они мелкие - Circle будет жутко тормозить. Я там на массиве рисую, о пикчербоксе вообще почти не знаю.
Это как?
А че, AutoRedraw у PicBox'a уже не работает? :~)
Все равно не понял, как это замрорзить.
У меня на пикчербокс выбран gdi-объект типа DIB Section, котороый вполне может быть Visual Basic-ом любезно удален при изменении свойства Autoredraw, а на каком массиве рисовать-то тогда?
Короче, пикчербокс морозить не вижу смысла - как от этого поменяется скорость работы с массивом? -никак.
http://alglib.sources.ru/graphics/wucircle.php
Я, кажется, как-то уже пробовал это смотреть. Ничерта не понял. Но можно попробовать еще раз.
Лучше пока ограничиться кружками без anti-alias'а. Их можно рисовать очень быстро (построчно).
Зато это не так круто выглядит. Не видно, как кружок смещается на доли пикселей. В таком случае, я наверно не буду ничего нового делать, просто оставлю пиксели вместо кружков - еще сильно быстрее будет.