Никак не могу найти понятного объяснения алгоритма растеризации закрашенного эллипса, желательно с антиаллиазингом. Единственная статья на эту тему, которую я нашел, была крайне трудна для меня в математическом плане и там было только про круг, у эллипса было написано что-то типа «делается на подобии круга, поэтому оставим вывод алгоритма читателям в качестве задания».
На одном сайте видел упоминание алгоритма Ву, мол он самый крутой и быстрый для этих целей, но само описание алгоритма найти не удалось. В википедии только алгоритм Ву для линии имеется.
Основную часть кода Алгоритма Ву я нашел тут: create.stephan-brumme.com/antialiased-circle/
Заполнение однородным цветом пришлось делать самому. Особенно долго я бился над полупрозрачностью — некоторые пиксели при закраске обрабатывались 2 раза, из-за чего они становились менее прозрачными. Но в итоге удалось сделать с одним прохождением по каждому пикселю!
Нарисовать эллипс очень просто.
Идем построчно, для каждой строки Х известен, решаем уравнение эллипса относительно Y.
Получится два корня, это левая и правая граница закрашиваемой линии на строке Х.
Только нужно помнить, что эти координаты (X, Y) рассчитаны, принимая за начало координат центр эллипса.
Т.е. прежде чем рисовать линию, прибавляем к ним (X0, Y0) — центр эллипса.
Хм, действительно, как-то я не догадался. Я более затратным методом реализовал:
// Это Java
// Уравнение эллипса, если его центр в начале координат: b^2 * x^2 + a^2 + y^2 = a^2 * b^2
// a - радиус по оси X; b - радиус по оси Y
float a2 = a * a;
float b2 = b * b;
float a2b2 = a2 * b2;
for (int y = centerY - b; y <= centerY; y++) {
for (int x = centerX - a; x <= centerX; x++) {
float dx = x - centerX;
float dy = y - centerY;
if (b2 * dx * dx + a2 * dy * dy < a2b2) {
rgb[y][x] = color;
//тут я привел код только для четверти эллипса, остальные три четверти отзеркаливаются
}
}
}
Да, ваш метод будет медленнее, потому что на каждую точку внутри эллипса вместо одной операции (присваивание цвета) требуется целых семь: 4 умножения, сложение, сравнение и присваивание.
Кроме того, многие реализации Canvas рисуют линию одним вызовом гораздо быстрее, чем если закрашивать ее попиксельно.
Если предполагается градиентная растеризация, то есть простор для творчества.
Ведь можно вести градиент от центра к контуру (простейший случай),
можно от отрезка, соединяющего фокусы.
А можно от фокусов по отдельности. Это будет очень красиво, но наверное сложно.