Какой алгоритм используется для вычисления круга с радиусом с плавающей точкой?

0

Алгоритм окружности окружности хорошо подходит для вычисления окружностей, когда их радиус является целым числом.

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

Однако, когда я пытаюсь адаптировать алгоритм выше, чтобы использовать арифметику с плавающей запятой (с округлением или без нее), она теряет свою симметрию и генерирует прерывистые пути (приводящие к некоторым очень странным формам).

Есть ли более подходящий алгоритм для моих целей?

  • 2
    Итак, вы спрашиваете, почему версия кода, которую вы не показываете, не работает? Видите какие-нибудь проблемы здесь? ;-)
  • 0
    В любом случае, весь этот алгоритм основан на целочисленной арифметике. Либо используйте целые числа с масштабированием, либо используйте базовую формулу sin и cos для круга.
Показать ещё 3 комментария
Теги:
geometry

3 ответа

2
Лучший ответ

Если вас интересуют только простые фракции (например, 4/3 и 5/3), я бы передискретировал (т.е. Использовал субпиксели, здесь 9 субпикселей на пиксели, поэтому вычисляйте круги с радиусом 4 и 5 субпикселей), а затем выведите хорошее значение пикселя из подпикселей. Если вы выходите на что-то еще, кроме ON, OFF, вы делаете сглаживание.

0

Я думаю, что приближение Тейлора может быть полезным

  • вычислить x в x ^ 2 = r ^ 2- y ^ 2, используя аппроксимацию Тейлора первого порядка (sqrt (u ^ 2 + a) = u + a/2u)
0

Основной рисунок круга...

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;
    }
}
  • 1
    Найти step и decide how to round две большие проблемы. Решить их было бы более проблематично, чем адаптировать алгоритм средней точки круга Metink.
  • 0
    Итак, step - это то, насколько гладким вы хотите, чтобы ваш круг был - вы можете придумать масштабирование для шага, основанное на вашем радиусе, если вы беспокоитесь о слишком большом количестве шагов для размера вашего круга. И до тех пор, пока вы decide how to round единообразно (например, всегда округлять вниз), вы не будете в конечном итоге получать отсоединенные сегменты, которые вы получите с помощью алгоритма окружности средней точки.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню