Saltar al contenido

Algoritmo de círculo de punto medio para círculos rellenos

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:

ingrese la descripción de la imagen aquí

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.

ingrese la descripción de la imagen aquí

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.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *