Sie sind auf Seite 1von 83

Técnicas de Realidad Virtual

Unidad II

Computación gráfica

Semana 8

Primitivas gráficas y algoritmos


Objetivo General

Analizar el conjunto de principios y


técnicas usadas en los sistemas de
realidad virtual y visualización.
Objetivo Específico

Exploración y diseño de modelos 3D para


la visualización de imágenes
Objetivo Instruccional

Comprender los factores relacionados


con el uso de primitivas graficas y
algoritmos de implementación.
Dibujo de puntos

Algoritmos comunes de trazo de rectas


Contenidos

Algoritmos comunes de trazo de círculos

Otras primitivas

Uso de primitivas de biblioteca

Princípios de animación

Mejora de la animación
La pantalla gráfica
Máxima x – 1
Dibujo de puntos

x = 0, y = 0

Máxima y – 1

x = Máxima x – 1
y = Máxima y – 1
Dibujo de puntos en C y Java
C
Dibujo de puntos

La función putpixel(int x, int y, int color) dibuja un


punto en la coordenada x,y con el color especificado.
Ejemplo: putpixel(50,25,7) dibuja un punto color gris en la
coordenada 50,25.

Java
En Java se dibuja en un objeto de la clase Graphics. No tiene una función
para dibujar puntos pero puede usarse:
Graphics g;
g.drawLine(50,25,50,25);
Ejemplo 1
Dibujo de puntos

#include <iostream>
#include <graphics.h>

using namespace std;

int main(int argc, char *argv[])


{
int i;
initwindow(400, 300);
for(i = 0; i< 1000; i++){
putpixel(rand()%400,rand()%300,rand()%15+1);
}
system("PAUSE");
closegraph();
return EXIT_SUCCESS;
}
Trazo de líneas rectas paralelas a
los ejes
Dibujo de puntos

La línea recta es la más fácil de dibujar


Las líneas rectas paralelas a los ejes se pueden trazar un un
simple lazo for.

El siguiente código traza un línea horizontal desde x a x+ancho.

for(i = x; i < x+ancho; i++)


putpixel(i,y,color);

De forma similar se traza un línea vertical


Ejemplo
#include <iostream>
#include <graphics.h>

using namespace std;


Dibujo de puntos

void lineaH(int x1, int x2,int y, int color){


int dx;
dx = x2>x1?x2-x1:x1-x2;
for(int i=0;i<dx;i++)
putpixel(x1+i,y,color);
}

int main(int argc, char *argv[])


{
int i;
initwindow(400, 300);
for(i = 0; i< 1000; i++){
lineaH(rand()%100,rand()%300,rand()%300,rand()%15+1);
}
getch();
closegraph();
return EXIT_SUCCESS;
}
Dibujo de Líneas Rectas
Una línea recta debe dibujarse como una sucesión de píxeles.
Dibujo de puntos

Efecto de escalera que se produce cuando se genera una línea


como una serie de píxeles.
Algoritmos comunes de trazos de líneas
Algoritmos para trazo de líneas
rectas

•Algoritmo DDA, algoritmo incremental básico


con aritmética de punto flotante.

•Algoritmo de Bresenham, algoritmo


incremental complejo con sólo aritmética
entera.
Algoritmos comunes de trazos de líneas
Algoritmo DDA

Ecuación básica de la recta


y  m x  b
m es la pendiente y b la intersección con el eje y

y2  y1
m b  y1  m  x1
x2  x1
Algoritmos comunes de trazos de líneas

Para cualquier intervalo Dx de x a lo largo de la recta,


se puede calcular el Dy correspondiente como:

Dy  m  Dx

Si la pendiente es positiva y menor que 1, se toman


variaciones de x iguales a 1 y se calcula y con:

yi 1  yi  m
Las rectas con pendiente mayor que 1, se invierten
los papeles de x y de y.
Algoritmos comunes de trazos de líneas void dda(int x1,int y1,int x2,int y2,int color){
int dx,dy,steps,k;
float x_increment,y_increment,x,y;
dx = x2-x1;
dy = y2-y1;
if(abs(dx)>abs(dy))
steps = abs(dx);
else
steps = abs(dy);
if(steps==0)
steps = 1;
x_increment = (float)dx/steps;
y_increment = (float)dy/steps;
x = x1;
y = y1;
putpixel((int)x,(int)y,color);
for(k = 1;k <=steps ;k++){
x = x+x_increment;
y = y+y_increment;
putpixel((int)x,(int)y,color);
}
}
Algoritmos comunes de trazos de líneas
Algoritmo de línea de Bresenham

Sección de una pantalla Trayectoria de la línea especificada


de despliegue donde se
desplegará un segmento 13
12
rectilíneo, comenzando
desde la posición (10, 11
10). Las posiciones de los 10
pixeles se representan por 9
las áreas rectangulares 10 11 12 13 14
numeradas.
Algoritmos comunes de trazos de líneas

Trayectoria de la línea especificada

Sección de una pantalla de 13


despliegue donde se 12
desplegará un segmento
11
rectilineo con pendiente
negativa, comenzando desde 10

la posición (10, 12). 9


10 11 12 13 14

El siguiente pixel que se grafique en cada uno de estos


ejemplos será aquel cuyo valor de y esta más próximo a la
posición real de y sobre la recta.
Algoritmos comunes de trazos de líneas
Sección de una retícula de la y = mx + b

pantalla donde se desplegará


una línea que pasará por:

x , y 
y +2
i
i i y +1
i
y
De aquí se tiene que: i

y  m xi  1  b x
i
x +1 x +2
i i

Definimos:

d1  y  yi d 2   y i  1  y
 m xi  1  b  y i  y i  1  m x i  1  b
Algoritmos comunes de trazos de líneas
la diferencia es
d2  d1  2m xi  1  2 yi  2b  1
Definimos pi como:

pi  Dx ( d1  d 2 )
 2 Dy  xi  2 Dx  yi  c
donde c es:
c  2Dy  Dx 2b  1
Obtenemos pi+1 de pi como:

pi 1  2Dy  xi 1  2Dx  yi 1  c
Algoritmos comunes de trazos de líneas

Restando pi+1 y pi:

pi1  pi  2Dy xi1  xi   2Dx yi1  yi 

Simplificando:

pi1  pi  2Dy  2Dx yi1  yi 

El parámetro inicial es:

p1  2Dy  Dx
Algoritmos comunes de trazos de líneas
1. De como entrada los extremos de la línea. Almacene el punto
del extremo izquierdo en (x1, y1) y el derecho en (x2, y2).
2. El primer punto que se selecciona para desplegar es el punto
del extremo izquierdo(x1, y1).
3. Calcule Dx = x2 - x1, Dy = y2 - y1 y p1 = 2 Dy - Dx. Si p1 = 0, el
siguiente punto será (x1 +1, y1), sino será (x1 +1, y1 +1).
4. Incremente x en 1. Se seleccionará yi o yi +1 dependiendo si pi
 0 o pi  0. En el primer caso
pi 1  pi  2Dy

pi1  pi  2Dy  Dx


y en el segundo

5. Repita hasta que x llegue a x2.


Algoritmos comunes de trazos de líneas void BresLine(int x1,int y1,int x2,int y2,int
color){
int xerr,yerr,deltax,deltay,dist,incx,incy,i;
xerr = 0;
yerr = 0;
deltax = x2-x1;
deltay = y2-y1;
if(deltax>0) Función en C para dibujar rectas con
incx = 1; cualquier pendiente.
else
if(deltax==0)
incx = 0;
else
incx = -1;
if(deltay>0)
incy = 1;
else
if(deltay==0)
incy = 0;
else
incy = -1;
deltax = abs(deltax);
Algoritmos comunes de trazos de líneas
deltay = abs(deltay);
if(deltax>deltay)
dist = deltax;
else
dist = deltay;
for(i = 0; i<=dist+1;i++){
putpixel(x1,y1,color);
xerr = xerr+deltax;
yerr = yerr+deltay;
if(xerr>dist){
xerr -= dist;
x1 += incx;
}
if(yerr>dist){
yerr -= dist;
y1 += incy;
}
}
}
Algoritmos comunes de trazos de líneas
Primitivas básicas en C
Define el color de la pluma
void setcolor (int color);

Regresa el color de la pluma actual


int getcolor (void);

Pone color de fondo


void setbkcolor(int color);

Regresa el color de fondo actual


int getbkcolor(void);

Borra el puerto de visión actual


clearviewport (void);
Algoritmos comunes de trazos de líneas
Primitivas de líneas en C
Dibuja línea entre (x1,y1) y (x2,y2)
void line (int x1, int y1, int x2, int y2);

Dibuja línea relativa al cursor gráfico


void linerel (int dx, int dy);

Dibuja línea desde el cursor gráfico a (x,y)


void lineto (int x, int y);

Mueve cursor gráfico en forma relativa


void moverel (int dx, int dy);

Mueve cursor gráfico en forma absoluta


void moveto (int x, int y);
Algoritmos comunes de trazos de líneas
Polígono con line
void poligono(int x, int y, int r,int c,
int n){ x,y
/*dibuja un polígono regular de n lados con
centro en x,y inscrito en un círculo de r a
a  p/n
radio r y de color c*/
float PI = 3.1415926535;
float a = PI/2-PI/n;
int x1 = (int)(x-r*cos(a)); x – r cos(a), y + r sin(a)
int y1 = (int)(y+r*sin(a));
putpixel(x,y,c);
setcolor(c);
for(int i = 2; i<=n+1;i++){
a = a+2*PI/n;
int x2 = (int)(x-r*cos(a));
int y2 = (int)(y+r*sin(a));
line(x1,y1,x2,y2);
x1 = x2;
y1 = y2;
}
}
Algoritmos comunes de trazos de líneas
Polígono con linerel
void poligono(int x,int y,int n, int
d,int color){
int x0=x,y0=y,x1=x,y1=y,k;
double a=0,da=2*3.14159265358979/n;
moveto(x0,y0);
for(k = 0;k <n-1 ;k++){
x1 = (int)(x1+d*cos(a)); x,y d
y1 = (int)(y1+d*sin(a));
a = a+da;
lineto(x1,y1);
}
lineto(x0,y0);
}
Algoritmos comunes para trazos de círculos
Algoritmos de generación de
circunferencias

La ecuación de la circunferencia
en coordenadas rectangulares es x  xc2   y  yc 2  r2

De ésta se puede despejar y


r
como sigue:
yc

y  yc  r 2   x  xc
2

xc
Función en C
Algoritmos comunes para trazos de círculos

void PlotPoint(int xc, int yc, void CircleSimple(int xc, int yc, int
int x, int y,int c) r,int c){
{ int x,y;
putpixel(xc + x,yc + y,c); double yr;
putpixel(xc - x,yc + y,c); x = 0;
putpixel(xc + x,yc - y,c); y = r;
putpixel(xc - x,yc - y,c); yr = r;
putpixel(xc + y,yc + x,c); PlotPoint(xc,yc,x,y,c);
putpixel(xc - y,yc + x,c); /* se cicla hasta trazar todo un
putpixel(xc + y,yc - x,c); octante */
putpixel(xc - y,yc - x,c); while (x < yr){
} x = x + 1;
yr = sqrt(r*r-x*x);
y = (int)round(yr);
PlotPoint(xc,yc,x,y,c);
}
}
Círculo básico en Java
Algoritmos comunes para trazos de círculos

void CircleSimple(Graphics g, int xc, int yc, int r){


int x,y;
double yr;
x = 0;
y = r;
yr = r;
PlotPoint(x,y);
/* se cicla hasta trazar todo un octante */
while (x < yr){
x = x + 1;
yr = Math.sqrt(r*r-x*x);
y = (int)Math.round(yr);
PlotPoint(x,y);
}
}
Algoritmos comunes para trazos de círculos
Algoritmo de circunferencia de
Bresenham

Se supone (xi, yi) la posición más próxima a la trayectoria, la


siguiente posición es por tanto (xi+1, yi) o bien (xi+1, yi-1).
x x +1 x +2
i i i

y
i

y -1
i

y -2
i

2 2 2
x + y = r
Una medida de la diferencia de coordenadas puede definirse
Algoritmos comunes para trazos de círculos

como:
d1  y i2  y 2
y
 y i2  r 2   x i  1
2 i
y d
1
d
d 2  y   y i  1
2 2
2 y - 1
i

 r   x i  1   y i  1
2 2 2
x + 1
i

Definiendo pi como la diferencia de d1 y d2 tenemos

pi  d1  d 2
 2 x i  1  y   y i  1  2r 2
2 2 2
i
Algoritmos comunes para trazos de círculos

El valor de pi+1 es:

 
pi1  2  xi  1  1  y   yi1  1  2r
2 2
2 2
i 1

Simplificando

pi1  pi  4xi  6  2 yi21  yi2   2 yi1  yi 

p1 se obtiene de (x1, y1) = (0, r)

p1  3  2r
1. Seleccione la primera posición como
 x , y   0, r
Algoritmos comunes para trazos de círculos

1 1

2. Calcule el primer parámetro como


p1  3  2r
si pi <0, la siguiente posición es (xi+1, yi), si no es (xi+1, yi-1)
3. Incremente x en 1. Seleccione pi+1 si pi <0 como

pi 1  pi  4 xi  6
y en caso contrario
pi1  pi  4 xi  yi   10
si pi+1 <0 el siguiente punto será(xi+2, yi+1). De lo contrario es (xi+2, yi+1 –
1). La coordenada y es yi+1=yi, si pi <0 o bien yi+1= yi–1 si pi  0.
4. Repita el paso 3 hasta que x y y sean iguales.
Algoritmos comunes para trazos de círculos
Algoritmo de punto medio para la
circunferencia
El método de trazo del punto medio de la circunferencia se basa en la
definición de la función circunferencia:

f circunferencia x, y   x 2  y 2  r 2

Un punto (x,y) arbitrario cumple con lo siguiente

 0, si  x , y  está dentro de la circunferencia



f circunferencia  x , y     0, si  x , y  está en la frontera de la circunferencia
  0, si  x , y  está fuera de la circunferencia

Para decidir entre el punto (xk+1, yk) y (xk+1, yk-1) se utiliza la
Algoritmos comunes para trazos de círculos

fórmula anterior evaluada en el punto medio entre los dos pixeles


pk  f circunferencia  x k  1, y k  1 2

  x k  1   y k  1 2  r 2
2 2

Si pk<0 el punto está dentro de la circunferencia y el pixel (xk+1,


yk) es el más próximo a la frontera. Sino, el punto está fuera y el
más cercano es (xk+1, yk-1).

Obtendremos una expresión recursiva para el siguiente parámetro


de decisión cuando evaluamos la función de circunferencia en la
posición xk +1 = xk +2.
pk  f circunferencia  x k 1  1, y k 1  1 2
Algoritmos comunes para trazos de círculos

 
  x k  1  1   y k 1  1 2  r 2
2 2

o
pk 1  pk  2 xk  1   yk21  yk2    yk 1  yk   1

Si pk<0, el incremento es 2xk +1 + 1. Sino el incremento es 2xk


– 2yk +1 +1. Los valores xk +1 y yk +1 se pueden calcular con:
2 yk 1  2 yk  2
2 xk 1  2 xk  2
El valor inicial es: 5
p0   r
4
Punto medio en C
Algoritmos comunes para trazos de círculos

void CircleMidPoint(int xc, int yc, int r, int c){


int x, y, p;
x = 0;
y = r;
p = 1 - r;
PlotPoint(xc,yc,x,y,c);
/* se cicla hasta trazar todo un octante */
while (x < y){
x = x + 1;
if (p < 0)
p = p + 2*x + 1;
else {
y = y - 1;
p = p + 2*(x - y) + 1;
}
PlotPoint(xc,yc,x,y,c);
}
}
Punto medio en Java
Algoritmos comunes para trazos de círculos

void CircleMidPoint(Graphics g, int xc, int yc, int r){


int x, y, p;
x = 0;
y = r;
p = 1 - r;
PlotPoint(g,xc,yc,x,y);
/* se cicla hasta trazar todo un octante */
while (x < y){
x = x + 1;
if (p < 0)
p = p + 2*x + 1;
else {
y = y - 1;
p = p + 2*(x - y) + 1;
}
PlotPoint(g,xc,yc,x,y);
}
}
Círculos en C
Algoritmos comunes para trazos de círculos

Dibuja un círculo
void circle (int x, int y, int r);

Dibuja un arco de circulo


Void arc (int x,int y,int stangle,int endangle,int radius );

Dibuja una elipse


void ellipse(int x, int y, int stangle, int endangle, int xradius,
int yradius);

Regresa las coordenadas del último arco dibujado


void getarccoords(struct arccoordstype *arccoords);
Estructura utilizada por getarccoords
struct arccoordstype { int x, y; int xstart, ystart, xend, yend; };
Ejemplo
Algoritmos comunes para trazos de círculos

#include <iostream>
#include <graphics.h>

using namespace std;

main(){
arccoordstype arco;
initwindow(300,300);
circle(100,100,50);
ellipse(200,100,45,270,50,100);
arc(200,200,0,135,50);
getarccoords(&arco);
cout << "x=" << arco.x << "\n";
cout << "y=" << arco.y << "\n";
cout << "xinicio=" << arco.xstart << "\n";
cout << "yinicio=" << arco.ystart << "\n";
cout << "xfin=" << arco.xend << "\n";
cout << "yfin=" << arco.yend << "\n";
getch();
return 0;
}
Rectángulos rellenos

Los rectángulos rellenos pueden generarse fácilmente


Otras primitivas

haciendo un barrido de líneas de rastreo desde la primera


coordenada y a la segunda. El siguiente código hace este
trabajo:

void Rectangulo(int x1,int y1,int x2,int


y2){
int i;
for(i = y1;i<=y2; i++)
line(x1, i, x2, i);
}
Relleno de polígonos: el relleno opera calculando los tramos que
se hallan entre la arista de la izquierda y la derecha del polígono.
Otras primitivas

El algoritmo requiere conservar una lista ordenada respecto a y


de las aristas activas en cada fase del proceso.
Recorte de círculos: Se puede recortar todo el círculo respecto a
un rectángulo. Si el círculo lo intercepta, se divide en cuadrantes
y se aplica la prueba de aceptación o rechazo trivial para cada
uno. También se aceptar y rechazar a nivel de píxel..
Texto: el texto puede definirse mediante mapas de bits para cada
conjunto de caracteres. Se dibuja usando la función CopyPixel
del sistema.
Otras primitivas en C
void bar (int left, int top, int right, int bottom);
void bar3d (int left, int top, int right, int bottom,
int depth, int topflag);
Otras primitivas

void drawpoly (int numpoints, int *polypoints);


void fillellipse (int x, int y, int xradius, int
yradius);
void fillpoly (int numpoints, int *polypoints);
void floodfill (int x, int y, int border);
void pieslice (int x, int y, int stangle, int endangle,
int radius);
void rectangle (int left, int top, int right, int
bottom);
void sector (int x, int y, int stangle, int endangle,
int xradius, int yradius);
void setfillpattern (char *upattern, int color);
void setfillstyle (int pattern, int color);
void setlinestyle (int linestyle, unsigned upattern,
int thickness);
Algoritmo pastel
Otras primitivas

Algoritmo para dibujar un diagrama de pastel.


1. Iniciar ang = 0
2. Sum = suma de valores a representar
3. Para todos los valores hacer
4. Poner color del sector
5. Dibujar sector desde ang/suma*360 hasta
(ang + valor) /suma*360
6. Incrementar ang en valor
7. Fin para
Ejemplo, diagrama de pastel
#include <graphics.h>
void pastel(int n, float *a, int x, int y, int r){
float suma = 0,ang = 0;
Otras primitivas

int i;
for(i = 0; i<n; i++)
suma +=a[i];
for(i = 0; i<n; i++){
setfillstyle(1,i+1);
sector(x,y,(int)(ang/suma*360),(int)((ang+a[i])/suma*360),r,r);
ang += a[i];
}
}
main(){
float a[]={25.3,35.2,56.1,48.7,13.6};
initwindow(200,200);
pastel(5,a,100,100,60);
getch();
return 0;
}
Uso de primitivas de biblioteca
Primitivas de texto en C
Despliega una cadena de texto en la posición del CP
void outtext (char *textstring);
Despliega una cadena en la coordenada x,y
void outtextxy (int x, int y, char *textstring);
Define el tipo de justificación para el texto
void settextjustify (int horiz, int vert);
Define la fuente, dirección y el tamaño del texto
void settextstyle (int font, int direction, int
charsize);
Define el tamaño del texto
void setusercharsize (int multx, int divx, int multy,
int divy);
Regresa el alto de una cadena de texto
int textheight (char *textstring);
Regresa el ancho de una cadena de texto
int textwidth (char *textstring);
Uso de primitivas de biblioteca
Primitivas de texto en C cont.
Constantes de texto
Justificación vertical:

LEFT_TEXT, CENTER_TEXT, RIGHT_TEXT

Justificación horizontal:

BOTTOM_TEXT, VCENTER_TEXT, TOP_TEXT

Fuentes:

DEFAULT_FONT, TRIPLEX_FONT, SMALL_FONT,


SANS_SERIF_FONT, GOTHIC_FONT, SCRIPT_FONT,
SIMPLEX_FONT, TRIPLEX_SCR_FONT, COMPLEX_FONT,
EUROPEAN_FONT, BOLD_FONT
Uso de primitivas de biblioteca
Primitivas de texto en C cont.
Tipos
struct textsettingstype
{
int font; // la fuente en uso
int direction; // dirección del Texto
int charsize; // tamaño del carácter
int horiz; // justificación Horizontal
int vert; // justificación Vertical
};

void gettextsettings(struct textsettingstype


*texttypeinfo);
Uso de primitivas de biblioteca
Primitivas de texto en C cont.
Otras formas de desplegar texto
Flujo de salida gráfico:

std::ostringstream bgiout;

Igual a outtext:

outstream(std::ostringstream& out=bgiout);

Igual a outtextxy:

outstreamxy(int x, int y, std::ostringstream&


out=bgiout);
Uso de primitivas de biblioteca
ejemplo
/* outtext example */
#include <graphics.h>
int main(void){
/* request autodetection */
int midx, midy;
/* initialize graphics and local variables */
initwindow(300,100);
midx = getmaxx() / 2;
midy = getmaxy() / 2;
/* move the CP to the center of the screen */
moveto(midx, midy);
/* output text starting at the CP */
outtext("This ");
outtext("is ");
outtext("a ");
outtext("test.");
/* clean up */
getch();
closegraph();
return 0;
}
/* settextstyle example */
Uso de primitivas de biblioteca #include <graphics.h>
/* the names of the text styles supported */
char *fname[] = { "DEFAULT font", "TRIPLEX font",
"SMALL font", "SANS SERIF_font",
"GOTHIC_font", "SCRIPT font",
"SIMPLEX font", "TRIPLEX SCRIPT font",
"COMPLEX font", "EUROPEAN font",
"BOLD font"};
int main(void){
/* request autodetection */
int style, midx, midy;
int size = 1;
/* initialize graphics and local variables */
initwindow(600,200);
midx = getmaxx() / 2;
midy = getmaxy() / 2;
settextjustify(CENTER_TEXT, CENTER_TEXT);
for (style=DEFAULT_FONT; style<=BOLD_FONT; style++) {
cleardevice();
if (style == TRIPLEX_FONT)
size = 4;
/* select the text style */
settextstyle(style, HORIZ_DIR, size);
/* output a message */
outtextxy(midx, midy, fname[style]);
getch();
}
closegraph();
return 0;
}
Uso de primitivas de biblioteca
Atributos de las primitivas en bgi

• Atributos de línea
• Atributos de relleno
• Atributos de caracteres
Uso de primitivas de biblioteca
Atributos de líneas

En bgi existen tres atributos para


las líneas
• color
• grosor
• patrón
Uso de primitivas de biblioteca Color
El color se establece con setcolor(int color).
Existen 16 colores predefinidos, del 0 al 15:
BLACK BLUE GREEN CYAN
RED MAGENTA BROWN LIGHTGRAY
DARKGRAY LIGHTBLUE LIGHTGREEN LIGHTCYAN
LIGHTRED LIGHTMAGENTA YELLOW WHITE
La función COLOR(r, g, b) permite obtener cualquier color dados los
valores las componentes de rojo, verde y azul.la función converttorgb(c)
convierte a RGB de Windows.
RED_VALUE(v) – regresa el valor de rojo de un color
GREEN_VALUE(v) – regresa el valor de verde de un color
BLUE_VALUE(v) – regresa el valor de azul de un color
IS_BGI_COLOR(v) – regresa verdadero si el color es BGI
IS_RGB_COLOR(v) – regresa verdadero si el color es RGB
Uso de primitivas de biblioteca
Grosor y patrón
Existen dos grosores de línea predefinidos, pero puede usarse cualquier
valor:
NORM_WIDTH 1
THICK_WIDTH 3
Los patrones de línea son:
SOLID_LINE, DOTTED_LINE, CENTER_LINE,
DASHED_LINE, USERBIT_LINE
La función:
setlinestyle(int linestyle,unsigned upattern,int
thickness );
Establece el tipo de línea. El patrón definido por el usuario se establece con
el entero sin signo upattern, cada bit de este entero de 16 bits especifica si
se pinta o no un pixel.
Uso de primitivas de biblioteca
Patrones de relleno de áreas
Para relleno de áreas existen los siguientes patrones predefinidos:

EMPTY_FILL, SOLID_FILL, LINE_FILL, LTSLASH_FILL,


SLASH_FILL, BKSLASH_FILL, LTBKSLASH_FILL,
HATCH_FILL,
XHATCH_FILL, INTERLEAVE_FILL, WIDE_DOT_FILL,
CLOSE_DOT_FILL, USER_FILL

La función setfillstyle(int pattern,int color) define el


patrón de relleno y el color.
El relleno definido por el usuario se establece con setfillpattern(
char *upattern,int color) el patrón de 8x8 se define mediante un
arreglo de 8 caracteres. El siguiente ejemplo rellena con corazoncitos:

char pattern[] =
{0x66,0x99,0x81,0x81,0x42,0x24,0x18,0x00};
setfillpattern( pattern, 15 );
bar(200,200,300,300);
Uso de primitivas de biblioteca Funciones de manejo de
ventanas
Se pueden crear varias ventanas de despliegue. La
función initwindow(), regresa un entero que
permite identificar cada ventana.
Para establecer la ventana actual se utiliza
setcurrentwindow(int window);
Para determinar la ventana que está en uso se utiliza:
getcurrentwindow();
Uso de primitivas de biblioteca
Manejo de imágenes
Se pueden manipular áreas de la pantalla mediante las siguientes funciones:
imagesize( int left, int top, int right, int bottom ); - determina el tamaño en bytes de
una región de la ventana.
getimage( int left, int top, int right, int bottom, void *bitmap ); - lee una región
rectangular de la pantalla y almacena su contenido en la variable bitmap, se debe
reservar espacio para almacenar la imagen.
putimage( int left, int top, void *bitmap, int op ); - despliega la imagen previamente
almacenada en bitmap. op puede ser: COPY_PUT, XOR_PUT, OR_PUT, AND_PUT,
NOT_PUT
readimagefile(const char* filename=NULL, int left=0, int top=0, int
right=INT_MAX, int bottom=INT_MAX); - lee un archivo de imagen en cualquier
formato bmp, gif, jpg, ico, emf y wmf y lo muestra en el recuadro especificado.
writeimagefile(const char* filename=NULL,int left=0, int top=0, int
right=INT_MAX, int bottom=INT_MAX, bool active=true, HWND hwnd=NULL); -
Escribe el recuadro de la imagen en un archivo bmp.
Si el nombre del archivo es NULL se abre ventana de diálogo.
Uso de primitivas de biblioteca
Ejemplo de imágenes
while(true){
c = getch();
#include <graphics.h> if(c == '1') p =0;
if(c == '2') p =1;
main(){ if(c == '3') p =2;
initwindow(600,600); if(c == '4') p =3;
setactivepage(0); if(c == 27) return 0;
readimagefile("Creek.jpg",0,0,600,600); setvisualpage(p);
setactivepage(1); }
readimagefile("Desert Landscape.jpg",0,0,600,600); }
setactivepage(2);
readimagefile("Forest.jpg",0,0,600,600);
setactivepage(3);
readimagefile("Humpback Whale.jpg",0,0,600,600);
int p=0;
char c;
Uso de primitivas de biblioteca
Demo de getimage putimage
void PutImageDemo(void){
static int r = 20;
static int StartX = 100;
static int StartY = 50;

struct viewporttype vp;


int PauseTime, x, y, ulx, uly, lrx, lry, size, i, width, height, step;
void *Saucer;
int MaxX,MaxY;
MaxX = getmaxx();
MaxY = getmaxy();
outtextxy(getmaxx()/2,0, "GetImage / PutImage
Demonstration");
getviewsettings( &vp );
Uso de primitivas de biblioteca /* Draw Saucer */
setfillstyle(SOLID_FILL,getmaxcolor());
fillellipse(StartX, StartY, r, (r/3)+2);
ellipse(StartX, StartY-4, 190, 357, r, r/3);
line(StartX+7, StartY-6, StartX+10, StartY-12);
circle(StartX+10, StartY-12, 2);
line(StartX-7, StartY-6, StartX-10, StartY-12);
circle(StartX-10, StartY-12, 2);
getch();
/* Read saucer image */
ulx = StartX-(r+1);
uly = StartY-14;
lrx = StartX+(r+1);
lry = StartY+(r/3)+3;
width = lrx - ulx + 1;
height = lry - uly + 1;
size = imagesize(ulx, uly, lrx, lry);
Uso de primitivas de biblioteca
Saucer = malloc(size);
getimage(ulx, uly, lrx, lry, Saucer);
putimage(ulx, uly, Saucer, XOR_PUT);

/* Plot some "stars" */


for ( i=0 ; i<5000; ++i )
putpixel(rand()%(MaxX), rand()%(MaxY), rand()%(
getmaxcolor()-1 )+1);
x = MaxX / 2;
y = MaxY / 2;
PauseTime = 70;
Uso de primitivas de biblioteca
while ( !kbhit() ) {
putimage(x, y, Saucer, XOR_PUT); /* draw image */
delay(PauseTime);
putimage(x, y, Saucer, XOR_PUT); /* erase image */
step = rand()%( 2*r ); //mover
if ((step/2) % 2 != 0 ) step = -1 * step;
x = x + step;
step = rand()%( r );
if ((step/2) % 2 != 0 )
step = -1 * step;
y = y + step;
if (vp.left + x + width - 1 > vp.right) x = vp.right-vp.left-width + 1;
else if (x < 0) x = 0;
if (vp.top + y + height - 1 > vp.bottom) y = vp.bottom-vp.top-height + 1;
else if (y < 0) y = 0;
}
free( Saucer );
getch();
}
Animación simple
Principios de animación

Una animación simple puede lograrse como sigue:

Dibujar

Esperar N ms

Borrar

Actualizar
Principios de animación
Animación #1
main(){
initwindow(400,300);
int x=rand()%400,y = rand()%50, vx = 5,vy = 5;
while(true){
setcolor(WHITE);
setfillstyle(1,WHITE); Dibujar
fillellipse(x,y,5,5);
delay(30);
setcolor(BLACK); Esperar N ms
setfillstyle(1,BLACK);
fillellipse(x,y,5,5);

}
x += vx; Borrar
y += vy;
if(x>400 || x<0) vx =-vx;
if(y>300 || y<0) vy =-vy; Actualizar
}
getch();
return 0;
}
Dibujo de un carro
(x – s, y – 2s)
Principios de animación

(x + s, y – 2s)
(x – 2s, y – s) (x + 2s, y – s)
(x – 3s, y – s)
(x + 3s, y – s)

(x, y) (x + 3s, y)
(x – 3s, y)
(x – 2s, y + s/3) (x + 2s, y + s/3)
Dibujo de un carro
Principios de animación

void carro(int x, int y, int size){


moveto(x-3*size,y-size);
linerel(size,0);
linerel(size,-size);
linerel(2*size,0); (x, y)
linerel(size,size);
linerel(size,0);
linerel(0,size);
linerel(-6*size,0);
linerel(0,-size);
circle(x-2*size,y+size/2,2*size/3);
circle(x+2*size,y+size/2,2*size/3);
}
Animación con un fondo
Principios de animación

Borrar pantalla

Dibujar fondo

Dibujar

Esperar N ms

Actualizar
void carro(int x, int y, int size){
Principios de animación

moveto(x-3*size,y-(size));
linerel(size,0);
linerel(size,-size);
linerel(2*size,0);
linerel(size,size);
linerel(size,0);
linerel(0,size);
linerel(-6*size,0);
linerel(0,-size);
circle(x-2*size,y+size/2,2*size/3);
circle(x+2*size,y+size/2,2*size/3);
}
Principios de animación

void fondo(){
int x = 0;
int d[] = {30,60,50,80,30,30,50,30};
int h[] = {70,100,140,30,80,30,60,70};
for(int i=0;i<9; i++){
setfillstyle(1,i+3);
bar(x,200,x+d[i],200-h[i]);
x += d[i];
}
}
main(){
initwindow(400,400);
int x=0,d=3;
Principios de animación

char c;
while(true){
cleardevice();
setcolor(WHITE);
fondo();
carro(x,200,8);
delay(30);
x += d;
if(x <0 || x>400) d =-d;
if(kbhit()){
c = (char)getch();
switch(c){
case 27:return 0;
default: d =-d;
}
}
}
}
Principios de animación
Dibujo de un carro relleno
Se requiere usar
void carro(int x, int y, int size){
int p[16];
fillpoly para
setcolor(WHITE); rellenar el carro.
setfillstyle(SOLID_FILL,RED);
p[0] = x-3*size; p[1] = y-size;
p[2] = x-2*size; p[3] = y-size;
p[4] = x-size; p[5] = y-2*size; (x, y)
p[6] = x+size; p[7] = y-2*size;
p[8] = x+2*size; p[9] = y-size;
p[10] = x+3*size; p[11] = y-size;
p[12] = x+3*size; p[13] = y;
p[14] = x-3*size; p[15] = y;
fillpoly(8,p);
setcolor(BLACK);
setfillstyle(SOLID_FILL,BLACK);
fillellipse(x-2*size,y+size/3,2*size/3,2*size/3);
fillellipse(x+2*size,y+size/3,2*size/3,2*size/3);
}
Dibujo de edificios
Principios de animación

void fondo(){
int x = 0;
int d[] = {30,60,50,80,30,30,50,30};
int h[] = {70,100,140,30,80,30,60,70};
for(int i=0;i<9; i++){
setfillstyle(1,i+3);
bar(x,200,x+d[i],200-h[i]);
x += d[i];
}
}
Principios de animación
Fondo #1
while(true){
cleardevice();
setcolor(WHITE);
Borrar pantalla
fondo();
carro(x,200,8);
delay(30); Dibujar fondo
x += d;
if(x <0 || x>400) d =-d;
if(kbhit()){ Dibujar
c = (char)getch();
switch(c){
case 27:return 0; Esperar N ms
default: d =-d;
}
} Actualizar
}
Mejora de animación con un fondo
Mejora de la animación

Dibujar fondo

Dibujar

Esperar N ms

Borrar

Actualiza
Fondo #2
while(true){
Mejora de la animación

setcolor(WHITE);
fondo();
carro(x,200,8);
setcolor(BLACK);
delay(30);
carro(x,200,8);
x += d;
if(x <0 || x>400) d =-d;
if(kbhit()){
c = (char)getch();
switch(c){
case 27:return 0;
default: d =-d;
}
}
}
Doble buffer
Mejora de la animación

El doble buffer hace uso de dos ventanas de salida, una visible


y otra no visible. Las funciones en C son:

setvisualpage(int n); establece la página


visual
setactivepage(p); establece la página
activa
swapbuffers( ); intercambia la página
visual y activa
int getactivepage( ); obtiene la página
activa
int getvisualpage( ); obtiene la página
visible
Mejora de la animación
Animación con doble buffer

Poner página
activa y visible

Dibujar fondo

Dibujar

Intercambiar
páginas

Actualiza
while(true){
//dibuja en la página oculta
setvisualpage(1-p); Poner página
Mejora de la animación

setactivepage(p); activa y visible


cleardevice();
fondo();
carro(x,200,8); Dibujar fondo
delay(10);
swapbuffers( );
Dibujar
p = 1-p;
x += d;
if(x <0 || x>400) d =-d;
if(kbhit()){ Intercambiar
c = (char)getch(); páginas
switch(c){
case 27:return 0;
default: d =-d; Actualiza
}
}
}
Implementación en C
main(){
Mejora de la animación

initwindow(400,400);
setactivepage(1);
/* lee la imagen desde un archivo y la
dibuja en la pantalla invisible*/
readimagefile("PGS_img01.jpg",0,0,400,400);
size = imagesize(0, 0, 400, 400);
/* reserva memoria para la imagen */
img = malloc(size);
/* guarda le imagen en memoria */
getimage(0,0,400,400,img);
// fondo();
int x=0,d=6,p=0,size=10;
char c;
while(true){
setcolor(WHITE);
//dibuja en la página oculta
Mejora de la animación

setvisualpage(1-p);
setactivepage(p);
setbkcolor(WHITE);
cleardevice();
fondo();
carro(x,200,size);
delay(30);
swapbuffers( );
p = 1-p;
x += d;
if(x <0 || x>400) d =-d;
}
}
Técnicas de Realidad Virtual

Unidad II

Computación gráfica

Semana 8

Primitivas gráficas y algoritmos

Das könnte Ihnen auch gefallen