Ecco come lo sto facendo:
sto usando i valori a virgola fissa con due bit di precisione (dobbiamo gestire punti e mezzo e valori quadrati di punti e mezzo)
Come citato in una risposta precedente, I' m usando anche valori quadrati invece di radici quadrate.
Per prima cosa, sto rilevando il limite di confine del mio cerchio in una 1/8 della circonferenza. Sto usando simmetrico di questi punti per disegnare i 4 "bordi" del cerchio. Poi sto disegnando il quadrato all'interno del cerchio.
A differenza del cerchio punto medio algoritmo, questo funzionerà anche con diametri (e con numeri reali diametri anche, con alcune piccole modifiche).
prego di perdonarmi se le mie spiegazioni non erano chiari, io sono francese;)
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);
}
Per utilizzare diametro non intero, è possibile aumentare la precisione del punto fisso o utilizzare i valori doppi. Dovrebbe essere possibile creare una sorta di anti-alias a seconda della differenza tra dY2 + (ray-x) * (ray-x) e ray2 (dx² + dy² e r²)
Molto chiaro. – dmckee
funziona davvero? l'ho provato ... non riempie totalmente il cerchio. Mi sto perdendo qualcosa ? In ogni caso, ci sono alcune risposte corrette di seguito. – AJed
@AJed Per sapere se ti manca qualcosa, dovremmo vedere il tuo codice, in [una nuova domanda personale] (http://stackoverflow.com/questions/ask) – AakashM