Алгоритм окружности окружности хорошо подходит для вычисления окружностей, когда их радиус является целым числом.
void CircleOptimized(int xc, int yc, int r, int color) {
unsigned int x= r, y= 0;//local coords
int cd2= 0; //current distance squared - radius squared
if (!r) return;
drawpixel(xc-r, yc, color);
drawpixel(xc+r, yc, color);
drawpixel(xc, yc-r, color);
drawpixel(xc, yc+r, color);
while (x > y) { //only formulate 1/8 of circle
cd2-= (--x) - (++y);
if (cd2 < 0) cd2+=x++;
drawpixel(xc-x, yc-y, color);//upper left left
drawpixel(xc-y, yc-x, color);//upper upper left
drawpixel(xc+y, yc-x, color);//upper upper right
drawpixel(xc+x, yc-y, color);//upper right right
drawpixel(xc-x, yc+y, color);//lower left left
drawpixel(xc-y, yc+x, color);//lower lower left
drawpixel(xc+y, yc+x, color);//lower lower right
drawpixel(xc+x, yc+y, color);//lower right right
}
}
Например, когда переданные r=1
и r=2
выходы выглядят следующим образом:
..... .XXX.
..X.. X...X
.X.X. X...X
..X.. X...X
..... .XXX.
r=1 r=2
Однако мне нужно еще пару шагов между r=1
и r=2
. Возможно (гипотетически) r=1.33
и r=1.66
которые могут выглядеть так:
..... ..... ..X.. .XXX.
..X.. .XXX. .X.X. X...X
.X.X. .X.X. X...X X...X
..X.. .XXX. .X.X. X...X
..... ..... ..X.. .XXX.
r=1.0 r=1.3 r=1.6 r=2.0
Однако, когда я пытаюсь адаптировать алгоритм выше, чтобы использовать арифметику с плавающей запятой (с округлением или без нее), она теряет свою симметрию и генерирует прерывистые пути (приводящие к некоторым очень странным формам).
Есть ли более подходящий алгоритм для моих целей?
Если вас интересуют только простые фракции (например, 4/3 и 5/3), я бы передискретировал (т.е. Использовал субпиксели, здесь 9 субпикселей на пиксели, поэтому вычисляйте круги с радиусом 4 и 5 субпикселей), а затем выведите хорошее значение пикселя из подпикселей. Если вы выходите на что-то еще, кроме ON, OFF, вы делаете сглаживание.
Я думаю, что приближение Тейлора может быть полезным
Основной рисунок круга...
public void DrawCircle(float stepSize, float radius, int colour)
{
float x, y;
float angle;
while (angle < 2*Math.PI)
{
x = radius * cos(angle);
y = radius * sin(angle);
// decide how to round your floating point X,Y here ...
drawpixel(x,y,colour);
angle += stepSize;
}
}
step
и decide how to round
две большие проблемы. Решить их было бы более проблематично, чем адаптировать алгоритм средней точки круга Metink.
step
- это то, насколько гладким вы хотите, чтобы ваш круг был - вы можете придумать масштабирование для шага, основанное на вашем радиусе, если вы беспокоитесь о слишком большом количестве шагов для размера вашего круга. И до тех пор, пока вы decide how to round
единообразно (например, всегда округлять вниз), вы не будете в конечном итоге получать отсоединенные сегменты, которые вы получите с помощью алгоритма окружности средней точки.