Professional Documents
Culture Documents
Curso de graficacin I
Contenido
Dibujo de puntos
Algoritmos comunes de trazo de rectas
Algoritmos comunes de trazo de crculos
Otras primitivas
Bibliotecas grficas en C y Java
Uso de primitivas de biblioteca
Principios de animacin
Mejora de la animacin
La pantalla grfica
0
Mxima x 1
x = 0, y = 0
0
Mxima y 1
x = Mxima x 1
y = Mxima y 1
Java
En Java se dibuja en un objeto de la clase Graphics. No tiene una funcin
para dibujar puntos pero puede usarse:
Graphics g;
g.drawLine(50,25,50,25);
Ejemplo 1
#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;
}
Ejemplo
#include <iostream>
#include <graphics.h>
using namespace std;
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;
}
Tarea
Escriba funciones en C para dibujar a) una lnea vertical y b)
una lnea diagonal a 45 grados, utilizando la primitiva para
dibujar un punto.
Ponga los parmetros adecuados en cada caso.
Algoritmo DDA
Ecuacin bsica de la recta
y m x b
m es la pendiente y b la interseccin con el eje y
y2 y1
m
x2 x1
b y1 m x1
y m x
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.
13
12
11
10
9
10
11
12
13
14
13
12
11
10
9
10
11
12
13
14
x ,y
i
y m x i 1 b
y = mx + b
y +2
i
y +1
i
y
i
x
x +1 x +2
i
i
Definimos:
d1 y y i
m x i 1 b y i
d 2 y i 1 y
y i 1 m x i 1 b
la diferencia es
d 2 d1 2m x i 1 2 y i 2b 1
Definimos pi como:
pi x ( d1 d 2 )
2 y xi 2 x yi c
donde c es:
c 2y x 2b 1
pi 1 2 y xi 1 2 x yi 1 c
pi 1 pi 2y x i 1 x i 2x y i 1 y i
Simplificando:
pi 1 pi 2y 2x y i1 y i
El parmetro inicial es:
p1 2 y x
pi 1 pi 2y
y en el segundo
pi 1 pi 2 y x
con
deltax = abs(deltax);
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;
}
}
}
Primitivas bsicas 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 visin actual
clearviewport (void);
Primitivas de lneas en C
Dibuja lnea entre (x1,y1) y (x2,y2)
void line (int x1, int y1, int x2, int y2);
Dibuja lnea relativa al cursor grfico
void linerel (int dx, int dy);
Dibuja lnea desde el cursor grfico a (x,y)
void lineto (int x, int y);
Mueve cursor grfico en forma relativa
void moverel (int dx, int dy);
Tarea
Escriba una funcin que dibuje una estrella de 5 picos. Ponga
como parmetros las coordenadas del centro, la distancia del
centro a uno de los picos y el color.
Ayuda: note que los picos son vrtices de un pentgono.
Distancia centro pico
x, y
Proyectos
Hacer las siguientes primitivas con funciones en C. Utilice las
primitivas de lnea de graphics.h.
Algoritmos de generacin de
circunferencias
La ecuacin de la circunferencia
en coordenadas rectangulares es
x xc 2 y yc 2
r
yc
y yc r x xc
2
xc
r2
Funcin en C
void PlotPoint(int xc,
int x, int y,int c)
{
putpixel(xc + x,yc +
putpixel(xc - x,yc +
putpixel(xc + x,yc putpixel(xc - x,yc putpixel(xc + y,yc +
putpixel(xc - y,yc +
putpixel(xc + y,yc putpixel(xc - y,yc }
Algoritmo de circunferencia de
Bresenham
Se supone (xi, yi) la posicin ms prxima a la trayectoria, la
siguiente posicin es por tanto (xi+1, yi) o bien (xi+1, yi-1).
x
y
x +1 x +2
i
i
y -1
i
y -2
i
2
2
2
x + y = r
d 2 y y i 1
2
y
i
y
r x i 1 y i 1
2
- 1
x + 1
i
pi d1 d 2
2 x i 1 y y i 1 2r 2
2
2
i
1
2
pi 1 2 x i 1 1 y
2
2
i 1
y i 1 1 2r
2
Simplificando
pi1 pi 4 x i 6 2 y i21 y i2 2 y i 1 y i
p1 se obtiene de (x1, y1) = (0, r)
p1 3 2 r
x , y 0, r
1
p1 3 2r
si pi <0, la siguiente posicin es (xi+1,
pi 1 pi 4 xi 6
y en caso contrario
pi 1 pi 4 x i y i 10
f circunferencia x, y x 2 y 2 r 2
x k 1 y k 1 2 r 2
2
pk f circunferencia x k 1 1, y k 1 1 2
x k 1 1 y k 1 1 2 r 2
pk 1 pk 2 x k 1 y k21 y k2 y k 1 y k 1
2 y k 1 2 y k 2
2 xk 1 2 xk 2
El valor inicial es:
5
p0 r
4
Punto medio en C
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);
}
}
Crculos en C
Dibuja un crculo
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; };
#include <iostream>
#include <graphics.h>
Ejemplo
x + 2*tamanio
y 2*tamanio
x 4*tamanio
y tamanio
x 2*tamanio
y tamanio
x + 4*tamanio
y + tamanio
x + 6*tamanio, y
x + 2*tamanio
y + tamanio
x + 4*tamanio, y
x 2*tamanio
y + 2*tamanio
x +2 *tamanio
y +2 *tamanio
Centro de la compuerta: x, y
x,y 2*tamanio
Arco con centro en: x, y+2*tamanio
Radio de:4*tamanio de 0 a 90 grados.
viewport(x,y-2*tamanio,x+6*tamanio,y)
x 4*tamanio
y tamanio
x 2*tamanio
y tamanio
x + 4*tamanio
y + tamanio
x + 4*tamanio*cos(30)+tamanio, y
x +2*tamanio
y +tamanio
x + 4*tamanio*cos(30), y
x 2*tamanio
y + 2*tamanio
x, y +2 *tamanio
//conexiones traseras
xp = x1+xp+(int)sqrt(4*size*4*size-size*size);
line(xp,y1+size,xp-size,y1+size);
line(xp,y1+3*size,xp-size,y1+3*size);
//conexione delantera
xp = x+(int)(4*size*cos(30*pi/180));
yp = y-2*size+(int)(4*size*sin(30*pi/180));
line(xp,yp,xp+size,yp);
}
Tarea
1. Basndose en las primitivas de compuertas and y or escriba
funciones para dibujar estas compuertas con diferentes
orientaciones: hacia arriba, hacia la izquierda y hacia abajo.
2. La primitiva drawOval(int x, int y, int w,
int h) de Java dibuja una elipse enmarcada en un rectngulo
como se muestra en la figura (las lneas punteadas no se
dibujan). Defina una primitiva equivalente para dibujar una
elipse en C utilizando la primitiva ellipse.
x, y
w
Otras primitivas
Rectngulos rellenos: Los rectngulos rellenos pueden
generarse fcilmente haciendo un barrido de lneas de rastreo
desde la primera coordenada y a la segunda. El siguiente
cdigo 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);
}
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);
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
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
Primitivas de texto en C
Despliega una cadena de texto en la posicin 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 justificacin para el texto
void settextjustify (int horiz, int vert);
Define la fuente, direccin y el tamao del texto
void settextstyle (int font, int direction, int
charsize);
Define el tamao 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);
Ejemplo
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 */
#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;
}
Tarea
Escriba una funcin en C para
dibujar un diagrama de barras de
un conjunto de hasta 10 datos.
Incluya como parmetro un
arreglo de cadenas para las
leyendas.
Tarea
Haga una pequea animacin utilizando alguna de las tcnicas
revisadas.
Atributos de lneas
En bgi existen tres atributos para las lneas
color
grosor
patrn
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
Grosor y patrn
Existen dos grosores de lnea predefinidos, pero puede usarse cualquier
valor:
NORM_WIDTH
1
THICK_WIDTH
3
Los patrones de lnea son:
SOLID_LINE, DOTTED_LINE, CENTER_LINE,
DASHED_LINE, USERBIT_LINE
La funcin:
setlinestyle(int linestyle,unsigned upattern,int
thickness );
Establece el tipo de lnea. El patrn 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.
Actividad
Defina los siguientes patrones de lnea y dibuje
algunas lneas con estos patrones:
Actividad
Defina los siguientes patrones de lnea y dibuje
algunas figuras con estos patrones:
Actividad
Escriba un pequeo programa que cree dos ventanas y
deibuje algunas primitivas en cada una de ellas.
Manejo de imgenes
Se pueden manipular reas de la pantalla mediante las siguientes funciones:
imagesize( int left, int top, int right, int bottom ); - determina el tamao en bytes de
una regin de la ventana.
getimage( int left, int top, int right, int bottom, void *bitmap ); - lee una regin
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 dilogo.
Ejemplo de imgenes
#include <graphics.h>
main(){
initwindow(600,600);
setactivepage(0);
readimagefile("Creek.jpg",0,0,600,600);
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;
while(true){
c = getch();
if(c == '1') p =0;
if(c == '2') p =1;
if(c == '3') p =2;
if(c == '4') p =3;
if(c == 27) return 0;
setvisualpage(p);
}
}
/* 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);
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;
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();
}
Actividad
Haga un programa que lea dos imgenes seleccionadas
por el usuario y las muestre en ventanas separadas.
Animacin simple
Una animacin simple puede lograrse como sigue:
Dibujar
Esperar N ms
Borrar
Actualizar
Animacin #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);
Esperar N ms
setcolor(BLACK);
setfillstyle(1,BLACK);
fillellipse(x,y,5,5);
x += vx;
Borrar
y += vy;
if(x>400 || x<0) vx =-vx;
Actualizar
if(y>300 || y<0) vy =-vy;
}
getch();
return 0;
}
Actividad
Haga una animacin que mueva 5 objetos a distintas
velocidades rebotando en la pantalla. Los objetos
deben dibujarse en diferentes colores.
Los objetos podran ser, por ejemplo un cuadro, un
crculo hueco, un tringulo, etc.
Dibujo de un carro
(x s, y 2s)
(x 2s, y s)
(x + s, y 2s)
(x + 2s, y s)
(x 3s, y s)
(x + 3s, y s)
(x 3s, y)
(x 2s, y + s/3)
(x, y)
(x + 3s, y)
(x + 2s, y + s/3)
Dibujo de un carro
void carro(int x, int y, int size){
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);
}
(x, y)
Actividad
Usando la tcnica anterior con linerel haga una
funcin para dibujar alguna de las siguientes figuras.
La figura debe poder dibujarse de cualquier tamao y
en cualquier posicin.
Actualizar
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;
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;
}
}
}
}
Actividad
Modifique la figura de la actividad anterior para que se
dibuje con un relleno.
Dibujo de edificios
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];
}
}
Fondo #1
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;
}
}
}
Borrar pantalla
Dibujar fondo
Dibujar
Esperar N ms
Actualizar
Fondo #2
while(true){
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
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 pgina
visual
setactivepage(p); establece la pgina
activa
swapbuffers( ); intercambia la pgina
visual y activa
int getactivepage( ); obtiene la pgina
activa
int getvisualpage( ); obtiene la pgina
visible
while(true){
//dibuja en la pgina oculta
setvisualpage(1-p);
setactivepage(p);
cleardevice();
fondo();
carro(x,200,8);
delay(10);
swapbuffers( );
p = 1-p;
x += d;
if(x <0 || x>400) d =-d;
if(kbhit()){
c = (char)getch();
switch(c){
case 27:return 0;
default: d =-d;
}
}
}
Poner pgina
activa y visible
Dibujar fondo
Dibujar
Intercambiar
pginas
Actualiza
Implementacin en C
main(){
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 pgina oculta
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;
}
}