Primitivas

 
Hardware
Modo 13h
Retrazado Vertical
Primitivas
La Paleta
Pantallas Virtuales
Sprites
Tablas Prefedifinidas
Efectos
Texto
Formatos gráficos
Periféricos
Optimizaciones
Herramientas
Cursos
Links
Foro
Correo Electrónico
Las primitivas son dibujos básicos, ya sean líneas, círculos, rectángulos, etc.
Todas las funciones que vayamos a crear, hacen uso de la rutina de poner pixeles PutPixel(), por lo que será esta la rutina que deberá estar mejor optimizada.
 

Círculos
 

Ahora vamos a empezar con una de las rutinas de uso mas frecuente, la de poner círculos en la pantalla. Para poder realizar esto usaremos las ecuaciones de la circunferencia en coordenadas polares que son:

Ecuaciones en coordenadas polares.

Estas ecuaciones serán las que ocuparemos para calcular cada punto (x,y) del círculo, donde el r será obviamente el radio de círculo y q será el angulo que forma el radio con la parte positiva del eje x. En forma gráfica sería así:

Círculo

El ángulo deberá estar en radianes ya que las funciones de seno y coseno que incluye C , trabajan son los ángulos en radianes. La fórmula para transformar grados a radianes es la siguiente:

Transformación de grados a radianes.

Entonces para dibujar el círculo de un radio determinado, solamente tenemos que hacer un ciclo desde 0 hasta 360, pero con incrementos pequeños, calcular cada punto con las ecuaciones en coordenadas polares e ir dibujando cada punto. El ciclo en vez de ir de 0 a 360 ira de 0 a 6.28 (360*3.14/180=6.28) ya que el ángulo debe estar en radianes.
Como dijimos el ciclo de 0 a 6.28 debe hacerse con incrementos pequeños, no contando de uno en uno, ya que para un circulo de radio muy grande, podrían aparecer huecos entre un punto y el siguiente, por lo tanto tenemos que usar un incremento fraccionario. El valor 0.005 produce buenos resultados. Dibujar el círculo punto a punto es una tarea un poco lento, debido a que se debe calcular en cada punto el seno y el coseno del angulo, y estas funcionas son muy lentas. Para solucionar esto  se deben crear tablas predefinidas o precalculadas, pero esto lo podrás ver en la sección correspondiente. 
Ahora veremos como nos quedaría una rutina en lenguaje C para dibujar un círculo en pantalla:
 

void Circle(int cx, int cy, int radio, unsigned char color)
{
    float angulo=0;
    int x, y;

    do
    {
        x = cx + radio * cos(angulo);
        y = cy + radio * sin(angulo);

        if((x>=0) && (y>=0) && (x<320) && (y<200)) 
            PutPixel(x, y , color);

        angulo+=0.005;
     } while(angulo<6.28);
}

Nótese que al calcular las coordenadas x e y, estamos sumándoles las coordenadas cx e cy. Esto se hace para trasladar el centro del círculo a cualquier punto que queramos. De esta forma, para dibujar un círculo solamente tenemos que especificar las coordenadas del centro, el radio y el color del círculo.
La condición que se encuentre antes del PutPixel nos sirve para verificar que las coordenadas que se calculan no se salgan de los bordes de la pantalla. Esta verificación hace que la rutina vaya un poco más lenta. Acuérdense que las funciones cos(), sin() se encuentran en math.h
 

Volver


Razón de aspecto y resoluciones cuadradas
 

Algo que se puede observar, es que nuestros círculos no son exactamente circulares, es decir, están un poco “alargados”. Esto se debe a que no estamos utilizando una resolución cuadrada.

Una resolución cuadrada es aquella en la que la resolución (o número de pixeles) en X es 4/3 de la resolución en Y, ya que esto corresponde con las medidas físicas de la pantalla y ocasiona que los pixeles sean cuadrados. Ejemplos de resoluciones “cuadradas” son 640x480, o 320x240 y 800x600.

Pero nuestra resolución de 320x200 no produce pixeles cuadrados, sino rectángulos que son un poco alargados en el sentido del eje Y.

Si queremos dibujar un círculo perfecto en el modo 320x200, tendríamos que dividir el radio de la coordenada Y por un factor de 1.2 ya que:

Factor de aspecto.

Podemos modificar nuestra función para colocar un círculo ara que dibuje círculos bien proporcionados, solo hay que cambiar la línea que dice:

y = cy + radio * sin(angulo);

por una que diga:

y = cy + radio * sin(angulo) / 1.2;

De esta forma podemos dibujar círculos más “perfectos”, aunque sea un poco más lento, ya que se hace una división extra por cada punto.
 

Volver


Líneas

Muchos pensaran que dibujar líneas es mucho más fácil que hacer un círculo, pero están muy equivocados. Las líneas son más difíciles de dibujar que los círculos, y aun mas difícil es dibujarlas rápido.

La razón principal es que para los círculos ya teníamos las funciones de seno y coseno precalculadas, y el resto es simplemente un ciclo.

Para las líneas es diferente. Primero tenemos que calcular la pendiente de la recta, ver si es positiva o negativa, ver si es mayor o menor que 1, y hasta que tengamos toda esa información podremos dibujar una línea.

Si las líneas son horizontales o verticales no hay ningún problema. Para dibujar una línea horizontal la función sería así: 
 

void LineH(int x, int y, int ancho, unsigned char color)
{
    int i;

    for(i=x; i<=x+ancho; i++)
        PutPixel(i, y, color);
}

Y para hacer la línea vertical:
 

void LineV(int x, int y, int alto, unsigned char color)
{
    int i;

    for(i=y; i<=y+alto; i++)
        PutPixel(x, i, color);
}

Ahora veremos como dibujar un línea si esta tiene cualquier pendiente, es decir esta inclinada hacia algún lado.  Para solucionar esto podemos utilizar la ecuación de la recta que es:

y = pendiente * x

pero nosotros veremos un algoritmo que es muchísimo más eficaz y se conoce con el nombre de ALGORITMO DE BRESENHAM. Este algoritmo se basa en que cuando vamos a colocar un punto, solo hay tres posibles soluciones, (x+1, y) o (x+1, y-1) o (x+1, y+1). El objetivo es trazar una línea entre los puntos (x, y) e (x1, y1). Veamos un ejemplo, si x2 e y2 sin mayores que x1 e y1 entonces calculamos:

longitud_x = abs(x2 - x1);
longitud_y = abs(y2 – y1);

(Nota: la función abs() se refiere al valor absoluto de un número)

entonces tenemos que longitud_x es mayor o igual a longitud_y . Así mediante otras dos variables que representen el punto actual a poner, inicializaremos los valores x1 para x e y1 para y. Como hemos dicho, este algoritmo se basa en ir tomando decisiones, por eso también tendremos que tener otra variable que nos indique la decisión tomada para saber hacia que posicion nos corresponde ir, así sabremos cuando tendremos que sumas uno a la variable Punto_actual_y:

Decision = (longitud_y + longitud_x) – longitud_x;

Punto_actual_x = x1;
Punto_actual_y = y1;

Y lo que tendremos que hacer ahora es tan solo ir repitiendo desde x1 a x2 el ciclo. Deberemos poder adaptar el algoritmo a todos los casos, ya que se puede dar que x1 e y1 sean mayores que x2 e y2, de manera que restaremos en uno en cada paso en vez de sumar. Como esta es muy poro enredado, veremos como nos quedaría la funcion realizada en lenguaje C. Pero antes haremos una función que nos será muy util en la rutina para colocar una línea, y es la siguiente:
 

int sgn(int x)
{
    if(x>0)  return(1);
    if(x<0)  return(-1);
    return (0);
}

la cual nos devuelve simplemente el signo de un número o bien cero.
 

void Line(int x1, int y1, int x2, int y2, unsigned char color)
{
    int i, s, u, v, dx1, dx2, dy1, dy2, m, n;

    u=x2-x1;
    v=y2-y1;
    dx1=sgn(u);
    dy1=sgn(v);
    dx2=sgn(u);
    dy2=0;
    m=abs(u);
    n=abs(v);
    if(!(m>n))
    {
        dx2=0;
        dy2=sgn(v);
        m=abs(v);
        n=abs(u);
    }
    s=m>>2; // s=m/2;
    for(i=0; i<=m; i++)
    {
        PutPixel(x1, y1, color);
        s=s+n;
        if (!(s<m))
        {
          s=s-m;
          x1=x1+dx1;
          y1=y1+dy1;
        }
        else
        {
            x1=x1+dx2;
            y1=y1+dy2;
        }
    }
}


 
Volver


Rectángulos
 

Dibujar un rectángulo es lo más simple que hay, simplemente se trazan dos líneas horizontales y dos verticales. Veamos entonces como nos quedaría el código:
 

void Box(int x1, int y1, int x2, int y2, unsigned char color)
{
      LineV(x2, y1, y2-y1, color); 
      LineV(x1, y1, y2-y1, color);
      LineH(x1, y1, x2-x1, color); 
      LineH(x1, y2, x2-x1, color); 
}

También se pueden crear cuadros rellenos de algún color, esto también es simple, veamos como nos queda:
 

void FillBox(int x, int y, int ancho, int alto, unsigned char color)
{
    int px, py;

    for(px=x; px<=x+ancho; px++)
        for(py=y; py<=y+alto; py++)
          PutPixel(px, py, color);
}


 
Volver


Ejemplos:

A continuación encontrarás varios ejemplos usando las rutinas que vimos:

Librería gráfica: vgalib.h


 
Bajar todos los ejemplos Bajar todos los ejemplos (138 Kb)
Volver

Anterior
Página principal
Siguiente
1
Hosted by www.Geocities.ws

1