Рисование дуги окружности
Есть метод для рисования дуги окружности (там ещё и переливание цвета от одного к другому на протяжении дуги есть), при маленьком радиусе отрисовывается всё нормально, но если задать слишком большой радиус появятся разрывы между каждым пикселем( и чем больше радиус, тем больше пустоты между каждым пикселем). Как исправить этот баг? Возможно надо сделать что-то по типу рисование прямой от одного пикселя до другого, но как это реализовать.
public static void drawCircleAcr(
final GraphicsContext graphicsContext,
final int x,final int y,
final int radius,
final Color startColor,
final Color endColor,
final int startAngle,final int arcAngle)
{
final PixelWriter pixelWriter = graphicsContext.getPixelWriter();
int angle, x1, y1;
for(int i = startAngle; i < arcAngle; i ++)
{
angle = i;
x1 = (int) Math.round(radius * cos(angle * PI / 180));
y1 = (int) Math.round(radius * sin(angle * PI / 180));
double fraction = (double)(i - startAngle) / (double)(arcAngle - startAngle); //отношение разницы между текущим углом и начальным углом дуги к разнице между начальным и конечным углами дуги
Color color = interpolate(startColor, endColor, fraction);
pixelWriter.setColor(x + x1, y + y1, color);
}
}
Пример вызова с нормальной отрисовкой
Rasterization.drawCircleAcr(canvas.getGraphicsContext2D(), 100, 200, 50,Color.BLUE,Color.RED,0,100);
Пример вызова где наблюдается баг
Rasterization.drawCircleAcr(canvas.getGraphicsContext2D(), 100, 200, 300,Color.BLUE,Color.RED,0,100);
Ответы (2 шт):
Шаг угла обратно пропорционален радиусу:
public static void drawCircleAcr(
final GraphicsContext graphicsContext,
final double x, final double y,
final double radius,
final Color startColor,
final Color endColor,
final double startAngle, final double endAngle)
{
final PixelWriter pixelWriter = graphicsContext.getPixelWriter();
double step = (180 / PI) / radius;
for(double angle = startAngle; angle < endAngle; angle += step)
{
double x1 = radius * cos(angle * PI / 180);
double y1 = radius * sin(angle * PI / 180);
double fraction = (angle - startAngle) / (endAngle - startAngle); //отношение разницы между текущим углом и начальным углом дуги к разнице между начальным и конечным углами дуги
Color color = interpolate(startColor, endColor, fraction);
pixelWriter.setColor((int)Math.round(x + x1), (int)Math.round(y + y1), color);
}
}
P.S. Это не значит что Брезенхэм плох. Он хорош, но сложен в программировании и отладке. А это решение решает вашу задачу, устроено просто, написано быстро.
Измените подход. Не рисуйте точки на окружности, а рисуйте линию пиксел за пикселом. От пиксела у вас есть три направления, в которых можно двигаться, соотвественно, три следующих пикселя - выбирайте из них тот, который будет ближе к дуге окружности. Собственно, это и есть алгоритм Брезенхэма для окружности, который хорошо описан в Википедии.
Это была моя первая графическая программа на ассемблере. Тогда не было Википедии, а возжно, и не было самого Брезенхэма :-). Помог школьный курс математики. И обратите внимание, что там не используются тригонометрические функции, квадраты и корни, а используется производная, что приводит к операциям сложения и битового сдвига.

