Вот как я это делаю:
Я использую значение с фиксированной точкой с точностью два бита (мы должны управлять половину точками и квадратных значениями половины точек)
Как упоминался в предыдущем ответе, я m также используя квадратные значения вместо квадратных корней.
Во-первых, я определяю границу границы своего круга в 1/8 части круга. Я использую симметричные эти точки, чтобы нарисовать 4 "границы" круга. Затем я рисую квадрат внутри круга.
В отличие от алгоритм окружности окружности, этот будет работать с ровными диаметрами (и с реальными диаметрами чисел тоже с небольшими изменениями).
Пожалуйста, простите меня, если мои объяснения не ясно, я французский;)
void DrawFilledCircle(int circleDiameter, int circlePosX, int circlePosY)
{
const int FULL = (1 << 2);
const int HALF = (FULL >> 1);
int size = (circleDiameter << 2);// fixed point value for size
int ray = (size >> 1);
int dY2;
int ray2 = ray * ray;
int posmin,posmax;
int Y,X;
int x = ((circleDiameter&1)==1) ? ray : ray - HALF;
int y = HALF;
circlePosX -= (circleDiameter>>1);
circlePosY -= (circleDiameter>>1);
for (;; y+=FULL)
{
dY2 = (ray - y) * (ray - y);
for (;; x-=FULL)
{
if (dY2 + (ray - x) * (ray - x) <= ray2) continue;
if (x < y)
{
Y = (y >> 2);
posmin = Y;
posmax = circleDiameter - Y;
// Draw inside square and leave
while (Y < posmax)
{
for (X = posmin; X < posmax; X++)
setPixel(circlePosX+X, circlePosY+Y);
Y++;
}
// Just for a better understanding, the while loop does the same thing as:
// DrawSquare(circlePosX+Y, circlePosY+Y, circleDiameter - 2*Y);
return;
}
// Draw the 4 borders
X = (x >> 2) + 1;
Y = y >> 2;
posmax = circleDiameter - X;
int mirrorY = circleDiameter - Y - 1;
while (X < posmax)
{
setPixel(circlePosX+X, circlePosY+Y);
setPixel(circlePosX+X, circlePosY+mirrorY);
setPixel(circlePosX+Y, circlePosY+X);
setPixel(circlePosX+mirrorY, circlePosY+X);
X++;
}
// Just for a better understanding, the while loop does the same thing as:
// int lineSize = circleDiameter - X*2;
// Upper border:
// DrawHorizontalLine(circlePosX+X, circlePosY+Y, lineSize);
// Lower border:
// DrawHorizontalLine(circlePosX+X, circlePosY+mirrorY, lineSize);
// Left border:
// DrawVerticalLine(circlePosX+Y, circlePosY+X, lineSize);
// Right border:
// DrawVerticalLine(circlePosX+mirrorY, circlePosY+X, lineSize);
break;
}
}
}
void DrawSquare(int x, int y, int size)
{
for(int i=0 ; i<size ; i++)
DrawHorizontalLine(x, y+i, size);
}
void DrawHorizontalLine(int x, int y, int width)
{
for(int i=0 ; i<width ; i++)
SetPixel(x+i, y);
}
void DrawVerticalLine(int x, int y, int height)
{
for(int i=0 ; i<height ; i++)
SetPixel(x, y+i);
}
Чтобы использовать диаметр не целое, то можно увеличить точность неподвижной точки или использовать двойные значения. В зависимости от разницы между dY2 + (луч - x) * (луч - x) и ray2 (dx² + dy² и r²) должно быть возможно сделать какой-то антиалиас
Очень ясно. – dmckee
действительно ли это работает? я попробовал это .. он не полностью заполняет круг. Я что-то упускаю ? В любом случае, есть несколько правильных ответов ниже. – AJed
@AJed Чтобы узнать, если вам что-то не хватает, нам нужно будет увидеть ваш код в [новом вопросе] (http://stackoverflow.com/questions/ask) – AakashM