Este artículo ha sido analizado por nuestros especialistas para que tengas la garantía de la exactitud de este post.
Solución:
La respuesta a la otra pregunta está perfectamente bien. Sin embargo, dado que está creando confusión, lo explicaré un poco.
El algoritmo que ves en Wikipedia básicamente encuentra x
y y
de 1/8 de un círculo (ángulos 0 a pi/4
) y luego dibuja 8 puntos que son sus espejos. Por ejemplo:
(o-y,o+x) x x (o+y,o+x)
(o-x,o+y) x x (o+x,o+y) <-- compute x,y
o
(o-x,o-y) x x (o+x,o-y)
(o-y,o-x) x x (o+y,o-x)
Lo que sugiere la otra solución, que tiene mucho sentido si miras de cerca esta imagen, es en lugar de dibujar 8 puntos, dibujar 4 líneas horizontales:
(o-y,o+x) x---------x (o+y,o+x)
(o-x,o+y) x-----------------x (o+x,o+y) <-- compute x,y
o
(o-x,o-y) x-----------------x (o+x,o-y)
(o-y,o-x) x---------x (o+y,o-x)
ahora si calculas (x,y)
para ángulos en [0, pi/4]
y dibuja estas 4 líneas para cada punto calculado, habrás dibujado muchas líneas horizontales llenando un círculo sin que ninguna línea se superponga a la otra.
Actualizar
La razón por la que obtiene líneas superpuestas en la parte inferior del círculo es que el (x,y)
las coordenadas se redondean, por lo que en esos lugares el (x,y)
moverse ellos mismos horizontalmente.
Si echas un vistazo a esta imagen de wikipedia:
Notará que en la parte superior del círculo, algunos píxeles están alineados horizontalmente. Dibujar líneas horizontales que se originan en esos puntos se superponen.
Si no quieres esto, la solución es bastante fácil. Tienes que mantener el anterior. x
con el que ha dibujado (ya que la parte superior e inferior son espejos del original (x,y)
, debe mantener la x anterior que representa la y de esas líneas) y solo dibujar las líneas horizontales si ese valor cambia. Si no es así, significa que estás en la misma línea.
Dado el hecho de que primero encontrará los puntos más internos, debe dibujar líneas para el punto anterior solo si el nuevo punto tiene diferentes x
(por supuesto, la última línea se dibuja siempre). Alternativamente, puede comenzar a dibujar desde el ángulo PI/4 hacia abajo hasta 0 en lugar de 0 a PI/4 y primero encontrará los puntos exteriores, por lo tanto, dibuja líneas cada vez que ve un nuevo x
.
Necesitaba hacer esto, aquí está el código que se me ocurrió. La imagen visual aquí muestra los píxeles dibujados donde el número es el orden en el que se recorren los píxeles, y los números verdes representan los píxeles que se dibujan utilizando el reflejo de la finalización de una columna usando simetría como se muestra en el código.
void drawFilledMidpointCircleSinglePixelVisit( int centerX, int centerY, int radius )
int x = radius;
int y = 0;
int radiusError = 1 - x;
while (x >= y) // iterate to the circle diagonal
// use symmetry to draw the two horizontal lines at this Y with a special case to draw
// only one line at the centerY where y == 0
int startX = -x + centerX;
int endX = x + centerX;
drawHorizontalLine( startX, endX, y + centerY );
if (y != 0)
drawHorizontalLine( startX, endX, -y + centerY );
// move Y one line
y++;
// calculate or maintain new x
if (radiusError<0)
radiusError += 2 * y + 1;
else
// we're about to move x over one, this means we completed a column of X values, use
// symmetry to draw those complete columns as horizontal lines at the top and bottom of the circle
// beyond the diagonal of the main loop
if (x >= y)
startX = -y + 1 + centerX;
endX = y - 1 + centerX;
drawHorizontalLine( startX, endX, x + centerY );
drawHorizontalLine( startX, endX, -x + centerY );
x--;
radiusError += 2 * (y - x + 1);
Se me ocurrió un algoritmo que dibuja el círculo ya lleno.
Itera sobre los píxeles sobre los que se dibujará el círculo y nada más.
De aquí en adelante, todo sobre la velocidad de la función dibujar píxeles.
¡Aquí hay un *.gif que demuestra lo que hace el algoritmo!
En cuanto al algoritmo aquí está el código:
//The center of the circle and its radius.
int x = 100;
int y = 100;
int r = 50;
//This here is sin(45) but i just hard-coded it.
float sinus = 0.70710678118;
//This is the distance on the axis from sin(90) to sin(45).
int range = r/(2*sinus);
for(int i = r ; i >= range ; --i)
int j = sqrt(r*r - i*i);
for(int k = -j ; k <= j ; k++)
//We draw all the 4 sides at the same time.
PutPixel(x-k,y+i);
PutPixel(x-k,y-i);
PutPixel(x+i,y+k);
PutPixel(x-i,y-k);
//To fill the circle we draw the circumscribed square.
range = r*sinus;
for(int i = x - range + 1 ; i < x + range ; i++)
for(int j = y - range + 1 ; j < y + range ; j++)
PutPixel(i,j);
Espero que esto ayude... algunos usuarios nuevos... lo siento por la necro-publicación.
~Shmiggy
Si estás de acuerdo, tienes la habilidad dejar un post acerca de qué le añadirías a esta noticia.