You are on page 1of 224

Bismarck Salvador Traña López__________________________________________ UNI

Introducción a la Programación grafica en C.
Para la mejor comprensión de este tutor hemos realizado un análisis de las Funciones que se suelen utilizar con mucha frecuencia al programar en el modo grafico de C, dando como resultado la librería conio.h, dos.h, stdlib.h, y evidentemente graphics.h. En este pequeño tutor solo haremos énfasis en estas librerías, puesto que al final del libro se encuentran las demás librerías que comúnmente encontramos con frecuencia en el programa. Muchos libros nos marean dándonos conceptos los cuales se aprenden conforme programando; esto no significa, que no sean importan tantees los ejercicios que aquí te enseñamos te ayudaran a darte todo el conocimiento así como también te los daremos conforme avancemos así que dejemos de hablar y aventurémonos en el mundo de la programación grafica. Lo primero que debemos saber al realizar una grafica son las dimensiones del ordenador (Monitor) en modo texto las dimensiones de este es 25X80 esto dependiendo de la versión de video instalada. En el modo grafico estas dimensiones cambian dependiendo del tipo de macro de inicialización se realice(ver Macro modos). Quedando la mas común de 640X480 modo VGA.

A la hora de desarrollar un programa gráfico se debe tener en cuenta los siguientes cuatro puntos: 1. Especificar el fichero o librería graphics.h # include<graphics.h>

2. Inicializar el modo grafico correspondiente mediante la Función initgraph;
Initgraph(&adaptador,&modo,”dirección de los archivos bgi”);

3. Crear y manipular las figuras graficas.
/*Desarrollo del programa*/ 4. Restaurar el modo de video antes de salir del programa(restaurar el modo texto) closegraph() o restorecrtmode()

Juan Carlos Gutiérrez Barquero____________________________________________

1

Bismarck Salvador Traña López__________________________________________ UNI
Otra de las cosas importantes que debemos saber es que Funciones contiene graphics.h

Funciones de Graphics.h
Esta librería se encuentra los prototipos de las Funciones que manipulan la parte gráfica en el entorno de MS-DOS. Arc bar bar3d circle cleardevice clearviewport closegraph detectgraph drawpoly ellipse fillellipse fillpoly floodfill getarccoords getaspectratio getbkcolor getcolor getdefaultpalette getdrivername getfillpattern getfillsettings getgraphmode getimage getlinesettings getmaxcolor getmaxmode getmaxx getmaxy getmodename getmoderange getpalette getpalettesize getpixel gettextsettings getviewsettings getx gety graphdefaults grapherrormsg graphfreemem graphgetmem graphresult imagesize initgraph installuserdriver installuserfont line linerel lineto moverel moveto outtext outtextxy pieslice putimage putpixel rectangle registerbgidriver registerbgifont restorecrtmode sector setactivepage setallpalette setaspectratio setbkcolor setfillpattern setfillstyle setgraphbufsize setgraphmode setlinestyle setpalette setrgbpalette settextjustify settextstyle setusercharsize setviewport setvisualpage setwritemode textheight textwidth

Es necesario conocer hacerca de los macros y estructuras, entre las estructuras tenemos: arccoordstype fillsettingstype Entre los macros se encuentran: colores drivers enlazar errores fuentes línea modos put_op trama linesettingstype palettetype textsettingstype viewporttype

Antes de comenzar a programar en modo grafico debemos estudiar lo que son los macros, que son instrucciones que nos ayudaran a realizar de una manera más efectiva nuestros gráficos.

Juan Carlos Gutiérrez Barquero____________________________________________

2

Bismarck Salvador Traña López__________________________________________ UNI

Colores :
Colores de Fondo
Constante BLACK BLUE GREEN CYAN RED MAGENTA BROWN LIGHTGRAY DARKGRAY LIGHTBLUE LIGHTGREEN LIGHTCYAN LIGHTRED LIGHTMAGENTA YELLOW WHITE Valor 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Significado Negro Azul Verde Cían Rojo Magenta Marrón Gris Claro Gris Oscuro Azul Claro Verde Claro Cían Claro Rojo Claro Magenta Claro Amarillo Blanco

Modo de 16 Colores
Constante BLACK BLUE GREEN CYAN RED MAGENTA BROWN LIGHTGRAY DARKGRAY LIGHTBLUE LIGHTGREEN LIGHTCYAN LIGHTRED LIGHTMAGENTA YELLOW WHITE 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Valor Significado Negro Azul Verde Cían Rojo Magenta Marrón Gris Claro Gris Oscuro Azul Claro Verde Claro Cían Claro Rojo Claro Magenta Claro Amarillo Blanco

Color del modo CGA Juan Carlos Gutiérrez Barquero____________________________________________ 3

Bismarck Salvador Traña López__________________________________________ UNI

Número Paleta 0 1 2 3

Color 1 CGA_LIGHT GREEN CGA_LIGHT CYAN CGA_GREEN CGA_CYAN

Significado Verde Claro Cían Claro Verde Cían

Color 2 CGA_LIGHTRED CGA_LIGHTMAGENTA CGA_RED CGA_MAGENTA

Significado Rojo Claro Magenta Claro Rojo Magenta

Color 3 CGA_YELLOW CGA_WHITE CGA_BROWN CGA_LIGHTGRAY

Significado Amarillo Blanco Marrón Gris Claro

Valor asignado: 1 2 3 Nota: Color 0 se reserva para el color de fondo y se asigna con lo función setbkcolor, pero los demás colores son fijos. Estas constantes se usan con setcolor.

Colores para las paletas.
Constante (CGA) BLACK BLUE GREEN CYAN RED MAGENTA BROWN LIGHTGRAY DARKGRAY LIGHTBLUE LIGHTGREEN LIGHTCYAN LIGHTRED LIGHTMAGENTA YELLOW WHITE Valor 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Constante (EGA/VGA) EGA_BLACK EGA_BLUE EGA_GREEEN EGA_CYAN EGA_RED EGA_MAGENTA EGA_LIGHTGRAY EGA_BROWN EGA_DARKGRAY EGA_LIGHTBLUE EGA_LIGHTGREEN EGA_LIGHTCYAN EGA_LIGHTRED EGA_LIGHTMAGENTA EGA_YELLOW EGA_WHITE Valor 0 1 2 3 4 5 7 20 56 57 58 59 60 61 62 63

Nota: Estas constantes se usan con las Funciones setpalette y setallpalette.el cual veremos en capítulos posteriores

Fuentes:

Juan Carlos Gutiérrez Barquero____________________________________________

4

Bismarck Salvador Traña López__________________________________________ UNI Fuentes para Texto Constante DEFAULT_FONT TRIPLEX_FONT SMALL_FONT SANS_SERIF_FONT GOTHIC_FONT SCRIPT_FONT SIMPLEX_FONT TRIPLEX_SCR_FONT COMPLEX_FONT EUROPEAN_FONT BOLD_FONT Valor 0 1 2 3 4 5 6 7 8 9 10 Valor Fuente bitmap de 8x8 Fuente escalable de tipo triple Fuente escalable pequeña Fuente escalable de tipo sans serif Fuente escalable de tipo gótico Fuente escalable de tipo manuscrito Fuente escalable de tipo manuscrito simple Fuente escalable de tipo manuscrito triple Fuente escalable de tipo complejo Fuente escalable de tipo europeo Fuente escalable en negrita Dirección del Texto Constante HORIZ_DIR VERT_DIR Valor 0 1 Significado Texto horizontal Texto vertical Justificación de Texto en la Horizontal Constante LEFT_TEXT CENTER_TEXT RIGHT_TEXT Valor 0 1 2 Significado Justificar a la izquierda Centrar el texto Justificar a la derecha Justificación de Texto en la Vertical Constante BOTTOM_TEXT CENTER_TEXT TOP_TEXT Valor 0 1 2 Significado Justificar debajo Centrar el texto Justificar arriba Tramas: Tramas predefinidas Juan Carlos Gutiérrez Barquero____________________________________________ 5 .

_._.. EMPTY_FILL usa el color de fondo para rellenar. Línea centrada ––––––––––– Línea discontinua _._. Driver: Dispositivos Gráficos Dispositivo/Constante DETECT CGA MCGA EGA EGA64 EGAMONO IBM8514 HERCMONO ATT400 VGA PC3270 Valor 0 1 2 3 4 5 6 7 8 9 10 Líneas: Estilos de Líneas Constante SOLID_LINE DOTTED_LINE CENTER_LINE DASHED_LINE USERBIT_LINE Valor 0 1 2 3 4 Significado Línea continua _______ Línea hecha con puntos ……. Línea definida por el usuario Nota: El grosor es definido escribiendo NORM_WIDTH para rallas normales y THICK_WIDTH para líneas mas gruesos Grosores para Líneas Modos de Escritura Juan Carlos Gutiérrez Barquero____________________________________________ 6 .Bismarck Salvador Traña López__________________________________________ UNI Constante 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 Valor 0 1 2 3 4 5 6 7 8 9 10 11 12 Significado Rellena con el color de fondo Rellena enteramente Rellena con líneas horizontales: --Rellena con rayas finas: /// Rellena con rayas gruesas: /// Rellena con rayas inversas y finas: \\\ Rellena con rayas inversas y gruesas: \\\ Rellena con líneas cruzadas cuadriculadamente: +++ Rellena con líneas cruzadas diagonalmente: XXXX Rellena con líneas entrelazadas Rellena con lunares bastante distanciados Rellena con lunares poco distanciados Rellena con la trama definida por el usuario Nota: Todos los tipos de tramas menos EMPTY_FILL usan el color de relleno seleccionado.

Bismarck Salvador Traña López__________________________________________ UNI Constante Grosor NORM_THICK THICK_WIDTH Valor 1 3 Significado Grosor es de 1 píxel Grosor es de 3 píxeles Constantes COPY_PUT XOR_PUT Valor 0 1 Significado Píxeles de la línea sobrescriben los píxeles existentes Píxel de la pantalla son el Resulta do de la operación OR de los píxeles existentes y los de la línea Modos: Modos Gráficos Dispositivo CGA Modo/Constante CGAC0 CGAC1 CGAC2 CGAC3 CGAHI MCGAC0 MCGAC1 MCGAC2 MCGAC3 MCGAMED MCGAHI EGALO EGAHI A64LO EGA64HI AMONOHI VGALO VGAMED VGAHI ATT400C0 ATT400C1 ATT400C2 ATT400C3 ATT400MED ATT400HI HERCMONOHI PC3270HI IBM8514LO IBM8514HI Código 0 1 2 3 4 0 1 2 3 4 5 0 1 0 1 3 0 1 2 0 1 2 3 4 5 0 0 0 1 Resolución 320X200 320X200 320X200 320X200 640X200 320X200 320X200 320X200 320X200 640X200 640X480 640X200 640x350 640X200 640X350 640x200 640X200 640x350 640X480 320x200 320x200 320x200 320x200 640x400 640x400 720X348 720X350 640X480 1024X768 Paleta 4 Clores 4 Clores 4 Clores 4 Clores 2 Clores 4 Clores 4 Clores 4 Clores 4 Clores 2 Clores 2 Clores 16 Colores 16 Colores 16 Colores 4 Colores 2 Colores 16 Colores 16 Colores 16 Colores 4 Colores 4 Colores 4 Colores 4 Colores 2 Colores 2 Colores 2 Colores 2 Colores 256 Colores 256 Colores Pagina 1 1 1 1 1 1 1 1 1 1 1 4 2 1 1 MCGA EGA EGA64 EGAMONO VGA ATT400 1* / 2** 2 2 1 1 1 1 1 1 1 2 1 HERC Si la tarjeta es de 64 K o la tarjeta es de 256 K Errores: Juan Carlos Gutiérrez Barquero____________________________________________ 7 .

Bismarck Salvador Traña López__________________________________________ UNI Códigos de Errores Constante grOk grNoInitGraph grNotDetected grFileNotFound grInvalidDriver grNoLoadMem grNoScanMem grNoFloodMem grFontNotFound grNoFontMem grInvalidMode grError grIOerror grInvalidFont grInvalidFontNum grInvalidDeviceNum grInvalidVersion Código 0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -18 Significado Ningún error Gráficos no iniciados Ningún adaptador gráfico detectado Fichero de dispositivo no encontrado Fichero de dispositivo no válido No hay memoria para cargar dispositivo No hay memoria para rellenar No hay memoria para usar floodfill Fichero de fuente no encontrado No hay memoria para cargar la fuente Modo gráfico no válido Error gráfico Error gráfico de Entrada/Salida Fichero de fuente no válido Número de fuente no válido Número de dispositivo no válido Número de versión no válido Put_op: Operaciones con putimage Constante COPY_PUT XOR_PUT OR_PUT AND_PUT NOT_PUT Valor 0 1 2 3 4 Significado Sobrescribir los píxeles existentes Operación OR Exclusivo con los píxeles Operación OR Inclusivo con los píxeles Operación AND con los píxels Invertir la imagen Nota: Estas operaciones se usan exclusivamente con la función putimage. Juan Carlos Gutiérrez Barquero____________________________________________ 8 . Métodos de Inicialización del modo grafico. El cual veremos en capítulos posteriores.

el código de error interno es activado. getch(). La función initgraph debe ser llamada antes de cualesquier Funciónes que generan una salida gráfica sean usadas. Función initgraph void far initgraph(int far *driver.Bismarck Salvador Traña López__________________________________________ UNI Antes de conocer los métodos de inicialización debemos conocer la función initgraph la cual nos permitirá realizar gráficos. &modo. el código es asignado un 0.h> #include <conio. “C:\\TC20\\BIN” ). Si *driver es asignado a DETECT. la función buscará en el directorio de inicio. Cuando el argumento *path es NULL. Método de inicialización del modo grafico a prueba de errores.h> void main() { int driver = EGA. La función initgraph buscará el dispositivo primeramente en este directorio. 1. cuando la función initgraph es llamada. Esta función es usada para cargar o validar un dispositivo gráfico y cambiar el sistema de vídeo a modo gráfico. Juan Carlos Gutiérrez Barquero____________________________________________ 9 . y un dispositivo y modo gráfico apropiados son seleccionados. 80 ). Otra forma para evitar cargando el dispositivo desde el disco cada vez que el programa es ejecutado es ligarlo o enlazarlo al dispositivo apropiado en un programa ejecutable. circle( 300. La función initgraph no retorna ningún valor. Estos valores deberían corresponder al dispositivo especificado en el argumento *driver. /* Pausa */ closegraph(). Si no. Existen varios valores a ser usados para el argumento *modo. Sin embargo. } Existen diferentes métodos de inicialización pero en este pequeño tutorial trataremos dos que suelen ser los más utilizados hoy en día. la función detectgraph es llamada. 200. getch(). int modo = EGAHI. Si no es encontrado. Existen varios valores a ser usados para el argumento *driver. initgraph( &driver. int far *path). Asignando a *driver cualquier otro valor predefinido inicia la carga del dispositivo gráfico correspondiente. ó 0. el código es asignado así: -2 grNotDetected La tarjeta gráfica no se encontró -3 grFileNotFound El fichero del dispositivo no se encontró -4 grInvalidDriver El fichero del dispositivo es inválido -5 grNoLoadMem No hay suficiente memoria para cargar el dispositivo Ejemplo: #include <graphics. int far *modo. solamente el directorio de inicio es buscado. Si la función initgraph termina con éxito. El argumento *path especificad el directorio donde los dispositivos gráficos están localizados.

modo.modo. ¿Qué son los primitivos gráficos…? Juan Carlos Gutiérrez Barquero____________________________________________ 10 . graphresult():Regresa el código error de la ultima llamada a una función grafica de turbo c un valor de 0 significa que no hubo error. DETECT: Dispositivo grafico de auto detección del la tarjeta de video y del modo grafico.h> # include<process. initgraph(&driver.&modo.h> void main() { int driver = DETECT.Bismarck Salvador Traña López__________________________________________ UNI #include <graphics. cuerpo del programa driver: Es la dirección de la variable que contiene el código del tipo de de driver o adaptador que tiene la computadora. exit(0)."c:\\tc20\\bin").” c:\\tc20\\bin”).h> # include <conio. #include <graphics. modo: Es la dirección de la variable que contiene el código del modo en que se podrá adaptar. grOk : regresa el código de error de la función graphresult(). int resultado. } getch(). initgraph(&driver. if(resultado!=grOk) { getch(). resultado=graphresult(). int modo = VGAHI. puede ser camino relativo o absoluto.h> void main() { int driver = VGA. Método de inicialización rápido del modo grafico. } cuerpo del programa 2. c:\\tc20\\bin: Es el directorio donde se encuentra el código del manejador.

La línea se dibuja usando el estilo de línea actual.  Figuras geométricas: LINEAS. La posición del cursor gráfico no es afectada por la función line. y el color actual. La función line() no retorna ningún valor. el grosor.  Relleno: tiene dos formas de realizarse. void far line(int x1. línea. C cuenta con 5 grupos de primitivos gráficos.Bismarck Salvador Traña López__________________________________________ UNI Definición. arcos. Ejemplo: Juan Carlos Gutiérrez Barquero____________________________________________ 11 . int x2.  Rasterop: Es una operación grafica que copia el área de una imagen para luego dibujarla en cualquier región de la pantalla. Esta función es usada para conectar dos puntos con una línea recta. puede ser un carácter.  Figuras geométricas: Dibujan las figuras de la geometría clásica: líneas. utilizando diferentes fuentes. coloreado o trasferido de la imagen. int y2). El primero es con polígonos. o circulo. El primer punto es especificado por los argumentos x1 e y1. círculos. polígonos etc. rectángulos. donde se definen los vértices del polígono a ser rellenado segunda es una operación grafica que busca algorítmicamente las fronteras de la región del relleno. El segundo punto es especificado por los argumentos x2 e y2. Un primitivo gráfico es un elemento fundamental de dibujo en un paquete grafico tal como un punto. o puede ser una operación tal como relleno. int y1.  Texto Gráfico: Sirve para escribir texto en modo grafico.  Gráficas Matemáticas: Dibujan los primitivos barras y sectores para conseguir dibujar las herramientas del sector.

El grosor de la circunferencia puede ser establecido por la función setlinestyle. getch(). /* Pausa */ closegraph(). int y. &modo.h> void main() { int driver = EGA. sin embargo. line( 20. El círculo no es rellenado pero es dibujado usando el color actual. 200. 30. "c:\\tc20\\bin" ). circle( 300. La función circle no retorna ningún valor.h> void main() { int driver = EGA.Bismarck Salvador Traña López__________________________________________ UNI #include <graphics. initgraph( &driver. 100 ). &modo. 50. closegraph(). 350. int radio). mientras que el argumento radio define el radio del círculo. 250 ). Ejemplo: #include <graphics. initgraph( &driver. 80 ). "C:\\tc20\\BIN" ). Esta función se utiliza para dibujar un círculo. el estilo de la línea es ignorado por la función circle. 40.h> #include <conio.modo = EGAHI. Los argumentos x e y definen el centro del círculo. getch(). } Juan Carlos Gutiérrez Barquero____________________________________________ 12 . line( 400. } CIRCULOS. void far circle(int x. int modo = EGAHI.h> #include <conio.

El arco no está rellanado. 20.h> void main() { int driver = EGA.int comienzo_angulo. Esta función dibujará un rectángulo sin rellenar su interior usando el color actual. /* Pausa */ closegraph(). pero es dibujado usando el color actual. La función setlinestyle puede usarse para establecer el grosor del arco. int derecha. ignorará el argumento trama de la función setlinestyle. int y.int superior. los argumentos derecha e inferior definen la esquina inferior derecha del rectángulo. La función rectangle() no retorna ningún valor. El arco tiene como centro el punto especificado por los argumentos x e y. Ejemplo: #include <graphics.Bismarck Salvador Traña López__________________________________________ UNI RECTANGULOS. "C:\\tc20\\bin" ). El perímetro del rectángulo es dibujado usando el estilo y grosor de línea actuales. Similarmente. void far rectangle(int izquierda. Juan Carlos Gutiérrez Barquero____________________________________________ 13 . Estos argumentos corresponden a los valores x e y de la esquina superior izquierda. La función arc. &modo. } ARCOS void far arc(int x. El arco comienza al ángulo especificado por el argumento comienzo_angulo y es dibujado en la dirección contraria al de las agujas del reloj hasta llegar al ángulo especificado por el argumento final_angulo. y es dibujado con el radio especificado: radio. getch(). La función arc usa el este (extendiéndose hacia la derecha del centro del arco en la dirección horizontal) como su punto de 0 grados. initgraph( &driver.modo = EGAHI. int inferior).h> #include <conio. sin embargo. rectangle( 20. 300 ). Esta función creará un arco circular. 400. int final_angulo. int radio). La esquina superior izquierda del rectángulo está definida por los argumentos izquierdos y superiores.

modo = EGAHI. int color). “c:\\tc20\\bin” ). for( t=0. La función putpixel no retorna ningún valor. getch().modo = EGAHI. 50+t. t<200. 135. for( radio = 25. 45. t%16 ). &modo.h> #include <conio. } PIXELES.t. radio < 175. /* Pausa */ closegraph(). closegraph(). t++ ) putpixel( 100+t. initgraph( &driver. int y. &modo.h> #include <conio.Bismarck Salvador Traña López__________________________________________ UNI La función arc no retorna ningún valor.h> void main() { int driver = EGA. Juan Carlos Gutiérrez Barquero____________________________________________ 14 . El argumento color específico el valor del color del píxel. } ELIPSES. Ejemplo: #include <graphics. "C:\\tc20\\bin" ). getch(). radio += 25 ) arc( 320. radio ).radio. initgraph( &driver. 175. Esta función es usada para colocar a un píxel en una posición en particular la cual es cuestionada por los argumentos x e y. void far putpixel(int x. Ejemplo: #include <graphics.h> void main() { int driver = EGA.

100. Esta función es usada para asignar el color de fondo al valor del color de fondo especificado por el argumento color.ser 0 grados.modo = EGAHI. El arco elíptico comienza con el ángulo especificado por el argumento comienzo_angulo y se extiende en un sentido contrario a las agujas del reloj al ángulo especificado por el argumento final_angulo.h. /* Pausa */ closegraph().h> #include <conio. La función setbkcolor no retorna ningún valor. El arco elíptico está centrado en el punto especificado por los argumentos x e y. int y_radio). 225. 45. 50 ). "C:\\tc20\\bin" ). &modo. el estilo de línea es ignorado por la función ellipse. int x_radio.h> void main() { int driver = EGA. Ejemplo: Juan Carlos Gutiérrez Barquero____________________________________________ 15 . El arco elíptico es dibujado con el grosor de línea actual como es establecido por la función setlinestyle. initgraph( &driver. 150. Ya que el arco es elíptico el argumento x_radio especifica el radio horizontal y el argumento y_radio especifica el radio vertical. Sin embargo. int comienzo_angulo. Ejemplo: #include <graphics. Existen varios valores para ciertos colores de fondo. }  Funciones básicas de graphics.el eje horizontal a la derecha del centro del elipse . int final_angulo. Esta función es usada para dibujar un arco elíptico en el color actual. int y. La función ellipse considera este .Bismarck Salvador Traña López__________________________________________ UNI void far ellipse(int x. Función setbkcolor void far setbkcolor(int color). getch(). La función ellipse no retorna ningún valor. ellipse( 300.

getch(). Esta función es usada para obtener el valor del color de fondo actual.h> #include <conio. Sin embargo.h> #include <stdio. color ). getch().color. setbkcolor( 4 ). printf( "Color de fondo: %d\n". 50 ). este valor puede cambiar con una llamada a la función setbkcolor. La función getbkcolor retorna el valor del color de fondo actual. 150. circle( 300. } void far setcolor(int color) Esta función coloca el atributo color es decir escoge un color entre 0 y 15 o su equivalente en inglés (ver pagina 3 Modo de 16 colores) todo lo que se dibuje después de esta instrucción tendrá el color establecido por la función setcolor el valor de esta es función es WHITE. El color de fondo. Existen varios valores para ciertos colores de fondo. Ejemplo: #include <graphics. } Función getbkcolor. Esta función no devuelve ningún valor. /* Pausa */ closegraph(). “C:\\TC20\\BIN” ). color = getbkcolor(). getch(). getch(). circle( 300. &modo. por defecto. &modo. 50 ). initgraph( &driver. /* Pausa */ closegraph().modo = EGAHI. Juan Carlos Gutiérrez Barquero____________________________________________ 16 .h> void main() { int driver = EGA. initgraph( &driver.h> #include <conio.h> void main() { int driver = EGA.Bismarck Salvador Traña López__________________________________________ UNI #include <graphics. "C:\\tc20\\BIN" ). int modo = EGAHI. int far getbkcolor(void). es el color 0. 150. setbkcolor( 4 ).

h> # include <stdlib. circle( 400. 80 ). circle(random(639). &modo.i.Bismarck Salvador Traña López__________________________________________ UNI Ejemplo. 200. cleardevice(). /*Detiene la ejecución del programa durante 30000 milisegundos*/ i=(i<16)?i:0. relleno.&modo. "C:\\tc20\\BIN" ). color = 1. La posición del cursor gráfico es la esquina superior izquierda de la pantalla posición (0.random(479). THICK_WIDTH ).random(i+8)). int relleno. /* Pausa */ setbkcolor( color ). setlinestyle( SOLID_LINE. do { setcolor(i). getch().h> # include <dos. como es establecido por la función setbkcolor.h> void main() { int driver = EGA. circle( 300. } Función cleardevices void far cleardevice(void). Juan Carlos Gutiérrez Barquero____________________________________________ 17 .0) . 20 )."c:\\tc20\\BIN"). initgraph( &driver. int modo = EGAHI.después de que la pantalla haya sido borrado. 200. La función cleardevice usa el color de fondo actual. para rellenar la pantalla. Ejemplo: #include <graphics. i++. relleno = 1. Esta función es usada para despejar una pantalla gráfica. setlinestyle( SOLID_LINE.h> # include <conio. THICK_WIDTH ). color.h> void main(){ int driver=DETECT. getch()./*Random definida en stdlib*/ delay(30000). La función cleardevice no retorna ningún valor. initgraph(&driver. i=0. relleno. /* Pausa */ closegraph(). }while(!kbhit()). # include <graphics.modo.h> #include <conio.

La función getmaxy retorna la coordenada máxima de la pantalla en la dirección vertical. Este valor suele ser la resolución vertical máxima menos 1. “C:\\TC20\\BIN” ). y_max ).Bismarck Salvador Traña López__________________________________________ UNI getch().modo = EGAHI. Esta función es usada para obtener la coordenada máxima de la pantalla en la dirección horizontal.h> void main() { int driver = VGA. Ejemplo: #include <graphics. Esta función es usada para obtener la coordenada máxima de la pantalla en la dirección vertical.h> #include <stdio. Este valor suele ser la resolución horizontal máxima menos 1. } Función getmaxy int far getmaxy(void). printf( "X máxima: %d\n". int x_max. Ejemplo: #include <graphics. } Juan Carlos Gutiérrez Barquero____________________________________________ 18 .h> void main() { int driver = EGA. initgraph( &driver. &modo. "C:\\TC20\\BIN" ). closegraph(). y_max = getmaxy(). } Función getmaxx int far getmaxx(void). initgraph( &driver.h> #include <conio. getch().x_max. closegraph().h> #include <conio. int modo = EGAHI. x_max.h> #include <stdio. y_max. x_max ). getch(). printf( "X máxima: %d\tY máxima: %d\n". x_max = getmaxx(). La función getmaxx retorna la coordenada máxima de la pantalla en la dirección horizontal. &modo. x_max = getmaxx().

Función bar void far bar(int izquierda. color = 1. busca desde un punto inicial llamado la semilla en todas las direcciones para encontrar una frontera que encierre la regio. El primero relleno de polígonos. Estos argumentos corresponden a los valores x e y de la esquina superior izquierda. x = 20. x. y. fill = (fill+1) % 12. &modo. do { setfillstyle( fill. } while( x < 620 ). getch(). color = (color+1) % 16. int derecha. y. usa la lista de vértices del polígono para calcular la geometría del interior. La barra no tiene borde. 320 ). color. color ). Antes de estudiar los dos métodos estudiaremos la función setfillstyle que será de gran importancia a la hora de realizar los dos tipos de rellenado y bar que es una función similar a rectangle.modo = EGAHI. Similarmente. int superior. y = 20. y += 10. x += 40. Turbo C utiliza dos métodos para definir la región de rellenos. } El patrón de relleno se define con las Funciónes setfillstyle y setfillpattern Juan Carlos Gutiérrez Barquero____________________________________________ 19 . "C:\\tc20\\BIN" ). La frontera se reconoce como el valor del píxel que tiene.Bismarck Salvador Traña López__________________________________________ UNI  Rellenos Es el proceso de rellenar una región de la pantalla con un patrón o color. Ejemplo: #include <graphics. int inferior). fill = 1. Esta función dibujará una barra rectangular y rellenada de dos dimensiones. x+40. La función bar no retorna ningún valor. los argumentos derecha e inferior definen la esquina inferior derecha de la barra. bar( x. /* Pausa */ closegraph(). initgraph( &driver.fill. El segundo relleno es por el método de inundación.h> void main() { int driver = EGA. La esquina superior izquierda de la barra rectangular está definida por los argumentos izquierdos y superiores. pero es rellenada con la trama de relleno actual y el color de relleno como es establecido por la función setlinestyle.h> #include <conio.

} LTSLASH_FILL es un estilo de relleno si desea estudiarlos se encuentran en el libro(Ver pagina # 5 ). La función setfillpattern no retorna ningún valor. 0xF0.Bismarck Salvador Traña López__________________________________________ UNI Función setfillstyle void far setfillstyle(int trama. /* Pausa */ closegraph(). La función setfillstyle no retorna ningún valor. 0xEE. 0x0A. int color).modo = EGAHI. 300 ). 0x33. mientras que el argumento color especifica el color de relleno. Un bit de 0 indica que el píxel correspondiente será asignado el color de relleno actual. Sin embargo. Ejemplo: #include <graphics. 0xF0.h> void main() { int driver = EGA. 0x0A. Cada byte representa una fila de ocho bits. 0x33. getch(). Juan Carlos Gutiérrez Barquero____________________________________________ 20 .h> #include <conio. donde cada bit está encendido o no (1 ó 0). bar( 50. En su lugar. 0x33. setfillstyle( LTSLASH_FILL. "c:\\tc20\\bin" ). 50. 0xEE. El argumento *trama apunta a una serie de ocho bytes que representa una trama de relleno de bits de 8 x 8.modo = EGAHI. Esta función es usada para seleccionar una trama de relleno definido por el usuario. Ejemplo: #include <graphics. se debería usar la función setfillpattern.h> void main() { int driver = EGA. Un bit de 0 indica que el píxel correspondiente no será alterado. char trama2[8] = { 0x0A. 0xF0. 0xEE. &modo. la trama USER_FILL (valor 12) no debería usarse para asignar una trama definida por el usuario. Existen trece valores ya definidos para tramas. int color). Función setfillpattern void far setfillpattern(char far *trama. 350. El argumento trama especifica la trama predefinida. 6 ). 0xF0. 0xEE }. char trama1[8] = { 0x33.h> #include <conio. 0x0A }. El argumento color especifica el color de relleno que será usado para la trama. Esta función es usada para seleccionar una trama predefinida y un color de relleno. initgraph( &driver.

h> #include <stdio. 260.modo = EGAHI. 260 ). La función fillpoly dibuja el perímetro del polígono con el estilo de línea y color actuales.Bismarck Salvador Traña López__________________________________________ UNI initgraph( &driver. &modo. } /*Este programa te muestra los diferentes colores con una misma trama trata de modificarlo para que obtengas todas las tramas con todos los colores*/ Juan Carlos Gutiérrez Barquero____________________________________________ 21 .h> void main() { int driver = EGA. color.color++) { setfillstyle( trama. La función fillpoly no retorna ningún valor. 300 }. /* Pausa */ closegraph(). y así sucesivamente. /* Pausa */ closegraph().trama. } getch(). 50. getch(). getch(). initgraph( &driver. El argumento *puntos apunta a un array de números de longitud numpuntos multiplicado por 2. respectivamente. puntos ). 150 ). setfillpattern( trama1. bar( 50. 500. 50. trama = SLASH_FILL. Ejemplo: #include <graphics. bar( 160.h> #include <conio. for(color=0. int far *puntos). 300. bar( 105. &modo. la función automáticamente cierra el polígono. 50. 4 ). 150. Al contrario que la función drawpoly. setfillpattern( trama2. 150 ). mientras que los dos siguientes especifican el siguiente punto. 160. Los dos primeros miembros del array identifica las coordenadas x e y del primer punto. int puntos[6] = { 300.color<=15. Esta función es usada para crear un polígono rellenado. el polígono es rellenado con la trama de relleno y color de relleno actuales. Relleno por medio de un polígonos. El argumento numpuntos es usado para definir el número de puntos en el polígono. 9 ). void far fillpoly(int numpuntos. fillpoly( 3. } 1. Luego. 100. 205. "C:\\tc20\\bin" ). color ). "C:\\tc20\\bin" ).

Nota: Esta función no Funciona con el driver IBM-8514.color<=15. } getch(). for(color = 0. 300. el área a ser rellenado debe estar rodeada por el color especificado por el argumento borde. /*verde*/ drawpoly( 4. puntos ). color ). el interior será rellenado. trama = SLASH_FILL. 300. Juan Carlos Gutiérrez Barquero____________________________________________ 22 .Bismarck Salvador Traña López__________________________________________ UNI 2. getch(). color. Los argumentos x e y especifican el punto de comienzo para el algoritmo de relleno. Ejemplo: #include <graphics. Para que la función fillpoly Funcione como es esperado. int puntos[8] = { 300. Si se encuentra fuera del área. el exterior será rellenado. void far floodfill(int x. El argumento borde especifica el valor del color del borde del área. setcolor( 10 ). int borde). Función moveto.color++) { setfillstyle( trama. void far moveto(int x. floodfill( 400. Cuando el punto especificado por los argumentos x e y se encuentra dentro del área a ser rellenada. initgraph( &driver. 500. Ya que el cursor es movido desde su posición anterior al punto especificado por los argumentos x e y. gety. getx.modo = EGAHI. }  Funciónes de coordenadas relativas Entre ellas tenemos las Funciónes moveto.h> #include <conio. "C:\\tc20\\bin" ). 300. lineto. 250. Estudiaremos cada una de ellas para afianzar mas conocimientos.trama. linerel.h> void main() { int driver = EGA. no hay dibujo alguno. /* Pausa */ closegraph(). int y. 10 ). Relleno por el método de inundación. int y). 50. moverel.h> #include <stdio. 50 }. &modo. Esta función es usada para colocar el cursor gráfico al punto especificado por los argumentos x e y.La función floodfill no retorna ningún valor. Esta función es usada para rellenar un área cerrado con el color de relleno y trama de relleno actuales. 100.

y el color actual. modo = EGAHI. Esta función es usada para dibujar una línea recta desde la posición actual del cursor gráfico hasta el punto especificado por los argumentos x e y. La función lineto no retorna ningún valor. lineto( 40. int dy). int y). lineto( 40. void far lineto(int x.h> void main() { int driver = EGA. 20 ). el grosor. La línea se dibuja usando el estilo de línea actual. 60 ). "C:\\tc20\\bin" ). Juan Carlos Gutiérrez Barquero____________________________________________ 23 .h> #include <conio. 20 ). getch(). lineto( 80. El argumento dy define la distancia relativa a moverse en la dirección vertical. closegraph().Bismarck Salvador Traña López__________________________________________ UNI La función moveto no retorna ningún valor. getch(). lineto( 80. } Función moverel. Después de que la línea recta haya sido dibujado. No se dibuja ya que el cursor es mudado. moveto( 20. "C:\\tc20\\BIN" ).h> #include <conio.modo = EGAHI. initgraph( &driver.h> void main() { int driver = EGA. Esta función es usada para mover la posición del cursor gráfico a una distancia relativa como los argumentos dx y dy. 90 ). } Función lineto. Estos valores pueden ser positivos o negativos. void far moverel(int dx. &modo. closegraph(). Ejemplo: #include <graphics. 60 ). initgraph( &driver. moveto( 20. 90 ). la posición del cursor gráfico es actualizado a la posición especificado por los argumentos x e y (el punto final de la línea). El argumento dx define la distancia relativa a moverse en la dirección horizontal. &modo. Ejemplo: #include <graphics.

moveto( 20. 20 ). &modo. initgraph( &driver. el grosor. closegraph(). "C:\\tc20\\bin" ). la posición del cursor gráfico es actualizado al último punto de la línea. y el color actual desde la posición actual del cursor gráfico a través de la distancia relativa especificada. La línea se dibuja usando el estilo de línea actual. El argumento dx especifica el número relativo de píxels para atravesar en la dirección horizontal. Estos argumentos pueden ser tanto valores positivos como negativos.modo = EGAHI. 30 ). &modo. moverel( 50. void far linerel(int dx. linerel( 20. linerel( 20. linerel( 40. "C:\\tc20\\bin" ). Esta función es usada para dibujar una línea recta a una distancia y dirección predeterminadas desde la posición actual del cursor gráfico.modo = EGAHI. closegraph(). 20 ). } Función getx. Cuando la línea esté terminada. } Función linerel. int dy). Juan Carlos Gutiérrez Barquero____________________________________________ 24 .Bismarck Salvador Traña López__________________________________________ UNI La función moverel no retorna ningún valor. moveto( 20. 40 ). getch(). Ejemplo: #include <graphics. initgraph( &driver.h> #include <conio.h> void main() { int driver = EGA. getch(). Ejemplo: #include <graphics. linerel( 40.h> #include <conio. La función linerel no retorna ningún valor. 50 ). 40 ). El argumento dy especifica el número relativo de píxels para atravesar en la dirección vertical.h> void main() { int driver = EGA. 30 ).

initgraph( &driver. closegraph(). &modo.h> #include <stdio.h> void main() { int driver = EGA. en la dirección vertical. x. Esta función es usada para obtener la posición.h> void main() { int driver = EGA. La función gety retorna la coordenada y del cursor gráfico. Esta función es usada para obtener la posición. del cursor gráfico. del cursor gráfico. Ejemplo: #include <graphics. relativo a la pantalla del usuario actual. El valor retornado especifica el lugar del píxel vertical del cursor gráfico (la coordenada y). El valor retornado especifica el lugar del píxel horizontal del cursor gráfico (la coordenada x).Bismarck Salvador Traña López__________________________________________ UNI int far getx(void).modo = EGAHI. "C:\\tc20\\BIN" ). x = getx(). y. closegraph(). x. La función getx retorna la coordenada x del cursor gráfico. 150 ). x = getx(). moveto( 300. Juan Carlos Gutiérrez Barquero____________________________________________ 25 . “C:\\TC20\\BIN” ). } Función gety. y ). y = gety(). relativo a la pantalla del usuario actual. y = gety().h. y. printf( "Cursor gráfico\n\nX: %d\tY: %d\n". x. x. printf( "Cursor gráfico\n\nX: %d\tY: %d\n". 150 ). Ejemplo: #include <graphics.h> #include <stdio. y ). moveto( 300. } Otras funciones de la librería graphics.modo = EGAHI. en la dirección horizontal. &modo. initgraph( &driver. int far gety(void).

/* Pausa */ closegraph().Bismarck Salvador Traña López__________________________________________ UNI En este capitulo describimos una a una las librerías de la librería graphics. bar3d( 100.modo = EGAHI. getch(). Ejemplo: #include <graphics. los argumentos derecha e inferior definen la esquina inferior derecha del rectángulo más frontal. Cuando sabemos como dibujar líneas. El rectángulo más frontal es rellenado usando la trama de relleno actual y el color de relleno como es establecido por la función setlinestyle. y otras figuras es hora de que empieces a conocer otro tipo de funciones en las cuales no hacen mucho énfasis los profesores como lo son las funciones bar3d. Dejemos de hablar y comencemos ya que los puedo aburrir. initgraph(&driver. int profundidad. rellenada con el color y estilo de línea actuales. palette y otras que presentan una gran gama de tareas de gran calidad grafica. La función bar3d no retorna ningún valor.&modo. setfillstyle( relleno. círculos. color ).h. El argumento banderin_tapa es usado para especificar si es o no es posible apilar varias barras encima de cada una. int banderin_tapa). 1 )."c:\\tc20\\bin").h> #include <conio. entonces la barra no está "tapada". Si banderin_tapa tiene un valor de cero. int superior. relleno = 11.color. int inferior.h> void main() { int driver = EGA. 150. entonces la barra está "tapada". Las funciones serán explicadas mediante un orden. La barra tiene borde. 25. 300. 50. en todas las tres dimensiones. permitiendo otras barras ser apiladas encima de ésta. Estos argumentos corresponden a los valores x e y de la esquina superior izquierda del rectángulo más frontal. getch(). Función bar3d void far bar3d(int izquierda. relleno. Esta función creará una barra rectangular y rellenada de tres dimensiones. Similarmente. } Función clearviewport void far clearviewport(void). color = 10. rectángulos. Juan Carlos Gutiérrez Barquero____________________________________________ 26 . Si banderin_tapa tiene un valor distinto a cero. La esquina superior izquierda de la barra rectangular más frontal está definida por los argumentos izquierdos y superiores.int derecha.

Bismarck Salvador Traña López__________________________________________ UNI Esta función es usada para rellenar la pantalla actual del usuario con el color de fondo actual. "C:\\tc20\\BIN" ). &b. 80 ).h> void main() { int a = EGA.h> void main() { int driver = EGA. circle( 300. "C:\\tc20\\BIN”).h> #include <conio. initgraph( &a.modo = EGAHI. El color de fondo puede ser establecido con la función setbkcolor. 150. setbkcolor( color ). 60 ). Ejemplo: #include <graphics. } getch(). color++ ) { circle( 100. clearviewport(). 350. /* Pausa */ closegraph(). &modo.h> #include <conio. Ejemplo: #include <graphics. getch(). Esta posición es (0. } Función detectgraph Juan Carlos Gutiérrez Barquero____________________________________________ 27 . 0 ). 100.b = EGAHI.0) según la pantalla actual del usuario. color<16. La función clearviewport no retorna ningún valor. /* Pausa */ closegraph(). for( color = 0. La posición del cursor gráfico es la esquina superior izquierda de la pantalla actual del usuario. 350. getch(). initgraph( &driver. } Función closegraph void far closegraph(void). La función closegraph no retorna ningún valor. setviewport( 150. getch().color. 200. La función closegraph libera toda la memoria usada por el sistema gráfico y luego restaura el modo de vídeo al modo de texto que estaba en uso anteriormente a la llamada a la función initgraph. Esta función es usada para cerrar el sistema gráfico como es iniciada por la función initgraph.

/* Pausa */ closegraph().h> #include <conio. getch(). &modo. pero no rellena el polígono. driver. int far *puntos).h> #include <stdio. el cual determina el driver óptimo a usar. o DETECT. inicia la Funciónalidad de auto detección. La función drawpoly no retorna ningún valor. si el argumento *driver es asignado el valor de 0. La función detectgraph no retorna ningún valor. initgraph( &driver. Si la función detectgraph no puede detectar ningún dispositivo gráfico. &modo. } Función drawpoly void far drawpoly(int numpuntos. La función drawpoly dibuja el perímetro del polígono con el estilo de línea y color actuales. Una llamada a graphresult resultará en un valor de retorno de -2. En otras palabras. modo. Ejemplo: #include <graphics. el argumento *modo es automáticamente establecido al modo de resolución mas alto para el driver. mientras que los dos siguientes especifican el siguiente punto. Existen varios valores que indican los diferentes dispositivos gráficos que pueden ser usados por el argumento *driver. Un valor de 0. Esta función es usada para crear un polígono con un número especificado de puntos. El argumento numpuntos es usado para definir el número de puntos en el polígono. circle( 300. modo ). printf( "Driver: %d\tModo: %d\n\n". el argumento *driver es asignado grNotDetected (-2). "C:\\tc20\\BIN" ). Para cada dispositivo existen varios valores que indican los diferentes modos gráficos que pueden ser usados por el argumento *modo. El argumento *puntos apunta a un array de números de longitud numpuntos multiplicado por 2.h> void main() { int driver. el primer punto debe ser igual al último punto. detectgraph( &driver. y así sucesivamente. 200. Los dos primeros miembros del array identifica las coordenadas x e y del primer punto. ). Ejemplo: #include <graphics. o DETECT. o grNotDetected. int far *modo). el número de puntos debe ser el número actual de puntos más 1 para poder crear un polígono cerrado. getch().Bismarck Salvador Traña López__________________________________________ UNI void far detectgraph(int far *driver. Esta función es usada para detectar el adaptador gráfico y el modo óptimo para usar con el sistema en uso. Sin embargo. 80 ).h> Juan Carlos Gutiérrez Barquero____________________________________________ 28 . Para la función drawpoly. respectivamente.

initgraph( &driver. trama = SOLID_FILL.h> void inicializar(void).Bismarck Salvador Traña López__________________________________________ UNI #include <conio. 50 }. drawpoly( 4. El argumento x_radio especifica el radio horizontal y el argumento y_radio especifica el radio vertical de la elipse. initgraph( &driver. 300. Ejemplo: #include <graphics. 300. getch(). int modo = EGAHI.h> void main() { int driver = EGA. 50. getch(). 300. void main() { int trama. } Función getarccords void far getarccoords(struct arccoordstype far *coordenadas_arco). &modo. /* Pausa */ closegraph().int x_radio. 150. setfillstyle( trama. color ). color. inicializar(). "C:\\tc20\\BIn" ). 100. color = 4. } void inicializar(void) { int driver = EGA. int y_radio). El centro de la elipse es especificado por los argumentos x e y. int puntos[8] = { 300. fillellipse( 300. Esta función es usada para dibujar y rellenar una elipse. Juan Carlos Gutiérrez Barquero____________________________________________ 29 . 500. &modo. puntos ). La función fillellipse no retorna ningún valor. getch().h> #include <conio. 100.modo = EGAHI. /* Pausa */ closegraph(). "C:\\tc20\\BIN" ). } Función fillellipse void far fillellipse(int x. 50 ). La elipse es dibujado con el perímetro en el color actual y rellenada con el color de relleno y la trama de relleno actuales.h> #include <stdio. int y.

Los miembros x e y definen el centro del arco. 315. Los miembros xstart e ystart definen las coordenadas x e y del punto de comienzo del arco.xstart. /* Pausa */ closegraph(). 45. yend. info_arco.xend. moveto( info_arco.yend ). int modo = EGAHI. "C:\\tc20\\BIN" ). y. La función getarccoords no retorna ningún valor. La proporción anchura-altura puede definirse como la proporción de la anchura del píxel del modo gráfico y la altura del píxel. radio+=25 ) { arc( 300. getch().ystart ). El argumento *coordenadas_arco apunta a la estructura de tipo arccoordstype que guarda la información recogida. struct arccoordstype info_arco. Esta proporción. lineto( info_arco. El valor para determinar la proporción anchura-altura con respecto al eje horizontal es retornado en el argumento *x_proporcion. El argumento *y_proporcion es asignado 10000. 150. &modo. int xstart. El argumento *x_proporcion es casi siempre menor que el valor de *y_proporcion. } getch(). Ejemplo: #include <graphics.h> void main() { int driver = EGA. int xend. Similarmente. } Función getaspectratio void far getaspectratio(int far *x_proporcion. }. el cual es retornado cuando se llama a la función getaspectratio. el valor para el eje vertical es retornado en el argumento *y_proporcion.Bismarck Salvador Traña López__________________________________________ UNI Esta función es usada para recoger las coordenadas del centro. radio<=100.h> #include <conio. usando los modos gráficos existentes. La sintaxis de la estructura arccoordstype es: struct arccoordstype { int x. for( radio=25. Esta función es usada para obtener la proporción anchura-altura del modo gráfico actual. ystart.int far *y_proporcion). info_arco. los miembros xend e yend definen las coordenadas x e y del punto de final del arco. es siempre menor o igual que 1. initgraph( &driver. Similarmente. radio ). Esto es debido al hecho de que la mayoría de los Juan Carlos Gutiérrez Barquero____________________________________________ 30 . y los puntos del comienzo y final de la última llamada con éxito a la función arc. getarccoords( &info_arco ).radio.

color = getcolor(). El valor del color obtenido es interpretado según el modo que esté en uso. int modo = EGAHI. getch(). 50 ). Esta función obtiene el valor del color actual. x_proporcion. La función getcolor retorna el valor del color actual.. y_proporcion ).h> void main() { int driver = EGA.h> #include <stdio.color. initgraph( &driver. /* Pausa */ closegraph(). directamente. es decir. initgraph( &driver. getaspectratio( &x_proporcion. /* Pausa */ closegraph().\nFactor x: %d\tFactor y: %d\n". Existen varios valores para ciertos colores de fondo. y_proporcion. Este color no es el mismo que el color de relleno. getch(). getch(). El color actual es el color usado para dibujar líneas.h> #include <conio. int x_proporcion. &modo. modo = EGAHI. 150. printf( "Color del perímetro: %d\n". } Juan Carlos Gutiérrez Barquero____________________________________________ 31 . circle( 300. etc. "C:\\Tc20\\BIN" ). getch(). x_proporcion = y_proporcion. arcos.h> #include <stdio.Bismarck Salvador Traña López__________________________________________ UNI modos gráficos tiene píxeles más altos que anchos. Ejemplo: #include <graphics. circle( 300. &y_proporcion ). } Función getcolor int far getcolor(void). 150.h> #include <conio. printf( "Proporción anchura-altura. 50 ). color ). &modo.h> void main() { int driver = EGA. La única excepción es en los modos de VGA que produce píxeles cuadrados. "C:\\tc20\\BIN" ). Ejemplo: #include <graphics. La función getaspectratio no retorna ningún valor. setcolor( 4 ).

&modo. cuando se llama a initgraph. %d". Juan Carlos Gutiérrez Barquero____________________________________________ 32 . getch(). El campo colors contiene los valores numéricos que representan los colores que ofrece el dispositivo en su paleta de colores. printf( "\n" ).h> #include <stdio. La estructura palettetype se define de la siguiente manera: #define MAXCOLORS 15 struct palettetype { unsigned char size. /* Pausa */ closegraph().h> void main() { int driver = EGA. i++ ) printf( ". "C:\\tc20\\BIN" ). 150. Esta función es usada para obtener una estructura que define la paleta según el dispositivo en la inicialización . palette->colors[0] ). signed char colors[MAXCOLORS+1]. circle( 300.Bismarck Salvador Traña López__________________________________________ UNI Función getdefaultpalette struct palettetype far *getdefaultpalette(void). Ejemplo: #include <graphics. int modo = EGAHI. } Función getdrivename char *far getdrivername(void). } El campo size indica el tamaño de la paleta. int i. La función getdefaultpalette retorna un puntero a una estructura del tipo palettetype.esto es. palette = getpalettetype(). printf( "Paleta\n\nTamaño: %d\nColores: %d". palette->colors[i] ). initgraph( &driver. palette->size. for( i=1. struct palettetype *palette = NULL. getch(). i<palette->size.h> #include <conio. 50 ).

150. 0x33. 0x00.Bismarck Salvador Traña López__________________________________________ UNI Esta función es usada para obtener una cadena de caracteres que contiene el nombre del dispositivo gráfico actual. Cada byte representa una fila de ocho bits. como es definida por la función setfillpattern.} Función getfillpattern void far getfillpattern(char far *trama). después de llamar a initgraph. int modo = EGAHI. initgraph( &driver. 0x00. 50. La función getdrivername retorna una cadena de caracteres conteniendo el nombre del dispositivo gráfico. initgraph( &driver.h> void main() { int driver = EGA. char trama1[8] = { 0x33.h> void main() { int driver = EGA. nombre ). char trama2[8] = { 0x00. "C:\\tc20\\BIN" ). 150 ). "C:\\tc20\\bin" ). 9 ). getch().h> #include <stdio. Un bit de 0 indica que el píxel correspondiente será asignado el color de relleno actual. Un bit de 0 indica que el píxel correspondiente no será alterado. 50 ). circle( 300. Juan Carlos Gutiérrez Barquero____________________________________________ 33 . 0x00. 0xEE. 0x33.h> #include <conio. bar( 50. Ejemplo: #include <graphics. &modo. La función getfillpattern no retorna ningún valor. 0xEE. strcpy( nombre. 0x00.h> #include <string. Esta función es usada para obtener una trama de relleno definido por el usuario. Ejemplo: #include <graphics. directamente. 150. printf( "Nombre del dispositivo gráfico: %s\n". 0x33. getdrivername() ). donde cada bit está encendido o no (1 ó 0). 0xEE }. 0x00. setfillpattern( trama1. char *nombre. y la guarda en memoria. Esta función debería ser llamada después de que un dispositivo haya sido definido e inicializado – esto es. &modo. 0xEE. El argumento *trama es un puntero a una serie de ocho bytes que representa una trama de relleno de bits de 8 x 8. getfillpattern( trama2 ). 0x00 }. modo = EGAHI.h> #include <conio. 0x00. getch(). /* Pausa */ closegraph().

h> #include <conio. printf( "Trama de relleno: %d\tColor de relleno: %d\n".Bismarck Salvador Traña López__________________________________________ UNI bar( 160. getch(). el cual es actualizado cuando se llama a la función getfillsettings. 4 ). Esta función es usada para obtener la información de tramas de relleno.h> void main() { int driver = EGA. directamente. 150 ). La función getfillsettings no retorna ningún valor.color ). } Función getgraphmode int far getgraphmode(void). /* Pausa */ closegraph(). getch(). 160. 50. info. getch(). struct fillsettingstype info. "C:\\tc20\\BIN" ). 260. La estructura es: struct fillsettingstype { int pattern. getfillsettings( &info ). int color. El campo pattern es la trama y el campo color es el color de relleno de la trama. 205. bar( 105. Juan Carlos Gutiérrez Barquero____________________________________________ 34 . Ejemplo: #include <graphics. &modo. getch(). El argumento *info apunta a una estructura de tipo fillsettingstype. int modo = EGAHI. setfillpattern( trama2.pattern. bar( 50.h> #include <stdio. 300 ). info. } Función getfillsettings void far getfillsettings(struct fillsettingstype far *info). 350. 50. initgraph( &driver. }. 260 ). /* Pausa */ closegraph(). Existen trece valores ya definidos para tramas.

unsigned upattern. El campo upattern es la trama de la línea del usuario solamente cuando el campo linestyle es igual a USERBIT_LINE. /* Pausa */ closegraph().h> #include <conio. trama. } El campo linestyle es el estilo de la línea recta. Esta función obtiene la información actual para las líneas.Bismarck Salvador Traña López__________________________________________ UNI Esta función es usada para obtener el valor del modo gráfico actual. 50. &modo.h> #include <stdio. Existen varios valores para los diferentes estilos y grosores de líneas rectas. Esta información es guardada en una estructura de tipo linesettingstype que es apuntado por el argumento *info. modo ). modo = EGAHI. El campo thickness es el grosor de la línea. } Función getlinesettings void far getlinesettings(struct linesettingstype far *info). getch(). initgraph( &driver. "C:\\tc20\\BIN" ). El estilo de línea. getch(). int thickness. Ejemplo: #include <graphics. bar( 50. directamente. modo = getgraphmode(). Cuando esto sea el caso. El dispositivo actual debe ser considerado cuando se interprete el valor de retorno.modo. Ejemplo: Juan Carlos Gutiérrez Barquero____________________________________________ 35 . La sintaxis para la estructura linesettingstype: struct linesettingstype { int linestyle. Esta función sólo debería ser llamada después de que el sistema gráfico haya sido inicializado con la función initgraph. La función getlinesettings no retorna ningún valor. 350. el miembro upattern contiene una trama de línea definido por el usuario de 16 bits. ó 4. printf( "Modo gráfico: %d\n". y grosor actuales son guardados en esta estructura. La función getgraphmode retorna el modo gráfico como es establecido por initgraph o setgraphmode. Existen varios valores para los modos de cada dispositivo. Un bit 0 indica que el píxel correspondiente no será alterado. Un bit 1 en esta trama indica que el píxel correspondiente será asignado el color actual. 300 ).h> void main() { int driver = EGA.

printf( "Líneas rectas. Para los modos de 16 colores. info. Similarmente.color_max. La función getmaxcolor retorna el valor máximo del color en la paleta en uso. getch(). int modo = EGAHI. "C:\\tc20\\bin" ). struct linesettingstype info. getch().modo =EGAH. getch().\nEstilo: %d\tTrama: %X\tGrosor: %d\n". para los modos de dos colores. 0xFF33. getlinesettings( &info ).upattern. setlinestyle( DOTTED_LINE. el valor de retorno es 1. 250. "C:\\tc20\\BIN" ). } Función getmaxcolor int far getmaxcolor(void). 50 ). info. La paleta en uso depende del dispositivo y modo inicializados.h> #include <conio. color_max = getmaxcolor().h> #include <stdio. initgraph( &driver. /* Pausa */ closegraph(). info. printf( "Color m ximo: %d\n". Esta función es usada para obtener el valor más alto de color en la paleta actual. el valor de retorno es 15.thickness ). closegraph(). &modo. color_max ).h> #include <stdio. Ejemplo: #include <graphics. circle( 350.h> void main() { int driver =EGA. } Función getmodename char *far getmodename(int num_modo). initgraph( &driver.linestyle.h> #include <conio.h> void main() { int driver = EGA. &modo. Juan Carlos Gutiérrez Barquero____________________________________________ 36 .Bismarck Salvador Traña López__________________________________________ UNI #include <graphics. THICK_WIDTH ).

La función getmodename retorna el nombre del modo gráfico que está contenido en todos los dispositivos gráficos. &modo_bajo. strcpy(nombre. &modo_alto ). int far *modo_bajo.nombre[i]). El valor más bajo del modo es retornado en *modo_bajo. modo_alto.i. y el valor más alto del modo es retornado en *modo_alto.getmodename(num_modo)). closegraph().h> #include <stdio.h> #include <string. directamente. int modo = IBM8514HI. el valor de -1 es retornado en ambos argumentos: *modo_bajo y *modo_alto. La función getmoderange no retorna ningún valor. } Función getmoderange void far getmoderange(int driver. Ejemplo: #include <graphics. Juan Carlos Gutiérrez Barquero____________________________________________ 37 . &modo.Bismarck Salvador Traña López__________________________________________ UNI Esta función es usada para obtener el nombre del modo gráfico especificado por el argumento num_modo. for(i=0. los modos alto y bajo del dispositivo actual son retornados. initgraph( &driver. num_modo = getgraphmode(). closegraph().i++) printf("%c". getmoderange( driver.h> #include <conio.h> void main() { int driver = IBM8514. Esta función es usada para obtener los valores altos y bajos del modo gráfico del dispositivo especificado por el argumento driver. &modo.h> void main() { int driver = EGA.h> #include <conio. initgraph( &driver."C:\\TC20\\BIN"). int far *modo_alto). Si el dispositivo especificado es inválido.nombre[i]. si el argumento driver es asignado -1. “C:\\TC20\\BIN” ). int modo_bajo. int num_modo. int modo = EGAHI. Ejemplo: #include <graphics.h> #include <stdio. char *nombre. getch(). Sin embargo.

palette. de %d á %d\n". ". modo_bajo. } Función getpalette void far getpalette(struct palettetype far *paleta).palette. Juan Carlos Gutiérrez Barquero____________________________________________ 38 . La función getpalette no retorna ningún valor. i<palette.h> void main() { int driver = EGA. for( i=1. getpalette( &palette ).". La estructura palettetype se define de la siguiente manera: #define MAXCOLORS 15 struct palettetype { unsigned char size. closegraph(). } El campo size indica el número de colores en la paleta.colors[i] ). "C:\\TC20\\BIN" ). El argumento *paleta apunta a una estructura del tipo palettetype donde la información de la paleta es guardada. palette.h> #include <conio. El campo colors contiene los valores numéricos que representan los colores que ofrece el dispositivo en su paleta de colores.size).colors[0] ). getch(). printf( "\t\t\t\t\tPaleta\n\nTama¤o: %d\n". directamente. initgraph( &driver. struct palettetype palette. } Función getpalettesize int far getpalettesize(void).Bismarck Salvador Traña López__________________________________________ UNI printf( "Alcance de modos.size.h> #include <stdio. modo_alto ). &modo. printf( "\n" ). signed char colors[MAXCOLORS+1]. printf("Colores: %d. Ejemplo: #include <graphics.i. i++ ) printf( "%d. int modo = EGAHI. Esta función es usada para obtener la información de la paleta actual. getch().

y. x. getch().h> #include <conio. 50.h> #include <conio. fillellipse( 300. initgraph( &driver. int modo = EGAHI. int num_colores. el modo gráfico en uso debe ser considerado. getch(). La función getpalettesize retorna el número de colores en la paleta actual. getch(). num_colores ). closegraph().%d): %d\n". &modo. Ejemplo: #include <graphics. color ). Cuando se evalúa el valor del color retornado. y ). la función getpalettesize retorna 16. printf( "Colores\n\nEl color del píxel (%d.Bismarck Salvador Traña López__________________________________________ UNI Esta función es usada para obtener el número de entradas de paleta válidas para la paleta actual. initgraph( &driver. int y).h> #include <stdio. y. modo = EGAHI. La función getpixel retorna el número del color del píxel especificado. y = 100. closegraph(). Ejemplo: #include <graphics. setfillstyle( SOLID_FILL. Esta función es usada para obtener el valor del color del píxel especificado por los argumentos x e y. “C:\\TC20\\BIN” ). “C:\\TC20\\BIN” ). x = 300.h> void main() { int driver = EGA. considerando el modo gráfico en uso. Estos argumentos especifican las coordenadas de la pantalla del píxel a ser evaluado.h> #include <stdio. Para modos de 16 colores. Existen varios valores para describir colores. } Función getpixel unsigned far getpixel(int x. 160. color. Juan Carlos Gutiérrez Barquero____________________________________________ 39 . 2 ). printf( "Paleta\n\nNúmero de colores: %d\n". num_colores = getpalettesize(). color = getpixel( x.h> void main() { int driver = EGA. 150 ). x. &modo.

la orientación del texto.h> # include<conio. info. int direction. info.font. "C:\\TC20\\BIN" ).charsize. Existen varios valores para describir el tipo. } Función getviewsettings void far getviewsettings(struct viewporttype far *info). Esta función es usada para obtener información acerca del área gráfica actual. la orientación. int modo = EGAHI. La síntaxis de la estructura viewporttype es la siguiente: Juan Carlos Gutiérrez Barquero____________________________________________ 40 .h> void main() { int driver = EGA.vert). int charsize. Esta estructura contiene información acerca de las esquinas superior izquierda e inferior derecha. la cual es apuntada por el argumento *info. info.direction. también como el banderín de recorte del área gráfica. Esta información es guardada en una estructura de tipo viewporttype. printf( "Texto\n\nFuente: %d\tSentido: %d\tTamaño: %d\n""Justificación:\nHorizontal: %d. closegraph(). info. gettextsettings( &info ). getch().h> #include <stdio.horiz. int vert. y la justificación horizontal y vertical. La función gettextsettings no retorna ningún valor. La síntaxis de la estructura textsettingstype es la siguiente: struct textsettingstype { int font. int horiz. }. el tamaño del carácter. Ejemplo: #include <graphics. Esta información es guardada en una estructura de tipo textsettingstype. la cual es apuntada por el argumento *info. Esta función es usada para obtener información acerca de la fuente gráfica actual. Vertical: %d\n". y justificación de fuentes. struct textsettingstype info. info. Esta estructura contiene información de la fuente actual en uso.Bismarck Salvador Traña López__________________________________________ UNI } Función gettextsettings void far gettextsettings(struct textsettingstype far *info). initgraph( &driver. &modo.

150. top. La función graphdefaults reinicia la pantalla del usuario para que cubra la pantalla entera. reinicia el estilo y trama de relleno a sus valores por defecto. modo = VGAHI. y reinicia la fuente y justificación de texto. &modo. 350. La función getviewsettings no retorna ningún valor. La función graphdefaults no retorna ningún valor. printf( "\t\t\t\tPantalla\n\nIzquierda: %d\tSuperior: %d\tDerecha: %d\t" "Inferior: %d\tBander¢n: %d\n". Esta función es usada para reiniciar todos los datos gráficos a sus valores originales. Juan Carlos Gutiérrez Barquero____________________________________________ 41 .top. &modo. setcolor( 4 ). bottom. info.0). int clip. y reinicia la paleta actual a sus colores por defecto. 250. info. 50 ). "C:\\TC20\\BIN" ). También reinicia el color de fondo y el actual a sus valores por defecto.h> # include<conio. int right. 200. initgraph( &driver. Ejemplo: #include <graphics. directamente. initgraph( &driver. int modo = VGAHI.Bismarck Salvador Traña López__________________________________________ UNI struct viewporttype { int left. getviewsettings( &info ).right.bottom. mueve el cursor a la posición (0.left.h> void main() { int driver = VGA. struct viewporttype info. "C:\\TC20\\BIN" ). info. }. info. graphdefaults().h> #include <conio. Ejemplo: #include <graphics. closegraph(). setviewport( 250.h> void main() { int driver = VGA. getch(). info.clip ). } Función graphdefaults void far graphdefaults(void).h> #include <stdio. circle( 300. o por defecto. 1 ).

strcpy( mensaje_error. getch(). } Función graphfreemem void far _graphfreemem(void far *ptr. closegraph(). La forma de hacer esto es simplemente creando la definición de la función. initgraph( &driver. Por defecto. La función graphresult debe ser usada para obtener el código de error usado para el argumento codigo_error. la función simplemente llama a free. con el mismo prototipo mostrado aquí. Esta función es llamada por la librería gráfica cuando se quiere liberar memoria.h> Juan Carlos Gutiérrez Barquero____________________________________________ 42 .h> #include <stdio. } Función grapherrormsg char *far grapherrormsg(int codigo_error). unsigned tamanyo). mensaje_error.h> void main() { int driver = EGA. Ejemplo: #include <graphics. closegraph(). &modo. “C:\\TC20\\BIN” ). Esta función es usada para obtener una cadena de caracteres conteniendo el mensaje de error para un código de error especificado. int codigo_error. Esta función es usada por la librería gráfica para desadjudicar memoria previamente reservada mediante una llamada a la función _graphgetmem. grapherrormsg( codigo_error ) ). pero se puede controlar la administración de memoria de la librería gráfica. getch(). Ejemplo: #include <graphics. /* Creamos un ERROR */ codigo_error = graphresult(). printf( "ERROR: \"%s\" (%d)\n". int modo = EGAHI. setgraphmode( 40 ). El argumento codigo_error específica el valor del código de error.Bismarck Salvador Traña López__________________________________________ UNI getch().h> #include <conio. char *mensaje_error. codigo_error ). La función _graphfreemem no retorna ningún valor. La función grapherrormsg retorna una cadena de caracteres.

initgraph( &driver.. pero se puede controlar la administración de memoria de la librería gráfica. } void far * far _graphgetmem( unsigned tamanyo ) { printf( "__graphgetmem ha sido llamado para " "adjudicar %d bytes en memoria\n" ). circle( 200. dispositivos gráficos. closegraph().modo = EGAHI. free( ptr ). } Función graphgetmem void far * far _graphgetmem(unsigned tamanyo). return malloc( tamanyo ).. printf( "para el montón (heap) interno\n". printf( "para el montón (heap) interno\n".h> #include <stdio. con el mismo prototipo mostrado aquí. getch(). la función simplemente llama a malloc.. printf( "Pulse cualquier tecla. unsigned tamanyo ) { printf( "__graphfreemem ha sido llamado para " "desadjudicar %d bytes en memoria\n" ). getch(). La forma de hacer esto es simplemente creando la definición de la función. 100. Por defecto.. &modo.h> void far _graphfreemem( void far *ptr. getch().h> void far _graphfreemem( void far *ptr. Esta función es usada por la librería gráfica para adjudicar memoria gráfica para búferes internos. “C:\\TC20\\BIN” ).h> #include <stdlib. printf( "para el montón (heap) interno\n".Bismarck Salvador Traña López__________________________________________ UNI #include <conio. Juan Carlos Gutiérrez Barquero____________________________________________ 43 .h> #include <conio. tamanyo ). } void main() { int driver = EGA.\n\n" ). tamanyo ). Esta función tiene como intención ser llamada por la librería gráfica cuando se quiere adjudicar memoria.h> #include <stdio. 50 ). getch(). tamanyo ).\n\n" ). printf( "Pulse cualquier tecla. La función _graphgetmem no retorna ningún valor. Ejemplo: #include <graphics.h> #include <stdlib. y fuentes. unsigned tamanyo ) { printf( "__graphfreemem ha sido llamado para " "desadjudicar %d bytes en memoria\n" ).

char *mensaje_error.. "C:\\TC20\\BIN" ). printf( "ERROR: \"%s\" (%d)\n". setgraphmode( 40 ). printf( "Pulse cualquier tecla. } Función graphresult int far graphresult(void).. tamanyo ). getch(). Ejemplo: #include <graphics.. o grOk. codigo_error ). getch(). reinicia el nivel de error a 0.h> void main() { int driver = EGA. return malloc( tamanyo ). closegraph(). getch(). mensaje_error. Existen varios valores de códigos de error. } Función installuserdriver Juan Carlos Gutiérrez Barquero____________________________________________ 44 . La función graphresult retorna el código de error de la última llamada gráfica sin éxito.\n\n" ). closegraph().h> #include <stdio. free( ptr ). printf( "para el montón (heap) interno\n".Bismarck Salvador Traña López__________________________________________ UNI printf( "Pulse cualquier tecla. initgraph( &driver. } void far * far _graphgetmem( unsigned tamanyo ) { printf( "__graphgetmem ha sido llamado para " "adjudicar %d bytes en memoria\n" ). modo = EGAHI. initgraph( &driver. /* Creamos un ERROR debe de ser 0 o 1*/ codigo_error = graphresult(). getch(). &modo. int modo = EGAHI. 100. circle( 200. “C:\\TC20\\BIN” ). int codigo_error. strcpy( mensaje_error. } void main() { int driver = EGA. Esta función obtiene y retorna el código de error para la última llamada sin éxito. &modo. Además. grapherrormsg( codigo_error ) ). 50 ).h> #include <conio.. getch().\n\n" ).

return grError. Esta función permite al usuario añadir dispositivos adicionales de otras compañías o grupos a la tabla interna BGI de los dispositivos. closegraph(). /* Forzamos a que use nuestra función para autodetectar */ driver = DETECT. en el directorio de inicio. modo. &modo ). if( SMGGA == driver ) return modo_sugerido. detectgraph( &driver. El argumento *nombre define el nombre del fichero nuevo del dispositivo . /* Intentamos instalar nuestra tarjeta gráfica: ** Súper Mega Guay Graphics Array (SMGGA) ** Ya sé que suena muy cursi. “C:\\TC20\\BIN” ). Ejemplo: /* Este programa no Funcionará. modo_sugerirdo=0. Esto sólo es para poner un ejemplo. Esta función carga un fichero de fuente escalable que no está provisto con el sistema BGI. El sistema gráfico puede tener hasta veinte fuentes instaladas a la vez. modo. } void main() { int driver. La función de autodetectación espera no recibir ningún parámetro y retorna un valor entero. Juan Carlos Gutiérrez Barquero____________________________________________ 45 . El parámetro *nombre especifica el nombre del fichero fuente a cargar.Bismarck Salvador Traña López__________________________________________ UNI int far installuserdriver(char far *nombre. } Función installuserfont int far installuserfont(char far *nombre). pero esto sólo es un ejemplo :) */ driver = installuserdriver( "SMGGA". El parámetro *detectar es un puntero a una función opcional para autodetectar que puede ser o no ser provisto con el dispositivo nuevo. int huge (*detectar)(void)).h> int huge detectarSMGGA( void ) { int driver.BGI. getch(). initgraph( &driver. detectarSMGGA ). &modo. ya que se necesitaría otra tarjeta gráfica desconocida por las librerías gráficas de BGI.*/ #include <graphics.h> #include <conio. La función installuserdriver retorna el parámetro del número del dispositivo que hubiese sido pasado a la función initgraph para seleccionar un dispositivo nuevo.

} closegraph().h> void main() { int driver = EGA. */ #include <graphics. int fuente_SMCF. getch(). HORIZ_DIR. Si la tabla interna de fuentes está llena. pero esto sólo es un ejemplo :) */ if( (fuente_SMGF = installuserfont( "SMGF. La función kbhit retorna 0 si no se ha registrado una pulsada de tecla. entonces el valor retornado es distinto a cero. * Esto sólo es para poner un ejemplo.getch(). &modo. si lo fue. Ejemplo /* Este programa no Funcionará. printf("Instalación completada")."C:\\TC20\\BIN" ). } Función kbhit int kbhit(void).getch(). indicando un error. para utilizar esta función se tiene que declarar la cabecera conio.h> # include<conio. HORIZ_DIR. initgraph( &driver. 4 ). Veremos el uso de esta función en el modo grafico. Revisa si se ha presionado una tecla.Bismarck Salvador Traña López__________________________________________ UNI La función installuserfont retorna el número de identificación de la fuente que es usada para seccionar la fuente nueva a través de la función settextstyle. Cualesquier pulsadas disponibles pueden ser recogidas con las Funciones getch o getche. un valor de -11 (grError) es retornado.h> #include<stdio.h Ejemplo: Juan Carlos Gutiérrez Barquero____________________________________________ 46 . /* Intentamos instalar nuestra fuente nueva: ** Súper Mega Chula Fuente (SMCF) ** Ya sé que suena muy cursi. 4 ).CHR" )) != grError ){ settextstyle( fuente_SMGF. ya que se * necesitaría tener una fuente nueva * y desconocida por las librerías gráficas de BGI. printf("Error de al instalar la aplicación").} else{ settextstyle( DEFAULT_FONT. int modo = EGAHI.

initgraph( &driver. “C:\\TC20\\BIN” ). "Hola %s!". La posición del cursor permanece sin ser cambiado al menos que la justificación horizontal actual es LEFT_TEXT y la orientación del texto es HORIZ_DIR. Juan Carlos Gutiérrez Barquero____________________________________________ 47 . initgraph( &driver.h> # include <dos. rectangle(10+i. &modo. texto con formato puede ser mostrada a través del uso de un búfer de caracteres y la función sprintf. nombre ). Cuando esto sea el caso. setcolor(BLUE). sprintf( mensaje.h> void main() { int driver = EGA. printf( "Escribe tu nombre: " ). char mensaje[40]. la posición del cursor es colocada horizontalmente a la anchura del píxel de la cadena de texto. valores. scanf( "%s". y justificaciones de texto. El argumento *cadena_texto define la cadena de texto a ser mostrado. &modo. outtext( mensaje ).h> #include <stdio.i.20. dirección. cualquier texto que se extiende a fuera del área gráfica actual es truncado. }while(!kbhit()).100). int modo = EGAHI. int modo = EGAHI.h> void main() { int driver = EGA. La cadena es mostrado donde está el cursor gráfico actualmente usando el color actual y fuente. La función outtext no retorna ningún valor. Además.BLUE). cuando se use la fuente por defecto. i++.Bismarck Salvador Traña López__________________________________________ UNI #include <graphics. Ejemplo: #include <graphics.h> #include <stdio. floodfill(20. setfillstyle(i. "C:\\TC20\\BIN" ). Aunque la función outtext está diseñada para texto sin formato. char nombre[25].BLUE). i=1.100+i.10. Esta función es usada para mostrar una cadena de caracteres.h> #include <conio. } Función outtext void far outtext(char far *cadena_texto). do{ delay(30000).h> #include <conio. nombre ).

La cadena es mostrada en la posición descrita por los argumentos x e y usando el color actual y fuente. getch(). scanf( "%s". int final_angulo. char far *cadena_texto). La porción circular de la cuña comienza con el ángulo especificado por el argumento comienzo_angulo y se extiende en un sentido contrario a las agujas del reloj al ángulo especificado por el argumento final_angulo. printf( "Escribe tu nombre: " ). } Función outtextxy void far outtextxy(int x. 150.h> void main() { int driver = EGA. int y. valores. closegraph(). Cuando se use la fuente por defecto. cualquier texto que se extiende fuera del área gráfica actual es truncado. Esta función es usada para dibujar y rellenar un una cuña circular. int modo = EGAHI. mensaje ). Ejemplo: #include <graphics. Esta función es usada para mostrar una cadena de caracteres. La cuña circular está centrada en el punto especificado por los argumentos x e y.Bismarck Salvador Traña López__________________________________________ UNI outtextxy( 300. mensaje ). La función outtextxy no retorna ningún valor.int comienzo_angulo. texto con formato puede ser mostrada a través del uso de un búfer de caracteres y la función sprintf.h> #include <stdio. sprintf( mensaje. dirección. Aunque la función outtextxy está diseñada para texto sin formato. "Hola %s!". char mensaje[40]. } Función pieslice void far pieslice(int x. closegraph(). getch(). initgraph( &driver. outtextxy( 300.h> #include <conio. 150. &modo. nombre ). La función pieslice considera este – el eje horizontal a la derecha del centro Juan Carlos Gutiérrez Barquero____________________________________________ 48 . char nombre[25]. y justificaciones de texto. int radio). El argumento *cadena_texto define la cadena de texto a ser mostrado. outtext( mensaje ). “C:\\TC20\\BIN” ). getch(). getch(). int y. nombre ).

“C:\\TC20\\BIN” ).EXE no depende de un fichero externo de dispositivo para poder ejecutarse. getch(). "C:\\TC20\\BIN" ). un número negativo. getch(). 20.h> void main() { int driver = EGA. &modo. getch(). pieslice( 300. initgraph( &driver. Registrando el dispositivo de esta manera. 45. Un código de error. el fichero . La función registerbgidriver retorna número del dispositivo cuando tiene éxito. 225. /* Pausa */ closegraph(). rectangle( 20. Ejemplo: #include <graphics.OBJ y ligado (o enlazado) dentro del programa. La función pieslice no retorna ningún valor. 150. registerbgidriver(IBM8514LO). 50 ).Bismarck Salvador Traña López__________________________________________ UNI – como su punto de referencia de 0 grados. es retornado si el dispositivo especificado es inválido. 300 ). initgraph( &driver.h> #include <conio. getch(). Esta función es usada para cargar y registrar un dispositivo gráfico. } Función registerbgidriver int registerbgidriver(void (*driver)(void)). Ejemplo: #include <graphics. Un fichero de dispositivo registrado puede ser tanto cargado desde el disco o convertido en un formato . /* Pausa */ closegraph(). int modo = EGAHI. } Juan Carlos Gutiérrez Barquero____________________________________________ 49 . El argumento *driver apunta a un dispositivo. El perímetro de la cuña es dibujado con el color actual y es rellenado con la trama y color de relleno actual. 400. int modo = EGAHI.h> #include <conio.h> void main() { int driver = EGA. &modo.

no es necesario ligarlo al programa. “C:\\TC20\\BIN” ). Nota: La fuente de defecto es la única que está disponible en el programa.h> #include <conio. La función restorecrtmode no retorna ningún valor. int modo = EGAHI. un número negativo. getch(). Registrando la fuente de esta manera. } Función restorecrtmode void far restorecrtmode(void). &modo.h> #include <stdio. Ejemplo: #include <graphics. Un código de error.h> void main() { int driver = EGA. outtext( "Esto es una prueba para cambiar entre modo gráfico. initgraph( &driver. Juan Carlos Gutiérrez Barquero____________________________________________ 50 . getch().OBJ y ligado (o enlazado) dentro del programa. el fichero . Ejemplo: #include <graphics. Esta función es usada para informar al sistema que la fuente apuntada por el argumento *fuente fue incluida durante el enlazo.Bismarck Salvador Traña López__________________________________________ UNI Función registerbgifont int registerbgifont(void (*fuente)(void)). &modo.h> #include <conio. outtext( "Esto es una prueba con la fuente \"Sans Serif\"" ). Un fichero de fuente registrado ha de ser convertido en un fichero objeto . int modo = EGAHI. es retornado si el dispositivo especificado es inválido. /* Pausa */ closegraph(). Esta función es usada para reiniciar el modo gráfico del vídeo al modo en uso anterior a la inicialización del sistema gráfico. registerbgifont(1)."C:\\TC20\\BIN" ). Esta función suele ser usada en conjunción con la función setgraphmode para cambiar entre ambos modos de texto y de gráficos.EXE no depende de un fichero externo de fuentes para poder ejecutarse.. initgraph( &driver.." ).h> void main() { int driver = EGA. La función registerbgifont retorna número del dispositivo cuando tiene éxito. ya que forma parte del sistema gráfico.

setfillstyle( SOLID_FILL.h> #include <conio. /* Pausa */ closegraph(). int final_angulo. } Función sector void far sector(int x. } Función setactivepage void far setactivepage(int pagina). 50 ). 100. restorecrtmode(). Esta función es usada para dibujar y rellenar la parte de una elipse. int y_radio).h> void main() { int driver = EGA. &modo. getch(). El argumento x_radio especifica el radio horizontal y el argumento y_radio especifica el radio vertical de la cuña elíptica. El argumento pagina específica el número de la página activa. int comienzo_angulo. getch(). int x_radio. sector( 300. La cuña elíptica es dibujado con el perímetro en el color actual y rellenada con el color de relleno y la trama de relleno actuales. -45. Esta función es usada para especificar un número de página que representa una sección de memoria del vídeo donde todos los datos gráficos para mostrar son enviados. int modo = EGAHI.y en modo texto. 150. getch(). Para usar esta función con eficacia.\nPulsa una tecla para volver\n" ). 6 ). Esta función es usada con la función setvisualpage para dibujar páginas no visuales y para crear animación. 45. Está sección de memoria se denomina una página activa. int y. Juan Carlos Gutiérrez Barquero____________________________________________ 51 . Ejemplo: #include <graphics. el adaptador de vídeo usado debe ser EGA o VGA y tener suficiente memoria para soportar múltiples páginas para gráficos. printf( ". La función sector no retorna ningún valor. rectangle( 200. 400. 150.. 250 ). /* Pausa */ closegraph().Bismarck Salvador Traña López__________________________________________ UNI getch(). “C:\\TC20\\BIN” ). getch().. La cuña elíptica comienza al ángulo especificado por el argumento comienzo_angulo y es dibujado en la dirección contraria al de las agujas del reloj hasta llegar al ángulo especificado por el argumento final_angulo. setgraphmode( modo ). El centro de la cuña elíptica es especificado por los argumentos x e y. initgraph( &driver. getch().

sector( 300.h> #include <conio. 50 ). 90. printf( "(Pulsa cualquier tecla para entrar en modo gráfico)\n" ). int visual=1. 150. signed char colors[MAXCOLORS+1]. 45. initgraph( &driver. 150. } El campo size indica el número de colores de la paleta actual. getch(). 270. cualquier otra tecla para salir\n" ). setfillstyle( SOLID_FILL. getch(). setfillstyle( SOLID_FILL. El campo colors es un array que contiene los valores numéricos que representan los colores que ofrece el dispositivo en su paleta de colores. el valor del color de ese elemento no cambiará. setactivepage( 0 ). sector( 300.h> #include <stdio. La síntaxis de la estructura palettetype es: #define MAXCOLORS 15 struct palettetype { unsigned char size. } Función setallpalette void far setallpalette(struct palettetype far *paleta). 50 ). 315. Todos los colores de la paleta actual son asignados a aquéllos definidos en la estructura palettetype. &modo. setactivepage( 1 ). 6 ). Si la entrada de cualquier elemento del array es -1. printf( "Instrucciones:\nPulsa el espacio para cambiar de " "página.h> void main() { int driver = EGA.Bismarck Salvador Traña López__________________________________________ UNI La función setactivepage no retorna ningún valor. "C:\\TC20\\BIN" ). 6 ). while( getch() == ' ' ) { setvisualpage( visual ). 150. Juan Carlos Gutiérrez Barquero____________________________________________ 52 . } closegraph(). Ejemplo: #include <graphics. Esta función es usada para asignar la paleta actual a la paleta definida en la estructura del tipo palettetype que es apuntado por el argumento *paleta. visual = 0==visual ? 1 : 0. 150. int modo = EGAHI.

“C:\\TC20\\BIN” ).h> void main() { int driver = EGA. Por ello. /* Pausa */ for( i=0.colors[i] ). i. sin embargo.size. &modo. int modo = EGAHI. 520.h> #include <conio. La función getaspectratio puede ser usada para obtener las opciones por defecto del modo actual anteriormente a ser modificados. temp. La proporción anchura-altura puede definirse como la proporción de la anchura del píxel del modo gráfico y la altura del píxel.colors[size-1-i]. alterando la proporción anchura-altura afectará la visualización de estas Funciones. i++ ) { temp = palette. La función setaspectratio no retorna ningún valor. i++ ) { y += 30. Ejemplo: #include <graphics. Esta función es usada para modificar la proporción anchura-altura del modo gráfico actual. } Función setaspectratio void far setaspectratio(int x_proporcion. si los valores pasados son inválidos. setcolor( palette.Bismarck Salvador Traña López__________________________________________ UNI Nota: Recuerda que todos los cambios hechos a la paleta tiene un efecto visual inmediato y que la función setallpalette no debería usarse con el dispositivo IBM-8514. line( 20. palette.h> Juan Carlos Gutiérrez Barquero____________________________________________ 53 . y ). Esta proporción es usada por el sistema gráfico para calcular círculos y arcos. y. i<size/2. } setallpalette( &palette ). for( i=0. y=0.colors[size-1-i] = temp. struct palettetype palette.colors[i]. /* Pausa */ closegraph(). int size. entonces la función graphresult retorna grError (-11) y la paleta no es alterada. Ejemplo: #include <graphics. i<size. La función setallpalette no retorna ningún valor. getpalette( &palette ). getch(). size = palette. int y_proporcion). palette.colors[i] = palette. } getch(). getch(). initgraph( &driver.

La función setgraphbufsize se debería llamar antes de llamar a la función initgraph. int buf_inicial. buf_inicial. Juan Carlos Gutiérrez Barquero____________________________________________ 54 . por ello.Bismarck Salvador Traña López__________________________________________ UNI #include <conio. 150. } Función setgraphbufsize unsigned far setgraphbufsize(unsigned bufer_tam). circle( 300. El búfer gráfico es usado por varias Funciones gráficos. /* Pausa */ setaspectratio( 2*x_proporcion. 50 ). Esta función suele usarse conjuntamente con restorecrtmode para cambiar entre modos gráficos y de texto. y_proporcion ). Esta función es usada para cambiar el tamaño del búfer gráfico interno como es asignado por la función initgraph cuando el sistema gráfico es inicializado. getch(). Además de seleccionar un nuevo modo. getch().h> void main() { int driver = EGA. buf_inicial = setgraphbufsize( buf_nuevo ). getaspectratio( &x_proporcion. } Función setgraphmode void far setgraphmode(int modo). buf_nuevo ).h> #include <conio. /* Pausa */ closegraph(). 150. “C:\\TC20\\BIN” ). int modo = EGAHI. printf( "Búfer inicial: %d\tBúfer nuevo: %d\n". 50 ). getch().h> void main() { int driver = EGA. La función setgraphbufsize retorna el tamaño anterior del búfer gráfico interno. y_proporcion. &modo. modo = EGAHI. initgraph( &driver. El argumento modo define el modo a usar según el dispositivo actual. circle( 300. “C:\\TC20\\BIN” ). &y_proporcion ). buf_nuevo=10000. Ejemplo: #include <graphics. initgraph( &driver. se debería tener un mayor cuidado cuando se altera este búfer del tamaño por defecto de 4096. &modo. closegraph(). Esta función es usada para seleccionar el modo gráfico actual pero solamente cuando el sistema gráfico haya sido inicializado con la función initgraph. getch().h> #include <stdio. la función setgraphmode despeja la pantalla y reinicia todas las opciones gráficas a sus valores por defecto.x_proporcion.

getch()..h> #include <stdio.Bismarck Salvador Traña López__________________________________________ UNI La función setgraphmode no retorna ningún valor.h> void main() { int driver = EGA. getch(). Existen varios valores para los diferentes estilos y grosores de líneas rectas.. printf( ".. getch().h> #include <conio. getch(). Un bit 1 en esta trama indica que el píxel correspondiente será asignado el color actual. initgraph( &driver. rectangle( 200. Ejemplo: #include <graphics. El argumento estilo específica la trama de línea predefinida para su uso. int grosor). line( 200. /* Pausa */ closegraph(). 400. 0. 100.unsigned trama. El argumento trama es una trama de 16 bits que describe el estilo de línea cuando el argumento estilo es USERBIT_LINE. modo = EGAHI.h> #include <conio. THICK_WIDTH ). &modo. “C:\\TC20\\BIN” )." ). /* Pausa */ closegraph(). initgraph( &driver. } Juan Carlos Gutiérrez Barquero____________________________________________ 55 . entonces la función graphresult retorna grError (11).\nPulsa una tecla para volver\n" ). outtext( "Esto es una prueba para cambiar entre modo gráfico. Esta función es usada para definir las características de líneas para líneas rectas. ó 4. si un argumento es inválido. 250 ). Ejemplo: #include <graphics.y en modo texto. “C:\\TC20\\BIN” ). getch(). 300. 50 ).modo = EGAHI. sin embargo. 400.h> void main() { int driver = EGA. restorecrtmode().. getch(). &modo. Un bit 0 indica que el píxel correspondiente no será alterado. setgraphmode( modo ). El argumento grosor define el grosor de la línea. La función setlinestyle no retorna ningún valor. setlinestyle( DOTTED_LINE. } Función setlinestyle void far setlinestyle(int estilo.

setpalette( i. /* Pausa */ for( i=0. y ). y.h> #include <conio. La función setpalette no retorna ningún valor. temp. i.int rojo. Para la IBM 8514 (y para el modo de 256K de la VGA). Esta función es para usarse con los dispositivos de IBM 8514 y VGA. i++ ) { y += 30.colors[size-1-i] ). y=0.colors[i] ). int modo = EGAHI. Para los modos de VGA. struct palettetype palette. int color). i<size. line( 20. &modo. verde. i++ ) { temp = palette. “C:\\TC20\\BIN” ). el intervalo de la paleta es de 0 á 255. El argumento color especifica el nuevo valor de color para el miembro de la paleta. } Función setrgbpalette void far setrgbpalette(int num_paleta. int azul). temp ). De cada byte (de cada argumento) sólo Juan Carlos Gutiérrez Barquero____________________________________________ 56 . setpalette( size-1-i. } getch(). si los valores pasados son inválidos. for( i=0. setcolor( palette. initgraph( &driver. Nota: Recuerda que todos los cambios hechos a la paleta tiene un efecto visual inmediato y que la función setpalette no debería usarse con el dispositivo IBM-8514. getch(). sin embargo. 520. Existen varios valores para los colores dependiendo del dispositivo. int size. /* Pausa */ closegraph(). Esta función es usada para modificar una sola entrada en la paleta actual. palette. size = palette. El argumento num_paleta especifica el miembro de la paleta a cambiar. el intervalo es de 0 á 15. El argumento num_paleta especifica el miembro de la paleta a ser modificado. Ejemplo: #include <graphics. int verde. getpalette( &palette ). y azul especifican la intensidad del color para el miembro de la paleta.size. i<size/2. } getch(). entonces la función graphresult retorna grError (-11) y la paleta no es alterada.h> void main() { int driver = EGA.colors[i]. Los argumentos rojo.Bismarck Salvador Traña López__________________________________________ UNI Función setpalette void far setpalette(int num_paleta.

h> #include <conio.Bismarck Salvador Traña López__________________________________________ UNI los seis bits más significativos son cargados en la paleta. Ejemplo: #include <graphics. } getch(). size = palette. La función setrgbpalette no retorna ningún valor. i++ ) setrgbpalette( i. for( i=0. y. 63-4*i ). si los valores pasados son inválidos. 2*i+33. mientras que el argumento vertical indica la justificación vertical. entonces la función graphresult retorna grError (-11) y la paleta no es alterada. Esta función es usada para especificar el método en el cual el texto es colocado en la pantalla con relación a la posición del cursor. /* Pausa */ closegraph(). La función settextjustify no retorna ningún valor. 520. &modo. } Función settextjustify void far settextjustify(int horizontal. i. y ). int size. “C:\\TC20\\BIN” ). el dispositivo BGI define las primeras dieciséis entradas a la paleta de la IBM 8514 a los colores por defecto de la EGA/VGA. i<size. getpalette( &palette ). El argumento horizontal define la justificación horizontal.h> #include <conio. y=0. i++ ) { y += 30.h> void main() { Juan Carlos Gutiérrez Barquero____________________________________________ 57 . Por razones de compatibilidad con otros adaptadores gráficos de IBM. line( 20.size. i<size. /* Tonos de naranja y azul */ getch(). sin embargo.h> void main() { int driver = EGA. Nota: Recuerda que todos los cambios hechos a la paleta tiene un efecto visual inmediato y que la función setrgbpalette no debería usarse con el dispositivo IBM-8514. setcolor( palette. Existen varios valores y constantes para las justificaciones. getch(). int modo = EGAHI. Ejemplo: #include <graphics. /* Pausa */ for( i=0. 42. initgraph( &driver.colors[i] ). struct palettetype palette. int vertical).

setcolor( 3 ). settextjustify( LEFT_TEXT. moveto(300. outtext( "(LEFT_TEXT. La fuente ha de estar registrada para resultados predecibles. BOTTOM_TEXT)" ). moveto(300. BOTTOM_TEXT)" ). line( 300. 200). TOP_TEXT)" ). getch(). 200. &modo. 300. El argumento fuente especifica la fuente registrada a usar. Esta función es usada para especificar las características para la salida de texto con fuente. “C:\\TC20\\BIN” ). outtext( "(RIGHT_TEXT. settextjustify( RIGHT_TEXT. moveto(300. Un valor distinto a 0 para el argumento tam_caracter puede ser usado con fuentes escalables o de bitmap. setcolor( 2 ). setcolor( 4 ). 200 ). BOTTOM_TEXT ). settextjustify( LEFT_TEXT. usa registerbgifont antes de usar esta función. int modo = EGAHI. TOP_TEXT)" ). BOTTOM_TEXT ). closegraph(). 200). el cual selecciona el tamaño del carácter definido por el usuario usando la función setusercharsize. 200). getch(). 200 ). moveto(300. 100. La orientación por defecto es HORIZ_DIR. outtext( "(RIGHT_TEXT.Bismarck Salvador Traña López__________________________________________ UNI int driver = EGA. 200. 200). El argumento tam_caracter define l factor por el cual la fuente actual será multiplicada. initgraph( &driver. 300. TOP_TEXT ). 100 ). settextjustify( RIGHT_TEXT. un valor distinto a 0 para el argumento tam_caracter. solamente Funciona con fuentes escalables. El argumento orientacion especifica la orientación en que el texto ha de ser mostrado. line( 300. La función settextstyle no retorna ningún valor. Existen varios valores y constantes para las justificaciones. outtext( "(LEFT_TEXT. 200. 500. 300 ). int tam_caracter). Juan Carlos Gutiérrez Barquero____________________________________________ 58 . 200. El argumento tam_caracter puede agrandar el tamaño de la fuente hasta 10 veces su tamaño normal. setcolor( 1 ). } Función settextstyle void far settextstyle(int fuente. es decir.int orientacion. TOP_TEXT ). line( 300. line( 300. Sin embargo.

h> #include <conio. 3 ). printf( "Escribe tu nombre: " ). 125.h> void main() { int driver = EGA. Juan Carlos Gutiérrez Barquero____________________________________________ 59 . los argumentos y_dividendo e y_divisor especifican la altura del carácter.h> void main() { int driver = EGA. el argumento tam_caracter de la función settextstyle debe ser 0. getch(). nombre ). outtextxy( 200. mensaje ). nombre ). outtextxy( 400.int y_dividendo. /* Esta fuente ha de ser enlazada antes de poder registrarla registerbgifont( sansserif_font ). char nombre[25]. */ initgraph( &driver.h> #include <stdio. closegraph(). int y_divisor). &modo. mensaje ). outtextxy( 100. "Hola %s!".h> #include <conio. 150. scanf( "%s". nombre ). La función setusercharsize no retorna ningún valor. "Hola %s!". sprintf( mensaje.h> #include <stdio. settextstyle( DEFAULT_FONT. settextstyle( SANS_SERIF_FONT. 2 ). nombre ).Bismarck Salvador Traña López__________________________________________ UNI Ejemplo: #include <graphics. Para que esta función afecte el tamaño del carácter. 1. “C:\\TC20\\BIN” ). 1. 0. La anchura del carácter se establece con los argumentos x_dividendo y x_divisor que representan la proporción. char mensaje[40]. mensaje ). printf( "Escribe tu nombre: " ). getch(). 2 ). Similarmente. int modo = EGAHI. int modo = EGAHI. scanf( "%s". } Función setusercharsize void far setusercharsize(int x_dividendo. char mensaje[40]. char nombre[25]. settextstyle( DEFAULT_FONT. int x_divisor. Esta función extablece las características de fuentes escalables. Ejemplo: #include <graphics. sprintf( mensaje. 50.

getch(). "Nueva" ). "C:\\TC20\\BIN" ). mientras que un valor distinto a 0 indica que los datos serán recortados. 300. La función setviewport no retorna ningún valor. 0 ). int recorte_banderin). setusercharsize( 1. initgraph( &driver. 1 ). outtextxy( 100. modo = EGAHI. 5. 0 ). settextstyle( SANS_SERIF_FONT. 5.int derecha. outtextxy( 15. 0 ). La esquina superior izquierda del área gráfica está definida por los argumentos izquierda y superior. moveto( 0. lineto( -50. &modo. 4 ). mensaje ). /* Fuera del área */ getch(). 300. mensaje ). lineto( 100. 50% de alto */ outtextxy( 100. 75% de alto */ outtextxy( 400. 200. setviewport( 250. Cuando el área gráfica es inicializada. 200. outtextxy( 15. 1. setviewport( 250. El área gráfica por defecto cubre la pantalla entera. sin embargo.h> void main() { int driver = EGA. los argumentos derecha e inferior definen la esquina inferior derecha del área gráfica. 3. la posición del cursor será mudado a la posición (0. getch(). entonces la función graphresult retorna grError (-11) y el área gráfica no será alterada. setcolor( 9 ). 0. “C:\\TC20\\BIN” ). 0 ). Juan Carlos Gutiérrez Barquero____________________________________________ 60 . Estos argumentos corresponden a los valores x e y de la esquina superior izquierda.h> #include <conio. si los valores pasados son inválidos. 2. getch(). mensaje ). Todos los datos de salida después de que el área gráfica haya sido inicializada serán con relación a este punto. Similarmente. 4. 1 ). /* 25% de ancho. El argumento recorte_banderin define si los datos para la salida gráfica serán recortados por el borde del área gráfico. 150. -20 ). int inferior. Esta función es usada para definir el área gráfico.0) (la esquina superior izquierda). 0. 1. 2 ). 125. 50. 450. settextstyle( SANS_SERIF_FONT. int superior. closegraph(). /* 50% de ancho. } Función setviewport void far setviewport(int izquierda.Bismarck Salvador Traña López__________________________________________ UNI initgraph( &driver. 450. lineto( 100. 100 ). settextstyle( SANS_SERIF_FONT. Ejemplo: #include <graphics. &modo. 100 ). "Inicial" ). setusercharsize( 1. Un valor de 0 para recorte_banderin indica que los datos de salida no serán recortados.

h> #include <stdio. getch(). 15. Esta función es usada para establecer la página visual como es especificado por el argumento pagina. 90. /* Pausa */ closegraph(). } Función setvisualpage void far setvisualpage(int pagina). 150. 315. la función setvisualpage (junto con la función setactivepage) permite al programador crear gráficos en páginas escondidas y pasar de página entre las que se han definido con información gráfica. setactivepage( 1 ).h> #include <conio. visual = 0==visual ? 1 : 0. } Juan Carlos Gutiérrez Barquero____________________________________________ 61 . setfillstyle( SOLID_FILL. 150. &modo. 6 ).Bismarck Salvador Traña López__________________________________________ UNI setcolor( 4 ). /* Fuera del área */ outtextxy( 25. 270. 50 ). -20 ). 40 ). initgraph( &driver. 150. La función setvisualpage no retorna ningún valor. Una página es una sección de memoria donde se guarda la información del vídeo. moveto( 120.h> void main() { int driver = EGA. Cuando se usa con un sistema (EGA o VGA) con suficiente memoria de vídeo para soportar múltiples páginas de gráficos. printf( "(Pulsa cualquier tecla para entrar en modo gráfico)\n" ). int visual=1. setfillstyle( SOLID_FILL. Ejemplo: #include <graphics. sector( 300. getch(). getch(). getch(). "C:\\TC20\\BIN" ). 45. setactivepage( 0 ). int modo = EGAHI. "Con recorte" ). 150. 50 ). printf( "Instrucciones:\nPulsa el espacio para cambiar de página. lineto( 150. 6 ). cualquier otra tecla para salir\n" ). } closegraph(). sector( 300. while( getch() == ' ' ) { setvisualpage( visual ). Esto es la base para crear animación.

&modo. setcolor( 10 ). en píxeles. 100 ). Juan Carlos Gutiérrez Barquero____________________________________________ 62 . "C:\\TC20\\BIN" ). Esta función es usada para establecer el modo lógico de escritura para líneas rectas. 500. getch(). Ejemplo: #include <graphics. int anchura. 50. de la cadena de texto especificada por el argumento *texto. closegraph(). setwritemode( COPY_PUT ). initgraph( &driver. 300 ). int modo = EGAHI. char mensaje[5] = "Hola". line( 20. La altura del texto se determina usando la fuente actual y el tamaño del carácter. el cual determina la interacción entre valores de píxeles existentes y los valores de píxeles en la línea.h> #include <conio. 220. 80. altura. bar( 50. 120 ). en píxeles. 60.h> void main() { int driver = EGA. del texto especificado por el argumento. Existen dos valores para los modos de escritura. line( 20.h> void main() { int driver = EGA. setfillstyle( SOLID_FILL. getch(). setwritemode( XOR_PUT ). La función setwritemode no retorna ningún valor. Ejemplo: #include <graphics. La función textheight retorna la altura. 1 ).h> #include <stdio. 220.Bismarck Salvador Traña López__________________________________________ UNI Función setwritemode void far setwritemode(int modo). El argumento modo especifica el modo de escritura.h> #include <conio. } Función textheight int far textheight(char far *texto). int modo = EGAHI. Esta función es usada para determinar la altura.

Bismarck Salvador Traña López__________________________________________ UNI

initgraph( &driver, &modo, "C:\\TC20\\BIN" ); outtextxy(10,10,mensaje); anchura = textwidth( mensaje ); altura = textheight( mensaje ); getch(); closegraph(); printf( "El mensaje: \"%s\" tiene de anchura: %d y altura: %d\n", mensaje, anchura, altura ); printf( "Pulsa una tecla para continuar...\n" ); getch(); } Función textwidth int far textwidth(char far *texto); Esta función es usada para determinar la anchura, en píxeles, de la cadena de texto especificada por el argumento *texto. La anchura del texto se determina usando la fuente actual y el tamaño del carácter. La función textwidth retorna la anchura, en píxeles, del texto especificado por el argumento. Ejemplo: #include <graphics.h> #include <conio.h> #include <stdio.h> void main() { int driver = EGA; int modo = EGAHI; int anchura, altura; char mensaje[5] = "Hola"; initgraph( &driver, &modo, "C:\\TC20\\BIN" ); outtextxy(10,10,mensaje); anchura = textwidth( mensaje ); altura = textheight( mensaje ); getch(); closegraph(); printf( "El mensaje: \"%s\" tiene de anchura: %d y altura: %d\n", mensaje, anchura, altura ); printf( "Pulsa una tecla para continuar...\n" ); getch(); }

Juan Carlos Gutiérrez Barquero____________________________________________

63

Bismarck Salvador Traña López__________________________________________ UNI

Estructuras del modo gráfico.
Estructura arccoordstype
struct arccoordstype { int x, y; int xstart, ystart; int xend, yend; };

Los miembros x e y definen el centro del arco. Los miembros xstart e ystart definen las coordenadas x e y del punto de comienzo del arco. Similarmente, los miembros xend e yend definen las coordenadas x e y del punto de final del arco. Esta estructura se usa como parámetro en la función getarccoords, que se usa para recoger las coordenadas del centro, y los puntos del comienzo y final de la última llamada con éxito a la función arc.
Ejemplo: #include <graphics.h> #include <conio.h> void main() { int driver = EGA,modo = EGAHI,radio; struct arccoordstype info_arco; initgraph( &driver, &modo, "C:\\tc20\\BIN" ); for( radio=25; radio<=100; radio+=25 ) { arc( 300, 150, 45, 315, radio ); getarccoords( &info_arco ); moveto( info_arco.xstart, info_arco.ystart ); lineto( info_arco.xend, info_arco.yend ); } getch(); /* Pausa */ closegraph(); } Estructura fillsettingstype struct fillsettingstype { int pattern; int color; };

Esta estructura se usa para obtener la información de tramas de relleno, mediante getfillsettings. El campo pattern es la trama y el campo color es el color de relleno de la trama. Existen trece valores ya definidos para tramas.

Juan Carlos Gutiérrez Barquero____________________________________________

64

Bismarck Salvador Traña López__________________________________________ UNI
Ejemplo: #include <graphics.h> #include <conio.h> #include <stdio.h> void main() { int gdriver = EGA,gmodo = EGAHI; struct fillsettingstype info; initgraph( &gdriver, &gmodo, "C:\\tc20\\BIN" ); getfillsettings( &info ); bar( 50, 50, 350, 300 ); getch(); /* Pausa */ closegraph(); printf( "Trama de relleno: %d\tColor de relleno: %d\n", info.pattern, info.color ); getch(); } Estructura linesettingstype. struct linesettingstype { int linestyle; unsigned upattern; int thickness; }

Esta estructura se usa para obtener la información actual para las líneas mediante la función getlinesettings. El campo linestyle es el estilo de la línea recta. El campo upattern es la trama de la línea del usuario solamente cuando el campo linestyle es igual a USERBIT_LINE, ó 4. Cuando esto sea el caso, el miembro upattern contiene una trama de línea definido por el usuario de 16 bits. Un bit 1 en esta trama indica que el píxel correspondiente será asignado el color actual. Un bit 0 indica que el píxel correspondiente no será alterado. El campo thickness es el grosor de la línea. Existen varios valores para los diferentes estilos y grosores de líneas rectas.
Ejemplo: #include <graphics.h> #include <conio.h> #include <stdio.h> void main() { int gdriver = EGA; int gmodo = EGAHI; struct linesettingstype info; initgraph( &gdriver, &gmodo, "C:\\tc20\\BIN" ); setlinestyle( DOTTED_LINE, 0xFF33, THICK_WIDTH ); circle( 350, 250, 50 ); getlinesettings( &info ); getch(); /* Pausa */

Juan Carlos Gutiérrez Barquero____________________________________________

65

Bismarck Salvador Traña López__________________________________________ UNI
closegraph(); printf( "Líneas rectas.\nEstilo: %d\tTrama: %X\tGrosor: %d\n",info.linestyle, info.upattern, info.thickness ); getch(); }

Estructura palettetype
#define MAXCOLORS 15 struct palettetype { unsigned char size; signed char colors[MAXCOLORS+1]; }; Esta estructura se usa para obtener una los datos que definen la paleta según cada dispositivo. El campo size indica el tamaño de la paleta. El campo colors contiene los valores numéricos que representan los colores que ofrece el dispositivo en su paleta de colores.
Ejemplo: #include <graphics.h> #include <conio.h> #include <stdio.h&t; void main() { int driver = EGA,modo = EGAHI,i; struct palettetype *palette = NULL; initgraph( &driver, &modo, "C:\\tc20\\BIN" ); palette = getpalettetype(); circle( 300, 150, 50 ); getch(); /* Pausa */ closegraph(); printf( "Paleta\n\nTamaño: %d\nColores: %d", palette->size, palette->colors[0] ); for( i=1; i<palette->size; i++ ) printf( ", %d", palette->colors[i] ); printf( "\n" ); getch(); } Estructura textsettingstype struct textsettingstype { int font; int direction; int charsize; int horiz; int vert; };

Juan Carlos Gutiérrez Barquero____________________________________________

66

charsize. gettextsettings( &info ).clip). } Juan Carlos Gutiérrez Barquero____________________________________________ 67 . también como el banderín de recorte del área gráfica. struct textsettingstype info. initgraph( &driver. &modo. info. info. Esta estructura contiene información de la fuente actual en uso. info.horiz.font. closegraph().modo = EGAHI.bottom. bottom. getviewsettings( &info ).left. struct viewporttype info. la orientación.h> void main() { int driver =IBM8514LO. Ejemplo: #include <graphics. printf( "Texto\n\nFuente: %d\tSentido: %d\tTamaño: %d\n" "Justificación:\nHorizontal: %d. info. Existen varios valores para describir el tipo. la orientación del texto. info.vert). info. closegraph().Bismarck Salvador Traña López__________________________________________ UNI Esta estructura se usa para obtener información acerca de la fuente gráfica actual mediante la función getextsettings. el tamaño del carácter.direction. int right.top. getch().h> #include <stdio. initgraph( &driver. "C:\\tc20\\BIN" ). }. printf( "Pantalla\n\nIzquierda: %d\tSuperior: %d\tDerecha: %d\t" "Inferior: %d\tBanderín: %d\n". Vertical: %d\n". info. Esta estructura contiene información acerca de las esquinas superior izquierda e inferior derecha. int clip. y justificación de fuentes.right. "C:\\tc20\\BIN" ). y la justificación horizontal y vertical. &modo. getch(). info. top.h> #include <conio.h> #include <stdio. info. info.modo=IBM8514HI. Esta estructura se usa para obtener información acerca del área gráfica actual mediante la función getviewsettings. } Estructura viewporttype struct viewporttype { int left. Ejemplo: #include <graphics.h> void main() { int driver = EGA.

getviewsettings( &info ). Procederemos a explicar cada una de ellas para realizar buestros ejercicios de movimiento. printf( "Pantalla\n\nIzquierda: %d\tSuperior: %d\tDerecha: %d\t" "Inferior: %d\tBanderín: %d\n". int clip. Las funciones pertenecientes al rasterop son: 1. bottom.left. closegraph(). Juan Carlos Gutiérrez Barquero____________________________________________ 68 . 2.h> #include <conio. info. Ejemplo: #include <graphics. }  Funciones de Rasterop. top. int right.right. info. &modo. initgraph( &driver.Bismarck Salvador Traña López__________________________________________ UNI Estructura time struct viewporttype { int left.top. info. "C:\\tc20\\BIN" ). Esta estructura contiene información acerca de las esquinas superior izquierda e inferior derecha. info. info. también como el banderín de recorte del área gráfica. 3. Esta estructura se usa para obtener información acerca del área gráfica actual mediante la función getviewsettings.h> void main() { int driver =IBM8514LO. 4.h> #include <stdio. }.bottom. son auellas que realizar la accion de mover una imagen ya sea transportando una imagen o copiandola.clip). struct viewporttype info.modo=IBM8514HI. Las funciones del rasterop. imagesize malloc getimage putimage Las cuatro complementan la operación de mover una imagen almacenándola en una variable temporal de tipo buffer. getch().

&modo. bar( 50. 50. los argumentos derecha y inferior definen las coordenadas x e y de la esquina inferior derecha de la imagen rectangular. Similarmente. initgraph( &driver. el valor retornado es 0xFFFF. int modo = EGAHI. 350. Si el tamaño==0. este regresa un Nulo(NULL) . o Nulo (NULL) si no existe suficiente espacio en nuevo bloque.Bismarck Salvador Traña López__________________________________________ UNI Función imagesize unsigned far imagesize(int izquierda.h.h> #include <conio. Regresa un puntero(indicador)al bloque recientemente asignado. int derecha. void *imagen.h> void main() { Juan Carlos Gutiérrez Barquero____________________________________________ 69 . Ejemplo: #include <graphics.h> #include <stdlib. Talvez no comprenda lo que quiera dar a entender pero ala hora del ejercicio lo entenderán. 100 ). La función imagesize retorna el número actual de bytes necesarios. 50. } /*En este ejercicio solo calculamos el tamaño de la imagen*/ Función malloc void *malloc(size_t size) Función definida en conio. 5 ). Ejemplo: #include <graphics. getch(). 300 ). Esta función es usada para determinar el tamaño del búfer necesitado para almacenar una imagen con la función getimage. Si esto no es el caso. setfillstyle( SLASH_FILL.int superior. int inferior).h> #include <conio. closegraph().h> void main() { int driver = EGA. 100. imagentam = imagesize( 50.h> #include <stdlib. ó -1. “C:\\tc20\\BIN” ). El tamaño está en bytes. Los argumentos izquierda y superior definen las coordenadas x e y de la esquina superior izquierda de la imagen rectangular. si el tamaño requerido es menor que 64 Kb menos 1 byte. int imagentam.

getch(). respectivamente.h> #include <stdlib. Esta función es usada para guardar una porción rectangular de la pantalla para un uso posterior. 50. 5 ). 100 ). setfillstyle( SLASH_FILL. &modo. respectivamente. 300 ). imagentam = imagesize( 50.h> #include <conio. 100. int imagentam. “C:\\tc20\\BIN” ). bar( 50. 100 ). void *imagen. free( imagen ). “C:\\tc20\\BIN” ). int modo = EGAHI. imagentam = imagesize( 50. Los argumentos derecha e inferior definen la esquina inferior derecha de la imagen rectangular. bar( 50. } Juan Carlos Gutiérrez Barquero____________________________________________ 70 . void far *imagen). getimage( 50. 50. 5 ). &modo. 350. 100 )). int superior.Bismarck Salvador Traña López__________________________________________ UNI int driver = EGA. int inferior. 50. imagen ). La función getimage no retorna ningún valor. initgraph( &driver. closegraph(). Estos argumentos representan las coordenades x e y de la esquina superior izquierda. Estos argumentos definen las coordenades x e y de la esquina inferior derecha.h> void main() { int driver = EGA. initgraph( &driver. 100. Ejemplo: #include <graphics. setfillstyle( SLASH_FILL. 100. 50. 350. imagen = malloc(imagesize( 50. } En este ejemplo calculamos en tamaño de la imagen y el número de bytes necesarios para contenerla Función getimage void far getimage(int izquierda. free( imagen ). El argumento *image apunta al búfer de memoria donde la imagen está guardada. imagen = malloc( imagentam ).int derecha. 300 ). getch(). La esquina superior izquierda del área rectangular que ha de ser guardada está definida por los argumentos izquierda y superior. int imagentam. 50. 50. 100. directamente. void *imagen. 100. int modo = EGAHI.

initgraph( &driver. imagen. 110. 50. 5 ).h> #include <stdlib. 100 ). Esta función coloca una imagen que fue previamente guardada con la función getimage en la pantalla. El argumento *image apunta al búfer de memoria donde la imagen está guardada. 50.Bismarck Salvador Traña López__________________________________________ UNI /*En este ejemplo solo conseguimos el tamaño de la imagen y guardamos la imagen en un buffer*/ Función putimage void far putimage(int izquierda . void far *image. getch(). La esquina superior izquierda donde será colocada la imagen está definida por los argumentos izquierda y superior.modo = EGAHI. &modo. respectivamente. setfillstyle( SLASH_FILL. putimage( 400. 300 ). /* Pausa */ closegraph(). 100. Los valores y consonantes usados por el argumento accion se describen a continuación ya que pudieron haberlos olvidado: Constante COPY_PUT XOR_PUT OR_PUT AND_PUT NOT_PUT Valor 0 1 2 3 4 Significado Sobrescribir los píxeles existentes Operación OR Exclusivo con los píxeles Operación OR Inclusivo con los píxeles Operación AND con los píxels Invertir la imagen La función putimage no retorna ningún valor. imagen = malloc( imagentam ). 50. Ejemplo: #include <graphics. La imagen se coloca en la pantalla con la acción definida en el argumento acción. getch(). getch(). putimage( 400.h> #include <conio. 50. getimage( 50. 100. imagen. void *imagen. Estos argumentos representan las coordenadas x e y de la esquina superior izquierda. int superior. imagentam. COPY_PUT ). 350. 100. “C:\\tc20\\BIN” ). imagen ).h> void main() { int driver = EGA. imagentam = imagesize( 50. bar( 50. } Este es el pequeño ejemplo del rasterop Juan Carlos Gutiérrez Barquero____________________________________________ 71 . int acción). free( imagen ). COPY_PUT ).

20). while(!kbhit()) { x=-180.&modo. circle(x+310. x-=1.h> # include <math.240-y.y. while(x>=-180 && !kbhit()) { y=-1*sqrt(15000*(1-((x*x)/32400))). void cuerpo(void). 1. cleardevice(). } x=180.h> void inicializar(void). cuerpo().240-y. delay(15000). } void cuerpo() { double x. void main(void) { inicializar(). initgraph(&drive.Bismarck Salvador Traña López__________________________________________ UNI Otros ejemplo de Rasterop. x+=1.20). } void inicializar(void) { int drive=DETECT. } } Juan Carlos Gutiérrez Barquero____________________________________________ 72 . # include <conio. delay(15000). cleardevice().modo. circle(x+310. while(x<=180 && !kbhit()) { y=sqrt(15000*(1-((x*x)/32400))).h> # include <dos."c:\\tc20\\bin").h> # include <graphics. Un círculo que realiza un movimiento iliptico.

void far *buffer. setcolor(RED).440."Enero").h> # include <graphics. system("cls"). inicializar(). setfillstyle(1.450."MOVIMIENTO DE ROTACION DE LA TIERRA al rededor del sol"). floodfill(485. } Realice un programa que muestre el movimiento de la tierra alrededor de la tierra y que mustre los meses del año conforme valla avanzando la image.Bismarck Salvador Traña López__________________________________________ UNI getch().BLUE).460).outtextxy(500.20. } else { Juan Carlos Gutiérrez Barquero____________________________________________ 73 . buffer=malloc(imagesize(0. x2=-300."Enero")."Febrero"). void main() { float y2.h> void inicializar(void).WHITE).600. # include <conio.460). outtextxy(500. floodfill(485.h> # include <stdlib.BLUE).x2. putpixel(random(639).440. rectangle(480. do { outtextxy(150.20.h> # include <math.random(480). } else { if((x2>=-200)&&(x2<-100)) { setcolor(BLUE).450.600.WHITE). while(x2<=300 && !kbhit()) { putpixel(random(639). outtextxy(500.x.450. setfillstyle(1.y1.450.GREEN).h> # include <dos.20)).h> # include <stdio.50.random(480).YELLOW). if((x2>=-300)&&(x2<-200)) { rectangle(480.450.h> # include <process.

460). delay(20000).440.310+x2+10.450."Junio").BLUE).00))*23850."Marzo").GREEN). Juan Carlos Gutiérrez Barquero____________________________________________ 74 .BLUE).450.440.240-y2+10.450.XOR_PUT)."Mayo"). setfillstyle(1.Bismarck Salvador Traña López__________________________________________ UNI if((x2>=-100)&&(x2<0)) { setcolor(YELLOW).MAGENTA). setfillstyle(1. floodfill(485. floodfill(485.460). setfillstyle(1. outtextxy(500.600.600. y2=sqrt((1-((x2*x2)/90000.CYAN). } else { if((x2>=0)&&(x2<100)) { setcolor(GREEN). outtextxy(500. floodfill(485.240-y2-10.10). } else { if((x2>=100)&&(x2<200)) { setcolor(CYAN). setfillstyle(1. rectangle(480. } else { if((x2>=200)&&(x2<299)) { setcolor(MAGENTA).YELLOW). rectangle(480. outtextxy(500.440. } } } } } } setcolor(WHITE). circle(310.600. rectangle(480. rectangle(480. getimage(310+x2-10.460).450.buffer)."Abril").BLUE). circle(310+x2.440. setfillstyle(1.YELLOW).460). floodfill(485.BLUE).450.600.240-y2.240-y2-10.buffer.450.450. outtextxy(500.240.00). putimage(310+x2-10.30).450.

440.460). outtextxy(501.450.RED).YELLOW). floodfill(485.450. putpixel(random(639). } free(buffer).GREEN). floodfill(485. setfillstyle(1.600. rectangle(480. floodfill(485. rectangle(480.600. rectangle(480.450.BLUE).460).BLUE). } else { if((x<=0)&&(x>-100)) { setcolor(GREEN)."Septiembre")."Agosto"). setfillstyle(1. while(x>=-300 && !kbhit()) { putpixel(random(639).600.450. outtextxy(500.440.random(480).460). } else { if((x<=100)&&(x>0)) { setcolor(YELLOW). x2+=2.450."Julio"). x=300. if((x<=300)&&(x>200)) { setcolor(RED).440. } else { Juan Carlos Gutiérrez Barquero____________________________________________ 75 . setfillstyle(1.YELLOW). rectangle(480. delay(30000).240. floodfill(485.LIGHTGRAY).450.WHITE). setfillstyle(1.440.450.BLUE).random(480).WHITE). } else { if((x2<=200)&&(x>100)) { setcolor(LIGHTGRAY).460).Bismarck Salvador Traña López__________________________________________ UNI floodfill(310.450. outtextxy(500. outtextxy(500."Octubre").600.BLUE). setcolor(WHITE).

440.30). setfillstyle(1. floodfill(485.XOR_PUT).MAGENTA).310+x+10. } /***********************INICIALIZAR***************************/ void inicializar(void) { int drive=DETECT.WHITE). floodfill(310.buffer).600. rectangle(480.Bismarck Salvador Traña López__________________________________________ UNI if((x<=-100)&&(x>-200)) { setcolor(CYAN).240. delay(20000). outtextxy(500. circle(310+x.BLUE).450.240-y1.CYAN). putimage(310+x-10. } } } } } } setcolor(WHITE). rectangle(480.00))*23850.240-y1-10.460). getimage(310+x-10.450.450.240. floodfill(485.modo. y1=(sqrt((1-((x*x)/90000.440. circle(310. } Juan Carlos Gutiérrez Barquero____________________________________________ 76 .240-y1+10. setfillstyle(1.240-y1-10.460). delay(2000)."Diciembre"). setfillstyle(1. outtextxy(500.BLUE). setcolor(WHITE).10). x-=2."c:\\tc20\\bin").450.&modo. }while(!kbhit())."Noviembre").00))*-1.YELLOW).buffer. initgraph(&drive. } else { if((x<=-200)&&(x>-300)) { setcolor(MAGENTA). } free(buffer).600.

} La función itoa int itoa(int value. que te parece si te doy una idea??? Declara un arreglo unidimensional donde escribiras los meses y hay un for que inicie en 1 y termine en 12 dentro de ese for llama a una funcion que es bottom_fond donde dibujaras un rectangulo que se pintará siempre de azul pero su color frontera seran las i recomendación (pasarle parámetros a la funcion para ahorrar códigodentro de ese misno for llama al arreglo bidimensional imprimiendo en las coordenadas del rectangulo y los demas cálculos son los mismos. Esta función es comúnmente usada con outtextxy(). Observación: es usada para convertir cadenas que contengas valores numéricas a fin de que estos valores puedan ser computados. para octales debe ser 8.h> void main(void) { char *string="545".Bismarck Salvador Traña López__________________________________________ UNI Existen otras maneras mas sencillas de hacerlo. char *string.h> de <stdlib.valor_entero). getch(). El macro atoi() convierte una cadena a su valor entero. valor_entero=atoi(string). aquí se colocará el valor entero convertido. int radix). Juan Carlos Gutiérrez Barquero____________________________________________ 77 . long int valor_entero. Ejemplo #include <stdio. Retorna el valor convertido de la cadena leída.string. recibe los siguientes parámetros: int value = es el valor que vas a convertir char *string = es una arreglo de caracteres o un puntero que apunte a char. clrscr().h> La función atoi int atoi(const char *s). para enteros hexadecimale debe ser 16. La función itoa convierte un entero a cadena.h> #include <conio. en el siguiente ejemplo deseo mostrar en pantalla gráfica el valor de una variable entera para lo cual tengo que convertirla a cadena. ejemplo para enteros decimales debe ser 10. Funciones mas utilizadas en <graphics. Si el valor no puede ser convertido el valor de retorno es 0.h> #include <stdlib. int radix = quiere decir el sistema en el que está el valor entero. el valor entero correspondiente es %d\n". printf("La cadena es %s.

initgraph(&adaptador. Las funciones rand() y random() son similares. } Funciones rand y random int rand(void). esta función no esta definida dentro de la ayuda de tc20 pero esta dentro del archivo BGI o include veremos cada una de las funciones asi como también como las funciones contenidas dentro de ella.rand(). cleardevice().stringx.modo.160.10). int x=150.h> void main(void) { int adaptador=DETECT.modo. itoa(y.stringx).150. Juan Carlos Gutiérrez Barquero____________________________________________ 78 .stringy).160.h> #include <conio. getch(). itoa(x.&modo.h> #include <stdlib.130.Bismarck Salvador Traña López__________________________________________ UNI Ejemplo #include <conio.h. outtextxy(150. initgraph(&adaptador. int random(int valor_final). outtextxy(170.stringy.h> void main(void) { char *stringx.random(16)). outtextxy(150.y=150.*stringy."c:\\tc20\\bin"). int adaptador=DETECT."c:\\tc20\\bin").10).&modo. El ejemplo siguiente simulara una cantidad de estrellas: #include <graphics.h> #include <stdlib."LOS VALORES DE X e Y SON:"). outtextxy(170.150."x="). el rango de valores para random() esta entre 0 y (valor_final – 1). ambas devuelve un valor seudo-aleatorio. } } Otra manera de realizar programas en modo grafico con gran efectiidad es utilizando la librería mouse. while(!kbhit()) { putpixel(rand()."y="). outtextxy(150. la primera no recibe parámetros y el rango del valores está entre 0 y RAND_MAX este usualmente es 32767.h> #include <graphics.

getch().h> #include<mouse. }while(!kbhit()).h> #include<conio. closegraph(). do{ mver().&modo. getch().paracomenzar tenemos: La función mver Void mver (void) La función mver muestra el puntero del ratón no es necesario en viar ningún parámetro. initgraph(&adaptador."c:\\tc20\\BIN").Bismarck Salvador Traña López__________________________________________ UNI Funciones de la librería Mouse. Ejemplo: #include<graphics. initgraph(&adaptador.h> #include<mouse.&modo.h> void main(){ int adaptador=DETECT.modo. mocultar() }while(!kbhit()). } Al utilizar estas dos funciones obtenemos un efecto del ratón muy vistoso.h> #include<conio."c:\\tc20\\BIN"). La función mver no retorna ningún valor. closegraph(). do{ mver().modo. Juan Carlos Gutiérrez Barquero____________________________________________ 79 .h> void main(){ int adaptador=DETECT. Ejemplo #include<graphics.h Todos las librerias aqui explicadas aparecen en la carpeta include de tc20. } La función mocultar void mocultar (void) Esta función oculta el puntero del ratón no recibe ni retorna ningún valor.

setbkcolor(BLUE).h> #include<conio. int mtest (void) Esta función sirve para testear el ratón en esta no es necesario enviar ningún parametro retorna: 0 si no esta instalado el ratón."c:\\tc20\\BIN"). 8 es para modo texto La función mxpos regresa la posición horizontal de un entero que seria la posición del ratón en x. y n si el número de botones del ratón. closegraph().Bismarck Salvador Traña López__________________________________________ UNI La función mtest. Juan Carlos Gutiérrez Barquero____________________________________________ 80 .h> #include<mouse. char *strx. Es necesario enviarunvalor para especificar el modo en cual sera usado. La funcion mtest retorna un entero Ejemplo: #include<graphics. initgraph(&adaptador.h> #include <conio.h> void main(){ int adaptador=DETECT. }while(!kbhit()).modo. 1 es para modo gráfico.&modo. mtest(). getch(). } La función mxpos int mxpos (int modo) Dice la posición de la coordenada x en la cual se encuentra el ratón.modo.h> #include <mouse. *stry. initgraph(&adaptador.&modo."c:\\tc20\\bin").h> #include <stdlib. do{ mver().y.h> void main(void) { int adaptador=DETECT. Ejemplo #include <graphics. int x.

initgraph(&adaptador. outtextxy(100. y=mypos(1).h> #include <conio. 8 es para modo texto La función mypos regresa la posición horizontal de un entero que seria la posición del ratón en y.100. while(!kbhit()) { setfillstyle(SOLID_FILL.stry).strx.strx).120.stry).stry. mver(). x=mxpos(1). itoa(x. setcolor(WHITE). 1 es para modo gráfico.BLUE).BLUE). int x. outtextxy(100.h> #include <stdlib.Bismarck Salvador Traña López__________________________________________ UNI while(!kbhit()) { setfillstyle(SOLID_FILL. mver().120.strx). x=mxpos(1).h> #include <mouse. outtextxy(100. Es necesario enviarunvalor para especificar el modo en cual sera usado. Ejemplo #include <graphics.} } } La función mypos int mypos (int modo) Dice la posición de la coordenada y en la cual se encuentra el ratón.h> void main(void) { int adaptador=DETECT."c:\\tc20\\bin").y.10). if(x!=mxpos(1)||y!=mypos(1)) { setcolor(BLUE).10). y=mypos(1). itoa(y.100. setbkcolor(BLUE).modo. *stry.&modo. char *strx. Juan Carlos Gutiérrez Barquero____________________________________________ 81 . outtextxy(100.

outtextxy(100.10).strx). initgraph(&adaptador.Bismarck Salvador Traña López__________________________________________ UNI itoa(x.stry). La función no retorna ningún valor.modo. outtextxy(100.y.h> #include<conio.stry). x.stry.10). outtextxy(100. closegraph().strx). int y) Esta función permite situar al curcor en una posición específica para su utilización es necesario enviar tres parámetros modo.h> #include<mouse. outtextxy(100.&modo.310. getch(). X: posición horizontal.100.240).h> void main(){ int adaptador=DETECT.} } } La función msituar void msituar(int modo."c:\\tc20\\BIN").120.120. Ejemplo #include<graphics.100. Y: posición vertical. }while(!kbhit()). } Juan Carlos Gutiérrez Barquero____________________________________________ 82 . /*Coloca el cursor en el centro de la pantalla*/ do{ mver(). if(x!=mxpos(1)||y!=mypos(1)) { setcolor(BLUE). Modo: 1 para modo gráfico.strx. msituar(1. 8 para modo texto. setcolor(WHITE). int x. itoa(y.

closegraph(). outtextxy(x+30. x=mxpos(1). int x1. Juan Carlos Gutiérrez Barquero____________________________________________ 83 . outtextxy(x+30.y.&modo. } delay(10000).h> #include<stdlib.h> #include<conio.h> #include<mouse. } if(mclick()==2) { setcolor(RED). int y1. Retorna 0 si no es presionado ningún botón."Diste un click derecho"). do{ mver().h> void main(){ int adaptador=DETECT. outtextxy(x+30. if(mclick()==1) { setcolor(GREEN).x2.y. 2.y.modo. }while(!kbhit()). initgraph(&adaptador. y=mypos(1). getch(). si se presionó el botón derecho del Mouse. outtextxy(x+30."c:\\tc20\\BIN").x. 1 si se presionó el botón izquierdo del Mouse."Diste un click izquierdo"). int y2) Esta función limita el espacio de movilización del cursor (ratón). no es necesario enviar un parámetro."Diste un click derecho")."Diste un click izquierdo").Bismarck Salvador Traña López__________________________________________ UNI La función mclick int mclick(void) Nos dice si se ha pulsado un boton del Mouse.x1.y.y1.y. setcolor(BLACK). } La función mlimit void mlimit(int modo. en esta función es necesario enviar cinco parámetros modo. Ejemplo #include<graphics. int x2.y2.

Juan Carlos Gutiérrez Barquero____________________________________________ 84 .h> #include<mouse. Modo: 1 para modo gráfico. }while(!kbhit()). rectangle(100. 8 para modo texto.500. Ejemplo #include<graphics. X2: limite de abajo Y2: límite de la derecha Retorna 1 si esta en esa area en caso contrario regresará 0 (cero). X1: límite de arriba.100.&modo. getch(). 8 para modo texto. } La función minlimit int minlimit(int modo.Bismarck Salvador Traña López__________________________________________ UNI Modo: 1 para modo gráfico. mver().int y2) Esta función verifica si el ratón se encuentra en un área determinada para la implementación de ésta función es necesario enviar cinco parámetros. mlimit(1.int x1."Dibuj‚ el rect ngulo para que observaran el limite").h> void main(){ int adaptador=DETECT."c:\\tc20\\BIN").h> #include<conio. Y1: límite ablajo. closegraph().int x2. do{ outtextxy(100.modo. X2: limite de abajo Y2: límite de la derecha Estas coordenadas formarán un rectángulo el cual sera el limite hasta donde podra llegar el ratón. initgraph(&adaptador.100.400). X1: límite de arriba.50.100.400).int y1. Y1: límite ablajo.500.

&modo.240.100. void cuadro(void). if(minlimit(1. getch(). /*Este programa te muestra las figuras geometricas*/ # include<stdio. void main(void) { inicializar()."Haz pulsado el rat¢n por encima del bot¢n").h> # include <dos. restorecrtmode().200.h> # include<conio.120)==1) { outtextxy(310.h> #include<conio.240.h> void main(){ int adaptador=DETECT. outtextxy(210."pasa el mouse por encima del bot¢n y veras el efecto").105. Juan Carlos Gutiérrez Barquero____________________________________________ 85 . do{ setcolor(WHITE).h> # include<graphics.h> # include<stdlib.100. setbkcolor(BLUE).modo. cuadro(). outtextxy(310. initgraph(&adaptador.h> # include <stdlib. rectangle(100.h> void inicializar(void).200.100. setcolor(BLACK).modo.h> #include<mouse.codigo.Bismarck Salvador Traña López__________________________________________ UNI Ejemplo #include<graphics. mver()."c:\\tc20\\BIN"). } }while(!kbhit()). } void inicializar(void) { int adaptor=DETECT. } Ejemplos de la de la VGA. delay(30000).120)."Haz pulsado el rat¢n por encima del bot¢n"). closegraph().

310. initgraph(&adaptor. /*q= izquierda abajo eje x w es igual eje y */ int a=465.4). } else { settextstyle(SMALL_FONT. 415. outtextxy(i. 105. 415.1.j-90. setlinestyle(SOLID_LINE. if((codigo=graphresult())!=0) { printf("%s". /* t= derecha arriba eje x k es igual eje y*/ int t=155. 365. setlinestyle(SOLID_LINE.240). } if(paginas==1) { /***************triangulo1**************************/ outtextxy(i-60.j-60). /*i=izquierda arriba eje x jes igual eje y*/ int q=465.410.340}. exit(1). rectangle(1.&modo.360.NORM_WIDTH).310."S=(b x h)/2").s=360.HORIZ_DIR. line(i-60.240.0. Juan Carlos Gutiérrez Barquero____________________________________________ 86 .w=120.480).270.360}. outtextxy(400.410.j+40). outtextxy(i-60.460.340. 205. 515. setcolor(9).360. 55.j+70. line(i-60.j-90.15. /*a= derecha abajo eje x s igual eje y*/ int pentagono[]={55."Tri ngulo rectangulo"). outtextxy(i-67.310.j-20."c:\\tc20\\bin").j+40. int hexagono[]={365."b").HORIZ_DIR.Bismarck Salvador Traña López__________________________________________ UNI printf("desea seguir viendo los graficos").j+40.getmaxy()-1).i-60.getmaxx()-1.j+40). setbkcolor(WHITE). 515. outtextxy(i-5. 155."Presione enter para ver las sig.4). line(0.grapherrormsg(codigo)). 255.i-60. line(i+100.i+100. int i=155.410. 565. line(310.THICK_WIDTH)."h").460."Fin de presentacion Presione enter para Salir")."Triangulo Rectangulo").340.15. while(paginas<=4) { system("cls").k=360. } } void cuadro(void) { int paginas=1.j+40. setcolor(8). if(paginas>=1&&paginas<=2) { settextstyle(SMALL_FONT. outtextxy(370.j-60.640.410. graficas").j=120.

settextstyle(SMALL_FONT.t-25."Tri ngulo rectangulo").a-60.t+100. line(t-60.s+40.w-60). outtextxy(q+10.s+40).s-60.a+100."Tri ngulo rectangulo").w+40).j-90.t+100.s-60).w-60). outtextxy(i-60.21.3. } if(paginas==2) Juan Carlos Gutiérrez Barquero____________________________________________ 87 .w+60.w+40).w-30.*/ outtextxy(i-60.HORIZ_DIR.q-50. /*cat opt.k+40.w-30.w+40. outtextxy(q-30. /*******************triangulo escaleno*****************************/ /*t es eje x k es eje y*/ outtextxy(t-60."h").q-50.w+75. outtextxy(q-45.k+40.s+70. line(a+20. /*line que corta al triangulo o cat opu*/ line(t-25.w+40).w+60)."S=(b x h)/2"). outtextxy(t.NORM_WIDTH).NORM_WIDTH).w+40.Bismarck Salvador Traña López__________________________________________ UNI /******************triangulo2****************************/ /* q eje x w eje y*/ outtextxy(q-100. outtextxy(a+10.s+40. line(q-50."b").NORM_WIDTH).k-60. /*hip*/ getch()."Tri ngulo rectangulo").q-100. outtextxy(t-67. /*Triangulo isosceles*/ line(t-60."S=(b x h)/2").w-20.s+40).q-50. line(t-60.15.s+40."(b x h)/2")."b").k-20. line(q-100.k+40.*/ line(a-60. setlinestyle(SOLID_LINE.w+40. /*outtextxy(q-5.HORIZ_DIR.8."b"). line(q-50. outtextxy(q-20. line(q-15.j-90. /*cat ady.w-60."c"). line(a+20.k+40).w+60.4). outtextxy(a+10.k+40. line(q+80.NORM_WIDTH)."Triangulo Isosceles"). outtextxy(i-60. outtextxy(q-80. outtextxy(q-57.s-90."h"). setlinestyle(DOTTED_LINE.j-90.k+40).k-90.t-60.t-60."S=-\/ p(p-a)(p-b)(p-c)'"). line(q-50."a").k-60.*/ line(t+100."P=(a+b+c)/2"). outtextxy(t-5. /*cat ady*/ line(a+100. /*********************triangulo isosceles***************************/ outtextxy(a-40.k+40).w+70. setlinestyle(SOLID_LINE.*/ setlinestyle(DOTTED_LINE.s-60.s-20.a+20. settextstyle(SMALL_FONT.q+110.a+20.k+40). outtextxy(a-5.s+40).w+40. /*hipoten.w-90.q+80."h").5)."Triangulo Rectangulo 3 lados diferentes")."Triangulo Escaleno").w+40.k+70.k-60).

"S=((B + b)* h)/2"). setlinestyle(SOLID_LINE. outtextxy(t-25."b").a-40.s-60.s-40).w-45.t+90. line(a+70. line(i-45. line(q-85.s.NORM_WIDTH).t+90. /*****************************Trapecio******************************/ line(q-60.w+45."B").s.k+60.q-60.k.t+90. outtextxy(q-35.j+60."h").k.j+25).k).j-25. setlinestyle(DOTTED_LINE.j+25).t.s+45.i-60.w.8.k).w+45.t.t+120.w-45). line(q+90.a-60. /*****************************Rombo***********************/ line(t-90. line(t-90.q+60. line(i-60.Bismarck Salvador Traña López__________________________________________ UNI { /********************Rectangulo******************/ line(i-45.k.j-25.j-25. line(t.j+25).k).8.8.NORM_WIDTH).j-25). line(a+100."Rectangulo").s)."d").s-60). line(a+100. outtextxy(i.k+60.w-45.k-60).NORM_WIDTH).w+45).k+30.j+25.j+25).k-90. outtextxy(i+3."b").k+60). outtextxy(i-52.w-45).s. rectangle(t-90.i+50.s). outtextxy(q. line(t.k+60).j-25.w+45).q-60. line(t.k-60. line(a+40. outtextxy(q.q+60.w+45.k. outtextxy(t-35.s). /*************************Pol¡gono*****************************/ line(a-60. outtextxy(q-52.k+60).a+70. Juan Carlos Gutiérrez Barquero____________________________________________ 88 . line(t+120. line(i-45. outtextxy(t-45.k+60). line(t+120."Rombo"). outtextxy(q-25. line(a+40.NORM_WIDTH). outtextxy(i-35."S=b x h").t+120. setlinestyle(SOLID_LINE.w+60. line(q-85.t.k-60.i+65.j. line(q-60.24. setlinestyle(DOTTED_LINE.k-60).w-60."h").w+50.k.k-60."D").t+90.i-45. line(t-90.k+75."S=(D * d)/2").j+30.q+90.k+70).t. /*altura*/ outtextxy(i-25.w-90.a-60.w-45).k-60.s-60.s+45). line(t. line(i+65.j-90."Trapecio").a+100.i+50.a+40.

j+55."S1"). outtextxy(i+30. outtextxy(q-35.k+10."Hex gono o poligono regular").i+100.i+20.j-85). outtextxy(i-35.s.BLUE).w+50). } if(paginas>4) exit(1). outtextxy(i+25.k-110."S2"). line(t.k+65."S= b * b").s.t.w+65.w+50.a-40. outtextxy(a-35. outtextxy(a+10.j+55. Juan Carlos Gutiérrez Barquero____________________________________________ 89 .GREEN).} Este programa te simula un paisaje nocturno con algunas efectos de estrellas.q+50. /*base*/ outtextxy(i-25.pentagono). setlinestyle(SOLID_LINE. } clrscr()."Poligono").j+55).s-30.s-40. outtextxy(a+25."a").s-100.Bismarck Salvador Traña López__________________________________________ UNI line(a-60.j+55).s+65.s+50)."S=(P * a)/2")."a"). /*cat*/ line(i-60. outtextxy(t-35. /*******************************cuadrado***********************/ rectangle(q-50.s-40). getch()."S3"). /****************************pent gono***********************/ fillpoly(5.i+20."b")."S=(P * a)/2").s-90. /*************Exagono o poligono regular*******************/ fillpoly(6. } if(paginas==3) { /*********************tri ngulo equilatero*********************/ line(i-60.s+60.j-85).i+55. floodfill(370.s+10. outtextxy(q-25."Triangulo equilatero").j-85. outtextxy(a+30.*/ line(a. outtextxy(a-25.i+20.j+55. /*cat*/ line(i+100.w-50."Cuadrado")."Pent gono"). outtextxy(q. setlinestyle(DOTTED_LINE.a.s+10.i-30. outtextxy(t-25.NORM_WIDTH)."S= (b * h)/2"). outtextxy(a-30."S= S1 + S2 + S3"). line(i+20."b").i+20.w-100.24.NORM_WIDTH).460. outtextxy(a-65.j-100. /*setfillstyle(LINE_FILL. outtextxy(t+10.hexagono).k-20. paginas=paginas+1. outtextxy(a-35.8. getch().k+50)."h").

370).&y1. ambiente().470.639. getch(). setcolor(LIGHTGRAY).h> # include <stdlib. lineto(210. int x1=0.&color).h> # define WHITE 15 void marco(int *.b.int *.h> # include <dos. moveto(x. lineto(150.int *. void ambientedos(void).&y).400). marco(&x1.x2=640.h> # include <graphics.int *."c:\\tc20\\bin"). system("cls"). void estrellas(int *. int y=0.int *).&x2.y=480.GREEN). void ambiente(void).479). lineto(0.LIGHTGRAY). } void ambiente(void) { int x=50.Bismarck Salvador Traña López__________________________________________ UNI # include <conio. estrellas(&x. setfillstyle(SOLID_FILL.0.&b. lineto(100. setcolor(LIGHTGRAY).int *). initgraph(&a. setbkcolor(BLUE). } void ambientedos(void) { Juan Carlos Gutiérrez Barquero____________________________________________ 90 .&y2. void main() { /*INICIALIZAR EL MODO GRAFICO DE MANERA RAPIDA*/ int a=DETECT. floodfill(1.y1=0. rectangle(0.color=6.y2=480. void montana(void). montana().h> # include <process. ambientedos().450). cometas().y). void cometas(void).370). x=0.

394).MAGENTA). floodfill(300.350).5.110.90. /*lado derecha | */ line(140. lineto(105.BROWN).350.382. /*union de la linea lateral con la casa*/ setfillstyle(SOLID_FILL.int *x2.365).365.Bismarck Salvador Traña López__________________________________________ UNI setcolor(BROWN). lineto(55.370).382.398. lineto(155. ellipse(310.367.400). setfillstyle(6. setfillstyle(SOLID_FILL. line(130.110.360).5). lineto(155.BROWN).400.345).150.140.368.365.YELLOW). lineto(125. lineto(22. floodfill(50. /*puerta lado izquierdo*/ line(120. rectangle(30.120. setcolor(RED). /*ventana abajo __*/ line(130. line(112. setcolor(YELLOW).int *y1.362.395).30).BROWN).5. Juan Carlos Gutiérrez Barquero____________________________________________ 91 .370). moveto(105. lineto(125.345).378).270.5).374).374).int *y2. /*puerta arriba*/ line(112. /*puerta abajo*/ setfillstyle(SOLID_FILL.364.int *color) { setbkcolor(BLUE). /*ventana arriba --*/ line(130.RED). /*puerta lado derecho*/ line(112.120.385.370).300.378.380.05.BROWN). floodfill(114.400). setfillstyle(SOLID_FILL.385.120. /*linea lateral | */ line(110.130. line(150.374.377).377.397.374).BROWN).BROWN).RED).270.90.112.YELLOW).MAGENTA).30).300.300. } void marco(int *x1. setcolor(BROWN).367.140. floodfill(135. floodfill(50.140. arc(310. floodfill(112.150.364). /*lado izquierdo | */ setfillstyle(SOLID_FILL. line(110.

BLUE).180.int *y) { int i.*y2). putpixel(t-5. line(0. } delay(4000). /*linea del lago superior */ /*monta¤a / */ /* monta¤a \ */ /* monta¤a ___ */ Juan Carlos Gutiérrez Barquero____________________________________________ 92 . putpixel(310. rectangle(*x1.(480-t).YELLOW). px=(rand()%640). color=getcolor().t.RED).RED). line(480.YELLOW).YELLOW). putpixel(t+1.i++) { montana(). putpixel(t-11.py.RED).200.100.250.494.i<=400. putpixel(px+10.200).30). line(560. putpixel(310. t+=3.560.250).(480-t)-9.639. py=(rand()%200).100. floodfill(300.(480-t)-12.color. setcolor(YELLOW).250).250.py+50.30).px=*x. } void estrellas(int *x.270. else { putpixel(310.BLUE). } } void montana() { setcolor(LIGHTGRAY).180.*y1. line(480.270. putpixel(t-11.50.Bismarck Salvador Traña López__________________________________________ UNI setcolor(*color).YELLOW). putpixel(px.*x2.90. t=1. putpixel(t+1. for(i=0.WHITE). if(i>=230) continue.YELLOW). setcolor(GREEN).250. setfillstyle(SOLID_FILL. ellipse(310.100.50.50.05.250).90.color).BLUE). putpixel(t-5.180.639.py=*y. arc(310.

100.180.180.80.YELLOW).h> Juan Carlos Gutiérrez Barquero____________________________________________ 93 .RED).80. } t+=3. putpixel(t+13. putpixel(t+13. putpixel(t+7.BLUE). putpixel(t+1. } else { putpixel(t+1.RED). } Este programa dibuja con el Mouse.RED).BLUE).BLUE). do { t=1.LIGHTGREEN).YELLOW).180. if((t+1)>=292 && (t+1)<=317) { putpixel(t+1.180. putpixel(t+7. } t=0.Bismarck Salvador Traña López__________________________________________ UNI setfillstyle(SOLID_FILL.RED). putpixel(t-5. putpixel(t+1. } void cometas(void) { int i. #include <mouse. floodfill(590. putpixel(t-11. putpixel(t-3.65. putpixel(t-11. } delay(2000).230.180.YELLOW). }while(!kbhit()).65.180. putpixel(t-9.i<=450.RED).65.80. putpixel(t-5. for(i=0.YELLOW).i++) { if(i>=230) continue.t.LIGHTGRAY). else { putpixel(t+3.BLUE).YELLOW).100.YELLOW).100.

h> #define ESC 27 void main() { int a=DETECT.getmaxy()-100). outtextxy(10. outtextxy(10.posy.450.getmaxy()-100). outtextxy(10." Bismarck Salvador Tra¤a L¢pez"). posx=mxpos(1)." se borrara").0.20."a) click izq sostenido para dibujar "). rectangle(100. outtextxy(10.420. mlimit(1.40.50. setcolor(YELLOW).60.Bismarck Salvador Traña López__________________________________________ UNI #include <stdlib. outtextxy(10. mocultar(). posx=mxpos(1).h> #include <conio.430. posx=mxpos(1)."c) presionar una vez click der indica que se escogera un nuevo punto donde").getmaxx()-100.h> #include <graphics.100.getmaxy()-100)."b) click izq dibuja una linea desde la pos. outtextxy(10.mypos(1)).30.1).mxpos(1).&b.100."d) click der sostenido para borrar"). posy=mypos(1). int posx." empezara a dibujar el click debe ser fuera del dibujo en caso contrario "). if(mclick()==1) { if(z==1) { z=0.100. outtextxy(10. rectangle(100.100.z=0.").h."c:\\tc20\\bin").getmaxx()-100.posy. anterior hasta la nueva pos.getmaxx()-100. posy=mypos(1). outtextxy(10.b."Juan Carlos Guti‚rrez Barquero")."e) presiona una tecla para salir o click si no has empezado ha dibujar").10. outtextxy(10.70. while(mclick()!=1) { setcolor(WHITE). mver()."Hecho por:"). } while(!kbhit()) { setcolor(WHITE). } Juan Carlos Gutiérrez Barquero____________________________________________ 94 . settextstyle(4. initgraph(&a. outtextxy(10+textwidth("Hecho por: "). posy=mypos(1). } line(posx.h> #include <stdio. mver().

mypos(1).BLACK). } clrscr().Bismarck Salvador Traña López__________________________________________ UNI else if(mclick()==2) { z=1. setcolor(BLACK).getmaxy()-100).codigo.100.h> void inicializar(void).h++) circle(mxpos(1). printf("desea seguir viendo los graficos").h> # include <dos. cleardevice().getmaxx()-100. # include<stdio.h> # include<graphics.h). mover(). void mover(void). } } void juego_visual(void) Juan Carlos Gutiérrez Barquero____________________________________________ 95 .&modo.h> # include <stdlib. exit(1).100. juego_visual().modo. } Este programa muestra el movimiento de una pelota. void juego_visual(void). void main(void) { inicializar(). fondo_de_la_pantalla(). initgraph(&adaptor. getch(). restorecrtmode()."c:\\tc20\\bin"). floodfill(mxpos(1). for(h=0. if((codigo=graphresult())!=0) { printf("%s".h> # include<conio.mypos(1). void fondo_de_la_pantalla(void).grapherrormsg(codigo)). } mlimit(1.h<=20. } void inicializar(void) { int adaptor=DETECT.

setcolor(YELLOW). sleep(1). i+=10.20).172. setbkcolor(BLUE).160. buffer=malloc(imagesize(127.400).98. rectangle(21. outtext("programa Cargado"). putimage(107+i. goto ala.20+i.160.i<=430. setcolor(WHITE).172.143))."Cargando programa de movimiento grafico"). getimage(107+i.98. setcolor(LIGHTBLUE). } void fondo_de_la_pantalla(void) { setbkcolor(BLUE).143). } void mover(void) { void far *buffer.20. sleep(1). if(i==430) { moveto(480. } } free( buffer). while(!kbhit()) { ala: circle(127+i. /*rectangle(127.Bismarck Salvador Traña López__________________________________________ UNI { int i.5.i++) { bar(10+i.XOR_PUT). delay(5000).*/ i=100.buffer. Juan Carlos Gutiérrez Barquero____________________________________________ 96 . for(i=11.buffer). outtextxy(5.180.30).20.450. } } sleep(1). if(i==300) { i=100. int i.147+i.30).200.

No se suele utilizar.11. Juan Carlos Gutiérrez Barquero____________________________________________ 97 .634. setcolor(BLACK). ya que el microprocesador era de 16 bits.Bismarck Salvador Traña López__________________________________________ UNI rectangle(1. etc. outtextxy(8.160. setcolor(RED). outtextxy(17."alir").LIGHTGRAY)."N"). Cuando aparecieron los primeros computadores existía una memoria de solo 640 Kb (memoria convencional) y el procesador que dominaba en aquella época era el 8086 y 8088 el cual podía direccionar hasta 1 Mb de memoria.5. Se utiliza como alojamiento de los modos alfanuméricos. setfillstyle(SOLID_FILL."uevo Juego").  Introducción. outtextxy(124. E000: Igual que D000. F000: Aquí se guardan todas la rutinas (funciones) de la ROM-BIOS.5. rectangle(110. B000: Es para las tarjetas de video monocromo MDA y Hercules.7. setcolor(BLUE).20).getmaxy()-1).LIGHTGRAY). setcolor(RED). setcolor(BLACK). rectangle(5. outtextxy(116. rectangle(6. el video."S"). Añadieron a este diferentes áreas de memoria.1. cartuchos ROM.5. floodfill(10. setcolor(BLUE). Hoy en día la configuración de todo PC está organizada en bloques de 64 kb. D000: Para cartuchos ROM.20). También sirve tarjeta CGA.11.20). que no forman parte del núcleo original de esta.11.100. } Modo 13h 320x200(). Organización de la memoria de un PC A000: corresponde a la memoria de la pantalla en los modos gráficos de las tarjetas EGA y VGA. para la BIOS. para la C000: Se depositan algunas rutinas BIOS. setcolor(LIGHTGRAY).11.getmaxx()-1.

SS. Con este registro podremos saber. por que el DOS trabaja en modo Real. las del Sistema Operativo y las iniciadas por el sistema (BIOS). Para eso utilizaremos Juan Carlos Gutiérrez Barquero____________________________________________ 98 . indican varias cosas según su valor. BP. tal y como indica su nombre. cada uno de estos se divide en dos partes. Los utilizamos para formar direcciones de 20 bits. ya sean a nivel DOS o BIOS. Las interrupciones. sirven para ayudar al funcionamiento de las instrucciones. Este lo usa el PC para “acordarse” en que punto se ha quedado a partir de la base CS. BX. el registro AX. Son unos registros de 16 bits que se usan como almacenamiento temporal. Con ellos referenciamos direcciones de memoria. las que son ejecutadas por el hardware. el valor excede de 65535 y por tanto no cabe en 16 bits. ejecutar un trozo de código y continuar con lo que se estaba haciendo. tienen como función interrumpir en medio de un procedimiento. El B. hay que conocer algunos conceptos que juegan un papel importante. pero a partir del 386 estos registros son de 32 bits. Registro de Puntero de Instrucción: IP (Instruction Pointer). Las interrupciones . Por ejemplo. Registros de dirección (Puntero / Indice): SP. que pueden valer 0 o 1. Los registros . DS. la parte alta (AH). términos como por ejemplo los registros. Hay de varios tipos.S ( Basic Input Output System) tiene una serie de interrupciones. Para hacer la programación del sistema. si por ejemplo después de una suma. para que cuando utilicemos alguna de ellas sepamos donde se encuentra. y DX. SS y ES.Bismarck Salvador Traña López__________________________________________ UNI El Procesador . junto con los registros de segmento CS. CX. Una definición un poco más acertada. Dentro de estas hay las enmascarable. y no puede direccionar más de 16 bits). y lleva el control de los programas. Podemos distinguir cinco tipos de registros diferentes: Registros Generales: Hay cuatro: AX. El tamaño de estos registros en un 286 es de 16 bits.O. De esta manera la CPU se ahorra de ir preguntado todo el rato a los diferentes periféricos si “necesitan” su ayuda (polling). y ES.I. Los registros son muy importantes para el ordenador. Estos bits. y la baja (AL). sería decir que los registros son como variables internas con las que el computador realiza operaciones. Tienen un propósito general para el programador. Registro de Bandera (Flag): Sirve para saber el estado y tener el control del procesador. Va cambiando su valor cada vez que saltamos a un punto del programa. Cada uno de estos registros se divide en dos partes de 8 bits cada una (esto es así. a los que hay que conocer si se quieren manejar las interrupciones. se divide en AH y AL (H de High y L de Low). y las no enmascarables (NMI). donde H significa High y L de Low. Registros de segmento: CS. para realizar operaciones aritméticas. DS. SI y DI.

y tiene una longitud de 256 entrada de 4bytes cada una. INTERRUPCION 01H: Un solo paso.Bismarck Salvador Traña López__________________________________________ UNI una tabla que nos servirá de “índice” para así obtener la dirección de la rutina. pero aunque hay más. INTERRUPCION 16H: Entrada teclado. es que permite usar a los programas diferentes periféricos independientemente de las características del hardware. INTERRUPCION 0BH y INTERRUPCION 0CH: Estas dos son para el Control de Dispositivo Serial. A continuación describiré todas las interrupciones de la BIOS y su finalidad de la 00H a la 1BH. Determinación equipo. O sea. INTERRUPCION 13H: Obtención tamaño memoria. Esta tabla se aloja en la parte más baja de la memoria. INTERRUPCION 05H: Imprime pantalla. es decir. 2 bytes de dirección (segmento) y 2 bytes de desplazamiento (offset). INTERRUPCION 04H: Desbordamiento. o sea. INTERRUPCION 02H: Interrupción no enmascarable. INTERRUPCION 15H: Servicios sistema. no serán comentadas ya que es de uso de la BIOS. INTERRUPCION 09H: Interrupción del teclado. Juan Carlos Gutiérrez Barquero____________________________________________ 99 . INTERRUPCION 14H: Comunicaciones i/o. INTERRUPCION 0EH: Control disco flexible. INTERRUPCION 11H: Obtener equipo instalado. que el Bios es un sistema de comunicación estándar. 1 kb en total. en 0000:0000. Hay rutinas de todas clases. Su función más importante. Esto nos ahorra mucho tiempo a la hora de programar para diferentes periféricos. El Bios dispone de las funciones principales que necesita un programa para la comunicación con el hardware del PC y los dispositivos conectados a él. INTERRUPCION 03H: Punto de ruptura. INTERRUPCION 10H: Servicios de video. INTERRUPCION 0DH y INTERRUPCION 0FH: Estas son para el Control del Dispositivo Paralelo. INTERRUPCION 00H: División entre cero. INTERRUPCION 08H: Sistema del cronómetro.

no significa que tengamos que rompernos la cabeza para poner un "¡Hola!" en pantalla. MS-DOS en nuestro caso. simplemente usaremos las funciones que nos pone a disposición nuestro lenguaje de programación favorito. y representarla es siempre igual para todos los computadores. Esto no quiere decir que las rutinas de la BIOS sean lentas de por si. por que si se hace mediante rutinas BIOS.Bismarck Salvador Traña López__________________________________________ UNI INTERRUPCION 17H: Salida impresora.  Introducción. tenemos unas ayudas que nos simplifican mucho la vida. Una de las cosas mas importantes en este tipo de programación es el acceso al hardware. que son los diferentes servicios a los que tenemos acceso. los algoritmos utilizados no varían. Esto es las funciones de el BIOS y del Sistemas Operativo. pantalla. se tendrá que pensar en el objetivo de la aplicación que se está desarrollando: si es un juego se tendrá que ir directo al hardware del computador. Por otro lado. la forma de tratar la información. esto sí es realmente la programación de sistemas. INTERRUPCION 1BH: Tomar control en interrupción del teclado. en la que se deben conocer como acceder al teclado. La Programación del Sistema A la hora de programar una aplicación. Pero lo que sí varía y que depende del sistema. las del sistema operativo. conlleva más tiempo mediante la programación directa al hardware. y en los demás registros los parámetros. Capitulo I. ya que cada uno de estos servicios. Para llamar a una interrupción utilizamos los registros. INTERRUPCION 18H: Entrada basic de rom. los podemos describir de forma muy general. INTERRUPCION 1AH: Lee y pone hora. donde en AX indicaremos por norma general el número de interrupción. Debemos saber por donde nos movemos si queremos que nuestra aplicación funcione correctamente. Resumiendo. es la forma en la que se debe tratar la información que entra en un programa y la forma en la que sale. impresora. ordenarla. Juan Carlos Gutiérrez Barquero____________________________________________ 100 . el juego quedará demasiado lento. archivos. Inicialización del modo gráfico. Estas rutinas (interrupciones) nos ahorrará mucho trabajo. Cada interrupción se divide en funciones. Aunque la programación de sistemas esté tan fuertemente ligada al hardware. Estas son las interrupciones del BIOS. tenemos que las diferentes capas a la que una aplicación puede acceder son tres: Para decidirnos por uno de los tres. lo que pasa es que son “universales” y llevan muchos tipos de comprobaciones. si lo que se quiere es hacer una aplicación en modo texto. etc. INTERRUPCION 19H: Cargador de arranque. pero hay más.

Este bit se denomina CHAIN-4. etc. permitiendo su modificación y lectura. Lamentablemente para usar los 256 colores solo se puede usar una resolución de 320x200 pixeles. En el primer caso (bit a 1) hablamos de modos lineales. Las tarjetas SVGA tienen cada una de ellas su conjunto de registros. El modo de acceder a cada controlador es distinto. que hace que la forma de programar sea distinta para cada uno. en el cual se han programado la mayoría de los juegos. hacen referencia al estado de este bit. Las tarjetas VGA tienen normalmente un mínimo de 256 Kb. modo texto (o alfanumérico) en el que se representan caracteres. Esta resolución es muy alta comparada con las antiguas tarjetas CGA y EGA. Este modo de vídeo es el conocido Modo 13h. demos. o de lectura/escritura. El inconveniente que presentan estas tarjetas. La VGA tiene una resolución máxima de 640x480 pixeles y puede mostrar simultáneamente un máximo de 256 colores. Los registros de estas tarjetas pueden ser. Los registros de las tarjetas constituyen el dispositivo de Entrada/Salida (E/S) de más bajo nivel de los adaptadores gráficos. Este modo es uno de los más usados en la programación gráfica. y en modo gráfico. Es en ellos donde se almacena la información relativa a como debe el computador representar los datos en la pantalla. por lo que estamos en el caso de los modos denominados planares. debido a su facilidad de uso y rapidez. por lo que la finalidad de este índice es señalar cuál de todos los registros es el que se modificará. La aparición de la tarjeta de video VGA (Video Graphic Array) como en el año 1987. El elemento que determina tanto la resolución como la cantidad de colores que podemos representar. aplicaciones gráficas. limitados a un plano. respectivamente. estando la memoria dividida en 4 segmentos o planos. La diferencia fundamental es la manera de gestionar la memoria. la forma de leer o escribir en los registros será diferente en cada caso. indicando que esta a 1 o 0. de lectura. que puede estar a 1 o 0. tendremos que acceder a estos registros. Cada uno de estos controladores tiene a su vez una serie de registros asociados. Cuando el bit está a 0. en el cual además de caracteres se pueden representar imágenes. Cuando hablamos de modos gráficos. Una tarjeta de video esta formada por varios controladores hardware integrados en una misma placa. Un mismo controlador puede controlar más de un registro. para lo cual se emplea un índice de puerto o index port. porque encadena los cuatro planos. es que aparecen problemas de compatibilidad. se almacena en código binario. Esta información hace referencia al color y atributos especiales. Cada adaptador tiene unas características determinadas. hizo que se convirtiera en un estándar de los computadores IBM y compatibles. la unidad representable es el pixel. La denominación chained (modos lineales) y unchained (modos planares). A la hora de programar las tarjetas gráficas. Un pixel (un punto) es la unidad mínima de información que podemos representar en pantalla. fuerza a usar los cuatro planos. No estaremos seguros de que todos nuestros programas que desarrollemos funcionen correctamente Juan Carlos Gutiérrez Barquero____________________________________________ 101 .Bismarck Salvador Traña López__________________________________________ UNI La pantalla de nuestro computador puede funcionar en dos modos. de escritura. es el adaptador. Existe un bit. Están conectados a puertos de E/S que los hacen accesibles. La información de un pixel.

Bismarck Salvador Traña López__________________________________________ UNI con todas las tarjetas. Existen modos superiores al 13h. Nosotros utilizaremos dos modos. es decir todos tienen el color 0 (negro). podremos crear nuestra primera rutina en lenguaje C para inicializar el modo 13h. Este problema se puede evitar si nos limitamos a utilizar el conjunto de registros de la VGA. el 13h y el 03h. este último los usaremos por la sencilla razón. Acuérdense de incluir la cabecera <dos. A continuación podrás ver los distintos modos de video. r. para esto utilizamos la función 00h de la interrupción 10h.al=0x13. Esta ultima es un interrupción software que facilita al programador tomar el control del hardware de un PC. Cuando se inicia este modo la memoria de video. La turina para incluir este modo sería: void Modo13h(void) { union REGS r. El nombre 13h viene del parámetro que hay que pasarle a la interrupción 10h para iniciar este modo. en este caso los 64 Kb se limpian. pero es el que tiene mayor número de colores. Qué significa todo esto. se debe regresar nuevamente al modo texto. Al iniciarse el modo 13h. los registros de la VGA se programan automáticamente con las características propias de este modo. Entrando al modo 13h . con los que la SVGA son perfectamente compatibles. Como podemos ver en la tabla el Modo 13h es uno de los que tiene menor resolución de los modos gráficos. &r). int86(0x10. que soporta la tarjeta VGA.h. El modo de video que utilizaremos se compone de 320 pixeles horizontales por 200 pixeles verticales.h> para utilizar la función int86 y la union REGS. En este caso nosotros queremos iniciar un nuevo modo de video. Ahora para iniciar el modo de video 13h debemos usar la función 00h de la interrupción 10h. &r. } Juan Carlos Gutiérrez Barquero____________________________________________ 102 . de que cuando se termina un programa gráfico. (320x200=64000) Después de haber visto todo la teoria necesaria. En este caso en el registro de 8 bits AL se le pasa el valor 00h y en el otro registro (también de 8 bits) se coloca el modo de video a inicializar. Este modo texto es de 80x25 y con 16 colores.ah=0. r. y para esto se les pasa unos parámetros. la cual esta encargada de activar modos de video específicos. pero estos pertenecen a tarjetas Super VGA o superiores. lo que sucede es que cada interrupción posee varias funciones y a su vez cada función también puede tener sub-funciones. La interrupción 10h esta encargado de dar los servicios de video.h. teniendo un total de 64000 pixeles. en este caso al modo 03h que es el que tienen por defecto todos los PC al ser encendidos.

r. Veamos de la primera forma: #include <dos. geninterrupt(0x10) . esto quedaría así: void SetMode(char mode) { union REGS r.ah=0. } y crear dos constantes con la directiva #define.h. esta función es similar al anterior. &r.h> para la funcion int86() # include <stdio. &r). sólo que el servicio 03h : void SetText(void) { _AX=0x0003 . } Para volver al modo texto usamos la misma interrupción 10h.al=mode. Otra rutina que nos será de mucha utilidad será la que regresa al modo texto. r. int86(0x10.h.Bismarck Salvador Traña López__________________________________________ UNI Lo que hemos hecho con esta función es simplemente llamar a la interrupción 10h con los parámetros necesarios para iniciar el modo 13h.h> para la funcion getch() Juan Carlos Gutiérrez Barquero____________________________________________ 103 . Podríamos crear una función general para que realice los cambios de modos de video. llamaríamos a la función SetMode de la siguiente forma SetMode(GRAFICO). es decir: #define TEXTO 0x03 #define GRAFICO 0x13 de esta manera para iniciar el modo 13h. } Otra manera seria: void SetMCGA(void) { _AX=0x0013 . la única diferencia es que al registro AL se le debe pasar el valor 03h.h> para la funcion printf() #include <conio. geninterrupt(0x10) . y para volver al modo texto simplemente: SetMode(TEXTO).

&r).h. ModoTexto().h. &r. getch(). void Modo13h(void) { _AX=0x0013 . geninterrupt(0x10) .h> para la funcion getch() unsigned char *DIR_VGA=(unsigned char *) MK_FP(0xA000. r. r. printf("Regreso a modo VGA"). Juan Carlos Gutiérrez Barquero____________________________________________ 104 . printf("Inicializacion correcta\npresione una tecla para volver\n al modo grafico").al=0x03. r. geninterrupt(0x10) . printf("Inicializacion correcta\npresione una tecla para volver\n al modo grafico").h. &r). } void main(void) { Modo13h(). &r.al=0x13.ah=0. } void ModoTexto(void) { union REGS r. int86(0x10.h. } De la segunda manera seria: #include <dos. 0).ah=0. getch(). int86(0x10. } void ModoTexto(void) { _AX=0x0003 .h> para la funcion printf() #include <conio. } void main(void) { Modo13h(). r.h> para la funcion int86() # include <stdio.Bismarck Salvador Traña López__________________________________________ UNI void Modo13h(void) { union REGS r.

geninterrupt(0x10). outportb(0x3c9.y.b).byte b) { outportb(0x3c8.h> para random() #include <conio. getch().poke. } void main(void) { int x.Bismarck Salvador Traña López__________________________________________ UNI getch(). El programa fue compilado con Turbo C Nota.byte g.x<=32.El programa debe ser compilado con alguno de estos modelos: COMPACT. geninterrupt(0x10). outportb(0x3c9. } void Modo13h(void) { _AL=0x13. void Setrgbpalette(byte c. for(x=1.0x000).c).g).geninterrupt #include <stdlib.x++){ Juan Carlos Gutiérrez Barquero____________________________________________ 105 . _AH=0. _AH=0.c. printf("Regreso a modo VGA"). } Un Ejemplo: Este es un ejemplo sencillo elaborado en el modo 13h (320*200) a 256 colores que realiza el efecto del fuego.ouportb. Modo13h().. #include <dos.LARGE o HUGE para que pueda funcionar correctamente. ModoTexto(). outportb(0x3c9.r).h> para kbhit() typedef unsigned char byte. } void ModoTexto(void) { _AL=0x03. byte far* Video= (byte far*)MK_FP(0xA000.h> para MK_FP.byte r.

y-=2.(y-2)*320+x. a la carpeta bin de TC20. “Svga256” es nombre del dispositivo debes omitir la extensión .(c<<8)+c). } Ya vimos un ejemplo en el modo13h y que les parecio el efecto del fuego bonito no pero que dirian si les digo que hay otro metodo de inicializacion que puede darle mas realce a sus programas.(y-1)*320+x.63. do{ y=60. para esta resolucion no estan disponibles las funciones setbkcolor(). }while(y<202). x+=2.63. Video[(y<<8)+(y<<6)+x]=random(2)*160. ni cleardevice(). Setrgbpalette(x+32. poke(0xA000.x*2-1.bgi .0).63. 768 verticales. poke(0xA000.x*2-1). Setrgbpalette(x+64.(c<<8)+c).63). 256 colores) Antes que nada debes copiar el archivo Svga256.63.bgi DetectVGA256 es una función que debes declarar anteriormente como: int huge DetectVGA256() { return 4.DetectVGA256). do{ c=(Video[(y<<8)+(y<<6)+x]+Video[(y<<8)+(y<<6)+x+2]+ Video[(y<<8)+(y<<6)+x-2]+Video[(y+2)*320+x+2])/4.63. ModoTexto(). si quieren saber un poco aquí les va: Se lla modo XGA Para poder ver estos ejemplos debes de tener intalada las librería que esta incluida en el tc20 que te obsequiamos Modo grafico con resolucion de 1024x768x256 (1024 pixeles horizontales. }while(!kbhit()). Luego tienes que poner dentro del main la siguiente instrucción: installuserdriver(“Svga256”. }while(x<=320). y+=2.que es un controlador para graficos. } y luego puedes llamar a la funcion initgraph() para empezar a trabajar en modo grafico.0.0). Aquí tienes el ejemplo completo: Juan Carlos Gutiérrez Barquero____________________________________________ 106 . Setrgbpalette(x+96.!No es broma ¡. } do{ x=0. if(c!=0) c--.x*2-1.Bismarck Salvador Traña López__________________________________________ UNI Setrgbpalette(x.

&tarj. x + 39.CHR").TIPOLETRA. 0."").9). 768). Juan Carlos Gutiérrez Barquero____________________________________________ 107 . /*Iniciamos el modo grafico*/ initgraph(&modo.bgi para acceder a 256 colores*/ installuserdriver("Svga256".0. setfillstyle(SOLID_FILL.6). int color=0. y + 39). /*y asi simulamos que hemos elegido un color de fondo*/ /*No se pueden utilizar los comandos cleardevice ni setbkcolor. if((color%16==0)&&(color!=0)) { x = 180. color++.x + 40. } void main() { int modo = DETECT. bar(x + 1. /*/Instalamos el driver SVGA. y = y + 40. /*Instalamos en nuestro proyecto el tipo de letra*/ TIPOLETRA = installuserfont("LITT.y=50.color). y + 1. while(color<256) { rectangle(x .h> int huge DetectVGA256() { /* 0 = 320x200x256 modo CGA 320(horizontal) con 200(vertical) pixeles(puntos) en 256colores 1 = 640x400x256 modo ATT400 2 = 640x480x256 modo VGA 3 = 800x600x256 modo SVGA 4 = 1024x768x256.10.x=180. y + 40). /*usamos el tipo de letra*/ setcolor(41). /*elegimos el color de relleno para dibujar una barra */ bar(0 . setfillstyle(SOLID_FILL. modo XGA Todos son los modos graficos estandar */ return 4.*/ setcolor(7).y .DetectVGA256).0. tarj.WHITE).h> #include <graphics.Bismarck Salvador Traña López__________________________________________ UNI #include<conio. x = x + 40. un gris oscuro*/ outtextxy(40. } } settextstyle(TIPOLETRA. /*usamos el color numero 18. setcolor(BLACK). settextstyle(TIPOLETRA."Prueba de Inicializacion del modo XGA 1024x768 pixeles"). 1028.

getch(). /* en pixels */ unsigned long int altura.bmp en modo 1024x768: #include <stdio."Huacho .h> #include <graphics.h> #include <conio. settextstyle(TIPOLETRA. /* numero de colores utilizados */ unsigned long int color_imp. unsigned long int num_color. unsigned long int offset.h> #define VAR 0 #define INVALIDO -1 #define FALLA 0 #define EXITO 1 #define KB_ESC 27 /* MACROS PARA LAS FUNCIONES GRAFICAS */ #define SEG_VIDEO 0xA000 #define M320x200 0x13 #define MTexto 0x3 struct cabecera { char ident[2]. } Ahora si quieren ver un programa funcionando a qui lo tienen Programa que carga imágenes . unsigned long int v_resolution. outtextxy(425. unsigned long int tam. unsigned long int tam_imagen. /* en pixels */ int planos. struct info_general { unsigned long int tam_cabecera.7). int tam_pixel. /* numeros de colores importantes */ }. Juan Carlos Gutiérrez Barquero____________________________________________ 108 . closegraph().Bismarck Salvador Traña López__________________________________________ UNI outtextxy(12.h> #include <dos.0.h> #include <mouse. setcolor(55).h> #include <stdlib.Peru").740."Como ves ahora si puedes usar el color negro en tus aplicaciones y usar una mayor resolucion: 1024x768"). /* tama¤o en bits de cada pixel */ unsigned long int compresion. /* en bytes */ unsigned long int h_resolution.690. }. unsigned long int anchura. char reservado[4].

1. struct info_general bmp_info. FILE *f. sizeof(struct cabecera). unsigned char verde. /* liberamos la memoria utilizada */ return 0. free(rgb). 1. /* leemos la informacion general del archivo */ fread( &bmp_info. f). void carga(void). unsigned char color). } void carga(void) { register int i. void despedida(void).*/ /*-------------------------------------------------------------------------*/ char verifica(char *fname). /* leemos la cabecera del archivo */ fread( &bmp_cab. unsigned char rojo. void modo_video(unsigned char modo). void mostrar_imagen(void). void info_general(void). void presentacion(void). f). void mostrar_pal(void). unsigned char reservado. char fname[50].Bismarck Salvador Traña López__________________________________________ UNI struct valor_rgb { unsigned char azul. void cambiar_pal(struct valor_rgb *pal). struct cabecera bmp_cab. fclose(f). void paleta(void). unsigned int y. void setpal(char col. void menu(void).num_color) /* si se usan todos los colores */ Juan Carlos Gutiérrez Barquero____________________________________________ 109 .char g. int main() { presentacion(). }. struct valor_rgb *rgb.char r. /*void putpixel(unsigned int x. /*leemos todos los colores que existen en la imagen */ if (!bmp_info. sizeof(struct info_general).char b).

. if (control == FALLA) { printf("\n ERROR FATAL: el archivo no existe o esta protegido.num_color = 1 << bmp_info.tam_pixel. f). /* leemos y almacenamos del archivo */ /* comprobamos que sea un archivo valido BMP */ if (bmp_cab. printf("\n ARCHIVO: "). 1. clrscr().ident[0] == 'B' && bmp_cab. printf("%55s". exit(1)... gets(fname). printf("\n\n\n Introduzca el nombre y ruta de ser necesario").num_color * sizeof(struct valor_rgb). } char verifica(char *fname) { f = fopen(fname."). bmp_info.num_color * sizeof(struct valor_rgb)). if (!f) return (FALLA). } if (control == INVALIDO) { printf("\n ERROR FATAL: el archivo no es un BMP valido. Juan Carlos Gutiérrez Barquero____________________________________________ 110 . if (!fname[0]) exit(0). /* calculamos dependiendo del numero de bits que ocupa cada pixel */ /* reservamos memoria dinamica para la tabla de colores RGB */ rgb = (struct valor_rgb *) malloc (bmp_info."rb"). control = verifica(fname).."---VISUALIZADOR DE IMAGENES BMP---"). exit(1).Bismarck Salvador Traña López__________________________________________ UNI bmp_info. fread(rgb. "). } void presentacion(void) { char control. } /* llamamos al menu principal */ menu(). carga().ident[1] == 'M') return (EXITO).

bmp_info.planos).color_imp). switch (opcion) { case '1': info_general(). printf("\n Tama¤o de la imagen: %ld bytes".bmp_info. } void menu(void) { char opcion..tam_imagen).bmp_info.bmp_info."). case '5': despedida(). printf("\n\n (3) MOSTRAR PALETA"). break.anchura).altura).bmp_cab.v_resolution). printf("\n Compresion: %d ". break. case '2': paleta(). printf("\n\n OPCION: "). printf("\n Tama¤o del archivo: %ld bytes". break. printf("\n\n\n PRESIONE CUALQUIER TECLA PARA CONTINUAR. printf("\n Offset del archivo: %ld". printf("\n Tama¤o de la cabecera: %d bytes". printf("\n\n (1) INFORMACION GENERAL DEL ARCHIVO"). opcion = getche().. printf("\n\n (5) SALIR").) { clrscr(). } } /* termina bucle for(.bmp_info. printf("\n Anchura: %d pixels". Juan Carlos Gutiérrez Barquero____________________________________________ 111 .bmp_info. printf("\n Numero de bits por pixel: %d bits". printf("\n Numero de colores importantes: %d colores". case '3': mostrar_pal()."<". printf("\n Resolucion horizontal: %d pixels/metros".bmp_info.bmp_cab.bmp_info. for (.num_color). printf("\n Numero de colores utilizados: %d colores".) */ } void info_general(void) { clrscr().h_resolution).tam_cabecera).bmp_info. printf("\n Numero de planos: %d". printf("%35s%s>\n". break.. printf("\n Resolucion vertical: %d pixels/metros".tam).bmp_info. printf("\n Altura: %d pixels". printf("\n\n (4) VISUALIZAR IMAGEN").fname). printf("\n\n (2) PALETA DE COLORES USADAS").bmp_info.offset).compresion).Bismarck Salvador Traña López__________________________________________ UNI else return (INVALIDO).tam_pixel). case '4': mostrar_imagen()..

. i++) setpal( i..azul). } printf("\n %10d %10d %10d %10d". int resto.azul / 4).j.Bismarck Salvador Traña López__________________________________________ UNI getch(). j = 1. i < 256.rojo / 4. i--. continue. if (i+1 == (bmp_info. pal[i-VAR]."Azul"). if (opcion == KB_ESC) break. printf(" Presione [ESC] para salir o cualquier tecla para continuar. printf("\n %10s %10s %10s %10s\n\n".. printf("\n %10s %10s %10s %10s\n\n"."Azul"). i."). pal[i-VAR]. char *linea. j++) { if (j == 20 || i == (bmp_info. char opcion. clrscr()."Color"."Verde". } void paleta(void) { register int i. rgb[i]. gotoxy(1. pal[i-VAR]. posicion = ftell(f).y. for (i = 0.rojo.verde. rgb[i].25). i <= (bmp_info.num_color)) break.num_color) ) { j = 0. rgb[i]. opcion = getch(). } } void mostrar_imagen(void) { register int x."Rojo". i++."Verde"."Color".num_color). } void cambiar_pal(struct valor_rgb *pal) { register int i. clrscr(). /* tomamos la posicion del puntero del archivo */ Juan Carlos Gutiérrez Barquero____________________________________________ 112 . unsigned long int posicion.verde / 4. for (i = 0."Rojo".

modo_video(M320x200).j. posicion. /* calculamos la cantidad de bytes necesario que sumado con la anchura sea un multiplo de cuatro */ resto = (4 * ((bmp_info. fseek(f. x < bmp_info. } void mostrar_pal(void) { register int i. /* reservamos memoria suficiente para albergar una linea de pixeles */ linea = (char *) malloc (bmp_info.altura . } getch(). i++) for (j = 0. gotoxy(20. j <= 50. for (i = 0. j++) putpixel(i. i < 256.Bismarck Salvador Traña López__________________________________________ UNI modo_video(M320x200)."). fseek(f.linea[x]). 1. y >= 0. mver().anchura + 3) >> 2)) . getch(). cambiar_pal(rgb). cambiar_pal(rgb). y--) { fread(linea. getch().anchura. } Juan Carlos Gutiérrez Barquero____________________________________________ 113 .i). SEEK_SET). bmp_info.bmp_info.y. for (y = bmp_info. f). } void despedida(void) { clrscr().j. for (x = 0.1.. printf("ESPERO QUE HAYA DISFRUTADO DEL PROGRAMA.anchura. /* restauramos la posicion inicial del puntero */ modo_video(MTexto).anchura). resto.13).anchura. exit(0). modo_video(MTexto). x++) putpixel(x.. SEEK_CUR).

asm { push ax push bx push di push es mov ax.[x] mov bl.char r.ah=0. int86(0x10.h. }*/ void setpal(char col.6 add di. installuserdriver("Svga256". r.char b) { Juan Carlos Gutiérrez Barquero____________________________________________ 114 .h. /* union REGS r.Bismarck Salvador Traña López__________________________________________ UNI /* ----FUNCIONES GRAFICAS ESCRITAS EN ENSAMBLADOR PARA SU MAYOR RAPIDEZ---. initgraph(&a.color.8 shl di.[color] mov es:[di]. unsigned char color) { unsigned char *vga=(unsigned char *) MK_FP(0xA000.&r.&b.&r).b. r.SEG_VIDEO mov es.bx add di.bl pop es pop di pop bx pop ax } memset(vga+x+(y*320). unsigned int y.ax mov bx.1).char g.[y] mov di.*/ int huge DetectVGA256() { return 4."c:\\tc20\\bin"). 0). } void modo_video() { int a=DETECT.DetectVGA256).al=0x13.bx shl bx.*/ } /*void putpixel(unsigned int x.

else setcolor(WHITE).r).238). int radio=180.Bismarck Salvador Traña López__________________________________________ UNI /*asm { mov dx. mov dx. } Ahora un Ejemplo de la utilización de las estructuras este programa se llama reloj analogo muestra la hora del sistema.b. initgraph(&a. xmin. yseg. h=0.h> #include <dos."*"). out dx.03c9h.03c8h. char mensaje[20].h> #include <stdio. mov al. out dx. yhora. outportb(0x3c9.hora.al.al. angulhora.al.col. int xseg.&b.b)."c:\\tc20\\bin").240. mov al. outtextxy(310+sin(6*h*(3.h> void main(void) { struct time tiempo. for(w=0. mov al.240-cos(h*(3. float angulmin. xhora. } Juan Carlos Gutiérrez Barquero____________________________________________ 115 .h> #include <math. outportb(0x3c9. ymin.h> #include <conio. out dx. out dx.r.h> #include <stdio.g).g.h.min.b.w++){ if(h%5==0) setcolor(RED).141592/180))*225. } */ outportb(0x3c8.141592/180)*6)*225.col). int seg.al. #include <graphics. int a=DETECT. outportb(0x3c9. h+=1. circle(310. mov al.w. anguloseg.w<=60.

ti_sec. yhora= 240 + 90 * sin(angulhora). seg=tiempo.ti_sec).mensaje). outtextxy(100. outtextxy(250. outtextxy(310.tiempo.0.230.420)."9").mensaje).ti_hour.240.240. line(310.ti_min. outtextxy(520.0d: %2.240. circle(310. line(310.yhora).hora.tiempo.ti_min.xhora.Bismarck Salvador Traña López__________________________________________ UNI settextstyle(1.xmin.433.390."12").240. sprintf(mensaje. xseg = 310 + radio * cos(anguloseg).230. hora=tiempo. yseg = 240 + radio * sin(anguloseg). outtextxy(250.14159)).ymin).0d". hora+=(min/60). sleep(1). outtextxy(300.xhora.ymin).240.240.xmin. setcolor(GREEN).8). } Juan Carlos Gutiérrez Barquero____________________________________________ 116 .14159)).390.yhora). if(hora>12) hora-=12.xseg.0f: %2. min=tiempo."3"). setcolor(WHITE). line(310."6").yseg). setcolor(RED).20."%2. angulmin=((min-15)/(3*3. ymin = 240 + 120 * sin(angulmin).360. angulhora=((hora*5-15)/(3*3. rectangle(240. } while(!kbhit()). xhora= 310 + 90 * cos(angulhora). setcolor(BLACK). xmin = 310 + 120 * cos(angulmin). line(310.xseg.240.14159)).yseg). do{ gettime(&tiempo).390. setcolor(WHITE). line(310. anguloseg=((seg-15)/(3*3. line(310.2).

void ProyectaPunto(float .teta= -M_PI/7.C #define ARRIBA 72 #define ABAJO 80 #define DERECHA 77 #define IZQUIERDA 75 #define ESC 27 #define ENTER 13 Ahora en otro programa copia este codigo y te sorprenderas de ver lo que hace #include <graphics.h> #include <conio.h> #include <dos. void Objeto().h> #include <math. float y. /*****************************************************************/ /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ProyectaPunto ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º Funcion: Localiza un punto en la pantalla 3D º º º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */ void ProyectaPunto(float x.TAM=15.float .pro_X.fi= -M_PI/7. } /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ IniciarGraficos ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º Funcion: Inicializa el modo grafico º º º Juan Carlos Gutiérrez Barquero____________________________________________ 117 . /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º Definicion de funciones º º º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */ void IniciarGraficos(). Primero guarda estas lineas de codigo en un programa de C con el nombre TECLA.y*sin(fi)*sin(teta). void instrucciones().B. pro_Y = z*cos(fi) + x*cos(teta)*sin(fi) .float).h> #include <stdio. void xyz(). float z) { pro_X = y*cos(teta) + x*sin(teta).h> #include <stdlib.Bismarck Salvador Traña López__________________________________________ UNI Ahora aremos un efecto que talvez les guste y lo estudien con detenimiento ya que merece mucha atención.h> #include "tecla.c" //es para el manejo del teclado float A.pro_Y.

exit(0).Y.B=getmaxy()/2.tam.Y0 = pro_Y.y. getch().z.A + X*TAM. setcolor(8).B . ProyectaPunto(0.X = pro_X.BGI no podes correr el programa : ( asi que buscalo el C:\\tc\\bgi"). line(A + X0*TAM. º º º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */ void main() { IniciarGraficos().Y0*TAM. ProyectaPunto(0. setcolor(8).0.Y*TAM. int x.tam=3.X. line(A + X0*TAM.Z º º º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */ void xyz() { float X0.&Modo. A=getmaxx()/2.A + X*TAM.0). outtextxy(x.0).Modo=VGAHI. xyz().B .y=B .0)."").B ."x"). initgraph(&Tarjeta.y.Y = pro_Y. closegraph().Bismarck Salvador Traña López__________________________________________ UNI ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */ void IniciarGraficos() { int Tarjeta=VGA. } /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ xyz ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º Funcion: Dibuja Lineas de Guia en las coordenadas X.0. } } /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ Main ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º Funcion: Main.Y*TAM).B .Y = pro_Y.Y*TAM).Y0.X0 = pro_X. ProyectaPunto(tam. Objeto(). Juan Carlos Gutiérrez Barquero____________________________________________ 118 .Y0*TAM.X = pro_X. setcolor(8).Y. x=A + X*TAM. if(graphresult()!=grOk){ printf("\nSi perdiste el archivo EGAVGA.

FF[8].AA[1]=pro_Y.B . } /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ Objeto ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º Funcion: Dibuja un objeto 3D º º º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */ void Objeto() { float angulo=-M_PI/100. setcolor(1).X = pro_X.yb2.yb1=3. ProyectaPunto(0.xb4=3. setcolor(8).0).za2=-3. ProyectaPunto(5.y.AA[2] = pro_X.zb1).ya4. xb1=3.CC[7]=pro_Y.EE[8]. /*-------------------------------------------*/ ProyectaPunto(xb1.A + X*TAM.BB[7] = pro_Y.estrellas[2].AA[6] = pro_X.BB[2] = pro_X. setcolor(RED).Y*TAM. ProyectaPunto(xb4.zb4=3."y"). outtextxy(x.AA[3] = pro_Y.ya3=-3.AA[4] = pro_X.Y*TAM).yb4=3.xa2=-3.Y = pro_Y. outtextxy(x. float AA[8].y=B .za4=3.za3).BB[4] = pro_X.-8.Y*TAM.0. ProyectaPunto(5.ya1=-3.8.zb2=-3.xb2=-3.ya3. ProyectaPunto(xa4.za4).CC[1]=pro_Y. unsigned char tecla.y. outtextxy(x. x=A + X*TAM.BB[3] = pro_Y.5.X=pro_X. xa1=3.ya1.CC[12].ya2=-3.CC[11]=pro_Y.Y = pro_Y.zb3=3. setcolor(8).CC[6]=pro_X.yb3.BB[1]=pro_Y. ProyectaPunto(xa3. ProyectaPunto(-4. int fo.za2).za3=3.B .3).tam).BB[5] = pro_Y.xa4=3.Y*TAM.yb2=3. xb3=-3. ProyectaPunto(xb2.0.y=B . ProyectaPunto(xb3.CC[9]=pro_Y.-5. float x.Y0*TAM.zb1=-3.BB[6] = pro_X.yb4.CC[0]=pro_X.0). ProyectaPunto(xa2.CC[4]=pro_X. setcolor(8).0).10.CC[5]=pro_Y.y.CC[8]=pro_X. do{ ProyectaPunto(xa1. ProyectaPunto(10.0).y=B .BB[8]. xa3=-3."z").y.AA[7] = pro_Y.AA[0]=pro_X.zb2). line(A + X0*TAM.ya2.Bismarck Salvador Traña López__________________________________________ UNI x= A + X*TAM.0.za1). x=A + X*TAM.-1)."JDZx").AA[5] = pro_Y.ya4=-3. ProyectaPunto(0.zb4).BB[0]=pro_X.yb1.zb3). setcolor(8).CC[10]=pro_X.za1=-3. ProyectaPunto(0. Juan Carlos Gutiérrez Barquero____________________________________________ 119 .yb3=3.

A + BB[6]*TAM.B .B . if(kbhit()) { tecla=getch(). line(A + BB[6]*TAM.AA[1]*TAM. putpixel(A + estrellas[0]*TAM.AA[7]*TAM. line(A + AA[6]*TAM.B . line(A + AA[0]*TAM.5. ProyectaPunto(-10.TAM*2.B .B .3.B . putpixel(A + estrellas[0]*TAM.estrellas[1]*TAM.0).A .CC[1]*TAM.7).estrellas[1] = pro_Y.-2).B . ProyectaPunto(10.BB[1]*TAM). circle(A + CC[4]*TAM.A + BB[0]*TAM.-3.estrellas[1]*TAM.A + AA[6]*TAM.B .estrellas[1] = pro_Y.B . line(A + AA[0]*TAM. setcolor(4).52).CC[5]*TAM.AA[1]*TAM.B . } setfillstyle(1.estrellas[1] = pro_Y.CC[7]*TAM.TAM*0.7).B .B .estrellas[1]*TAM.estrellas[0] = pro_X.AA[5]*TAM.B .estrellas[1] = pro_Y.A + BB[6]*TAM. circle(A + estrellas[0]*TAM. /*-----------------------*/ ProyectaPunto(5.AA[1]*TAM. ProyectaPunto(-10. line(A + BB[4]*TAM.B .7).0.estrellas[1]*TAM.-2).TAM*0.TAM*2.BB[1]*TAM). ProyectaPunto(-5. putpixel(A + estrellas[0]*TAM.estrellas[1] = pro_Y.A + BB[2]*TAM.AA[7]*TAM).BB[3]*TAM).CC[11]*TAM.estrellas[1]*TAM.-3.25).B . circle(A + CC[8]*TAM.B . setcolor(2).CC[9]*TAM.AA[3]*TAM.AA[7]*TAM).7).7).A + BB[4]*TAM.AA[5]*TAM.B .B .A + BB[4]*TAM.2).Bismarck Salvador Traña López__________________________________________ UNI circle(A + CC[0]*TAM. putpixel(A + estrellas[0]*TAM. line(A + AA[4]*TAM.BB[7]*TAM).BB[3]*TAM). line(A + AA[0]*TAM. circle(A + CC[10]*TAM. setcolor(8).B .A + BB[0]*TAM. ProyectaPunto(-15-0.BB[7]*TAM.B .B .B .BB[1]*TAM.estrellas[0] = pro_X.AA[3]*TAM).B .B . tecla=IZQUIERDA.estrellas[0] = pro_X.B .B .estrellas[1]*TAM.-2).2). circle(A + CC[6]*TAM. line(A + AA[2]*TAM.B .BB[5]*TAM.estrellas[0] = pro_X. line(A + BB[0]*TAM.AA[3]*TAM.BB[3]*TAM.A + AA[2]*TAM. line(A + AA[4]*TAM.B .-3.AA[5]*TAM).A + BB[2]*TAM.8).TAM*0.2. Juan Carlos Gutiérrez Barquero____________________________________________ 120 .2).B .A + AA[4]*TAM. setcolor(3).estrellas[1] = pro_Y.BB[5]*TAM).BB[7]*TAM).B . line(A + AA[2]*TAM.-2).-2).5). xyz().estrellas[0] = pro_X.BB[5]*TAM). setcolor(YELLOW).B .B .TAM*0.estrellas[0] = pro_X.A + AA[6]*TAM.B . putpixel(B + estrellas[1]*TAM. line(A + BB[2]*TAM.B .

clrscr().Bismarck Salvador Traña López__________________________________________ UNI switch(tecla) { case DERECHA:teta-=angulo. void Juego(void).h> #include<stdio.break.2.break. no se quien es el autor. void Libera(void). case 120:if(TAM<30)TAM+=0.0. void Pinta_rapido(void). Juan Carlos Gutiérrez Barquero____________________________________________ 121 . #define colorfondo 0 #define colorcabeza 4 #define c 1 #define bordear 40 #define bordeab 460 #define bordeiz 20 #define bordede 620 /*acotamos la parte valida de pantalla*/ void Inicio(void). }/*endcase*/ if(!kbhit()){delay(50).h> # include <dos. void Escribe_record(void).break. void Avanza(void). int Es_punto(int x. } /*Ahora un juego de la serpientes este es un programa que encontre en Internet. void Pinta_serpiente(void).break.h> #define clear.getmaxx(). le hice algunos cambios */ #include<stdlib.} bar(0. }while(tecla!=ESC). void Lee_record(void). void Salir(void).2. void Crece(void).break.h> #include<graphics. case IZQUIERDA:teta+=angulo. case 122:if(TAM>0)TAM-=0.int y). case ABAJO:fi+=angulo.break. void Pinta_pantalla(void). int Choque(void). case ARRIBA:fi-=angulo.h> #include<conio.getmaxy()).

50.xa.4). cprintf("Û"). textcolor(14). cprintf("Û"). cprintf ("Û"). i<81.Bismarck Salvador Traña López__________________________________________ UNI struct bola{ int x. cprintf("Û").80.superado=0.gotoxy(40.30. textcolor(4).vel. gotoxy(36. gotoxy(34. cprintf("O").gotoxy(42.ya. int m. cprintf ("Ä").*ant.v.9).*indice. /*Para la lista*/ void main(void) { detectgraph(&tarj.modo. cprintf("Û"). int y.&modo). cprintf("Û"). cprintf("Û"). i++) { gotoxy(i. gotoxy(33.1).10}.3).6). cprintf("Û").5). cprintf ("ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ").40. /*La serp no es mas que una lista doble de puntos con su x y su y*/ struct bola *sig.*ultimo. /*No hay mas remedio que usar todas estas globales*/ struct bola *cabeza.radio=5. }.gotoxy(44.gotoxy(41. Juan Carlos Gutiérrez Barquero____________________________________________ 122 . gotoxy(34.7). gotoxy(39.8).60. cprintf (" ÛÛÛÛÛ ÛÛÛÛÛ").7).7). } void Inicio(void) { int i. cprintf ("ÛÛ ÛÛÛ ÛÛÛ ÛÛ").punt[9]={90. cprintf ("ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ").puntos. gotoxy(34.3)./*comprueba el hw y detecta la tarjeta a usar*/ Inicio(). cprintf("Û"). gotoxy(36. for (i=1. cprintf("Û"). cprintf (" Û ÛÛ ÛÛ Û").5). cprintf("O").70.20.gotoxy(44. gotoxy(33. gotoxy(40. gotoxy(40. } textcolor(1).max. gotoxy(38.5).gotoxy(40.9).2). cprintf (" Û Û"). gotoxy(34.1). Juego().4).4). gotoxy(34.2). gotoxy(34. cprintf ("ÛÛÛÛÛÛÛÛÛÛÛÛÛ"). clear.4). cprintf ("ÛÛ ÛÛÛÛÛÛÛ ÛÛ"). int longitud=0.tarj.9).

\n\r"). cprintf("TECLAS:\n\n\r"). cprintf ("Û Û Û Û Û Û Û Û").12). cprintf ("ÛÛÛ Û Û Û Û ÛÛÛ ÛÛÛ"). gotoxy(31. cprintf ("Dise¤ado por Abdul Ruiz"). initgraph(&tarj. case 6:v=4.break.break.. clear. cprintf("Espera..").break.Bismarck Salvador Traña López__________________________________________ UNI textcolor(9). gotoxy(31. getch().19). cprintf ("Dime el nivel de dificultad 1(Minima). gotoxy(29./*Para saber si hay algo de comida en la pantalla*/ int mov=radio*2.case 8:v=2.break..break. gotoxy(31.. switch(m) { case 1:v=9. cprintf(" <Ä(Izq) (Ab) Ä>(Der) 1(Izq) 2(Ab) 3(Der)\n\r"). cprintf ("CopyRight (c) 2002")./*configuramos los colores del juego*/ setcolor(colorfondo). }while(m<1 || m>9).break.14).case 3:v=7. por favor. cprintf("Si utilizas el teclado numerico. cprintf ("Û Û Û Û Û Û Û Û").16).&modo.&m). gotoxy(31. getch()./*iniciamos modo grafico*/ setbkcolor(colorfondo). } } void Juego(void) { int obj=0. textcolor(15).y2. char t. gotoxy(31. sleep(5).case 2:v=8.a. cprintf("Salir: S\n\n\r"). cprintf(" -(Ar) 5(Ar)\n\r").17). cprintf("MOVIMIENTOS o en el t. asegurate de que este activado\n\n\n\r")./*La tecla pulsada y la anterior*/ char pito=7.11). do{ scanf("%d".case 7:v=3.break. cprintf ("Û ÛÛÛ ÛÛÛ Û Û ÛÛÛ"). cprintf("Pausa: P\n\r"). delay(5500).case 5:v=5.break. Juan Carlos Gutiérrez Barquero____________________________________________ 123 .13).c). clear.break. setfillstyle(1. cprintf ("ÛÛÛ Û Û ÛÛÛ ÛÛÛ ÛÛÛ").case 4:v=6. gotoxy(31.case 9:v=1. cprintf("Pulsa una tecla para empezar"). int x2."c:\\tc20\\bin").10).9(Maxima): ").num. gotoxy(29.

/*ponemos otras dos bolitas de cuerpo*/ Crece(). }while(Es_punto(x2. } Juan Carlos Gutiérrez Barquero____________________________________________ 124 . }while(y2>bordeab-radio || y2<bordear+radio). delay(10000). vel=v*300./*ponemos una tecla (para que empiece yendo hacia la derecha)*/ superado=0. t=77. } /*si se pulsa una tecla*/ if(kbhit()) { a=t. cogemos una pos aleatoria*/ if(obj==0) { do{ do{ x2=(((rand()%((bordede/(radio*2))-1)+1))*radio*2)-radio. }while(x2>bordede-radio || x2<bordeiz+radio). obj=1.pito). do { /*si no hay objeto. cleardevice(). gotoxy(35. /*se guarda la anterior*/ t=getch(). Pinta_pantalla(). pierde*/ Salir(). do{ y2=(((rand()%((bordeab/(radio*2))-1)+1))*radio*2)-radio.y2)). /*si se choca. Crece(). /* y se coge*/ } if(Choque()) { printf("%c". /*la colocamos*/ cabeza->y=bordeab-radio. Crece().15). printf("ADELANTE"). /*creamos la cabeza*/ cabeza->x=bordeiz+radio.Bismarck Salvador Traña López__________________________________________ UNI Lee_record().

break. cabeza->y=cabeza->y-mov. case 'p':/*pausa*/ Juan Carlos Gutiérrez Barquero____________________________________________ 125 . setfillstyle(1. liberamos mem. /*arriba */ case 75: case '1': Avanza(). break. cerramos el modo grafico y exit*/ Libera().12). if(obj==1) /*si hay objeto.c). exit(2).Bismarck Salvador Traña López__________________________________________ UNI Pinta_pantalla(). break. break. Escribe_record(). cabeza->x=cabeza->x-mov. closegraph(). /*abajo*/ case 's': case 'S': /*si quiere salir. /*derecha */ case 80: case '2': Avanza().y2. cabeza->x=cabeza->x+mov. lo pintamos de otro color*/ { setfillstyle(1.radio-2). break. /*izquierda */ case 77: case '3': Avanza().radio-2. } switch(t) /*evalua la tecla*/ { case 72: case '5': Avanza(). cabeza->y=cabeza->y+mov. fillellipse(x2.

Crece(). case 9: Crece(). }*/ delay(vel).break.Crece(). Pinta_serpiente(). } /*si se pasa por encima del objeto.Crece(). i++.Bismarck Salvador Traña López__________________________________________ UNI cleardevice(). printf("Pausa").15).break. } } /*cuantas mas bolas tenga que dibujar el ordenador.Crece().Crece().Crece(). case 4: case 5: Crece(). case 2: case 3: Crece(). t=getch(). break.Crece().pito). case 6: case 7: case 8: Crece(). Pinta_serpiente(). cleardevice().Crece().break. volvemos a poner la enterior*/ default: t=a. se borra y se crece*/ if(cabeza->x==x2 && cabeza->y==y2) { puntos+=punt[v-1]. /*si la tecla pulsada no hace nada.Crece(). mas se*/ /*ralentiza el juego. printf("%c".Crece(). obj=0. gotoxy(37. esto lo contrarestamos disminuyendo el delay*/ /*cada 30 bolitas(lo he calculado a ojo) if((longitud)/(i*30)<0) { vel-=15. switch(m) { case 1: Crece(). break.Crece().Crece().break. if(puntos>max) { Juan Carlos Gutiérrez Barquero____________________________________________ 126 .

felicidades"). /*no hace falta comentar nada*/ if(superado!=0) { Escribe_record(). break. } void Salir(void) { char opc.Bismarck Salvador Traña López__________________________________________ UNI max=puntos. Libera(). }while(opc!='R' && opc!='I' && opc!='S'). switch (opc) { case 'R': Libera(). Juego(). do{ opc=toupper(getch()). case 'S': closegraph().10). Libera(). Juego(). break. printf("Estas muerto. printf(" Puntuacion maxima conseguida. } }while(1). break. } gotoxy(11. } } void Avanza(void) { indice=ultimo. gotoxy(11. superado=1. puntos=0.(S)Salir").15). exit(1).(I)Reiniciar. Inicio(). eres el mejor. lo siento (R)Reintentar. case 'I': closegraph(). Juan Carlos Gutiérrez Barquero____________________________________________ 127 .

setfillstyle(1. al pintar*/ /*una bola y moverla.Bismarck Salvador Traña López__________________________________________ UNI xa=ultimo->x. no?. } } void Pinta_serpiente(void) { int i=0.radio).*/ void Pinta_rapido(void) { setfillstyle(1.c). /*sin comentarios*/ while(i<longitud) { fillellipse(indice->x. ya=ultimo->y.radio). indice=cabeza. fillellipse(indice->x.indice->y.colorcabeza). i++. Juan Carlos Gutiérrez Barquero____________________________________________ 128 .c). co¤o pues pintemos solo*/ /*la primera.colorcabeza).cabeza->y. indice=indice->sig. fillellipse(cabeza->x. fillellipse(cabeza->sig->x. y asi. mida lo que mida la serpiente.indice->y. i++. si esta media mucho. indice=indice->ant.radio. } } /*Como hemos comprobado en anteriores versiones.cabeza->sig->y. y no se ralentiza casi nada. indice->y=indice->ant->y.radio).radio).ultimo->y.radio.radio. indice=indice->sig.radio). se ralentizaba el juego mogollon. se queda su estela pintada.radio. segunda y ultima bolita.*/ /*solo pintaremos 3 bolas. fillellipse(ultimo->x. y sabemos que. al pintar la serpiente entera*/ /*. setfillstyle(1. setfillstyle(1. /*nos quedamos con la posicion de la cola*/ /*corremos cada bola a la pos de la bola anterior*/ while(indice!=cabeza) { indice->x=indice->ant->x.radio.

} indice=ultimo. este=malloc(sizeof(struct bola)). ultimo=este. } void Crece(void) { struct bola *este. devolvemos un 1*/ while(indice!=NULL) { if(cabeza->x==indice->x && cabeza->y==indice->y) return 1. if((cabeza->y<bordear+radio)||(cabeza->x<bordeiz+radio)||(cabeza>x>bordede-radio)||(cabeza->y>bordeab-radio)) return 1.Bismarck Salvador Traña López__________________________________________ UNI } int Choque(void) { indice=cabeza->sig. indice=indice->sig. /*si la cabeza esta en la pos de alguna bola o sale de los limites. ultimo->sig=NULL. cabeza->x=bordeiz+radio. } Juan Carlos Gutiérrez Barquero____________________________________________ 129 . se a¤ade una struct bola al final de la lista*/ if(cabeza==NULL) { ultimo=cabeza=este. este->ant=ultimo. cabeza->ant=NULL. } else { ultimo->sig=este. cabeza->y=bordeab-radio. longitud++. /*pues eso. } return 0. este->y=-100. este->x=-100. ultimo->sig=NULL.

c).m.int y) { indice=cabeza->sig. while(indice!=ultimo) { aux=indice.ya. rectangle(bordeiz-1. free(aux).1). printf(" Serpiente v1 Desarrollado por Abdul Ruiz Chaos\n\r").bordear-1. longitud=0.radio. indice=indice->sig. : %4d Puntuacion :%4d Longitud : %4d". printf("Nivel : %1d Punt. /* dibujamos los bordes de la pantalla */ setcolor(15). } aux=indice. } void Pinta_pantalla(void) { gotoxy(1.Bismarck Salvador Traña López__________________________________________ UNI void Libera(void) { struct bola *aux. setcolor(0). setfillstyle(1. gotoxy(10.Max. } int Es_punto(int x. la pantalla vibraba mucho*/ setfillstyle(1. indice=cabeza. Pinta_rapido().max.colorfondo).longitud).bordede+1. porque usando un cleardevice(). /* dibujamos la serp */ /*"borramos" la ultima bola*/ /*este metodo es mas util.radio). fillellipse(xa. free(aux). /*no hace falta comentario*/ cabeza=ultimo=NULL.puntos.2).bordeab+1). Juan Carlos Gutiérrez Barquero____________________________________________ 130 .

arch). } } void Escribe_record(void) { FILE *arch. } fclose(arch)."rb"))!=NULL) { fread(&max. arch=fopen("chaos.arch). } void Lee_record(void) { FILE *arch.sizeof(int). if((arch=fopen("chaos.1.1.ars". indice=indice->sig. } else { max=puntos. if(puntos>max) { max=puntos.sizeof(int). fwrite(&max.Bismarck Salvador Traña López__________________________________________ UNI while(indice!=NULL) { if(x==indice->x && y==indice->y) return 1."wb").ars". } return 0. } Juan Carlos Gutiérrez Barquero____________________________________________ 131 . fclose(arch).

Se hablaba por entonces ya del término complejidad. El concepto de línea se amplió pasando a ser el lugar geométrico compuesto por la unión de los puntos de corte de dos arcos realizados con un compás. lo que nosotros llamamos . Ya en 1672 se demostró que cualquier construcción que pudiera realizarse sólo con regla y compás podría hacerse usando sólo compás. pero sí intentaban reducirse el número de pasos a realizar para resolver un problema. han supuesto las herramientas matem áticas para el diseño de algoritmos rápidos. exigió de pronto el conseguir métodos que no sólo funcionaran. Un tratamiento algorítmico implica eliminar el término infinito. sobre todo por aquel entonces: la memoria y el tiempo de CPU. Hoy por hoy a pesar de utilizar máquinas más potentes. no computacional pero sí de dificultad para medir la complicación de su realización. propicia usar estas máquinas para resolver problemas clásicos que siempre fueron resueltos a base de reglas y compás. posee un conjunto de primitivas asociadas. El primer algoritmo que pueda considerarse completo es la construcción Euclídea. la mayoría de las veces compartido. Por un lado la distancia es un tema esencial en conceptos geométricos y la teoría de la convexidad es analizada para obtener propiedades globales. no sólo en disciplinas inmediatamente relacionadas con la Geometría. el incremento del uso de la computadoras en investigación y desarrollo.1.Bismarck Salvador Traña López__________________________________________ UNI 1 Introducción a la Geometría Computacional 1.complejidad temporal. A partir de finales de los años 60 y 70. Este algoritmo además da una colección de instrucciones y reglas. Pero la memoria de las máquinas y el tiempo de ejecución de éstas. Ya en 1902 se describió un conjunto de pasos para contar como realizar sobre papel una serie de primitivas Euclídeas.complejidad del algoritmo. la Geometría métrica y la teoría de la convexidad. por ejemplo el crecimiento del análisis real. Se puede decir que fue una aproximación a lo que entendemos hoy por .. Hoy día la Geometría Computacional se utiliza como herramienta básica. Constituían una herramienta muy importante para resolver problemas prácticos. No se hablaba del problema en función del conjunto de entrada. también se plantea en Juan Carlos Gutiérrez Barquero____________________________________________ 132 . Historia de la Geometría Computacional La Geometría fue estudiada desde la antigua Grecia y Egipto.. no ambiguo y tiene un final. La Geometría ha tenido momentos de especial realce. Poco a poco se fueron dando cuenta de que todo problema posee un esfuerzo mínimo de realización. porque fue el primero que satisfizo todos los requerimientos: es correcto. La Geometría Algorítmica está basada en caracterizaciones de objetos geométricos en términos de propiedades de subconjuntos finitos. sino que intentaran optimizar al máximo dos recuerdos muy importantes.

Por otra parte. El término nace en 1975 por Shamos y desde entonces los trabajos y los estudios en esta disciplina han ido creciendo de forma espectacular. básicamente de su tamaño. Juan Carlos Gutiérrez Barquero____________________________________________ 133 . Por el contrario es beneficioso en muchas ocasiones realizar un buen diseño a pesar de utilizar gran cantidad de esfuerzo y emplear estructuras de datos complejas. Para medir dicha eficiencia. Así. Como entrar en detalles de compiladores diferentes y de distintas arquitecturas es muy amplio y además es absolutamente cambiante. Sistemas de Información Geográficos. se da por supuesto que tiene que ser eficiente con grantes cantidades de datos y además hay que suponer que dicho algoritmo va a ser ampliamente utilizado. por lo que hoy sigue siendo un problema a resolver.2. un algoritmo poco eficiente con pocos datos es preferible utilizarlo a otro que necesite gran cantidad de tiempo en diseñarse. va a ser más rápido si tiene que procesar diez datos que si tiene que realizar lo mismo con una entrada de tamaño cien. Algo similar ocurre con respecto a la eficiencia. Calidad del código que genera el compilador en el programa objeto. codificar y depurar es preferible a otro que realice lo mismo pero que no cumpla estas carácter ísticas. Obviamente un algoritmo. cuando nuestro algoritmo pretende resolver un problema clásico. basta decir que cuanto más rápido mejor. Algunas aplicaciones donde la Geometría Computacional es necesaria es la Informática Gráfica. etc. Las instrucciones y arquitectura de las computadoras. un algoritmo es eficiente cuando usa adecuadamente los recursos del ordenador y lo hace con la mayor rapidez posible. hay que tener en cuenta ciertos parámetros:     Dependencia de los datos de entrada del programa. como puede ser en Geometría Computacional. Un algoritmo fácil de entender. Tiempo de ejecución de dicho programa. Robótica. si se consigue finalmente un método de resolución que realice buenos tiempos de ejecución para entradas grandes de datos. Eficiencia de los algoritmos Existen distintas formas de medir algoritmos o de clasificarlos. 1. Lo que haremos será estudiar los algoritmos en función de la entrada. Para optar por escribir un tipo de algoritmo que cumpla con las especificaciones anteriores tambi én es necesario saber cuantas veces va a ejecutarse dicho algoritmo y con qué cantidad de datos. y además en la complejidad o tiempo que emplea el algoritmo para su ejecución. Los recursos son siempre referidos al tiempo de ejecución y al tiempo de CPU que necesita para ejecutarse. Por tanto. nuestro propósito es no sólo entender y utilizar algoritmos que funcionen en Geometría Computacional sino que también sean eficientes.Bismarck Salvador Traña López__________________________________________ UNI muchas ocasiones incrementar el número de datos a procesar. o programa puesto que se está ejecutando.

Pero esto no siempre es verdadero para todo n. n tiende a infinito. Se dice que T(n) es (g(n)) cuando existe una constante c tal que T(n) fi cg(n). si un algoritmo va a ser utilizado pocas veces. O(n) o O(nlogn). siendo c una constante. De esta forma se puede acotar el problema con una cota superior que nos permita conocer el margen en el que nos podemos mover. si la eficiencia a nivel de tiempo en CPU implica un alto coste en cantidad de almacenamiento o porque se encuentre en dispositivos de memoria masiva. en ocasiones el tiempo de ejecución se refiere a grandes cantidades de información y por tanto. puesto que depende excesivamente de la máquina empleada. Así O(n2) es mejor que O(n3). A menos que un algoritmo tenga una velocidad de crecimiento baja. O(n) es mejor que O(n2) pero peor que O(nlogn). el costo de escritura de una algoritmo eficiente puede que no merezca la pena. es decir. Por otro lado. o en O(nlog n). En muchas ocasiones es necesario referirse al tiempo de ejecución esperado del algoritmo en el peor de los casos para una entrada de tamaño n. Es una cota inferior o lo que es lo mismo: el algoritmo se ejecutará al menos en el tiempo que la función g(n) indica. También existen cotas inferiores para hablar del tiempo de ejecución.Bismarck Salvador Traña López__________________________________________ UNI Vamos a denominar T(n) al tiempo de ejecución de un programa con tamaño n. A pesar de todo lo expuesto anteriormente. Por ejemplo. Por último. Para no especi ficar el tiempo en segundos. Por tanto es lo que llamamos cota superior que nos identifica el peor caso. Para calcular la eficiencia de un algoritmo hay que tener en cuenta ciertos casos: Juan Carlos Gutiérrez Barquero____________________________________________ 134 . más rápido se ejecutará el algoritmo para un conjunto de entrada de tamaño dado. En el caso genérico decimos que T(n) es O( f (n)). un crecimiento modesto en la rapidez de la computadora no infiuirá gran cosa en el tamaño del problema. Por ejemplo un programa con tiempo O(100n) es más lento para n menor que 20 que otro que se ejecute en tiempo O(5n2). T(n) = cn2. se usará una función expresada en términos de n. Tampoco es necesario si siempre va a recibir un conjunto de entrada pequeño. En algunas ocasiones un algoritmo puede permitirse el lujo de ser algo más lento si a cambio es más didáctico. Cuando decimos que el tiempo de ejecución T(n) de un programa es O(n2) significa que existen constantes enteras positivas c tales que T(n) fi cn2. en algoritmos numéricos es tan importante la precisión de los cálculos como la eficiencia de éstos. El caso medio también puede ser interesante en casos donde se conozca que el peor caso se produce con una probabilidad muy pequeña. En algoritmos típicos de Geometría Computacional lo que se busca sobre todo son ejecuciones en tiempo lineal O(n). Cuanto menor sea la representación gráfica de la función f (n).

se considera tiempo cuadrático (suponiendo que el cuerpo del bucle tuviera un tiempo contante). Este método es muy habitual en los problemas resueltos con el método Divide y Vencerás. También existen simplificaciones. el tiempo totalserá de T1(n)+T2(n). n >1.  En las proposiciones condicionales. Cuando éste proceso de división termina necesita un tiempo lineal para unir los resultados de las dos mitades. Sin embargo. Cuando se hacen llamadas a procedimientos no recursivos. pero en procesos recursivos se trabaja de forma distinta. parte then o parte else. Juan Carlos Gutiérrez Barquero____________________________________________ 135 . El tiempo global de esta instrucción se toma de nuevo como el mayor de las dos partes que la forman. En el siguiente ejemplo tenemos a un algoritmo recursivo. el proceso divide el problema en dos mitades de aproximadamente el mismo tamaño. la parte de la condición suele considerarse tiempoconstante si no necesita realizar llamadas a otras funciones. Siguiendo este proceso hasta el término i entonces T(n) = ic+T(n–i). multiplicadas por el orden del conjunto de instrucciones del cuerpo del bucle. Si tenemos dos bucles de n ciclos. se suman todos los tiempos de ejecuci ón según las pautas anteriores. El término T(n –1) se sustituye por n –1: T(n–1) = c+T(n–2). Cuando i = n–1. sustituyendo tenemos que T(n) = c+c+T(n–2). se considera únicamente el más lento de los dos y eltiempo de ejecución vendrá dado por tanto por O(max( f (n). uno dentro de otro.O(c f (n)) se considera siempre O( f (n)). Para el caso general. tenemos que T(n) = c +T(n –1).Bismarck Salvador Traña López__________________________________________ UNI  Si T1(n) y T2(n) son tiempos de ejecución de dos fragmentos de programa. siendo O( f (n)) eltiempo para T1(n) y O(g(n)) para T2(n). por ejemplo. T(n) = nc+T(1) = ncfi= O(n).  Una asignación u operación aritmética suele considerarse con tiempo O(1). Supongamos la siguiente función:  En un ciclo se suele determinar por el número de iteraciones Para n > 2.g(n)) .

Por ejemplo. los de tipo geométrico deben ser definidos explícitamente por el programador. Los datos enteros sí garantizan su transformación íntegra a un tipo de dato almacenado en memoria. a la hora de ser procesados por un ordenador. Introducción A nivel de tratamiento de la información. a no ser que alguno de ellos aparezca. siempre que éste sea menor que una valor dado. TipoPoligono. sin embargo si queremos saber exactamente el lugar de intersección. Los algoritmos aparecerán mayormente escritos en lenguaje Pascal. son reemplazados por lo que denominamos tipos de datos. no por razones prácticas sino didácticas. el tipo de dato TipoPunto. así usamos el concepto de variable o de constante. Nos servirá igualmente para recordar conceptos a nivel computacional. ahora identificaremos los anteriores en Pascal para poder trabajar con ellos a lo largo de este tema: Juan Carlos Gutiérrez Barquero____________________________________________ 136 . Cuando una variable de tipo real nace en la ejecución de un programa y a su vez es utilizada como entrada para crear otras nuevas. en Geometría Computacional es clara la preferencia por los tipos de datos enteros. es preferible hacer uso de la aritmética entera. Muchos conceptos típicamente matemáticos se denominan de forma análoga cuando se representan internamente.1.2. En este curso utilizaremos varios de estos tipos de datos. Los tipos de datos identifican el tipo de cada una de estas posibles variables o constantes. sí era necesario realizar algún cálculo en coma flotante.3. para saber si dos segmentos intersecan basta utilizar aritmética entera. lo que se denomina aritmética entera. Por ejemplo.Bismarck Salvador Traña López__________________________________________ UNI 1. Sin embargo. este proceso repetido puede hacer que el dato se aleje del valor correcto.3. 1. Los tipos de datos que cualquier lenguaje de programación soporta cubren el espectro más habitual. sin embargo. En las clases de prácticas se definirán muchos de ellos. 1.3. el ordenador debe transformar todo dato de la recta real en un tipo de dato de una computadora que tiene un espacio finito de almacenamiento. etc. Operaciones básicas en Geometría Computacional En este apartado entraremos en contacto con métodos para la resolución de algunos de los problemas más elementales en Geometría. Algunos tipos de datos simples Los datos geométricos. Por esta razón. y siempre que sea posible. La razón es obvia. los datos reales o en coma flotante pierden casi siempre cierta precisión al ser guardados.

Ahora vemos el código: Int Area2(tPointi a. igualmente fácil de manejar computacionalmente. # define y 0. En caso contrario el valor será igualmente válido y medirá el área. pero tendrá el signo negativo. /*Declaración de un arreglo de puntos*/ /*********REPRESENTACION DE UN PUNTO***********************/ # define PMAX 100 Typedef tpointi tpolygoni[PMAX] Por simplicidad computacional. Las técnicas de tricoloreado dos tecnicas utilizadas para la representación de los guardas y otras entidades diferentes de las triangulaciones y vasadas en las diagonales si desean información de estas acudan al libro geometry computacional in C.3. El algoritmo escrito en pseudocódigo aparece a continuación. Cuando se dice que un polígono es un array de puntos. Cálculo del área Una de las operaciones más elementales en Geometría es el cálculo del área de un triángulo. aunque no es objetivo de esta asignatura el cálculo matemático correspondiente. se emplea un array con dos posiciones para un punto. sea del tipo que sea. typedef enum{ FALSE. tPointi c) { return : = ( ( a [ 0 ] *b[1])–(a [ 1 ] * b [ 0 ]) + ( b [ 0 ] * c [1])–(b [ 1 ] * c [ 0 ]) + ( c [ 0 ] * a[1])–(c [ 1 ] * b [ 0 ]) ) . se opta por trabajar siempre con aritmética entera. Juan Carlos Gutiérrez Barquero____________________________________________ 137 . Por razones argumentadas anteriormente. # define DIM 2 /*Dimensión del punto*/ typedef int tpointi(DIM). La función AreaTriangulo2 evitará la división por dos y calculará el doble del área del triángulo. tPointi c.Bismarck Salvador Traña López__________________________________________ UNI /************REPRESENTACION DE UN PUNTO*********************/ # define x 0. por lo hay que tener en cuenta que para obtener el valor real del área será necesario hacer la división correspondiente.3. realmente tenemos una matriz bidimensional con un total de dos columnas. identifi cando la posición 0 para guardar el valor de la x y la posición 1 para el de la y. TRUE}bool. } El resultado de este cálculo será positivo siempre que los vértices abc sean recorridos en orden inverso a las agujas del reloj. 1. El método para realizar este cálculo no es otro que la resolución de un determinante 3x3.

el área puede calcularse sumando las áreas de los triángulos resultantes o incluso restando los de aquellos que no tengan superficie. Este dato es muy importante. El número de triángulos obtenidos será de n–1. basta con calcular el área de todos los triángulos que se pueden formar lanzando diagonales desde cualquier vértice. – porque va a ser siempre el mecanismo utilizado para numerar los vértices cuando trabajemos con polígonos. siempre partiendo del punto p y siguiendo con dos vértices sucesivos del – modo siguiente: Juan Carlos Gutiérrez Barquero____________________________________________ 138 . Veamos el siguiente ejemplo: se ha elegido un punto cualquiera p. interior o exterior al polígono y se han trazado diagonales a todos sus vértices. como en el siguiente ejemplo: El área del polígono puede calcularse de dos modos:   Area (abd) + area (bcd) Area(abc) – area(adc) Este mismo principio puede extenderse a cualquier polígono. indistintamente del tipo y número de vértices que tuviera. Si el polígono no es convexo.Bismarck Salvador Traña López__________________________________________ UNI El cálculo del área de un polígono convexo es bien sencillo. hasta el resto de los vértices del polígono convexo. Los vértices de éste han sido enumerados del o al n–1 en orden inverso a las agujas del reloj.

suma=0. Intersección de segmentos Una de las operaciones elementales en Geometría Computacional es la intersección de segmentos. for(i=1. podemos optar por tomar al punto del polígono s[0]. es que todas las áreas de los triángulos no contenidas en el interior del polígonos son sumadas y restadas una vez con resultado igual a cero. return suma. Por tanto. sea interior o no al polígono. Se ha señalado utilizando un símbolo + cuando el cálculo se realiza en el sentido antihorario y con – cuando el área es negativa. a s[0]. el área correspondiente se resta. int i. El resultado lo podemos escribir a continuación: Veamos el código: int AreaPolygoni(tpointi s. finalmente será necesario dividir por dos el resultado final. sea en sentido horario. int n) { float suma. como podemos observar en la figura. lo que implicará siempre que el área de dicho triángulo es positiva. sumando unas veces las áreas y otras restándose automáticamente según sea la salida de dicha función.s[i]. Cuando el recorrido de los vértices del triángulo siempre en la forma pvivi+1. o lo que es lo mismo computacionalmente. cálculo válido para otros muchos problemas. es decir.i<n-1. podemos hacer uso de la función AreaTriangulo2 tantas veces como triángulos se vayan formando con el proceso anterior. Sin Juan Carlos Gutiérrez Barquero____________________________________________ 139 . por ejemplo el triángulo p67.Bismarck Salvador Traña López__________________________________________ UNI El triángulo p01 se traza en sentido inverso a las agujas del reloj.4.s[i+1]).i++) suma=suma+Area2(s[0].3. el resultado finalmente es el deseado. El resultado final. } 1. Como de cada triángulo se calcula el doble de su área. Como el punto P puede ser cualquier punto.

tpointi c) { Return Area2(a. tpointi b. El subprograma correspondiente únicamente necesita realizar una llamada a la función AreaTriangulo2 anteriormente vista. Es necesario observar que no es lo mismo el segmento ab que el segmento ba computacionalmente hablando. Aprovechamos un cálculo en principio de distinta índole. /*Si areamayor que cero retorna TRUE */ } No es difícil entender que este mismo principio sirve para determinar si el punto c está justamente a la derecha (la función anterior nos devuelve un valor f alse). el resultado es positivo si la lectura ordenada de los vértices nos da un recorrido antihorario. el algoritmo de intersección de segmentos va utilizar otra serie de subrutinas necesarias. lo que indica que los tres puntos son colineales: Juan Carlos Gutiérrez Barquero____________________________________________ 140 .b. Veamos el codigo: bool Left(tpointi a. Observemos la siguiente figura: El triángulo imaginario abc se dibuja en orden inverso a la agujas del reloj. El área del triángulo bac es negativa porque el punto c está a la derecha del segmento ba.Bismarck Salvador Traña López__________________________________________ UNI embargo. Esta propiedad puede ser útil para determinar si un punto c está a la izquierda del segmento ab. o si el área del triángulo abc es igual a cero. Si recordamos una de las propiedades de la función del cálculo del área del triángulo. lo que automáticamente nos está indicando que el punto c está a la izquierda de ab.c)fi0. para determinar la posición de un punto con respecto a un segmento. y siguiendo con la dinámica de trabajar siempre que sea posible con aritmética de enteros.

si d está a la izquierda de ab y c está a la derecha (o al revés) y además 3. El código debe tener en cuenta todos los casos citados anteriormente. Para solventar este problema es más conveniente establecer un margen de error permitido. es la operación XOR(a. Juan Carlos Gutiérrez Barquero____________________________________________ 141 . No quiere decir ésto que no pueda migrarse dicho código a operaciones en coma fiotante.Bismarck Salvador Traña López__________________________________________ UNI Veamos el codigo en C: bool Collineal(tpointi a.b. La operación válida para implementar el . no son colineales 2. } Debemos insistir en que el código anterior da por supuesto que todos los cálculos se realizan únicamente utilizando aritmética de enteros. puesto que no siempre el valor que nosotros consideramos como cero (o cualquier otro valor concreto) lo entienda así un tipo de dato en coma fiotante. si el valor absoluto de la variable real a es menor que un valor próximo a cero. Para saber si dos segmentos ab y cd intersectan. deberíamos saber si: 1..001 :::. si a está a la derecha de cd y b lo está a la izquierda (o al revés) Nos podemos dar cuenta en la figura de que si no se cumple algunas de estas premisas no tenemos garantía de que ambos segmentos intersecten. y operar así: i f abs(a) < 0.c)==0.b) cuya tabla de verdad da el valor verdadero cuando a y b son distintos. o lo que es lo mismo. tpoint b. pero en ese caso jamás debería realizarse una operación como esta i f a = 0 ::::. tpoint c) { return Area2(a.al revés.

d. tpoint b.b. If(a[x]!=b[x]) return ( (a[x]<=c[x]) && (c[x]<=b[x]) || (a[x]>=c[x] ) && (c[x]>=b[x]) ). tpointi d) { If( Between (a. Lo mismo debe hacerse para la ordenada.d. Una intersección impropia ocurre cuando un extremo de uno de los segmentos está justo en en alguna posición del otro. else return ( (a[y]<=c[y]) && (c[y]<=b[y]) || (a[y]>=c[y] ) && (c[y]>=b[y]) ). tpointi c.d. /*Hay intersección propia*/ else If(Between (a. /*No hay interseccion*/ } El inconveniente del método es la redundancia. La siguiente función en Pascal detecta primero si existe la posibilidad de colinealidad con la función Entre. tpointi b. Posteriormente hace el mismo proceso que IntersectaSegmento.c)) Return FALSE.b.a) || Between (c.Bismarck Salvador Traña López__________________________________________ UNI bool Intersect(tpointi a.d) || Between (c.b) ) } Juan Carlos Gutiérrez Barquero____________________________________________ 142 .c. tpoint c) { If(!Collineal(a.a) || Between (c. tpoint b.b.d) || Between (c. que será capaz de saber si un punto c está o no en el segmento ab. tpointi c. Ahora realizaremos una nueva versión del algoritmo utilizando la primitiva Entre.b.d)) Return TRUE. Veamos el codigo en C: boll Between (tpoint a.c) || Between (a.d.d) && Left(c. Veamos el código: bool IntersecImprop(tpoint a.b) ) return TRUE. tpointi d) { If (IntersectProp(a.a) || Left(c.d. Para ellos veremos si la coordenada x de c cae en el intervalo determinado por la coordenada x de a y b. } Esta versión del algoritmo además cuenta con al ventaja de poder trabajar con las intersecciones de forma propia o impropia.b.c) || Between (a.b) Return TRUE.b.b.b. else return(Left(a. /*Hay interseccion impropia*/ else return FALSE.c) || Left(a.d.

b.d)) && Xor (Left(c.b.P[i1])) /**/ return (Left(P[i].P[i1]P[i1]) && LeftOn(P[j].P[j].b) ) return FALSE.c) || Collineal (a.P[inl])).Bismarck Salvador Traña López__________________________________________ UNI Ahora veremos la function propia en C: bool IntersecProp (tpoint a tpoint b.b.c).d. pero para saber si es o no interno necesitamos realizar un procesamiento adicional. Una diagonal es aquel segmento que une dos vértices del polígono de forma que no intersecte con ningún otro eje de dicho polígono y además sea interno al polígono.Left (c. } Juan Carlos Gutiérrez Barquero____________________________________________ 143 .b))).P[inl]) && Left (P[j].d. Left (a. tpointi c. no siendo necesario un procesamiento completo del polígono P. Este cálculo puede realizarse en tiempo constante porque si una diagonal es interior a un polígono P en su vecindario (vértices próximos).d.P[i1])).P[i].a) || Collineal (c.b. determina si el vector que une los vértices i y j del polígono P es interior o no al polígono. return (Xor(Left (a. Cálculo de diagonales El cálculo de una diagonal tiene como objetivo la triangulación de polígonos.5.d) || Collineal (c. } bool Xor (bool x. también lo es para todo el polígono. Existen dos casos.d. el – caso convexo en el que el resto del polígono está en la parte de menor ángulo y el caso cóncavo en cuyo caso el ángulo es mayor que  La siguiente función .inl. tpointi d) { If( Collineal(a.a). else return (!(LeftOn[P[i]. inl=(i+n-1)%n. i1=(i+1)%n. int n. Para saber si existe o no intersección puede utilizarse el proceso anterior.3. } 1. Veamos el codigo: Esta función verifica si un vertice es convexo boll InCone(int i.P[i+. Diremos que un segmento s es interno a P si y sólo si es interno al cono cuyo vértice es vi y cuyos lados pasan a través de vi–1 y vi+1. if(LeftOn(P[inl]. bool y) { return !x^!y.P[i]. tpoligoni P) { int i1.

tpolygoni P) { return(InCode(i. El caso convexo ocurre cuando el vértice vi+1 está a la izquierda del eje trazado por vi–1vi. k++) { K1=(k+1)%n. En este caso. for(k=0. if( !( ( k==i) || ( K1==i ) || ( k==j) || ( k1==j ) ) ) Juan Carlos Gutiérrez Barquero____________________________________________ 144 . para que se trate de – un eje interno debe ocurrir que vi–1 esté a la izquierda de viv j y que vi+1 lo – esté a la izquierda. tpoligono p) { Int k. tpoint b.P)()).*/ bool Diagonal (int i.n. int j. } Vemos en la figura siguiente los dos casos comentados anteriormente. k<n. Este cálculo necesita forzosamente un tiempo de ejecución lineal. lo vemos en la figura de la izquierda. Pero el segmento i j es una diagonal si no intersecta con ninguna otro de las aristas del polígono. y que será invocado por la función Diagonal cuyo código resulta bastante evidente: el segmento i j es una diagonal del polígono P de tamaño n si es interior y además no intersecta con ninguna arista. } /*Esta function verifica si una diagonal se intersecta con una arista del poligono */ bool Diagonalie (int i.tpoint c) { return Area2(a.k1. Por tanto.b. int j. La función DiagonalfiIE se encargará de realizar este chequeo. Veamos el código: Es/*ta function verifica la possible diagonal entre dos vertices.int n.j.n. El caso cóncavo aparece a la derecha.j. int n.P) && Diagonaie(i.Bismarck Salvador Traña López__________________________________________ UNI bool LeftOn (tpointi a.c)fi0. una diagonal es aquel segmento interior que está dentro del polígono.

break. Veremos que el siguiente método puede ser perfectamente válido para lograr la triangulación de cualquier polígono P de tamaño n. p[j].P. if(n>3) for(i=0. ClipEar1(i1. k<n-1 .i2. i2=(i+2)%n. labels[k] = labels [k+1]. int labels [ ]) { Int k. } } /*Esta funccion obtiene los vértices de la possible diagonal */ void TriRecurse(int n. int n. en un conjunto de triángulos fáciles de procesar.i1. i<n.3.Bismarck Salvador Traña López__________________________________________ UNI if ( Intersect (p[i]. tpoligoni p. } /*Cierre del if*/ } /*Cierre del for*/ } /**Cierre de la funcion/ 1.n. Permite. if (Diagonal(i. y a pesar Juan Carlos Gutiérrez Barquero____________________________________________ 145 .p. Un ejemplo completo: triangulación de un polígono La triangulación de polígonos es un cálculo muy importante en muchas aplicaciones de Geometr ía Computacional. p[k]. p[k1])) return FALSE. } } return TRUE.i2. k++) { point assign (p[k+1]). para lo cual reasigna las etiquetas del polígono.labels). Sin embargo. TriRecurse(n-1.labels[i2]).labels). dividir un polígono con posible cierta complejidad. for(k=I.p)) { printf("%d %d lºn". aparte de otras muchas aplicaciones.6.i++) { i1=(i+1)%n. int labels []) { int i.*/ void ClipEar1 (int i. tpoligoni P.n. /*Esta function remueve el triangulo formado por la diagonal y la arista asociada ala diagonal.

El algoritmo trabaja en O(n3) porque realiza un total n–3 llamadas recursivas y cada una de ellas. void Trinagulate1 (int n. Esta función triangula el poligono P de n vertices.\n"). así como la ejecución completa del bucle). al igual que los desarrollados para otras disciplinas.Bismarck Salvador Traña López__________________________________________ UNI de su simpleza. en el peor de los casos. puesto que el vértice i1 queda aislado al encontrarse la diagonal ii2.*/ void PointAssign(tpoint a. necesita – un tiempo cuadrático (la función diagonal es lineal.pt. este algoritmo resulta Evidentemente lento.i<DIM. su utilización no es aconsejable y por ello no se ha implementado en un leguaje de programación. La llamada recursiva se realiza cuando se localiza una diagonal. y como en ese momento el número de vértices a procesar es uno menos. for(i=0. dejando cada vez que se llama un polígono más pequeño.i++) a[i]=b[i].i<n. clrscr(). Como veremos a lo largo de este curso. cualquier polígono puede ser triangulado en tiempo O(nlog n). Vemos que es un método recursivo porque se llama a sí mismo. } /*Esta función asigna al punto "a" el valor del punto "b". for(i=0. tpoligoni) { tpoligoni. Como veremos en sucesivos capítulos. TriRecurse(n. deberán combinar adecuadamente junto con su conjunto de Juan Carlos Gutiérrez Barquero____________________________________________ 146 .i++) { PointAssign(pt[i]<P[i]).Labels). son estudiados. Los algoritmos geométricos. y en Geometría Computacional todos los problemas cuyas soluciones inmediatas sean susceptibles de mejora. } printf("Diagonales de la triangulacion. tpoint b) { int i. int labels[PMax]. La función EliminaVertice se encargaría de este operación.pt. } La razón por la que este algoritmo no es desde luego nada interesente es por su tiempo de ejecución. labels[i]. para valores de n elevados.

realizando el acceso a la información indicando la posición donde se localiza el dato. actualizar uno ya existente o eliminar algún otro. por ejemplo. se ha ido convirtiendo en una nueva filosofía de programación con los nuevos lenguajes orientados a objetos. independientemente de su organización interna. también deber llevar asociado un conjunto de operadores. Las estructuras de datos pueden considerarse como implementaciones concretas de tipos de datos abstractos. Existen multitudes de estructuras de datos ampliamente documentadas en la bibliografía. El acceso y manejo de los datos en un contenedor se realiza a través de un localizador. un índice de un array o un puntero. En cualquier caso. Las características de una estructura de datos va en relación al orden de ejecución de sus operaciones y a los requerimientos de espacio. como insertar un nuevo dato.1. Dependiendo de la estructura del contenedor.Bismarck Salvador Traña López__________________________________________ UNI sentencias.4. Los programas trabajan con información que permanece en memoria principal o en algún dispositivo de memoria secundaria. Contenedores secuenciales Juan Carlos Gutiérrez Barquero____________________________________________ 147 . Los TDAs (notación anglosajona) han evolucionado hasta convertirse en clases de objetos. Un tipo de dato es una colección de objetos a la que se le da una representación matemática. más un conjunto de operaciones que lo manejan. Una secuencia es un contenedor que almacena los elementos con un orden lineal determinado. Un tipo de dato abstracto o TDA es un tipo de dato. Una estructura de datos además de proporcionar un modo de acceso. La mayoría de las estructuras de datos pueden verse como contenedores que mantienen información de un determinado tipo con un cierto orden. la estructura de datos más idónea dependerá siempre del problema que se pretenda resolver. obtener programas eficientes. La organización que se le da a dichos datos es lo que denominamos estructuras de datos. Lo que inicialmente se concibió como un concepto matemático que se adaptó a la sintaxis de los lenguajes de programación tradicionales. el localizador proporcionará un modo de acceso a los datos. los contenedores secuenciales o secuencias y los asociativos. permite el acceso por clave. Introducción a las estructuras de datos El estudio de las estructuras de datos y los métodos para la organización de dichos datos es uno de los aspectos clásicos más importantes para construir algoritmos eficientes. a las estructuras de datos correctas para conseguir el objetivo final. 1. existen dos tipos fundamentales de contenedores. En este apartado repasaremos algunas de las estructuras de datos usadas en el curso. Por el contrario un contenedor asociativo. Dependiendo de la organización interna y del modo de acceso a los datos.

Cualquiera de ellas implementada sobre una lista puede considerarse como una estructura de datos dinámica. La organización interna de los datos depende del tipo de contenedor asocitivo. actualización. todo nodo padre es mayor que su hijo izquierdo pero menor o igual que su hijo derecho. las estructuras de datos se eligen según la asociación de objetos geométricos que representen. La Geometría Computacional. acceso a los datos o actualización eficiente de éstos. por árbol o por tabla hash. la operación de inserción de un elemento en posiciones intermedias es de orden lineal. 1. Estas estructuras de datos garantizan búsquedas en O(logn). Las primeras forman una sucesión de nodos o elementos informativos unidos unos a otros mediante punteros. Los arrays son contenedores implícitos con acceso directo. Sobre cualquiera de los contenedores secuenciales anteriormente citados puede construirse estructuras de datos muy conocidas y empleadas. aunque normalmente el acceso a los puntos extremos es constante. siempre que todas las ramas del árbol permanezcan a la misma altura. enfatiza los aspectos computacionales de Juan Carlos Gutiérrez Barquero____________________________________________ 148 . en contraste con la disciplina clásica basada en proporcionar teoremas matemáticos. La elección de un tipo de estructura de datos o de otro va a depender del tipo de objetivo que se persiga: captura de información estructural. Normalmente. Por ejemplo. pero existen otros aspectos como son la naturaleza espacial de los objetos geométricos o sus propiedades estructurales que requieren del manejo de estructuras de datos más específicas para construir algoritmos eficientes. Algunos métodos de programación utilizados en C. La diferencia fundamental es que el acceso a la información se realiza siempre utilizando una clave y no una posición. El tiempo de acceso en este tipo de estructuras permite eliminar en cada consulta la mitad del grueso de la información. Las estructuras de datos consideradas de carácter general son ampliamente utilizadas en Geometría Computacional. El tiempo de acceso es lineal. Esta consideración también puede realizarse sobre arrays dinámicos. Los primeros mantienen un árbol binario de búsqueda o Inorden. optimización del espacio requerido o del número de operaciones de E/S. que puede identificar o no de forma unívoca al dato. Las operaciones fundamentales son de inserción. Contenedores asociativos Los contenedores asociativos poseen una filosofía de manejo y una estructura interna totalmente diferente a las secuencias. las pilas (LIFO) o las colas (fiFO).4. manteniendo una relación de orden entre nodos padre e hijos. Esta ventaja de acceso en tiempo constante se ve mermada por poseer menor fiexibilidad. En otras ocasiones. borrado y búsqueda por dicha clave.Bismarck Salvador Traña López__________________________________________ UNI Las secuencias más usuales son las listas enlazadas y los arrays.

En muchas ocasiones S deberá estar ordenada bajo algún criterio con coste O(nlogn). Pero si añadir un nuevo elemento a la solución parcial del problema tiene coste constante o logarítmico.n–1g tal y como indica el Algoritmo 1. sk–1g. 1. El algoritmo trabaja siempre de forma similar.1. en otras ocasiones los métodos de resolución están íntimamente relacionados con las capacidades de la propia Geometría. Existen una serie de técnicas y paradigmas de programación que vienen siendo muy habituales no sólo en el campo de la Geometría Computacional. el algoritmo final se procesará en O(nlogn). Supongamos que se pretende procesar una nube de n puntos en el plano S.5. entonces devolver RC 3. obtiendo finalmente Prob(S). A continuación daremos un repaso a los paradigmas de programación más empleados dentro de la Geometría Computacional.p) 5. el problema se resuelve convenientemente. – Posteriormente y uno a uno. Algunos de estos métodos como el divide y vencerás ya habían proporcionado la solución óptima a problemas como la ordenación.Bismarck Salvador Traña López__________________________________________ UNI los problemas y atiende a las propiedades geométricas para encontrar algoritmos eficientes. (Pt1. Si p está dentro de RC 2. Que un problema geométrico tenga solución dentro de la Geometría Computacional no basta en muchas ocasiones. i = fk. La idea sobre la que trabaja este método consiste en construir la solución de modo iterativo. se desea además que la solución se encuentre en un tiempo óptimo. para resolver cualquier problema Prob(S) bajo esta técnica. Método incremental Éste puede ser considerado como uno de los métodos más simples e intuitivos.Pt2) := puntosTangentes(RC. :::. considerando que la entrada se produce de modo incremental. – Si en un problema de tamaño n. s1. se resolverá Prob(Si) para el resto de si 2 S. Para cada una de las nuevas entradas.p) 1. :::. sino 4. los primeros k puntos de S. entonces el tiempo global del algoritmo será de O(n2). también conocido como el método iterativo. la misma cota impuesta por el algoritmo de ordenación. Conectar Pt1 con p y p con Pt2 Juan Carlos Gutiérrez Barquero____________________________________________ 149 . Eliminar aristas en RC de Pt1 a Pt2 6. Incremental(RC. Inicialmente Prob se resuelve de forma trivial para fs0. el coste de insertar un nuevo dato es O(n). Algoritmo 1 Incremental-generalizado.

pueden trabarse con tiempos del orden de O(nlog n).Bismarck Salvador Traña López__________________________________________ UNI Ahora veremos los puntos tangentes: 1. Por ejemplo en el problema de intersección de segmentos. considerándose válida para problemas en dos dimensiones cuando el conjunto de entrada se produce en un cierto orden.1. cuando la línea encuentra un nuevo segmento. Si el procesamiento de dichos objetos geométricos es constante. Juan Carlos Gutiérrez Barquero____________________________________________ 150 . una línea. Normalmente se escogen estructuras de datos con tiempos de actualización y de acceso logarítmico.5.1. etc) lo procesa modificando el conjunto de estructuras que datos que participen en la construcción de dicho algoritmo. El método supone que una línea horizontal (o vertical) recorre el plano de arriba hacia abajo (o en sentido contrario). de hecho. la implementación de este paradigma sigue las mismas premisas que las dadas para el método incremental citado anteriormente. Cada vez que dicha línea encuentra un ítem (un punto. se realizará una inserción en alguna estructura de datos capaz de mantenerlos ordenados de izquierda a derecha (en el caso de que la línea de barrido sea horizontal). Línea de barrido Esta estrategia es una particularización del método incremental. La solución de la mayoría de estos problemas puede ser incremental. La validez de esta técnica está basada en la observación de que la parte que queda por encima o por debajo de la línea de barrido se ha construido correctamente. como es el caso de la intersección de dos segmentos.

Ordenar todos los vértices de W en sentido horario según la semi-línea P..Si w es visible desde p. ordenar según distancia al punto p. y sea T un árbol de búsqueda equilibrado. la técnica de localización de los puntos más lejanos.Insertar en el árbol los obstáculos que incidan en w y que estén en el lado horario de P.Bismarck Salvador Traña López__________________________________________ UNI Esta técnica es empleada para diferentes problemas como la intersección de segmentos.. 7.. en caso de empate. E). 6. partición de polígonos en subdivisiones monótonas. sea E el conjunto de aristas. Sea W la unión de los vértices de S y los puntos de Q. 1. 1. intersección de semiplanos. los métodos de Jarvis y Graham para el cálculo de la envolvente convexa. 3. y otros más. entonces añadir la arista e=(p. y.5. 4. w) al grafo G.Ordenar las aristas que intersectan con P e insertarlas en el árbol equilibrado T. Existen técnicas análogas para dimensiones mayores. Algoritmo 1 El algoritmo de la línea de barrido rotatoria (Rotational Sweep Line): Entrada: Un conjunto de obstáculos poligonales S y un conjunto de puntos Q. el diagrama de Voronoi y triangulación de Delaunay.Eliminar del árbol los obstáculos que incidan en w y que estén en el lado antihorario de P. Salida: Un grafo de visibilidad G = (V..2. Divide y Vencerás Juan Carlos Gutiérrez Barquero____________________________________________ 151 .Para cada vértice w de V: 2.Para cada vértice w de la lista ordenada W: 5.

Normalmente se basa en la sucesiva división en partes iguales del problema original. Para que el algoritmo se considere eficiente se espera que el Paso 3. hasta conseguir que éste posea un tamaño lo suficientemente pequeño como para poder resolverse fácilmente. los problemas se van resolviendo recursivamente y combinando sus soluciones para obtener la solución final. El segundo ejemplo de ecuación de recurrencia de la Sección 1. étricos.Bismarck Salvador Traña López__________________________________________ UNI Esta técnica clásica de programación es válida para resolver de forma eficiente problemas Geom. El Algoritmo 2 resume los pasos empleados para resolver el problema Prob(S) partiendo del conjunto de datos S y realizando sucesivas divisiones por dos.2 corresponde al método Divide y Vencerás. El método más eficiente de ordenación.a) que divide el problema en subproblemas y el Paso 3. Algoritmo 2 Paradigma de divide y vencerás Juan Carlos Gutiérrez Barquero____________________________________________ 152 . el quicksort.c) que combina las soluciones parciales. está basado en este paradigma. Llegado a un punto en que la división deja de tener sentido. se realice en tiempo lineal.

Bismarck Salvador Traña López__________________________________________ UNI Juan Carlos Gutiérrez Barquero____________________________________________ 153 .

Bismarck Salvador Traña López__________________________________________ UNI Es un ejemplote Voronoi. Esta técnica es ampliamente utilizada y sirve de base para construir Juan Carlos Gutiérrez Barquero____________________________________________ 154 .

Bismarck Salvador Traña López__________________________________________ UNI algoritmos aleatorios. los campos en los que ha resultado un cálculo útil sorprenden por lo aparentemente poco relacionados con las matemáticas en general y la geometría en particular. El estudio de la envolvente convexa en dos dimensiones ha sido objeto de especial interés. 2 La envolvente convexa y triangulación de polígonos 2. Además. el diagrama de Voronoi. etc.1.1. De nuevo esta idea es extensible intuitivamente a otras dimensiones. Puede emplearse para construir la envolvente convexa. Pero exiten otras definiciones válidas: la envolvente convexa de un conjunto de puntos en el plano es la unión de todos los triángulos determinados por dicho conjunto de puntos. considerando a ésta como el menor conjunto convexo que contiene a dicho conjunto. y puede servir de partida para construir algoritmos simples para el cálculo de la envolvente convexa. como la forma que adquiriría una goma elástica envolviendo a todos los puntos del conjunto que están fijos sobre el plano. Introducción El cálculo de la envolvente convexa de un conjunto de puntos en espacios euclídeos ha sido sin duda uno de los problemas a la vez más básicos y más ampliamente estudiados a lo largo de la historia de la Geometría Computacional. Un conjunto convexo del plano se define como el conjunto que verifica que el segmento que une a dos cualesquiera de sus puntos está totalmente contenido en él.1. Evidentemente. La idea de conjunto convexo nos lleva inmediatamente a la de envolvente convexa. esta definición puede ser aplicada en cualquier espacio euclídeo n-dimensional. Existen una serie de características asociadas a los puntos que Juan Carlos Gutiérrez Barquero____________________________________________ 155 . Este concepto es fácil de entender en cierto modo si consideramos a la envolvente convexa de un conjunto de puntos en el plano. La envolvente convexa 2.

2. es decir. Tal es el caso del reconocimiento de patrones. al que habría que añadir otras técnicas posteriores. etc. no se puede encontrar una algoritmo que trabaje en menor tiempo para todos los casos. Todos estos trabajos constituyen el conjunto clásico de algoritmos para la resolución de la envolvente convexa. si es posible trazar una recta pasando por dicho punto de forma que todo el conjunto S0. procesamiento de imágenes. Sin duda es uno de los planteamientos de la Geometría Computacional que más soluciones ha conseguido. Pero la envolvente convexa posee aplicaciones fuera del ámbito de la Geometría. Como se ha indicado con anterioridad.1. Todos estos algoritmos construyen la envolvente convexa en tiempo  (nlog n). lo que nos proporciona un método en triempo O(n4). puede definirse como punto extremo a cualquier punto de la envolvente convexa. El método propuesto por Preparata y Shamos en 1985 fue denominado Quickhull por su similitud con el método de ordenación Quicksort. necesitaríamos procesar O(n3) triángulos para cada uno de los n puntos. Un ejemplo de resolución El problema de encontrar la envolvente convexa de un conjunto de puntos puede ser interesante porque es equivalente a encontrar todo el conjunto de puntos extremos de dicha nube. Este método. Por tanto. y todo punto extremo tiene la propiedad de que es posible trazar una línea recta a través de él de modo que el resto de puntos queden a un lado. que estudiaremos en este curso. Supongamos que una explotación petrolífera extrae diferentes tipos Juan Carlos Gutiérrez Barquero____________________________________________ 156 . el cálculo de la envolvente convexa ha sido aplicado ampliamente a disciplinas en ocasiones ajenas a la Geometría Computacional y en espacios distintos de dos dimensiones. Pero bajo esta definición. Los algoritmos propuestos para este problema son realmente numerosos. 2. Otra propuesta diferente se dió a conocer en 1973 como . Desde incluso antes del nacimiento oficial de esta disciplina se conoce el trabajo de Graham en el año 1972. posee un tiempo de ejecución cuadrático. Un punto q 2 S pertenece a la envolvente convexa de S. sin embargo supone un interesante ejemplo basado en manejo de ángulos del cual partiremos para el tratamiento del diagrama polar. La envolvente convexa posee una cota de  (nlog n). S0 = S–fqg quede a un lado de dicha recta. lo cual no es eficiente teniendo en cuenta que se trata de un problema (nlog n).. q 2CH(S). También podemos decir que un punto es extremo si y sólo si está dentro de algún posible triángulo cuyos vértices son cualesquiera de los puntos de la nube original.La marcha de Jarvis. Se han propuesto estrategias siguiendo los paradigmas más empleados como el método incremental y el divide y vencerás.Bismarck Salvador Traña López__________________________________________ UNI forman parte de la envolvente convexa en el plano y que han servido igualmente para definirla y construirla.

2. Para cada i hacer 2.1. cayera fuera de dicha envolvente.3 Algoritmo trivial 1. Ph está a la izqda de (Pk. la solución sería la contrucción de la envolvente convexa tridimensional. Para cada k ≠ i ≠ j hacer Juan Carlos Gutiérrez Barquero____________________________________________ 157 . Para cada k ≠ i ≠ j hacer 4.1.Pj) y 6. Si Ph está a la izqda de (Pi. obteniendo el siguiente esquema: Todo punto que caiga dentro de la envolvente convexa de todas las muestras representadas por puntos en el plano. indica que puede ser producida. Este problema sería un problema 3D si cada mezcla tuviera tres componentes. la combinación final no podría producirse.Pi) 8. Para cada i hacer 2. Para saber si es posible obtener este producto final e f basta con considerar las anteriores mezclas como puntos del plano. Para cada h ≠ i ≠ k ≠ j hacer 5.   Determinación de aristas extremas 1. e2 = A16%B20% y e3 = A7%B15% y queremos obtener e f = A13%B22%. Si el objetivo es conseguir los componentes A y B pero en una nueva proporción.4 Algoritmo trivial 2. Ph está a la izqda de (Pj. Para cada j ≠ i hacer 3.Bismarck Salvador Traña López__________________________________________ UNI de componentes mezclados en distinta propoción. entonces Ph no es extremo  Complejidad: O(n4 ) 2. Supongamos que partimos de las mezclas: e1 = A10%B35%. podemos hacer uso de la envolvente convexa del modo siguiente. Si por contra. Para cada j ≠ i hacer 3.Pk) y 7.  Determinación de puntos extremos 1.

Pj) no es extremo  Complejidad: O(n3 ) 2.c. b := punto más a la izquierda de S Juan Carlos Gutiérrez Barquero____________________________________________ 158 . Encontrar punto p más pequeño en coord. i := i[0] 3.A).6 Quick Hull QuickHull(a. Calcular el ángulo en sentido antihorario entre Pj y la arista anterior de la EC 6. Si S={a. Sea k el índice del punto con ángulo menor 7.b.1.c) 5.QuickHull(c.b} entonces devolver (a.b) 6.B) ConvexHull(S) 1. 2. 5.1. Marcar (Pi. devolver concatenar(QuickHull(a. y. Hasta que i = i0 2.b. c := índice del punto con máxima distancia a (a.S) 1. Para cada j ≠ i hacer 5. i := k 9.b) 4. a := punto más a la derecha de S.Pj) entonces (Pi. Repetir 4.Pk) como una arista de la EC 8. sino 3. Si Pk no está a la izqda de (Pi.5 Gift Wrapping 1. B := puntos a la izquierda de (c. A := puntos a la izquierda de (a. sea i[0] su índice 2.Bismarck Salvador Traña López__________________________________________ UNI 4.b) 2.

QuickHull(b.izquierda(b.S))) La idea básica del quickhull (envolvente rápida) es que para la mayoría de las configuraciones de puntos se puede en cada paso descartar muchos puntos a la hora de construir la envolvente convexa. En cada una de ellas encontramos el punto más alejado a la recta que define dicha región obteniendo así cuatro nuevos puntos y un polígono de a lo más ocho lados que divididirá a los puntos que no hemos eliminado en ocho regiones que tratamos individualmente siguiendo la misma regla anterior.a. ahora todos los puntos en el interior de dicho cuadrilátero no son extremos.b. El primer paso del quickhull es encontrar los cuatro puntos extremos en las direcciones norte. sur.Bismarck Salvador Traña López__________________________________________ UNI 3. trataremos cada una de estas regiones independientemente. Juan Carlos Gutiérrez Barquero____________________________________________ 159 . este y oeste y formar el cuadrilátero que ellos definen (este cuadrilátero puede ser degenerado).b. Así nos quedan puntos repartidos en cuatro regiones no conectadas entre si.izquierda(a.a. devolver concatenar(QuickHull(a. con lo cual pueden ser descartados.S)).

Por lo tanto. Ejemplo: Juan Carlos Gutiérrez Barquero____________________________________________ 160 . un análisis del algoritmo nos lleva a que su complejidad en tiempo es cuadrática. Sin embargo. El QuickHull suele calcular la envolvente convexa en un tiempo mucho más corto que si lo hacemos a través del diagrma de Voronoi. centrémosno ahora en encontrar un algoritmo óptimo.Bismarck Salvador Traña López__________________________________________ UNI En nuestro ejemplo en el paso siguiente se obtine ya la envolvente convexa.

Bismarck Salvador Traña López__________________________________________ UNI
2.1.4. Graham's scan Este es sin duda uno de los algoritmos más importantes para el cálculo de la envolvente convexa, no únicamente por su simpleza sino también por su rapidez. El proceso realiza primero una ordenación angular de los puntos. El punto tomado de referencia para tal fin debe ser un punto de la envolvente convexa, por ejemplo el de menor ordenada y al que llamaremos p0. El resto de puntos quedan ordenados de izquierda a derecha obteniendo la secuencia p1, p2,…, pn–1. El proceso seguido por Graham toma sucesivamente triángulos elegidos según el orden conseguido tras la ordenación. Siempre que el triángulo formado abc, posea una superficie positiva, el vértice central, es decir, el vértice b será tenido en cuenta como probable punto de la envolvente. Pero cuando dicho área es negativa, b es descartado definitivamente. Para comprender dicho algoritmo, será necesario repasar el concepto de pila. Una pila es un tipo de dato abstacto (tipo de dato más operaciones para su manejo) muy restrictivo a la hora de manejar los datos que almacena. Se construye utilizando una estructura de datos lineal, array o lista enlazada, sobre la que sólo se pueden introducir (push) o sacar elementos (pop) por uno de sus extremos, lo que se denomina cima o tope de la pila. Algoritmo Scan de Graham 1. Encontrar el punto inferior más a la derecha (P0) 2. Ordenar todos los puntos angularmente alrededor de P0; aquellos puntos que estén en el mismo ángulo colocar primero el más cercano a P0: etiquetarlos P1,...,Pn-1 3. Pila S := (Pn-1,P0) 4. t := tope de S (P0) 5. i := 1 6. Mientras que i<n hacer 7. Si Pi está estrictamente a la izqda de (Pt-1,Pt) 8. entonces Push(S,i); i := i+1 9. sino Pop(S) Ejemplo: El orden de ejecución de este algoritmo viene dado por la necesidad de ordenar los puntos angularmente. Cualquier ordenación necesita al menos un tiemo O(nlogn). A este tiempo se le debe añadir el del proceso ideado por Graham. Para averiguar este tiempo basta con percatarse que en cada paso un punto es tenido en cuenta o es descartado. En el peor de los casos, cuando la envolvente convexa es un triángulo, necesitamos del orden de 2n–3 operaciones.

Juan Carlos Gutiérrez Barquero____________________________________________

161

Bismarck Salvador Traña López__________________________________________ UNI

El Scan de Graham construye una lista que al final será la de los puntos extremos ordenados. Supondremos que no existen tres puntos alineados (aunque esta condición puede ser eliminada). Comenzamos encontrando el primer punto con el orden lexicográfico, llamemosle p0. A continuación ordenamos los puntos por el ángulo que forman con p0.

Suponemos que partimos de la lista ordenada así obtenida. En cada momento, tendremos tres puntos, llamémosles Inicial, Medio y Final. Nos preguntamos si el ángulo IMF es positivo (en el sentido contraro de las agujas del reloj o negativo. Si es positivo, la lista la dejamos como estaba y el anterior Medio pas a ser Inicial y el final pas a ser Medio y escogemos el siguiente en la lista para ser el nuevo Final. Si es negativo, eliminamos Medio de la lista, el anterior Inicial pasa a ser Medio, el Final sigue como Final y escogemos el anterior de la lista para ser el nuevo Incial. La lista resultante después de recorrer todos los puntos será la de los extremos de la envolvente convexa. Teorema 5.1: El Scan de Graham calcula la envolvente convexa de n puntos en el plano en tiempo óptimo O(n log n).

Juan Carlos Gutiérrez Barquero____________________________________________

162

Bismarck Salvador Traña López__________________________________________ UNI

2.1.4. La marcha de Jarvis La marcha de Jarvis está basada en el siguiente resultado, que sirve de definición para la envolvente convexa: El segmento l, definido por dos puntos de la nube de puntos, es un eje de la envolvente convexa si todos los puntos de la envolvente convexa están a un lado de ésta. Siguiendo este criterio podríamos descubrir para cada punto los n2 combinaciones posibles, lo que nos da un fácil pero costoso O(n3) algoritmo. Sin embargo, Jarvis pudo bajar la cota al comprobar que si pi pj es una arista perteneciente a la envolvente convexa, la siguiente arista la encontramos partiendo de p j en tiempo lineal. Veamos el siguiente ejemplo: Partiendo de s6, el punto de menor ordenada, alcanzamos a s5 tras realizar un barrido angular en sentido antihorario desde la horizontal. El siguiente punto de la envolvente se puede localizar partiendo de s5 y haciendo un nuevo barrido angular, localizando así a s1. Es fácil de intuir que este proceso tardará en ejecutarse un tiempo proporcional al número de puntos en la envolvente y al tamaño de la nube. Cada barrido angular necesita un tiempo de proceso del orden de O(n) pasos. Si la envolvente final posee k puntos, el tiempo final de ejecución es del orden de O(nk). En el mejor de los casos el comportamiento puede ser lineal, por ejemplo si la envolvente es un triángulo. El peor de los casos, sin embargo, se da cuando todos los puntos están en la envolvente convexa, convirtiéndose en un método cuadrático.

Juan Carlos Gutiérrez Barquero____________________________________________

163

Bismarck Salvador Traña López__________________________________________ UNI

2.1.5. Algoritmo Incremental La ventaja de unos métodos con respecto a otros a veces viene dada por su velocidad computacional y otras veces por su fácil extensión a tres dimensiones, lo que habitualmente llamamos problemas 3D. El método incremental para el cálculo de la envolvente convexa es uno de estos casos. En todo método incremental se supone que se ha resuelto el problema para un tamaño n y que en cada paso se añade un nuevo punto dando solución a un problema de tamaño n+1. Para el cálculo de la envolvente convexa ordenamos inicialmente los puntos del conjunto P de izquierda a derecha, por ejemplo, obteniendo el conjunto p0; p1; :::; pn–1. Tomamos los tres primeros puntos tras esta ordenación sabiendo que el polígono que forman p0; p1; p2, un triángulo, es convexo. El siguiente paso intenta añadir el siguiente punto, p3, de modo que se tras finalizar este paso tengamos la envolvente convexa de los primerso cuatro puntos p0; p1; p2; p3. Para añadir cada nuevo punto pi+1 basta con lanzar tangentes desde este punto hasta el polígono convexo obtenido en el paso anterior. Localizaremos dos tangentes, una superior y otra inferior, como vemos en la siguiente figura:

 Siempre ocurre que el punto más bajo de tangencia es tal que pi, es tal
que q está a laizquierda de pi–1 pi pero a la derecha de pi pi+1.

 El punto pj será el punto de mayor tangencia si q está a la derecha de p
j–1 pj pero a laizquierda de pj pj+1. – El procedimiento PuntosTangentes calcula los puntos resultantes de lanzar tangentes desde el punto q al polígono P de tamaño n obteniendo como

Juan Carlos Gutiérrez Barquero____________________________________________

164

El mecanismo para conseguir. 2. pn_1. Juan Carlos Gutiérrez Barquero____________________________________________ 165 . en un nuevo polígono convexo. En este caso.1. así como lo serán los puntos pt1 y pt2. sin embargo no lo es para B. El orden de ejecución del algoritmo es la suma de los siguientes términos: 1. es posible que algunos otros vértices del polígono convexo desaparezcan. necesita en el peor de los casos un tiempo O(n2). :::. Este caso concreto es cuando tenemos tres puntos. En el ejemplo de la figura.Bismarck Salvador Traña López__________________________________________ UNI resultado los vértices pt1 y pt2. la operación de ordenación con coste O(nlogn) 2. por ejemplo. El algoritmo determina que el vértice p[i] es un punto tangente si recorriendo cada arista del polígono P dicho vértice implica un cambio de resultado tras ejecutar la función IzquierdaOSobre. El proceso termina cuando para los dos polígonos se encuentra una tangente. pj+1. la secuencia de vértices i+1. Necesitamos calcular dos tangentes que unan dichas envolventes. pi. el siguiente paso es unir dos a dos los polígonos convexos resultantes de la etapa anterior. El resultado final sería el polígono P = p0. Operación que en el peor de los casos es lineal. Sin embargo.6. Por tanto. Se comenzaría suponiendo que el segmento que une el punto más a la derecha de A y el punto más a la izquierda de B es una tangente válida.q. :::.Método Divide y Vencerás Los métodos divide y vencerás siempre trabajan de modo similar. y aunque el algoritmo es susceptible de añadir mejoras. En el ejemplo. la etapa de unión de dos polígonos convexos en un único polígono convexo no es inmediata. pi_1. Pero obtener los dos puntos tangentes no implica de ningún modo que el proceso ha finalizado. El siguiente paso es hacer exactamente lo mismo pero bajando sucesivos vértices de B. la tangente inferior. A2-B5 ya es una tangente para A. p1. partimos de una nube de puntos ordenada de izquierda a derecha que se divide en dos mitades A y B de aproximadamente el mismo tamaño. una tangente superior y otra inferior. :::. Para cada una de estas mitades. Como esta suposición es falsa para este ejemplo. pj . continuamos el proceso de división hasta que finalmente el tamaño de la nube de puntos es tan pequeño que puede resolverse el problema fácilmente. Sin embargo. El proceso finaliza obteniendo la envolvente convexa de todos los puntos. decidimos bajar vértices sucesivamente hasta que por fin para el polígono A se localiza una envolvente. El punto q será parte ahora del nuevo polígono convexo. j–1 claramente desaparece al añadir el nuevo – punto. Cuando el problema no pueda dividirse más. podemos observarlo en la siguiente figura.

puesto que el dado en dicho tema posee un tiempo de ejecución poco eficiente. El tiempo de ejecución de un algoritmo divide y vencerás depende en gran medida del comportamiento de la función de mezcla de cada pareja de diagramas polares. sabemos que contamos con un algoritmo en tiempo O(nlog n).1.Bismarck Salvador Traña López__________________________________________ UNI Para saber si ab es tangente a un polígono observemos los siguientes gráficos: queda como ejercicio la implementación de las funciones TangenteMenor y TangenteMayor. En esa ocasión se hizo incapié de la necesidad de encontrar un algoritmo eficiente para realizar este cálculo. 2. para ello serán necesarios dos pasos diferentes: la partición de cualquier polígono en particiones monótonas y la triangulación de cada una de estas porciones. Triangulación de polígonos En el Tema 1 hicimos referencia por primera vez a la triangulación de polígonos. Si Juan Carlos Gutiérrez Barquero____________________________________________ 166 . Cuando ésto se realiza en tiempo lineal. En esta sección conseguiremos triangular cualquier tipo de polígono en tiempo óptimo O(nlogn).2. ocurre que sólo encontramos como máximo dos intersecciones del polígono con dicha recta. como es este caso. 2. Polígonos monótonos Un polígono monótono con respecto a la vertical es aquel que si se recorre con una línea horizontal bajando a lo largo del total del polígono.2.

p [ j ] ) AND NOT Adyacente ( L i s t a I n icio(l). p [ j ] ) SINO SI Adyacente ( L i s t a F i n a l ( l ) . v . p [ j ] ) AND NOT Adyacente ( L i s t a F i nal(l). considerándo al vértice vi como cúspide si vi–1 y vi+1 están ambos arriba o abajo. La ventaja de triangular un polígono monótono es más o menos intuitiva: al bajar una línea horizontal imaginaria a lo largo de todo el triángulo y encontrarse con el vértice vi.p[j]) ENTONCES v<_ L i s t aSa c a I ni c io ( l ) MIENTRAS (NOT ListaVacia ( l ) ) REPETIR v <_ L i s t aSa c a I ni c i o ( l ) ListaMeteFinal ( Diagonales . x . p ) ListaCrea ( l ) l i s t aCr e a ( Diagonales ) ListaMeteFinal ( l . Intuitivamente hablando. dibujando diagonales según el siguiente algoritmo. p [ 1 ] ) PARA j <_ 2 HASTA n_1 REPETIR SI Adyacente ( L i s t a I n i c i o ( l . entonces hablamos de polígono extrictamente monótono. bien por la derecha. v ) ListaMeteFinal ( l . p [ 0 ] ) ListaMeteFinal ( l . n . un polígono monótono será aquel que no posee cúspides interiores. bien por la izquierda.Bismarck Salvador Traña López__________________________________________ UNI además no consideramos la existencia de aristas horizontales. v . p [ j ] ) v <_ ListaFinalSaca ( l ) SI NOT ListaVacia ( l ) ENTONCES x<_L i s t a F i n a l ( l ) FIN_MIENTRAS ListaMeteFinal ( l .p[j]) ENTONCES v<_ListaSacaFinal ( l ) x<_F i n a l L i s t a ( l ) MIENTRAS ( Angulo ( p [ j ] . x ) < Pi ) REPETIR ListaMeteFinal ( Diagonales . v ) ListaMeteFinal ( l . ALGORITMO TriangulacionMonotona ENTRADA: El Ìpolgono S de Òtamao n SALIDA : El conjunto de Diagonales que t r i a n g u l a n e l Ìpolgono INICIO Ordenar (S. p [ j ] ) FIN_MIENTRAS ListaMeteFinal ( l . se sabe que su diagonal irá a un punto visible desde dicho punto. p [ j ] ) Juan Carlos Gutiérrez Barquero____________________________________________ 167 . La idea es ir bajando paulatinamente vértice a vértice.

El tiempo de ejecución de este algoritmo es O(nlog n).1.3–4. v ) FIN_MIENTRAS FIN_SI FIN_SI FIN_PARA En la siguiente figura podemos observar el conjunto de diagonales obtenidas tras la ejecución de este algoritmo para el polígono monótono de ejemplo. s1. Veamos como funciona el algoritmo en sus primeros pasos para este ejemplo. teniendo en cuenta que sólo se unen puntos visibles entre sí (ángulo <) y que no son adyacentes. El proceso de ordenación de los vértices ya posee este orden de ejecución. Además habría que añadir un Juan Carlos Gutiérrez Barquero____________________________________________ 168 . observamos que s2 es adyacente al final de la lista l (2a sentencia condicional) pero el algoritmo no construye aún diagonales porque el Angulo(s[2]. por lo que dicho algoritmo no podría ejecutarse en menor tiempo. Al ordenar los puntos de mayor a menor obtenemos la numeración que vemos en la figura. Las siguientes iteraciones son iguales. Al entrar por primera vez en el bucle con j = 2. hasta que para j = 4 se construyen las diagonales 1–4. s2.Bismarck Salvador Traña López__________________________________________ UNI SINO v<_L i s t aSa c a I n i c io ( l ) v<_L i s t aSa c a I n i c io ( l ) MIENTRAS NOT ( ListaVacia ( l ) ) v<_L i s t aSa c a I ni c i o ( l ) ListaMeteFinal ( Diagonales . la lista l = s0. p [ j ] . s1.2–4.0)>por lo que la lista acaba siendo l =s0. La idea básica del algortimo es – – – construir diagonales con el comienzo de la lista l o con el final de ésta . Antes de entrar en el bucle.

pero sin embargo aseguramos el tiempo lineal del proceso. es un punto o el vacío.2. la intersección del polígono con h es conexa. Vértice final: el vértice vi es de final si vi–1 y vi+1 poseen mayor ordenada y su ángulo interior es menor que π. puesto que todo vértice es procesado como mucho dos veces. En este apartado completamos el proceso de triangulación eficiente de polígonos dando un algoritmo capaz de encontrar diagonales tales que dividan dicho polígono en particiones monótonas. puesto que todas las operaciones del algoritmo. el cálculo del ángulo.. La definición para x-monótono es análoga. uno cuando entra en la lista y otra vez cuando sale de ésta. 2. Antes de ver el funcionamiento del polígono determinaremos los cinco tipos de vértices que podemos encontrar: Vértice comienzo: el vértice vi es de comienzo si vi–1 y vi+1 poseen menor ordenada y su ángulo interior es menor que π. Partición de un polígono en componentes monótonas La triangulación de polígonos monótonos desde luego deja de tener sentido si no es posible particionar cualquier tipo de polígono en particiones monótonas. operaciones con el final y principio de la lista. esto es. etc. Juan Carlos Gutiérrez Barquero____________________________________________ 169 . se ejecutan en tiempo constante.2.Bismarck Salvador Traña López__________________________________________ UNI tiempo lineal. Vértice Partición: el vértice vi es de partición si vi–1 y vi+1 poseen menor ordenada ysu ángulo interior es mayor que π. Tan sólo nos puede plantear un problema los bucles MIENTRAS. Consideramos a un polígono y-monótono si para cada horizontal h.

La idea será localizar los vértices que rompen la monotonía. Las estructuras de datos implicadas son las siguientes: P: será un array conteniendo los vértices del polígono.Bismarck Salvador Traña López__________________________________________ UNI Vértice Mezcla: el vértice vi es de mezcla si vi–1 y vi+1 poseen mayor ordenada y suángulo interior es mayor que π. Q: La línea imaginaria bajando por el plano se encontraría los puntos de P de Juan Carlos Gutiérrez Barquero____________________________________________ 170 .línea de barrido. Utilizaremos la técnica de . ordenados como es habitual en sentido antihorario. el destino de éstos será también un objetivo primordial del algoritmo. Vértice Regular: cualquier otro vértice no considerado anteriormente. para encontrar las distintas particiones monótonas. Desde ellos se lanzarán diagonales. los de partición y los de mezcla.

T: Se trata de alguna estructura de datos con tiempo de acceso logarítmico.Q) I n i c i l i z a r L i s t a ( T) I n i c i a l i z a r L i s t a (D) Para k<_ 0 hasta n_1 Repet i r i <_Q( k ) Juan Carlos Gutiérrez Barquero____________________________________________ 171 . tanto de izquierda a derecha. siendo ei = vi –vi+1. Puede ser un array o una lista. Los valores podrán ir cambiando hasta que se localice el valor correcto. VAR D: TipoLi s ta ) ENTRADA: El Ìpolgono P de Òtamao n SALIDA : El conjunto D de diagonales INICIO Ordenar_Y ( P. Almacenará los vértices ei. Q será un vector de tamaño n con los índices de P identificando los puntos ordenados de mayor a menor ordenada. y sobre todo por ventajas computacionales. Para no duplicar los puntos. el conjunto de diagonales conseguidas por el algoritmo. con excepción de en–1 = vn–1v0.Bismarck Salvador Traña López__________________________________________ UNI mayor a menor ordenada. es decir. D: Mantiene el resultado. El conjunto de ejes se almacenan por la coordenada x. n . Algoritmo de triangulación PROCEDIMIENTO HacerMonotono (VAR P : TipoPol igono . Ayu: Es un array que almacena en todo momento el vértice candidato para unir a los vértices de partición y mezcla.

i _1) 2 : ( _ Mezcla_) Si TipoVer t i ce ( P. Cada una de las n iteraciones de bucle se ejecuta en tiempo logarítmico.P) Ayu ( i )<_i 4 : ( _ Regular_) Si Inter iorDecha ( P. Ayu ( j ) )=2 Entonces L i s t a I n s e r t a r (D. { i_Ayu ( j ) } ) Ayu ( j )<_ i ListaInser tarOrdenado ( T . Ayu ( j ) ) = 2 Entonces L i s t a I n s e r t a r (D. i _1) ListaInser tarOrdenado (T. i _1) j <_ ListaBuscar Izdo ( T . i . { i_Ayu ( i _1)}) L i s t aEl imi n a r ( T . La ordenación de los vértices puede realizarse en tiempo O(nlog n).P) Ayu ( i ) <_ i 1 : ( _ Final _) Si TipoVer t i ce (P . { i_Ayu ( i _1)}) L i s t aBo r r a r (T. i ) Si TipoVer t i ce ( P. Ayu ( i _1))=2 Entonces L i s t a I n s e r t a r (D. Ayu ( i _1))=2 Entonces I n s e r t a r L i s t a (D. { i_Ayu ( i _1)}) L i s t aEl imi n a r ( T . Juan Carlos Gutiérrez Barquero____________________________________________ 172 . { i_Ayu ( j ) } ) Ayu ( j ) <_ i 3 : ( _ ÛPa r t i c i n ) j <_ ListaBuscar Izdo ( T . i . el correspondiente a las operaciones de manejo de la estructura de datos T. { i_Ayu ( j ) } Ayu ( j )<_ i FIN_SI FIN_SI FIN_CASE FIN El tiempo de ejecución del algoritmo es óptimo. i ) SEA 0 : ( _ Comienzo _) ListaInser tarOrdenado (T. i ) Entonces Si TipoVer t ice (P .Bismarck Salvador Traña López__________________________________________ UNI 34 2 La envolvente convexa y triangulaciÛn de polÌgonos EN CASO DE QUE TipoVer t i ce (P. i . Ayu ( i _1))=2 Entonces L i s t a I n s e r t a r (D. i ) Si TipoVer t ice (P. i ) L i s t a I n s e r t a r (D.P) Ayu ( i )<_i Sino j <_ListaBuscar Izdo (T.

puesto que la intersección de polígonos convexos cuenta con un orden de ejecución menor que si se trata de polígonos generales. únicamente conocer si existe dicha intersección. Los problemas que necesitan del procesamiento de intersecciones pueden ser de distinta índole. es necesario el manejo de intersecciones entre iguales o diversos objetos geométricos. Sin embargo. En muchas ocasiones para hacer los mapas más manejables y legibles. En realidad virtual o diseño de circuitos VLSI el manejo de intersecciones es fundamental. cuando dos de estos mapas necesitan ser manejados al mismo tiempo (por ejemplo para conocer las carreteras que llegan a una ciudad). densidad de población. la realidad a veces necesita simular la forma de cualquier línea mediante una polilínea o conjunto de segmentos unidos a modo de cadena. siendo n y m el número de ejes de los dos polígonos. ciudades. Intersección de polígonos convexos El tiempo de ejecución para conocer la intersección de dos polígonos cualesquiera es O(nm). De hecho. ríos y montañas. así una carretera puede ser representada mediante una polilínea y un núcleo urbano puede serlo mediante conjunto de polígonos. la información que contienen se divide en distintos tipos de mapas.1. Pero existen otras áreas de interés más próximas a la Topografía como son los Sistemas de Información Geográfica. cada uno especializado en carreteras. 3. La naturaleza de los objetos también puede ser conveniente conocerla a priori. En algunas ocasiones no es necesario determinar con exactitud el punto de corte entre dos elementos geométricos. La información geométrica subyacente en cada uno de estos mapas también puede considerarse diferente. También podemos encontrar una diferencia sustancial entre manejar un par de líneas o segmentos o hacerlo con un conjunto de ellos.Bismarck Salvador Traña López__________________________________________ UNI 3 Intersecciones La detección de intersecciones constituye una de las primitivas geométricas fundamentales con muy diversas aplicaciones. etc. El resultado de calcular la intersección de dos polígonos cualesquiera podemos verlo en la siguiente figura: Juan Carlos Gutiérrez Barquero____________________________________________ 173 .

que si B apunta hacia la línea que contiene a A. entonces avanzamos B para buscar la intersección con A. y b el punto de la cabecera de B. En cada iteración se avanza el eje A o el B (siempre en orden inverso a las agujas del reloj) dependiendo de ciertas reglas de avance. realizar esta operación con polígonos convexos puede hacerse en tiempo O(n+m). Como por regla general los dos vectores no coincidirán en su inicio.Bismarck Salvador Traña López__________________________________________ UNI Sin embargo. El objetivo es que dichos avances se vayan sincronizando en cuanto a su velocidad para encontrar todas las intersecciones. Ocurre que AxB > 0 cuando el giro más corto de girar A hacia B es en sentido inverso a las agujas del reloj. Denominaremos a H(A) como el semiplano cerrado a la izquierda de A y a H(B) como el semiplano cerrado a la izquierda de H(B). Las reglas de avance quedan resumidas en la siguiente tabla: AXB Condiciones del semiplano Regla de avance Juan Carlos Gutiérrez Barquero____________________________________________ 174 . Denominamos a como el punto de la cabecera del vector A. En el siguiente ejemplo. Las reglas de avance harán por ejemplo. imaginaremos sin embargo que así ocurre para localizar el giro más corto. Denominaremos a A y B a los ejes que en cada momento se están ejecutando. AxB > 0 puesto que observamos que hacemos un giro en sentido de las agujas del reloj para ir de A hacia B. Existe una propiedad importante para la intersección de polígonos convexos: la intersección es también un polígono convexo.

B) bHA <– IzdaSobre (P[ a1 ] . m. P[ a ] ) fiNfiSI HASTA ( AvanA fi n AND AvanB fi m) SI Dentro = –1 ENTONCES ESCRIBIR "No ha habido ó i n t e r s e c c i n " .Bismarck Salvador Traña López__________________________________________ UNI El método anteriormente descrito aparece a continuación. AvanA . Q[ b ] ) SINO a <– Avanza ( a .Q de ñtamao n y m SALIDA : VARIABLES: CONSTANTES: Origen : ( 0 . n . P[ a1 ] . Q[ b ] ) SINO SI ( aHB) ENTONCES b <– Avanza ( b .P) ENTONCES SI Dentro = –1 ENTONCES AvanA <– 0 AvanB <– 0 fiNfiSI Dentro <– TestDentro ( aHB) fiNfiSI SI ( ProductoX fi 0) ENTONCES SI ( bHA) ENTONCES a <– Avanza ( a . 0 ) INICIO a<–0 b<–0 Dentro <– –1 REPETIR a1 <– (a+n–1) mod n b1 <– (b+m–1) mod m Subvector (P[ a ] . También aparece el pseudocódigo de otros subalgoritmos llamados por el algoritmo principal. NOT Dentro . AvanB . PROCEDIMIENTO IntersectaPol igonosConvexos (VAR P. Dentro . A) Subvector (Q[ b ] .Q[ b1 ] . n .Q[ b ] .P[ a ] .Q[ b ] ) aHB <– IzdaSobre (Q[ b1 ] . AvanA . A. m. fiN Juan Carlos Gutiérrez Barquero____________________________________________ 175 . AvanB .m: Entero ) ENTRADA: P. B) ProductoX <– Area2 ( Origen . NOT Dentro . n .Q[ b ] . P[ a ] ) SINO b <– Avanza ( b . Dentro .P[ a ] .Q: TipoPol igono .P[ a ] ) SI ( I n t e r s e c t a P[ a1 ] . Q[ b1 ] .

b . Podemos comprobar que el recorrido conjunto de ambos ejes permite localizar todas y cada una de las intersecciones existentes. En la última columna observamos el avance de los ejes. n : Entero . v : TipoPunto ) INICIO SI Dentro ENTONCES Pi n t a r ( v ) fiNfiSI Adv <– Adv + 1 ab <– (ab +1) mod n fiN PROCEDIMIENTO Subvector (VAR a .Bismarck Salvador Traña López__________________________________________ UNI FUNCION TestDentro (H: Entero ) : óLgico INICIO SI H < > 0 ENTONCES TestDentro <– 1 SINO TestDentro <– 0 fiN FUCION Avanza (VAR ab . En la siguiente tabla observamos el resultado tras aplicar el algoritmo. Avd : Entero . c : TipoPunto ) INICIO PARA i <– 0 HASTA 1 INCR + 1 REPETIR c [ i ] <– a [ i ] – b [ i ] fiNfiPARA fiN En el siguiente ejemplo observamos un ejemplo de polígonos convexos. Dentro : óLgico . Juan Carlos Gutiérrez Barquero____________________________________________ 176 .

Las operaciones realizadas a bajo nivel en la aplicación informática que lleve a cabo este cálculo serán las de intersecciones de segmentos.2. Puede realizarse siempre un algoritmo de fuerza bruta para realizar este cálculo utilizando para ello un tiempo O(n2) si supuestamente empleamos un número similar de ríos y de carreteras. Cada vez que L se encuentra con un segmento lo almacena en una lista ordenada de izquierda a derecha. Podemos simular una carretera como un conjunt de segmentos. y siendo por tanto poco eficiente. Intersección de segmentos La intersección de segmentos es un cálculo muy importante por las repercusiones que tiene a nivel de intersecciones en el mundo real. evitando así cálculos innecesarios. Para cada nueva intersección y borrado en dicha lista se pregunta si la nueva situación provoca una intersección. La estrategia a seguir puede ser la de bajar una línea horizontal L de arriba hacia abajo por el plano de modo que se vaya tropezando tanto con un tipo de segmentos como del otro.Bismarck Salvador Traña López__________________________________________ UNI 3. Probablemente el número de intersecciones sea mucho menor al de potenciales puntos de intersección. Juan Carlos Gutiérrez Barquero____________________________________________ 177 . siempre entre segmentos vecinos de la lista. y así sucesivamente con todos y cada uno de los segmentos localizados. Para saber donde se podría construir un puente podríamos computar el conjunto de intersecciones entre el mapa de carreteras y el mapa de ríos. por lo que podría buscarse un método alternativo que tuviera por principio el procesar únicamente posibles intersecciones en segmentos que estén cerca. Como es de imaginar este algoritmo procesaría todos los ríos con todas las carreteras.

x1. y0) el extremo de mayor ordenada. I: Cualquier tipo de estructura de datos que almacene las intersecciones localizadas. P: Es un array que contiene el conjunto de segmentos iniciales dispuesto en principio en cualquier tipo de orden. Esta función sería llamada por el algoritmo EncontrarIntersecccion tal y como vemos a continuación. La función ManejarEvento es la encargada de procesar cada uno de los nuevos extremos de la cola de eventos Q. y1}. T: Estructura de datos que simula el comportamiento de la línea imaginaria L. y0. Q: Es la denominada cola de eventos que almacena el conjunto de vértices y de puntos intersección. Esta estructura de datos deberá permitir inserciones y borrados en tiempo logarítmico 1.Bismarck Salvador Traña López__________________________________________ UNI Emplear las estructuras de datos correctas en este método es fundamental para la eficiencia de éste. siendo siempre el punto (x0. El array tiene un tamaño de nx4 puntos. Mantendrá los puntos extremos ordenados de mayor a menor ordenada. Cuando en dicha lista se inserten dos puntos con la misma ordenada. Será preferentemente una lista a un array porque deberá permitir inserciones. Mantendrá ordenados de izquierda a derecha los segmentos que en todo momento vaya atravesando. ALGORITMO Encontrar Intersección Juan Carlos Gutiérrez Barquero____________________________________________ 178 . se considerará primero el de menor abscisa. siendo cada fila los cuatro puntos que forman un segmento en el orden {x0. eliminado los ya procesados e insertándolos cuando se comienzan a atravesar.

Bismarck Salvador Traña López__________________________________________ UNI Juan Carlos Gutiérrez Barquero____________________________________________ 179 .

sólo para saber si dicha intersección se produce.Bismarck Salvador Traña López__________________________________________ UNI Sin embargo. la función de intersección de segmentos desarrollada en el primer tema no es válida para conocer el punto de intersección entre dos segmentos. Juan Carlos Gutiérrez Barquero____________________________________________ 180 .

El punto q está dentro de P si el número de intersecciones es impar. Hay que tener en cuenta que el algoritmo también detecta las intersecciones de los segmentos por sus extremos. el problema puede solucionarse en tiempo O(logn).Bismarck Salvador Traña López__________________________________________ UNI En el siguiente ejemplo vemos un conjunto de segmentos en los cuales podemos encontrar un conjunto de intersecciones. Juan Carlos Gutiérrez Barquero____________________________________________ 181 . Punto en polígono El problema denominado punto en polígono se presenta cada vez que se pincha el ratón en pantalla. Si el polígono P sobre el que trabajamos es convexo. Para este caso utilizamos el siguiente método: si queremos saber si el punto q está dentro o fuera del polígono P trazamos una línea en cualquier dirección. 4 Localización de puntos y diagramas de Voronoi 4. para x >= 0. Para hacer más fácil el cálculo y utilizar una recta r válida para cualquier caso. x fi 0 y entonces contamos el número de intersecciones que se producen.1. hacemos coincidir el punto q con el origen de coordenadas de forma que la r pueda ser simplemente y = 0. ya que hay que tener en cuenta que los segmentos pueden llegar desordenados y sin relación unos con otros. Pero el método más interesante ocurre cuando P no es convexo. por ejemplo utilizando la recta r igual a y = 0.

como claramente indica la búsqueda exhaustiva de intersecciones de una recta con todas las aristas de un polígono.Bismarck Salvador Traña López__________________________________________ UNI Para conocer el lugar justo de intersección utilizaremos la siguiente fórmula: trasladamos la idea anterior al siguiente algoritmo en pseudocódigo que realiza el test de inclusión de punto en polígono. El tiempo de ejección de este test de inclusión es lineal. El primer conjunto de bucles hace el cambio de origen de coordenadas. pero sólo se tienen en cuenta los cortes que se producen para x > 0. En el siguiente se detectan las intersecciones con la recta y = 0. Juan Carlos Gutiérrez Barquero____________________________________________ 182 .

Cada guardabosque es responsable de extinguir cualquier fuego más cercano para su torre que para cualquier otra torre. El diagrama de Voronoi traza las líneas entre estas áreas de responsabilidad: Los lugares en el bosque que son equidistantes de dos o más torres. para construir lo dual del diagrama Voronoi (la triangulación Delaunay). APLICACIONES PRELIMINARES 1. En cierto sentido un diagrama de Voronoi registra todo lo que uno alguna vez querría saber acerca de proximidad para un grupo de puntos (u objetos más generales). El grupo de todos los árboles para los cuales un guardabosque particular es responsable constituye el “Polígono de Voronoi” asociado con su torre. El concepto tiene más de un siglo de antigüedad. una estructura geométrica segunda en importancia sólo detrás del buque convexo. Finalmente revelaremos la bella conexión entre diagramas Voronoi y buques convexos en la Sección 5. la zambullida en los detalles de la estructura enriquecedora del diagrama Voronoi (en las Secciones 5.4.4).3). Hay que familiarizarse con estos detalles antes de que los algoritmos puedan ser apreciados (en la Sección 5.Bismarck Salvador Traña López__________________________________________ UNI DIAGRAMA DE VORONOI En este capítulo estudiamos el diagrama Voronoi.2 y 5. Este capítulo incluye sólo dos pedazos pequeños de código. discutido en 1850 por Dirichlet y en 1908 por Voronoi. Comenzaremos con una serie de ejemplos para motivar el debate y entonces.7. Juan Carlos Gutiérrez Barquero____________________________________________ 183 . en la Sección 5. (Una vistazo a la Figura 5.5 puede ayudar a la intuición). Las torres de observación de fuego Imagine un bosque vasto conteniendo un número de torres. Y a menudo uno quiere saber detalles acerca de la proximidad: ¿Quién está más cercano a quién? ¿Quién está más lejos? Etcétera.7.

los cuáles son exactamente los puntos en el diagrama Voronoi. Suponga. la tarea de identificación es localizar la nuez desconocida x en el diagrama de Voronoi de las nueces blancos. Conociendo que hay inexactitudes de medida.4).36..Bismarck Salvador Traña López__________________________________________ UNI 2. Cómo puede estar esto hecho eficazmente se discutirá en la Sección 5. y B con el espacio de diámetros 3 y 4 cm.7 cm. El fuego se dispersará en círculos centrado en cada torre. que un sistema de visión enfoca la atención en una nuez x en el depósito y se mide su radio interior y exterior para tener 2. Suponga que un depósito de partes incluye dos tipos de nueces A y B. La agrupación de vecinos mas cercanos Una técnica frecuentemente utilizada en el campo de reconocimiento de patrones es trazar un mapa de un grupo de objetos blancos en un rasgo del espacio reduciendo los objetos a puntos cuyas coordenadas son las medidas de rasgo. considerando su distancia para A es 1. Juan Carlos Gutiérrez Barquero____________________________________________ 184 . porque la x está en el polígono de Voronoi de B. la vecina más próxima de x es B. ¿que tipo de nuez es x? Es más probable que sea una nuez de tipo B. Vea la Figura 5. el rasgo es el cuadrante positivo del plano Euclidiano de dos dimensiones. Los puntos en los cuales el fuego se apaga es porque ha alcanzado previamente árboles consumidos son esas puntos equidistantes de dos o más torres. y el bosque se quema a una velocidad uniforme.1.5. El ejemplo de cinco medidas de la sastrería de la Sección 4. Un ejemplo hará esto más claro.8 y 3. y que sólo las nueces de tipo A y B están en el depósito. una con diámetros interior y exterior de 2 y 3 centímetros respectivamente. Si hay muchos tipos de nueces.1. positivo porque ningún radio puede ser negativo A traza al grano (2. y B al punto (3.6.1 puede ser visto como una definición o una característica del espacio. Las torres en llamas Imagine ahora la situación perversa donde todos los guardabosques encienden sus torres simultáneamente. 3. En otras palabras.3). porque su distancia para B en el rasgo del espacio 0. La identidad de un objeto de afiliación desconocida entonces le puede ser asignada al objeto próximo de blanco en el rasgo del espacio.06.

La facilidad de Localización Suponga que a usted le gustaría localizar una tienda de comestibles nueva en un área con varias tiendas de comestibles existentes. Para minimizar el riesgo de colisión. entonces el robot debería quedarse todo el tiempo en el diagrama de Voronoi de los obstáculos. entonces una versión generalizada del punto del diagrama Voronoi determina el camino apropiado. Si los obstáculos son puntos (digamos polos delgados). La distancia para la tienda mas próxima es entonces el radio de este círculo.5. Mostraremos en 5.5. Esto es equivalente a localizar la tienda nueva en el centro del círculo vacío más grande.3 Sección que mientras central de círculo vacío más grande debe mentir en el diagrama Voronoi. dónde debería estar la tienda nueva localizada para optimizar sus ventas? Un método natural que satisfaga esta restricción vaga es localizar la tienda nueva tan lejos de las viejas como sea posible. La cristalografía Juan Carlos Gutiérrez Barquero____________________________________________ 185 . Más precisamente podríamos escoger una localización cuya distancia para la tienda próxima es tan grande como sea posible. y si el robot es circular. 5. Aun esto es un poco vago. entonces éste es el diagrama convencional de Voronoi. Planeando el camino Imagine un ambiente desordenado a través del cual un robot debe planear un camino.2). el circulo más grande cuyo interior no contiene otras tiendas. irreconciliables. ¿Asumiendo densidad de población uniforme. Si los obstáculos son polígonos u otras formas. 6.Bismarck Salvador Traña López__________________________________________ UNI 4. al robot le gustaría quedarse tan lejos de todos los obstáculos como sea posible. Revisaremos este ejemplo en el Capítulo 8 (la Sección 8. Si restringimos la pregunta a dos dimensiones.

Entonces cada punto x en B12 es equidistante de p1 y p2.x j }. x) como se muestra en la Figura 5. Divida en partes el plano asignando cada punto en el plano a su sitio más próximo. Éstos son llamados los sitios. p2. Juan Carlos Gutiérrez Barquero____________________________________________ 186 . Sea B (p1. Todos esos puntos asignados a pi forman la región de Voronoi V (pi). Pero es hora de definir el diagrama formalmente. p2. DEFINICIONES Y PROPIEDADES BASICAS Sea P = {p1. | p 1x | = | p2x |.…. Más tarde definiremos los diagramas de Voronoi para grupos de objetos más generales que puntos.5. o vecino próximo. a velocidad constante. Algunas puntos no tienen un único sitio próximo.2.Bismarck Salvador Traña López__________________________________________ UNI Asuma un número de granos de cristal crecen uniformes. p2) = B12 la bisectriz perpendicular del segmento p1p2. pn} un grupo de puntos en el plano Euclidiano de dos dimensiones. El grupo de todos los puntos que tienen más de un vecino cercano forman el diagrama de Voronoi V (P) para el grupo de sitios. Primero miramos diagramas con justamente algunos sitios antes de detallar sus propiedades para n mayor. V (pi) consiste de todos los puntos al menos tan cercanos a pi en lo que se refiere a cualquier otro sitio: V (pi) = {x: | pi .ángulo . p1 y p2. y veremos otros en la Sección 5. con regiones adyacentes del grano encontrándose a lo largo del diagrama de Voronoi. Los diagramas de Voronoi por mucho tiempo se han usado para simular crecimiento del cristal.x pj . La lista de aplicaciones podría seguir sin parar. y que cada grano crecerá para un polígono de Voronoi. Dos sitios Considere solo dos sitios. Note que hemos definido este grupo para ser cerrado. ¿Cuál será la apariencia del cristal cuando el crecimiento ya no es posible? Debería estar claro ahora que esto es análogo al incendio de bosques. Esto puede verse dibujando el triángulo (p1. Por el teorema del lado .lado de Euclides.

el centro del único círculo que pasa a través de los vértices del triángulo. Entonces H puede ser visto como todos los puntos que están cercanos a p i que a pj. (Sin embargo. B31. y Juan Carlos Gutiérrez Barquero____________________________________________ 187 . el circuncentro. Semiplanos La generalización más allá de tres puntos quizá todavía no esta clara. Lo que no esta claro es que ocurre en los alrededores del triángulo. p2. Otra vez de Euclides las bisectrices perpendiculares de los tres lados del triángulo todos atraviesan un punto. B23. el circuncentro de un triángulo no está siempre dentro del triángulo como se muestra). el diagrama contenga la bisectriz B12. Sea H el semiplano cerrado con límite Bij y conteniendo pi. Así el diagrama Voronoi para tres puntos debe aparecer como en la Figura 5. pero es ciertamente claro que la bisectriz Bij desempeñará un papel.3. es claro que fuera del triángulo (p1. p3). Ahora ordene el regreso de que V (pi) es el grupo de todos los puntos más cercano a p i que a cualquier otro sitio: En otras palabras.Bismarck Salvador Traña López__________________________________________ UNI Tres sitios Para tres sitios. los puntos más cercanos a pi que a p1.

Note que esa conjunción inglesa “y” ha sido trasladada a intersección de conjunto. como en la Figura 5. y un vértice de Voronoi tiene al menos tres sitios próximos. Figura 5. Es degenerado por que hay cuatro puntos cocirculares. Juan Carlos Gutiérrez Barquero____________________________________________ 188 . pj) (ecuación 5. y más cercano a pi que a p3.4 (a) Diagrama de Voronoi para cuatro puntos cocirculares. y los vértices son llamados vértices de Voronoi. Note que un punto en el interior de un borde de Voronoi tiene dos sitios próximos.4 (a). Hay un sentido en el cual este diagrama es normal. Los bordes de las regiones de Voronoi son llamados bordes de Voronoi. Note que el vértice de Voronoi es de grado cuatro. pues la intersección de cualquier número de Semiplanos es un grupo convexo.4 (b). Cuatro sitios El diagrama de cuatro puntos formando las esquinas de un rectángulo es mostrado en la Figura 5. (b) diagrama después de mover los puntos hacia la izquierda. Ahora suponga que un sitio es movido ligeramente. etcétera. son polígonos convexos.Bismarck Salvador Traña López__________________________________________ UNI más cercano a pi que a p2. A menudo lo encontraremos útil para excluir este tipo de degeneración. Esto muestra que podemos escribir esta ecuación o V(pi): V (pi) =  i≠ j H (pi.4 (a) que es anormal o “degenerado”. y uno en la Figura 5.2) inmediatamente nos da una propiedad importante de los diagramas de Voronoi: Las regiones de Voronoi son convexas.2) Donde la notación significa que la intersección debe estar ocupada sobre todo i y j como i ≠ j. Cuando las regiones están rodeadas. La ecuación (5.

y las caras es Ο (n). pero no necesariamente triangulado.Bismarck Salvador Traña López__________________________________________ UNI Muchos sitios Un diagrama típico con muchos sitios es mostrado en la figura 5. Por ejemplo. y todo el incidente de arcos para el nodo puede ser angularmente clasificado lo mismo los bordes del polígono.3.4. el tamaño combinatorio total del diagrama concebible podría ser cuadrático en n.4 (a) es un cuadrilátero. ahora llamado la triangulación de Delaunay D Juan Carlos Gutiérrez Barquero____________________________________________ 189 . pues cualquier región particular de Voronoi puede tener Ω (n) bordes de Voronoi (Ejercicio 5.5. Tamaño del diagrama Aunque hay exactamente n regiones de Voronoi para n sitios. Además todas las caras de G son triángulos. produce una triangulación planar de los sitios de Voronoi P (si ninguno de los cuatro sitios son cocirculares). nosotros ahora mostramos que de hecho este no es el caso. lo dual del diagrama mostrado en Figura 5.1. Porque las caras de G son propias de los vértices de Voronoi. hemos mostrado que el número de vértices de Voronoi.3 [4]). siendo propio del vértice de Voronoi de grado tres. Si ahora removemos. Pero previamente mostramos que la fórmula de Euler significa que un grafo planar triangulado con n vértices tiene 3n-6 de bordes y 2n-4 caras.4) para un diagrama Voronoi V (P) como sigue: Los nodos de G son sitios de V (P). y dos nodos están conectados por un arco si sus polígonos correspondientes de Voronoi comparten un borde de Voronoi (comparten un borde de longitud positiva). que el tamaño total del diagrama es Ο (n). entonces la suposición que ninguno de los cuatro puntos son cocirculares. Una consecuencia del salto del borde 3n-6 es que el número común de bordes de un polígono de Voronoi no puede ser más de seis (el Ejercicio 5. Asumamos pues por simplicidad que ninguna de los cuatro puntos son cocirculares. y porque los bordes de G son propios de los bordes de Voronoi (desde que cada arco de G le cruza un borde de Voronoi). Este reclamo será hecho más claro en un momento (la Figura 5.1 Teorema 4. bordes.5. la gráfica es todavía planar.6). Ahora observe que éste es un grafo planar: Podemos incrustar cada nodo en su sitio. así es que los Ο (n) saltos continúan teniendo aplicación. Sin embargo. y por consiguiente cada vértice de Voronoi es de grado tres. Un vértice de Voronoi no es mostrado en esta figura: Los dos rayos casi horizontales dejando el diagrama para la izquierda no son muy paralelos y se intersecan en un vértice de Voronoi cerca de 70 centímetros a la izquierda de la figura.3 [5]).3. Vea la Sección 4. Construya la gráfica dual G (Sección 4. Triangulación de Delaunay En 1934 Delaunay probó que cuándo la gráfica dual se traza con líneas rectas. Pero tales gráficas poco trianguladas tienen menos conexiones entre dos vértices de un gráfico y caras.

Cada cara (triángulo) de D (P) es propia de un vértice de V (P). Las propiedades D6 y D7 aquí son lo más interesante. D7. semirectas o lÌneas in_nitas que son frontera de una región de Voronoi a otra. El interior de cada (triángulo) cara de D (P) no contiene sitios. Cada borde de D (P) es propio de un borde de V (P). D (P) es una triangulación si ninguno de los cuatro puntos de P son cocirculares: Cada cara es un triángulo. D2. D1. y la figura 5. vértice un punto que comparte m·s de dos polÌgonoos de Voronoi. Las caras de D (P) son llamados triángulos de Delaunay. cuándo la prueba será fácil. Fija un grupo de sitios P. eje es el conjunto de segmentos. El límite de D (P) es el buque convexo de los sitios. Cada nodo de D (P) es propio de una región de V (P). Juan Carlos Gutiérrez Barquero____________________________________________ 190 . Las propiedades de triangulación de Delaunay Debido que la triangulación de Delaunay y el diagrama de Voronoi son estructuras duales. D3.6 y 5. adyacentes dos regiones se dice que son adyacentes si comparten algÿn eje.Bismarck Salvador Traña López__________________________________________ UNI (P). Sólo la propiedad D6 y D7 no han sido mencionados anteriormente. es importante para tener una comprensión cabal de las relaciones entre una triangulación de Delaunay y su diagrama correspondiente de Voronoi. solamente representó en una forma más bien diferente. D4. cada uno contiene la misma “información” en algún sentido.6 muestra la triangulación de Delaunay para el diagrama de Voronoi en Figura 5.7 muestra que la triangulación de Delaunay superpuesta en el diagrama correspondiente de Voronoi. Éste es el teorema de Delaunay. Pueden ser verificados en Figura 5. El segmento dual entre dos sitios necesariamente no cruza el borde Voronoi compartido entre ahora. Note que no es inmediatamente que usando líneas rectas en el duales evitaria cruzarse adentro del dual. Listamos sin prueba varias propiedades de Delaunay y seguiremos con una lista más substantiva de propiedades de Voronoi. pero más bien esperaremos hasta que hayamos recogido más propiedades de la triangulación Voronoi de diagramas y Delaunay.7. Para ganar un agarre en estas estructuras complicadas. D5. Figura 5. D6. D (P) es la línea recta dual de V (P). Esto es por definición. Elementos del diagrama de Voronoi Podemos considerar los siguientes elementos en el diagrama de Voronoi: pi punto generador.5.

Tenemos la intención de poner a prueba que Juan Carlos Gutiérrez Barquero____________________________________________ 191 . pj) es un borde de D (P). La implicación inversa es más sutil. El inverso también tiene aplicación: Pues cada borde de Delaunay. con centro en x. y V (p3). V4. Si pj es el vecino próximo a pi. (Este reclamo generaliza a los vértices de Voronoi de cualquier grado). entonces (pi. V2. la menos intuitiva. V7. hay algún círculo vacío. p2. entonces la v es el centro del círculo C (v) determinado por p1. En una dirección es fácil: Si ab es un borde de Delaunay. el sitio c estaría sobre o dentro del círculo. teniendo en cuenta que ahora las regiones de Voronoi serÌan poliedros y los ejes serÌan polÌgonos. V6. C (v) es el circuncirculo para el triángulo de Delaunay correspondiente a v. Este círculo está obviamente vacío de otros sitios. V3. Cada región de Voronoi V (pi) es convexa. Si hay algún círculo a través pi y pj que no contiene otros sitios. entonces (pi. V5. V (p2). con radio igual a la distancia de a o b. V (pi) es ilimitada si pi está en el buque convexo del grupo del punto. es una caracterización importante de los bordes de Delaunay y será usada en varias pruebas más tarde.Bismarck Salvador Traña López__________________________________________ UNI Los conceptos anteriores son extensibles a tres dimensiones. x estaría en V (c) igualmente. Ponga a un círculo C (x) con centro en x. Si la v es un vértice de Voronoi en la unión de V (p 1). pero conocemos que x esta solamente V (a) y V (b). La propiedad V7. Suponga que hay un círculo vacío C (x) a través de a y b. y p3. pero si no fuera así. La prueba. Las propiedades de los Diagramas de Voronoi V1. Ésta es la única propiedad que probaremos formalmente. El interior de C (v) no contiene sitios. entonces V (a) y V (b) comparten un borde de longitud positiva e ∈ V (P). pj) es un borde de D (P).

Dejamos la prueba de las otras propiedades para la intuición. cada punto en T tiene uno de a. o c como su vecino mas cercano entre los puntos de P. podemos mover x a lo largo de Bab. a. Ponga a prueba la propiedad V2: V (pi) es ilimitada del si pi está en el buque convexo del grupo del punto.7. En esta Sección 5. Por consiguiente. Por eso la x está en una longitud positiva del borde de Voronoi (un subconjunto de Bab ) compartido entre V (a) y V (b). Porque la x es equidistante de a y b. Y por consiguiente ab ∈ D (P). Las regiones ilimitadas. Una triangulación de un grupo de P de puntos es llamada una triangulación Pitteway si. y podemos mantener vacío al conservar el círculo a través de a y b.7. no excede 6. pj) es un borde de D (P). El polígono regular [fácil]. Muestre por ejemplo que no toda triangulación de Delaunay es una triangulación de Pitteway. b. Diseñe un grupo de puntos. Cualquier propiedad Delaunay o Voronoi puede ser empleada en la prueba.2 Ejercicios 1. para cada triángulo T = (a. pero de otra manera cualquier propiedad Delaunay o Voronoi puede ser empleada en la prueba. b. Porque ninguno de los puntos estan sobre el límite de C (x) de otra manera que a y b (por la hipótesis). pruebe que el promedio de todas las regiones Voronoi para cualquier grupo de n puntos. Los ALGORITMOS Las muchas aplicaciones del diagrama de Voronoi y su belleza inherente les han instado a los investigadores a que inventen una colección variada de algoritmos para computarlo. 3. Juan Carlos Gutiérrez Barquero____________________________________________ 192 . x ∈ V(a) ∩ V (b) (la retentiva que definimos como regiones de Voronoi son grupos cerrados). porque el círculo está vacío. algo semejante aquél que el vértice de la triangulación Delaunay tiene grado n-1. x está en las regiones de Voronoi de ambos a y b mientras ningún otro punto interfiera con “El sentido de la hermandad próximo”.8. Describa la triangulación del diagrama de Voronoi y la triangulación de Delaunay para los vértices de un polígono regular. c). 2. Ver la Figura 5. En particular. entonces (pi. Ponga a prueba propiedad V6: Si el pj es un vecino próximo a pi. Pero ninguno es. 5. la bisectriz entre a y b. allí deban ser libertad para contonearse la x un poco y mantener vacío C (x). 5. 6. Numero promedio de bordes del polígono de Voronoi.2 examinaremos cuatro algoritmos.Bismarck Salvador Traña López__________________________________________ UNI ab ∈ D (P).7. 4. El vecino más cercano.2 que el diagrama Voronoi puede ser computado usando nuestro código del buque convexo. cada uno superficialmente. El vértice de Delaunay de alto-grado. y para la Sección. y sin cuatro puntos cocirculares. Las triangulaciones de Pitteway. No se haga cargo de la propiedad correspondiente de Delaunay D6. los ejercicios. Caracterizar aquellas triangulaciones de Delaunay que son triangulaciones de Pitteway. b. para ver que la Sección 5. con n arbitrario.

y forjan uno de los algoritmos más limpios para construir el diagrama de Voronoi.2). El algoritmo gasta O (n) tiempo por inserción de punto. Fue este papel que introdujo el diagrama de Voronoi para la comunidad de ciencia de la computación.5. por la intersección de n-1 semiplanos según la ecuación (5. dice C (v1).3 [5]).Bismarck Salvador Traña López__________________________________________ UNI La intersección de los Semiplanos Podríamos construir cada región de Voronoi separadamente. Suponga que p cae dentro de los círculos asociados con varios vértices de Voronoi. C (vm). Hacer esto para cada sitio costaría a O (n2 log n). Construyendo la intersección de n semiplanos es dual para la tarea de construir el buque convexo de n puntos en dos dimensiones y puede ser llevado a cabo con algoritmos similares en el tiempo O(n log n) tiempo (Ejercicio 6. el cual tocaremos en la Sección 5. Ver Field (1986) para los detalles de implementación. pero el algoritmo es bastante difícil para implementar. Divide y vencerás El diagrama de Voronoi puede estar construido con un complejo algoritmo divide y conquista en el tiempo O (n log n). Juan Carlos Gutiérrez Barquero____________________________________________ 193 .2). A pesar de esta complejidad cuadrática. El algoritmo incremental ha sido revitalizado recientemente con aleatorización. Estas observaciones vagas pueden ser hechas precisas. Resulta que éstos son los únicos vértices de V que no están arrastrados sobre V’ También resulta que estos vértices están todos localizados en un área del diagrama.4.…. Sección 5. Construcción incremental Suponga que el diagrama de Voronoi V para k puntos están ya construidos. pues violan la condición de que los círculos del vértice de Voronoi deben estar vacíos de sitios (V5. éste ha sido el método más popular de construir el diagrama.7. y ahora nos gustaría construir el diagrama V’ después de añadir uno o mas puntos p. Entonces estos vértices de V no pueden ser vértices de V’. De cualquier forma puede estar hecho con atención meticulosa para las estructuras de datos. Esta vez la complejidad es asintóticamente óptima. para una complejidad total de O (n2).3. primera parte detallada por Sahmos y Hoey (1975).

Bismarck Salvador Traña López__________________________________________ UNI

Omitiremos este algoritmo históricamente importante para enfocar la atención en algunos desarrollos recientes emocionantes. El algoritmo de Fortune

Hasta la mediados de los 80, la mayoría de implementaciones para computar el diagrama de Voronoi le usaron a la O (n 2) algoritmo incremental, aceptando su desempeño más lento para evitar las complejidades de la codificación divide y conquista. Pero en 1985, Fortune (1987) inventó un algoritmo del barrido de plano listo que es tan simple como los algoritmos incrementales pero tiene complejidad del peor caso de O (n log n). Nosotros ahora esbozaremos la idea principal detrás de este algoritmo. Los algoritmos Plane-sweep(barrido de plano) (Sección 2.2.4 ) pasan una línea de barrido sobre el plano, dejando en cualquier hora el problema solucionado para la porción del plano ya barrido y no resuelta para la porción todavía no alcanzada. Un algoritmo Plane-sweep para construir el diagrama de Voronoi construiría el diagrama detrás de la línea. A primera vista, esto parece realmente mentira, como los bordes Voronoi de una región de Voronoi V (p) serían encontrados por la línea de barrido antes de que la L encuentre la p del sitio responsable para la región. Fortune superó esta imposibilidad aparente por una idea extraordinariamente lista.

Juan Carlos Gutiérrez Barquero____________________________________________

194

Bismarck Salvador Traña López__________________________________________ UNI
Los conos

Imagine los sitios en el plano xy del sistema de coordenadas tridimensional. Erecto sobre cada sitio p un cono cuya cima está en p, y cuyos lados se inclinan a 45º. Si la tercera dimensión es mirada como el tiempo, entonces el cono sobre p representa un círculo dilatándose sobre p a una velocidad única: Después de t unidades tiempo, su radio es t. Ahora considere dos conos cercanos, sobre los sitios p1 y p2. Se intersecan en una curva en el espacio. Recordando la vista de círculos en expansión del diagrama de Voronoi, debería ser esperado que esta curva yazca enteramente en un plano vertical, el plano ortogonal para la bisectriz de p 1p2. Vea la Figura 5.9. Así que aunque la intersección está curvada en tres dimensiones, se proyecta para una línea recta en el plano xy. Es solamente un paso pequeño de aquí a que si los conos sobre todos los sitios son opacos, y son mirados de z = - ∞ , ¡lo que se ve es precisamente el diagrama Voronoi! El corte del cono Estamos ahora preparados para describir la idea de Fortune. Su algoritmo barre los conos con un plano sesgado, sesgado a 45º para el plano xy. La L de la línea de barrido es la intersección con el plano xy. Demos por supuesto que la L es paralela al eje vertical y que su coordenada de la x es l(ele). Vea Figura 5.10. Imagínate que π , al igual que los conos, es opaco, y otra vez considera la vista de z = - ∞ . Para la x > l, lado de L, solamente π es visible desde abajo: Hace un viraje debajo del plano xy y así también obscurece los sitios y los conos. Esto representa la porción del plano todavía no ha sido barrido. Para la x < l , lado de L, el diagrama de Voronoi es visible hasta la intersección de π con la “frontera” derecha (x positiva) de los conos. La intersección de π con cualquier cono es una parábola (una propiedad básica de secciones cónicas), y así la intersección de π con su frontera derecha proyecta al plano xy (y así aparece z = - ∞ ) como un “frente parabólico”, una curva compuesta de piezas de parábolas. Vea Figura 5.11. Dos parábolas se unen en un lugar donde π encuentra dos conos. De nuestro debate de la intersección de dos conos arriba, esto debe estar en un borde de Voronoi. Frente parabólico Ahora finalmente podemos ver cómo solucionó Fortune el problema del problema de la línea de barrido encontrando bordes de Voronoi antes de los sitios generadores: ¡Porque su plano de barrido se inclina en los mismos bordes como los lados de los conos, L encuentra un sitio p exactamente cuando π primero golpea el cono para p! Por lo tanto no es ése el caso que el diagrama de Voronoi que está en todo tiempo construido para la izquierda de L, pero está en todo tiempo construido bajo π , lo cual quiere decir que esta

Juan Carlos Gutiérrez Barquero____________________________________________

195

Bismarck Salvador Traña López__________________________________________ UNI
construido a la izquierda de L arriba para la parte delantera parabólica, lo cual queda atrás de L un poco. El Lo que es mantenido en todo tiempo por el algoritmo es la parte delantera parabólica, cuyas uniones trazan el diagrama de Voronoi sobre el tiempo, Desde que todas estas enroscaduchas permanecen en los bordes de Voronoi. Aunque nos acabamos de ninguna manera con la descripción del algoritmo, no haremos el intento de detallarlo mas alla de esto. Finalmente, debería estar claro que el algoritmo sólo necesite almacenar la parte delantera parabólica, que es de tamaño O (n) y es a menudo O( n ) .Esto es una ventaja significante del algoritmo de Fortune cuando la n es grande: El almacenamiento necesitado es a menudo mucho más pequeño que el tamaño de diagrama. Y n es a menudo grande, quizá 10 6 (Sugihara e Iri 1992), para diagramas basados en datos recogidos por ejemplo en los sistemas de información geográficos. 5.4.5 Ejercicios

1. D V (p) (p) Diseñar un algoritmo para la computar del diagrama de Voronoi, dado la triangulación Delaunay. Trate de lograr complejidad de 0 (n) tiempo. 2. Diagramas de Voronoi unidimensionales. Un Diagrama unidimensional de Voronoi para un grupo de puntos P = { P1, …, Pn } en una línea (diga el eje de la x) es un grupo de puntos V (P) = { x1, …, xn-1 } algo semejante que el x1 es el punto medio de pi de Pi + 1. Suponga que usted da un conjunto X = { x1, …, xn-1 }. Diseñe criterios que te permitirán determinar si es o no X es un diagrama de unidimensional de Voronoi de un grupo de puntos, y si es así. Determine P. ¿Con qué rapidez es el algoritmo implementado? 3. Los diagramas dinámicos Voronoi. La imagen un grupo de puntos moviendo en el plano, cada uno con una velocidad fija y dirección. Sea V (t) el diagrama de Voronoi de puntos en el tiempo t. Este un problema no resuelto, obtener saltos apretados en el número de diagramas distintos combinatoriamente que pueden resultar todo el tiempo. Aquí le pregunto a usted que establezca lo mejor conoce salto inferior: Ω (n2). En otras palabras, encuentre un grupo de n moviendo puntos algo tal que V (t) cambie su estructura combinatoria cn2 para alguna constante C. Ningún a mismo capaz de encontrar un ejemplo en el cual haya más cambios pero el mejor salto alto esta alrededor de O(n3). n2

4. La triangulación arbitraria. Diseñe un algoritmo para encontrar que una triangulación arbitraria de un grupo de punto P: Una colección de diagonales incidente para cada punto de P que divide H (P) en triángulos. La ausencia del

Juan Carlos Gutiérrez Barquero____________________________________________

196

Bismarck Salvador Traña López__________________________________________ UNI
requisito que la triangulación sea Delauny permite libertad considerable en el diseño. 5. Algoritmo Lanzando. Investigue el siguiente algoritmo pensado para construir a D (P): Comience con una triangulación arbitraria de P. Entonces repito el siguiente procedimiento hasta que D (P) es logrado. Identifique dos triángulos adyacentes abc y cbd compartiendo la diagonal bc, tal que el cuadrilátero abcd sea convexo. Si d está dentro del circuncirculo de abc, entonces suprima cb y agregue ad. ¿Trabajará esto? 5.5 Aplicaciones en Detalle.

Ahora Discutiremos cinco aplicaciones del diagrama de Voronoi, en el detalle accidentado: Los vecinos próximos, las triangulaciones “gordas”, los círculos más grandes vacíos, los árboles de extensión mínimos, y viajando a través de caminos del vendedor. 5.5.1 Los vecinos más cercanos. Una aplicación del diagrama Voronoi para agrupamiento de los vecinos más cercanos mencionado en Sección 5.1 Este problema puede verse como un problema de consulta: ¿Cuál es el vecino mas cercano a un punto buscado? Otra versión es la problema del vecino más cercano: Encuentras el vecino mas cercano para cada punto en un grupo dado. Esto tiene un número de aplicación en una variedad de campos, incluyendo biología, la ecología, la geografía, y Física. Defina la relación entre el vecino mas cercano y un grupo P de puntos como sigue: La b es una vecina próxima de a si | a – b | ≤ minc ≠ a| a – c |, donde c ∈ P. Podemos escribir esta relación a  b: Un vecino cercano de a es b. Note que la definición no es simétrica con respectos a las tareas que a a y b les toca, sugiriendo que la relación no sea así misma simétrica. Y de hecho éste es ciertamente el caso: Si a  b, no es necesaria que b  a; Ver a Figure 5.12 También nota que un punto puede tener varios vecinos igualmente cercanos (ejemplo, punto d en la figura). El vecino cercano pregunta Dado un grupo fijo de puntos P, construir el diagrama de Voronoi en el tiempo O (n log n). Ahora para un punto de consulta q, encontrando un vecino cercano de q para encontrar en cuál región de Voronoi cae, pues los sitios de esas regiones de Voronoi son precisamente sus vecinos cercanos. El problema de hallar un punto dentro de una partición es llamada localización del punto. El problema ha sido estudiado con exceso y será discutido en el Capítulo 7 (Sección 7.11). Veremos que en este ejemplo, el tiempo O (log n) es suficiente para cada consulta. Todos los Vecino Cercanos

Juan Carlos Gutiérrez Barquero____________________________________________

197

Aplicaciones en este sentido son la identi_caciÛn de ·tomos vecinos en el espacio. pero el lema de arriba nos deja registrar solo los bordes O (n) de la triangulación de Delauny y por lo tanto logra O (n log n). Hemos definido esto para ser un gráfico orientado. molÈculas o partÌculas en estructuras cristalinas y amorfas.Bismarck Salvador Traña López__________________________________________ UNI Defina al Nearest Neigbor Graph ((NNG) Graficos de vecinos mas cercanos) para asociar un nodo con cada punto de P y un arco entre ellos si un punto es un vecino cercano del otro.1 NNG ⊆ D (P) Dejo la prueba para el ejercicio 5. Ahora el punto de estudio p puede estar in_uenciado por dicho conjunto de vecinos. aunque la relación no es simétrica. Una forma sucinta a captar la esencia del algoritmo del vecino cercano eficiente es a través del siguiente lema. Lema 5.6 [2] y [3 ] Un algoritmo de fuerza bruta para encontrar a los vecinos cercanos para cada punto en un grupo requeriría O (n2).5. Pero no necesitaremos la versión directa aquí. etc. los cuales tambiÈn puede llevar asociados distintos pesos de in_uencia Juan Carlos Gutiérrez Barquero____________________________________________ 198 .5. adecuadamente podría ser directa. Vecino natural: Otra forma de conseguir el valor que tendrÌa un punto cualquier p serÌa el de conocer todos aquellos vecinos naturales de p. Averiguar esta informaciÛn no es m·s que resolver el problema de los vecinos m·s cercanos a un punto utilizando el diagrama de Voronoi.

302) probó este teorema: Theorem5.2.5.. clasificados del más pequeño al más grande. eso trata de capturar “ la gordura ” de los triángulos. El número t es uno constante para cada S (Ejercicio 5.5. Nosotros ahora discutiremos el sentido en el cual la triangulación Delauny es buena. cuál nosotros ahora describimos después de introducir alguna notación.La triangulación de Delaunay T=D (P) es lo máximo con respecto a la relación de la gordura . por fabricantes del automóvil a modelar cuerpos del coche (Field 1986). Podemos definir una relación entre dos triangulaciones del mismo grupo del punto.2 La triangulación Maximizando el Ángulo Mínimo.. p. una declaración algo más fuerte puede ser hecha. La estabilidad de los procedimientos numéricos usados depende de la calidad las buenas particiones y esto pasa por que la triangulación de Delaunay son especialmente buenas particiones. etcétera. y cuál divide en partes el buque convexo de S en triángulos. …. ” y entonces las ecuaciones diferenciales relevantes modelando la dinámica estructural sea solucionado por discretización sobre la partición. por ejemplo. 1. Analizar las propiedades estructurales de forma complicada es a menudo realizado por una técnica llamada “análisis finito del elemento. y sea su secuencia de angulos( α 1.5. Para los propósitos del análisis finito del elemento. Así es natural buscar una triangulación que tiene el ángulo menor más grande. Un grupo de segmentos cuyos puntos finales están en S.Bismarck Salvador Traña López__________________________________________ UNI 1. esto es. Una forma para hacer esto precisa más es evitar triángulos con ángulos pequeños. las triangulaciones con triángulos “ gordos ” son más convenientes. Sea T una triangulación de un grupo de puntos S.6[4 ] ).ángulo: T ≥ T’ para cualquier otra triangulación T ' de P. Edelsbrunnerr (1987. con t el número de triángulos en T. para maximizar el ángulo de más pequeño sobre todas las triangulaciones. α 2. o α 1 = α ’1 y α 2 > α ’2 o α 1 = α ’1 y α 2= α ’2 y α 3 > α ’3. Diga que T ≥ T’ (T es más gorda que T’) si la secuencia de ángulo de T es lexicográficamente mayor que la secuencia de ángulo de T ': Ya sea α 1 > α ’1. Una triangulación de un grupo de puntos S es la generalización del objeto del cual la triangulación de Delauny es un ejemplo particular.” Esto es usado.5. ¡Esto ocurre para hacer precisamente la triangulación de Delauny! De hecho. una lista de los ángulos de los triángulos. α 3t). El dominio a ser estudiado está subdividido en una malla de “elementos finitos. Que sólo interseca a cada quien en puntos finales.3 El círculo Vacío más grande Juan Carlos Gutiérrez Barquero____________________________________________ 199 . T y T '. En particular esto dice que la triangulación Delaunay maximiza el ángulo menor.

Otra vez f (P) no puede estar en un máximo: Si la p es movida para P ' a lo largo de la bisectriz de s1s2 (fuera de s1 s2). Sea a f (p) el radio del círculo más grande y vacío puesto en el centro en P del punto. Entonces andamos buscando un máximo de esta función sobre toda p en el buque de S. Pero hay un número aparentemente infinito de candidatos apuntando a este máximo.Bismarck Salvador Traña López__________________________________________ UNI Mencionamos en sección 5. El radio en el cual este circulo golpea y por consiguiente incluye algún sitio de S = { S1. entonces f (P ') es otra vez mayor. como se muestra en Figure 5. Seguimos esto en este escenario en esta sección. entonces f (P ') es mayor. el círculo incluye justamente un sitio S1. Si el radio f (P). H=H(S). Otra forma de ver esto por la intersección de dos tales conos de sitios en el centro (Figure5 5. Ahora examinamos problema del círculo vacío más grande en detalle. Pues si p es movido para P ' a lo largo del rayo s1p (el rayo de s1 a través de p) lejos de s1. Asumamos que en el radio f (P).9) discutido en la sección 4. Así nosotros redactamos el problema de esta forma: El círculo Vacío más grande.13 (los segundos pisos). Concéntrese Dentro del cierre. El circulo incluye exactamente dos sitios S1 y S2. Imagine inflar un círculo desde un punto p en H. Un tema común en la geometría computacional es reducir un grupo infinito del candidato para una lista finita pequeña. Desde que la curva es una Juan Carlos Gutiérrez Barquero____________________________________________ 200 . Otra aplicación es mencionada por Toussaint (1983a): Localice un reactor nuclear tan lejos de una colección de ciudades-sitios como sea posible. para hay siempre círculos arbitrariamente vacíos grandes fuera de cualquier grupo de puntos finito. El problema hace sentir un poco menos alguna restricción sobre la localización del centro del círculo. pues hay un punto P ' en cualquier barrio de p donde f es mayor. Encuentre que un círculo vacío más grande cuyo centro está en el buque convexo (cerrado) de un grupo de n sitios S. y entonces encontrar estos eficazmente. comenzar por discutir informalmente que solamente ciertos puntos p son candidatos verdaderos para un máximo de f. entonces debería ser claro que f (p) no puede ser un máximo de la función del radio. … Sn } es el valor de f (P). como se muestra en Figure 5. vacíos en que no contiene sitios en su interior.13 (baje círculos). la curva de intersección de dos conos represe la distancia de los sitios para puntos en la bisectriz. Por eso la p no pudo haber sido un máximo local de f. y más grande que no hay otro semejante con estrictamente radio mayor.4. Nota que esa suposición de que p es estrictamente interior para el buque garantiza que hay una p ' como esa también en H.4. asumamos temporalmente a esta subdivisión que la p es estrictamente interior para H.1 el problema de encontrar el círculo vacío más grande entre un conjunto S de sitios: El centro de tal círculo es una buena localización para una tienda nueva.

entonces el movimiento de p en cualquier dirección resulta en moverse p más cercano para algún sitio.3). Note que no es necesariamente cierto que cada vértice de Voronoi represente un máximo local de f (p) (el Ejercicio 5. La razón que nuestras anteriores discusiones no ejercen es esa moviéndose p para p ' el movimiento fuera del buque. Juan Carlos Gutiérrez Barquero____________________________________________ 201 . ningún punto interior de la bisectriz es un máximo local: La distancia aumenta de una dirección o otra. Nosotros ahora hemos establecido este hecho: Lema 5. y así disminuir a f (P). Es única cuando el círculo incluye tres sitios que f (P) pudo estar en el máximo.5. Si lo tres sitios “entrecruzados” el centro p.6[5 ] ). en el sentido que hizo girar más que lo que un semicírculo (como en Figure 5.Bismarck Salvador Traña López__________________________________________ UNI hipérbola ascendente. y nuestra especificación problemática restringieron centros para el buque. entonces la p debe ser coincidente con un vértice de Voronoi. Nosotros ahora discutimos aún más informalmente que por encima de que un círculo máximo debe incluir dos sitios.5.3 Si el centro p de un círculo vacío más grande es estrictamente interior para el buque de la sitio H (S). Centro dentro del convexo Ahora consideremos que el circulo de centro p está en el buque H =H(S).

Juan Carlos Gutiérrez Barquero____________________________________________ 202 . Así adecuadamente podría ser que f (P) está en el máximo. Entonces moviendo p en uno u otro caso a lo largo de h debe aumentar su forma de distancia s1.Bismarck Salvador Traña López__________________________________________ UNI Supongo que f (p) es un máximo con p en H y el círculo incluye justamente s1 de sitios. Si. Primero. cortado en rodajas por un plano vertical (la Figura 5. Hemos mostrado este hecho: Lema5. Entonces p debe permanecer sobre un borde Voronoi.9). y esto implicaría a esa f (P) = 0. sin embargo. entonces es posible que la dirección a lo largo de la bisectriz de los sitios que aumenta sus distancias sea la dirección que va fuera del buque. Así es que p está en el interior de un borde de H. pues los vértices de H es todos los sitios mismos. que no puede ser esa p está en un vértice de H.5.4 si el centro p de un circulo vació mas grande permanece en el buque de sitios H (S). el círculo centró en p contiene s1 de dos sitios y s2.

la intersección del con el límite del buque.14). Para v del vértice Voronoi haga Si la v está dentro de H: V ∈ H entonces El radio de cómputo si el grupo cerrado de gente giró alrededor de v y actualización llega al límite. El algoritmo: círculo Vacío MÁS GRANDE Computar el diagrama Voronoi V (s) de la S de sitios. pero localizar un vértice Voronoi en H e intersecar un borde de Voronoi con e puede estar consumado en el tiempo O (log n).5. Dejamos Detallamos para ejercitar a 5. Note que no cualquier vértice de Voronoi está necesariamente dentro del buque (la Figura 5. Juan Carlos Gutiérrez Barquero____________________________________________ 203 .1. Para cada e del borde Voronoi haga El cómputo p =e ∩ ∂ H. El regreso llegue al límite. que necesita comprobar que v ∈ H dentro del algoritmo.6[6. Computar el buque convexo H=H (S). El radio de cómputo de círculo giró alrededor de actualización de la P llegue al límite. y estas eficiencias conducen a un algoritmo O (n log n) en conjunto.Bismarck Salvador Traña López__________________________________________ UNI El algoritmo Nosotros ahora hemos establecido nuestro meta: Ha encontrado un grupo finito de punto que son centros potenciales de círculos vacíos más grandes: Los vértices de Voronoi y las intersecciones entre bordes de Voronoi y el buque de sitios. Esto sugiere el algoritmo 5. Una implementación ingenua de este algoritmo requeriría el tiempo cuadrático en n. debido a Toussaint (1983a).

Bismarck Salvador Traña López__________________________________________ UNI

Lo mínimo que se extiende a lo largo un árbol. Lo mínimo que se extiende a lo largo un árbol. (MST)(A minimum spanning tree) de un grupo de puntos es la longitud del arbol que se extiende a lo largo de todos los puntos: es decir en árbol más pequeño cuyos nodos son precisamente esos en el grupo. Cuando el largo de un borde es medido por la longitud usual del segmento Euclideano conectando sus puntos finales, el árbol es a menudo llamado el Euclideano mínimo extendiéndose a lo largo de árbol, abreviado a EMST. Aquí sólo considerarán las longitudes Euclideano y así también dejarán caer al modificador redundante. Un ejemplo es mostrado en Figure 5.15. MST tienen muchas aplicaciones. Pues el ejemplo es la topología de la red que minimiza la longitud total del alambre que usualmente minimiza ambos costo y el tiempo que se demora. Algoritmo de Kruskal Aquí consideraremos el problema de computar el MST de un grupo de puntos en el plano. Veamos primero el problema más general de computar el MST para una gráfica G. Aunque es de ninguna manera obvio, una estrategia ávida sin discernimiento es encontrar al MST, basada en la intuición simple que un árbol más pequeño debería estar cercano de los bordes más pequeños. Esto sugiere que puede estar tal árbol construido arriba del incrementalmente añadiendo borde más pequeño, todavía ningún explorado, lo cual también mantiene un arbolado (alifaticidad). Este algoritmo es conocido como el algoritmo de Kruskal y se publico en 1956. Sea T el árbol incrementalmente construido, y sea la notación T + e quiere decir que el árbol T une el borde e. El algoritmo Kruskal se muestra en Algoritmo 5.2. No nos detendremos para probar este algoritmo,¿ esta bien?. pero sólo demanda que su complejidad se domina por el primer paso ordenando. Esto requiere (E log E) de tiempo, dónde la E es el número de bordes en la gráfica.

El algoritmo: El ALGORITMO DE KRUSKAL Ponga en cortocircuito bordes de G por el largo por ahí: E1, e2 Inicializar T para que este vacío Mientras la T no avanza a rastras haga Si T + e1 es acíclica Entonces T + T + ei Juan Carlos Gutiérrez Barquero____________________________________________ Ii + 1 El algoritmo 5.2 el algoritmo de Kruskal.

204

Bismarck Salvador Traña López__________________________________________ UNI

MST ⊆ D (p) Para el MST de puntos en el plano, hay ( n ) bordes, así es que la complejidad 2 del paso de clasificación es O (n2 log n) si es cargada fuera en la gráfica completa. Para llamar a este registro de los bordes de la triangulación de Delaunay de proximidad en algún sentido, es razonable esperar que sólo los bordes de Delaunay alguna vez necesiten ser usados para construir un MST. Y afortunadamente esto es cierto, como se muestra en el siguiente teorema. Teorema 5.5.5 Lo mínimo que se extiende a lo largo un árbol es un subconjunto de triangulación Delaunay: MST D (p). Prueba. Queremos mostrar que si ab ∈ MST, entonces ab ∈ D. Implica that ab ∈ MST y suponga lo contrario que ab ∉ MST. Entonces tratamos de derivar una contradicción enseñando lo que se supuso MST no es mínimo. Recuerde que si ab ∈ D, entonces hay un círculo vacío a través de a y b (Propiedad V7 y Teorema 5.3.1) .en caso contrario ab ∉ D, ningún círculo a través de a y b puede estar vacíos. En particular, el círculo de diámetro ab debe de tener un sitio dentro de este. Así se supone que C está en este círculo, como se muestra en figura 5.16. Entonces | ac | < | ab |, y |bc|< |ab|; Estas desigualdades tienen aplicación aun si C está en el círculo, puesto que la C es distinta de a y b. La extracción de ab desconectará el árbol en dos árboles internos, con a en primera parte, Ta, y b en el otro, Tb. Suponga sin la pérdida de generalidad que e esta en Ta. Elimine ab y añada el borde bc para hacer un árbol nuevo, T’ = Ta bc +Tb. Este árbol es mas corto, así el único único usado ab, no podría serminimo. Hemos alcanzado una contradicción negando que ab está en D, así es que debe ser ese ab D.

Juan Carlos Gutiérrez Barquero____________________________________________

205

Bismarck Salvador Traña López__________________________________________ UNI

Esto entonces produce una mejora en el primer paso de algoritmo de Kruskal: Primero encuentre la triangulación de Delaunay en el tiempo O (n Long n), y entonces clasifique sólo esos bordes O (n), en el tiempo O (n logn). Resulta lo demás de algoritmo de Kruskal puede ser implementado para poner a funcionar en O (n log n), para que la complejidad total por encontrar el MST para el grupo de n untos en el plano es O (n log n). 5.5.5. El Problema del Vendedor de viajes. Uno de los problemas más estudiados en la informática es el problema del vendedor de viajes: Encuentre el más pequeño camino cerrado que visita cada punto en un grupo dado. Tal camino se llamado El camino Vendedor de viajes(TSP); imagine los puntos como ciudades que el vendedor debe visitar en el orden arbitrario antes de devolver casa. Este problema tiene tremenda importancia práctica, no sólo para esa aplicación si no porque muchas otras problemáticas pueden reducirse a él. Se ha probado que desafortunadamente, el problema es duro NP, un término técnico que ningún algoritmo polinómico conoce para resolverlo (Garey y Johnson 1979); Ni parece probablemente al momento de escribir la presente que a ser encontrada. Las combinaciones de significado práctico y la inflexibilidad han conducido a una búsqueda para los algoritmos de heurísticas efectivos y de aproximación. Uno de los algoritmos de la aproximación más simples es basado en la triangulación de Delaunay, Vía lo mínimo que Se extiende a lo largo el árbol. La idea es más bien algo simple, pero no obstante hace un trabajo razonable. Encuentra al MST para el grupo de puntos, y simplemente lo lleva cabo y lo allá por la manera ilustrada en Figure 5.17. Debería estar claro que la excursión construida por aquí tiene exactamente dos veces el largo del MST, desde que cada borde del árbol se cruza una vez en cada dirección.

Juan Carlos Gutiérrez Barquero____________________________________________

206

Bismarck Salvador Traña López__________________________________________ UNI

Ahora obtenemos un límite dentrote que esta mal este doble-MST recorrido podría ser. Sea M la longitud de Lo mínimo que se extiende a lo largo un árbol y M2 la longitud de a doble-MST; claro M2 = 2M. Sea T la longitud de El camino de un Vendedor de viajes r y T1 la longitud de un TSP con un borde removido. Note que T1 se extiende a lo largo del árbol.

Las siguientes desigualidades son inmediatas: T1 < T, M ≤ T1, M < T, M2 < 2T. Esto entones logra un límite superior constante en la calidad del recorrido: Lo doble-MST no está peor que dos veces la longitud de TSP.

Juan Carlos Gutiérrez Barquero____________________________________________

207

pero una variación leve Conocido como las gamas “Heurísticas Christofides”. Esbozaré sólo el más simple tan heurístico. Note que el camino fue acortado. dónde la p son optativo para cualquier ∈ . Encuentran un ejemplos que muestre ese NNG pueden ser un subconjunto correcto de D (p). eso es. Ponga a prueba a Lema5. Heurístico puede ser único acorta el camino. 2. Más heurísticos sofisticaron generalmente encuentran un camino dentro de un poco porcentaje óptimo (Bentley 1992). Los Números de triángulos en una estrangulación. con la modificación que si el próximo sitio ya se ha visitado hasta ahora por el camino.1: Si la b es una vecina próxima de a.6 Los ejercicios 1. Esto hace el efecto de tomar una ruta más directa para recorrer MST . …. El recorrido del camino doble-MST de entrada. Usa un grupo de segmentos llamados un “El mínimo de Euclideano emparejando” como un guía para atajos y puede garantizar un longitud del camino no más de (3/2) T. NND D. considerando que el recorrido doble-MST sigue un camino encorvado Si. Entonces ab D (p). Desafortunadamente este heuristico no garantiza un desempeño mejorado. El grado de NING.5. Sj-1. no más de 50 % más largo que lo óptimo. El vértice de Voronoi no un máximo local. en un tiempo O (np). puede ser esperanza para un problema completo a NP. lo cual se basa en la determinación comprensible para no volver a visitar un sitio dos veces. Un resiente descanso teórico es sin dudarlo el esquema de aproximación de Polinomio-tiempo para el TSP. 5. Si+1 . Un ejemplo es mostrado 5. ¿Cuál es grado mínimo de salida de un nodo de un Grafico de vecino mas cercano(NING) (la Sección 5..1) de n puntos en dos 2 dimensiones? ¿Cuál es el grado máximo de un nodo? Demuestran ejemplos que justifiquen su respuesta.5. Construya un grupo de puntos que tiene un vértice de Voronoi estrictamente p dentro del buque. NNG y D [Fácil] . salte el sitio y considera conectarse al próximo uno a lo largo del doble-MST recorrido. acerca de lo mejor. proporcionales para 1/ 5.Sj. Vea a Arora (1996) y Mitchell (1996). algo Juan Carlos Gutiérrez Barquero____________________________________________ 208 . Éste es un método de llegar dentro (1 + ∈ ) de ∈ > 0. 4. e intento probar que son máximos.5. aunque este desempeño no está garantizado en su estado actual para el algoritmo citado anteriormente. Comprobar que el número de triángulos t en cualquier triangulación de algún grupo de puntos reparados S esat una constante toda triangulación de S tiene la misma t. Si ponemos en un índice los sitios por el orden en que ellos se visitan a lo largo del recorrido del MST.18.Bismarck Salvador Traña López__________________________________________ UNI Este resultado puede ser mejorado con heurísticas diversas. a algunos sitios que Si podría conectar para Sj por un segmento de la línea recta o un atajo al recorrido. 3.

no a diferencia del Teorema 5. Diseñe un algoritmo “de fuerza bruta” para construir al RNG. si |Pi + Pj| ≤ max { | Pi + Pm |. y con Pi de dos nodos y Pj conectado por un arco ellos son para que no acerca de cualquier otro punto.) Esta ecuación determina una región “ prohibida ” dentro de la cual ningún punto Pm puede mentir si Pi y Pj son adyacentes en el RNG. 8. j (Vea Jaromezyk + y Toussaint (1992).5).5. el cual es el lugar de puntos geométricos que no tienen un único vecino cercano. No se preocupe por eficiencia. Ponga a prueba a ese RNG: Cada borde del RNG es también borde de la triangulación de Delauny. son la intersección de dos discos abiertos centradas en Pi y Pj. análogamente y para la versión de Dos dimensiones (bidimensional): Es el dual de V (p). El tamaño de triangulación de Delaunay en tres dimensiones. Pj). eso es.…. El Gráfico del Barrio relativo (RNG) de juego de puntos P1.3.Bismarck Salvador Traña López__________________________________________ UNI semejante que f (p) no es un máximo local. m ≠i . a. Juan Carlos Gutiérrez Barquero____________________________________________ 209 . c. y b El n/2 puntos uniformemente distribuidos en el origen del eje z simétrico al origen.3 6. O (n). Use (b) diseñar un algoritmo más rápido. donde la f es función del radio definido en la sección 5. El algoritmo del círculo vacío. ¿Qué es su complejidad de tiempo? b. Sostenga la opinión que el tamaño de D (p) es Ω (n2). El detalle (en el código pseudo) cómo llevar a cabo el algoritmo del círculo vacío (Algoritmo 5.1 Esta región. Mostrar que esto no se mantiene en tres dimensiones: El tamaño de D (p) puede ser cuadrático.. llamada Lune ( Pi. Defina a D (p) en tres dimensiones exactamente. Tenemos que mostrar cual es el tamaño de la triangulación de Delaunay adentro de dos dimensiones es lineal.| Pi + Pm | }. (Compárese con Teorema 5. Sea P un punto determinada consistente en dos partes: a El n/2 puntos uniformemente distribuidos alrededor de un círculo en el plano x y centrados en el origen. Pn es un gráfico cuyos nodos corresponden a los puntos. ambos de radio | Pi – Pj |. 7.5.1) con el fin de que su complejidad de tiempo es O (n log n).

5.Bismarck Salvador Traña López__________________________________________ UNI 9.19 para ayudar a formar a hipótesis Juan Carlos Gutiérrez Barquero____________________________________________ 210 . Los puntos con el vecino mas cercano de una region de voronoi mas remota.2. Los puntos con dos vecinos mas lejanos limitan con forma de bordes F (P). ¿Cuál es F (P) para tres sitios? c. 10. Defina el diagrama de puntos más remotos de Voronoi F (P) asociado cada punto del plano para el sitio que es su “vecino más remoto”. Que es F (P) para dos sitios? b. Uso Figure 5. Confirmar esta conjetura es un problema. Pero parece que este salto superior es débil: Jaromezyk y Kowaluk (1991) suponen que el tamaño es O (n). Uso 5. parecido al Delaunay y Voronoi en Sección 5.3.19 y 5 5. a. El tamaño del gráfico del barrio relativo (RNG) en dimensiones del árbol.19. Derive algunas propiedades estructurales de diagrama más remoto Voronoi. y esta relación contiene dimensiones arbitrarias.3. Ejercicio[7] anteriormente establecido ese RNG D (P) en dos dimensiones. el sitio que está más lejos (fuera). así es que es más pequeña que la triangulación de Delaunay. MST ⊆ RNG Pruebe que cada borde de un MST es un borde del RNG.1 y 5. Los puntos más remotos de Voronoi.2. Vea Figura 5. Se ha demostrado el tamaño que tiene el RNG en dimensiones del árbol es O (n3/2) (Jaromezyk y Toussaint 1992).3.5) 11. (Compárese con Teorema 5.

Ejes Medios El diagrama de Voronoi puede ser generalizado en varias direcciones. que están dentro de un grupo de puntos internos P que un punto bien cerrado entre los puntos de ∂ P. En esta sección tocamos una generalización. cada punto sobre el segmento horizontal dentro del rectángulo está equidistante de los puntos verticales de arriba abajo y están por encima y por debajo de los lados del rectángulo. Juan Carlos Gutiérrez Barquero____________________________________________ 211 .20 definimos el diagrama de Voronoi como el grupo de puntos cuyo sitio más cercano no es único.20. Muestre cómo el círculo más remoto del radio – el diagrama del punto de Voronoi puede usarse para computar lo más pequeño – que rodea un grupo dado del punto. y algunas de estas generalizaciones tienen importante significado práctico. en particular el límite continúo de un polígono. Asuma que F (P) está disponible. Define los ejes medios de un polígono P. L Mínimo que se expande a lo largo de un Círculo. El eje medio de un rectángulo se muestra en la figura 5. Estos puntos son equidistantemente mejor cerrados en dos o más sitios. Una definición muy similar puede ser usada para una colección de puntos arbitrarios. Cada punto sobre un segmento diagonal esta equidistante de dos lados adyacentes del rectángulo y los dos puntos finales del segmento horizontal están equidistante de tres lados del rectángulo. una de las más simples: aceptando un grupo de sitios que son un grupo infinitos de puntos. pero aquí examinaremos solo el caso donde los puntos forman el límite de un polígono.Bismarck Salvador Traña López__________________________________________ UNI 12. En la sección 5.

todos de cuyas fronteras son compensaciones interiores por una distancia fija. Uno puede suponer a partir de este ejemplo que el eje medio del polígono convexo P está un árbol cuyos permisos son los ejes de P. Expandidas o externas compensaciones cuentan en la versión exterior del eje medio. El proceso de transformación dentro de los ejes medios son en ocasiones llamados “Transformación de Bosques Quemados” por si una imagen del polígono P tal como un césped seco que alumbra con un fuego a los bordes de P. Los ejes medios fueron introducidos por Blum en 1967 para el estudio en forma biológica.1 debería ser evidente. ocho vértices en un polígono convexo. el observo de manera semejante a un esqueleto (eje) las amenazas bajo el medio (mediana) de alguna forma. Puede ser usada para calcular una compensación interior de un polígono. donde la tolerancia de ingeniería es llevada naturalmente a formas de compensación. La conexión entre esta analogía y la quema del bosque discutido en la sección 5. todo esto causará que queme todo dentro de el a una velocidad uniforme y los ejes medios sean el grupo de puntos extintos donde el fuego conozca al fuego de otra dirección. A veces los ejes medios de P están definidos como el sitio central de los círculos máximos: los círculos dentro de P estos no son los mismos encerrados en algunos otros sitos dentro de P.Bismarck Salvador Traña López__________________________________________ UNI Un ejemplo mas completo se muestra en la figura 5. Esto es un porcentaje verdadero y está realmente lleno de polígonos no convexos. Esta es menos aparente para un polígono convexo que para un no convexo y formas planas que era el principal interés de Blum.21.22. Juan Carlos Gutiérrez Barquero____________________________________________ 212 . uno puede caracterizar la forma de cierta sección de la estructura de estos ejes medios y esto va incluido un interés considerable entre los investigadores en el reconocimiento de patrones y visiones de computadoras. los vértices de los ejes medios están en el centro de los círculos tocando tres puntos distintos del limite como se muestra en la figura 5. por ejemplo bookstein lo usa para caracterizar las diferencias entre los huesos de la mandíbula normales y los deformados. Calcular compensaciones es un importante problema en la manufacturación. Todo punto de los ejes medios está en el centro de un circulo que toca el límite de los puntos más lejanos y así es como los vértices de Voronoi están en los centros de los círculos tocando tres sitios.

Ejercicios • Eje medio de un polígono no convexo. Para polígonos convexos. 0 (n) veces es suficiente.Bismarck Salvador Traña López__________________________________________ UNI El eje medio de un polígono de n vértices puede ser construido en 0 (n log n) time. asintoticamente menor pero más prácticos de logaritmos están disponibles. ¿Qué puedes decir acerca de la forma funcional de estas curvas? Juan Carlos Gutiérrez Barquero____________________________________________ 213 . Mostrar por ejemplo que el eje medio de un polígono no convexo puede contener segmentos curvados.

pero hay mucho más aquí que esta observación trivial que puede ser aclarada con la consideración de las tangentes a la parábola. Aurenhammer & Gärtner. pero compuesta de segmentos rectos incluso para polígonos no convexos. Claramente la triangulación unidimensional de Delaunay es simple el camino conecta x1 a x2 a… xn . el poligono se agrieta y el proceso de encogimiento de las piezas continúa. Estructura recta. Estos puntos pueden ser vistos como una proyección de la ascendencia de x en la parábola z= x2. vía tridimensional hulls triangulación unidimensional de Delaunay. introdujo una estructura que es similar al eje medio. Mover cada borde de un paralelo al mismo interior a una velocidad constante con bordes adyacentes encogiendo y creciendo así que los vértices viajan a lo largo del ángulo bisector. Juan Carlos Gutiérrez Barquero____________________________________________ 214 . Cuando un borde se encoge hasta la longitud cero. x2i). Describe lo que debe parecer el eje medio de un polígono. Aichholzer. Alberts. X. Forma algunas suposiciones acerca de las propiedades de la estructura recta. Eje medio de un polígono. pero veremos que esto es una proyección sobre el eje x de un conjunto de puntos bidimensionales con coordenadas (xi.xn} un conjunto de puntos sobre el eje x. Empezaremos en una dimensión donde la matemática es transparente sea P= {x1. sus bordes vecinos se hacen adyacentes. tanto como el borde más alto del hull es descartado.Bismarck Salvador Traña López__________________________________________ UNI • Eje medio y el diagrama de Voronoi o hay alguna relación entre el eje medio de un polígono convexo P y el diagrama de Voronoi de los vectores de P? Supone algunos aspectos de esta relación y pruébalos y construye contra ejemplos. Cuando un vértice reflejo choca hacia adentro de un borde. Es trivialmente verdadero que el connuex hull de estos puntos bidimensionales proyectado hacia abajo a la triangulación unidimensional de Delaunay.…. E. Trabaja manualmente la estructura recta con unas formas letras conectadas del alfabeto: T. Entonces esta conexión nos dará un método fácil para calcular la triangulación de Delaunay y del diagrama de Voronoi. Conexión con el Convexo Hulls El 1986 Ellels Brunner & Seidel decubrió una bella conexión entre la triangulación de Delaunay y el convex hulls en una de las más altas dimensiones: primero explicaré entre el convex hull bidimensional y la triangulación unidimensional de Delaunay (que son admitimademente triviales) y entonces generaliza la triangulación bidimensional de Delaunay y el tridimensional convex hull.

yi.23 con a= 5 y r= 3 así que el disco es el segmento [2. Esto es ilustrado en la figura 5. De esta manera la ecuación de la tangente a la parábola en el punto (a. yi) | (xi. a2) es z-a2= 2a (x-a) z= 2a x-a2 En preparación para estudiar el mismo proceso en tres dimensiones.Bismarck Salvador Traña López__________________________________________ UNI La pendiente de la parábola z= x2 en el punto x= a es 2a (porque dz/dx= 2x).8]. El paraboloide es z= x2 + y2. (Ver la figura 5. eso es. Cuando la tangente es aumentada por esta cantidad su ecuación se convierte en z=2a x-a2 + r2 Entonces la tangente aumentada intersecta la parábola en + r lejos de a. trazar cada punto como sigue: (xi.24) toma los sitios/puntos dados en el plano y los proyecta hacia arriba hasta que toca el paraboloide. ahora investigaremos la intersección entre esta tangente y la parábola cuando la tangente es trasladada verticalmente una distancia r2. Triangulación Bidimensional de Delaunay Repetimos el mismo análisis en dos dimensiones. Nota que x= a + r puede ser pensado como la ecuación de un circulo unidimensional de radio r centrado en a. x2i + y2i) Juan Carlos Gutiérrez Barquero____________________________________________ 215 . el punto original de tangencia.

26.25. El reclamo es que esta es una triangulacion de Delaunay. Ver la figura 5. Ahora establecemos esta fenomenal conexión formalmente. Ahora descarta las caras más altas de este hull.Bismarck Salvador Traña López__________________________________________ UNI Toma el convex hull de este conjunto de puntos tridimensionales. b) es z=2a x + 2b y – (a2 + b2) (Esta es una analogía directa a la ecuación z= 2a x – a2: dz/dx= 2x and dz/dy= 2y) Ahora cambiamos este plano superior por r2. La ecuación del plano tangente encima del punto (a. exactamente como cambiamos la línea tangente en la subsección previa z= 2a x +2b y – (a2 + b2)+ r2 (x-a)2 + (y-b2)= r2 Juan Carlos Gutiérrez Barquero____________________________________________ 216 . Proyectar esto al plano xy. en el sentido de times un producto positivo el resultado es una “condra” más baja. Todas esas caras que son exteriores punteando los puntos superiores normales. ver la figura 5.

están más que el r2 arriba.Bismarck Salvador Traña López__________________________________________ UNI El plano cambiado intercepta el paraboloide en una curva (una elipse) que proyecta a un círculo. Por eso el círculo determinado adentro de los planos x y está vacío en todos los otros sitios. Comience con el plano t contiguo para el paraboloide por encima de p = (a. entonces en algún punto cesará de intersecar el paraboloide. Si traducimos verticalmente hacia abajo. Entonces podemos observar como un cambio ascendente de este plano contiguo. Por eso cada cara triangular inferior del buque convexo es propia de un triángulo Delaunay. Ahora debería estar claro que el análisis previo tiene aplicaciones. pk) que forma una cara del buque de convexo en tres dimensiones.27 y 5. ¡Por eso la proyección del “fondo” del buque convexo se proyecta para la triangulación Delaunay! Otra vez evacue a Figure 5. b. Desde que están arriba π .28.26. Por eso forma un triángulo Delaunay. b). Considere el plano π a través de tres puntos en el paraboloide ∆ = ( pi. pj. Cuando los t golpes una punto q en el paraboloide que esta por encima de un sitio. La proyección de su intersección con el paraboloide es un círculo en expansión puesto en el centro en p. Ahora revisemos desde un punto de vista para dirigirnos s la triangulación Delaunay. todo las otras puntos del paraboloide están arriba. Su punto de contacto se proyecta hacia abajo para p. cuál es el r2 debajo. Digamos que el último punto que toca es (a. a2 b2). Llame a la cantidad de cambio r2. cuándo atraviese los tres sitios cuya proyección forma la cara ∆ del buque del triángulo soportada por π . Así el círculo está vacío t hasta π los límites exteriores. las intercepciones del círculo en expansión en el sitio en el plano que es la proyección de q. Por eso estos puntos se proyectan fuera del círculo de radio r en el plano x y. Ahora muévase t arriba. Desde ∆ esta en una cara inferior del buque. Este plano parte de la paraboloide. Un corolario útil para el debate citado anteriormente es éste: Juan Carlos Gutiérrez Barquero____________________________________________ 217 . Esto es ilustrado en la figura 5. Déjeme explicar esta compenetración importante otra vez de otra manera.

7.z*/ Juan Carlos Gutiérrez Barquero____________________________________________ 218 .y.1 en parte como la curiosidad.1 Cuatro puntos (xi.7. esto significa que la triangulación de Delaunay puede ser computada en el mismo tiempo límite. xi2 yi2) en un plano. i = 1. Esto conduce a otro algoritmo O (n log n) para construir el diagrama de Voronoi.2 el código conciso permite increíblemente computar la triangulación de Delaunay.z[MAX]. La coplanaridad de estas puntos puede ser comprobada viendo si el volumen del tetraedro que determinan (la Ecuación 1. /*Intreda de puntos x. yi). Desde que el buque convexo en tres dimensiones puede ser computado en el tiempo O (la Sección 4. De hecho. La implementación de la Triangulación de Delaunay: El código O (n4) Teorema 5. yi. es relativamente fácil computar el diagrama Voronoi (el Ejercicio 5.Bismarck Salvador Traña López__________________________________________ UNI Corolario 5.2. si O (n4) es aceptable (y raramente lo es). entonces la triangulación de Delaunay puede ser computada con menos esas treinta líneas de código de la C! Esto es presentado en código 5. En general.7. consisten en una mentira del círculo si (xi.15 y 4.2 La triangulación de Delaunay de un grupo de puntos en dos dimensiones es precisamente la proyección para el Plano x y del buque convexo inferior de lo transformado apunta en tres dimensiones. Una vez que la triangulación Delaunay está en tus manos. 3.y[MAX].6) es cero. esta relación entre diagramas Voronoi y podría abombar buques que yo una dimensión más alta mantengo en dimensiones arbitrarias. 2. si uno es indiferente sobre la complejidad de tiempo ¡En particular. pero también a enfatiza cómo la comprensión profunda de geometría puede conducir al código limpio. Como se podría esperar. puede ser que el más uso común de código del buque del 4D es para construir mallas sólidas de Delaunay tetraédrico. Así ambos el diagrama Voronoi y la triangulación Delaunay en tres dimensiones pueden forjarse de un buque convexo en cuatro dimensiones.7. transformado por mapeo arriba para el paraboloide z = x2 y2. La implicación Teorema 5. 4.2) (n log n). main() { int x[MAX].5[2 ] ). el diagrama de Voronoi dual para un grupo de puntos de d-dimensional es la proyección del buque “ inferior ” de puntos en d + 1 dimensión.

i++) for(j=0.+ } } La estructura O (n4) del código es evidente yo los cuatro de para lazos anidados.j. (i. k).&n). j.k).&x[i]. int i.k)*/ flag=flag&& ((x[m]-x[i]*xn+ (y[m]-y[i]*yn+ (z[m]-z[i]*zn<=0. /*Numero dep puntos introducidos*/ /*induce de cuatro puntos*/ /*localizacion normal de (i. Si es así. z[i]=x[i]*x[i]+y[i]*y[i]. } /*por cada tres (i. el programa revisa y ve si todos los otros puntos m están o por encima del plano conteniendo i.m++) { /*revizar si m se acerca (i.j<=n-2.j.m.k.2 debería ser evidente). k) es salida como triángulo Delaunay. i<n. y k. /*solo examina las caras del boton de la paraboloide zn <0*/ if(flag==(zn<0)) /*para otro punto m*/ for(m=0.k++) if(j!=k) /*computar la triangulacion normal*/ xn=(y[j]-y[i]*z[k]-z[i])-(y[k]-y[i]*z[j]-a[i]). Juan Carlos Gutiérrez Barquero____________________________________________ 219 .j++) for(k=0.j. zn=(x[j]-x[i]*y[k]-y[i])-(x[k]-x[i]*y[j]-y[i]). j. Para cada triple de puntos (i.i. j.&y[i]).k)*/ /*Intrda de puntos y computar z=x^2+y^2*/ scanf("%d". (La símil arridad para el algoritmo del buque de dos dimensiones en Algoritmo 3.j. if(flag) printf("%d\t%d\t%d\n". int flag.k<=n-2.Bismarck Salvador Traña López__________________________________________ UNI int n. i++) { scanf("%d %d".j.i<=n-2. for(i=0. yn=(x[k]-x[i]*z[j]-z[u])-(x[j]-x[i]*z[k]-z[i]).k)*/ for(i=0.m<n.

pero… 3. (xn.000 tan n tomaba varios días. la m-loop podría quebrarse cuando un punto es descubierto debajo del plano del I. Pues dos prueban carreras con n = 100 y n = 200 puntos.7.000 líneas de ) acerca del razonamiento que entró en Teorema 5. el tiempo de computar fue 12 y 239 segundos respectivamente. de Delaunay dual. Las modificaciones adicionales son relativamente menores. j. representando las dos triangulaciones del cuadrado. La prueba de por encima de plano es realizada chocheando la orientación exterior normal para el triángulo. El código devuelve todos los triángulos dentro de una cara de triangulación Delaunay cuyo límite consta de cuatro o más puntos del cocircular. Obtener más salida útil requeriría el postprocesamiento. Aunque es interesante para ver tal código sucinto computar un propósito guste la triangulación Delaunay.2. Triangulación de Delaunay 3D cáscara: O (el n2) el Código Es una tarea fácil convertir el código cuadrático desarrollado en Capítulo 4 para construir el buque del 3D en el código cuadrático para construir la triangulación Delaunay. Así una mueca cuadrada resulta en salida cuatro de triángulo. Juan Carlos Gutiérrez Barquero____________________________________________ 220 . zn). 2. Hay ineficiencias obvias en el código (por ejemplo. es impráctica para varias razones: 1.Bismarck Salvador Traña López__________________________________________ UNI Triang. La dependencia de tiempo del n4 es inaceptable. con un vector de punto para apuntar m. Estos podrían repararse fácilmente al precio de alargarle un poco. yn. k). exhibiendo un más de 24 incremento de 16 pliegues para el doble número de puntos. Toda la complejidad está en el código del buque (código de casi 1. Esto indica 1.

Como esperada. f->vertex[1]->Vnum. }while(f!=faces). 5. el código más rápido usaron 0. y para las cuales el código del dt2. Como en código secreto 5. este está consumado computando las coordenadas de la z de un vector normal para cada f de la cara. f->vertex[0]->Vnum. esta implementación O (n2) es mucho más rápida que el código O (n4): En la misma n = 100 y n = 200 ejemplos que mientras código más lento usó 12 y 239 segundos. y su proyección encima del Plano x y es un triángulo de Delaunay. Ilustramos con un ejemplo de n = 10 puntos cuyas coordenadas son ostentadas en la tabla 5. Esta parte pequeña que el ejemplo detiene adecuadamente dentro del rango seguro de la computar de volumen discutió comparación para el código del buque del 3D.5 vueltas así de en una O (n log n) esperado algoritmo de tiempo.12). Además.29. después del buque entero se forja. int Flower=0. Si Normz (f) < z. la aceleración del randomizadas discutió en Sección 4.3 segundos respectivamente. Note que las coordenadas de la z son infundidas arriba en la magnitud cuadrando.2 y 1. un procedimiento LowerFaces se siente llamado al lazo sobre todas las fases e identifique cuáles es en la carena (código 5.Bismarck Salvador Traña López__________________________________________ UNI Primer. que la rutina ReadVertices (código 4. entonces la cara está en la carena.2).Flower). La salida Postscript del código es mostrada en Figure 5. } Juan Carlos Gutiérrez Barquero____________________________________________ 221 . El rango de dt2. Esta computar. En segundo lugar. encarnado en Normz.c (código 5. } f=f->next.10) debería leer en x.1.c [programación] . /*numero total*/ do{ if(Normz(f)<0){ Flower++. printf("%d lower faces identificada\n". Encuentro un grupo del punto cuyas coordenadas son tan pequeñas como sea posible. void LowerFaces(void) { tFace f=faces.1.5 Ejercicio 1.7. es justamente un cambio leve para Collinear (Código 4. y y computar z= x2 +y2. f->vertex[2]->Vnum).2) devuelve un resultado incorrecto debido al derramamiento del cálculo de volumen.

Modifique el código del dt2. b. } 2. G = 2(A(c1 – b1 ) – B(c0 – b0 )). b.1 Coordenadas de sitios de Delaunay. b=f->vertex[1]. Las coordenadas de la p central = (p0. c=f->vertex[2]. (Vea ejercicio 5.5.Bismarck Salvador Traña López__________________________________________ UNI int Normz (tFaces f) { tvertex a. c. a=f->vertex[0]. p1 = (AF – CE)/G. B= b1 – a1. Hay que repetidamente construir círculos a través de tres puntos dadas a. p0 = (DE – BF)/G. E = A(a0 + b0 ) + B(a1 + b1 ).6 [1]). Incluyendo z= x2 +y2 I 0 1 2 3 4 5 6 7 8 X 31 -13 -63 -5 87 40 23 64 0 Y -76 21 -83 -66 -94 71 -46 -80 -57 X2+y2 6737 610 10858 4381 16405 6641 2645 10496 3249 Juan Carlos Gutiérrez Barquero____________________________________________ 222 . C = c0 – a0. Tabla 5.c para computar el diagrama de Voronoi de la triangulación de Delaunay. F = C(a0 + b0 ) + D(a1 + b1 ). p1) pueden ser computadas como sigue: A = b0 – a0. D à V (P) (P) [programación] . return (b->v[x]-a->v[x])*(c->v[x]-a->v[y])(b->v[y]-a->v[y])-(c->v[x]-a->v[x]). D = c1 – a1. c.

8.7) y mostraremos la conexión que se realiza utilizando las ecuaciones mas relevante.8. x(2a – 2b)=a2 – b2. Aunque todo esto se entiende que tienes que esperar al siguiente capitulo (Sección 6. x=(a+b)(a-b) 2(a-b) x= a+b 2 De esta manera la proyección de las intersecciones están adyacentes al diagrama de Voronoi y al grupo de puntos 5.4) siendo x=a y otro siendo x=b: z=2ax-a2 z=2bx – b2 Donde se intersecan resolviendo las ecuaciones simultáneas la solución sería 2ax-a2 = 2bx – b2.2 Diagrama de Voronoi bidimensinal Juan Carlos Gutiérrez Barquero____________________________________________ 223 .1 Diagrama de Voronoi unidimensional Considerando dos tangentes examinadas en la sección 5. 5.1 (ecuación 5.7.Bismarck Salvador Traña López__________________________________________ UNI 9 -14 2 200 5.8 Conexión a arreglos Tenemos que mostrar que la triangulación de Delaunay puede ser derivada de la transformación paraboloide e indican que es fácil de obtener el diagrama de Voronoi si es posible obtener el diagrama de Voronoi directamente de la transformación del paraboloide.

O'Rourke. P. Algorithms and Applications. donde estan a y b y otra donde esta c y b. Si observamos las tangentes opacas planas de z=+infinito (con el paraboloide transparente) debería ser visible en la primera intersección su primera intersección es la bisectriz entre los lugares que generan las tangentes planas la proyección de estas primeras tangentes es precisamente el diagrama de voronoi! También tenemos que recordar la situación al visualizar la proyección de puntos dentro del paraboloide de z=-infinito vea la triangulación de Delaunay la observación de las tangentes planas del paraboloide y estos puntos de z=+infinito vea el diagrama de Voronoi. [3] J. Nievergelt. Widmayer. z = 2cx + 2dy – c2 + d2 ¿donde están los intersectos? Resolviendo la ecuación simultanea 2ax + 2by – a2 + b 2 = 2cx + 2dy – c2 + d2 x(2a – 2c) + y(2b – 2d) = ( a2 . I. [4] F.c 2) + (a2 + b 2 ) Esta ecuación es precisamente la bisectriz perpendicular del segmento de (a. Shamos. Preparata y M. 1985. Algorithmic Foundations of Geographic Information Systems. 1997. 1997.8). Springer-Verlag. Computational Geometry. 1994. Kreveld. Springer. Kreveld. O. Roos. Bibliografía [1] M. 73 Juan Carlos Gutiérrez Barquero____________________________________________ 224 .2) (ecuación 5. P.d) ver figura 5. J.7. Berg.31. Overmars. M. New York. Computational geometry: an introduction. Springer. Cambridge University Press. Computational Geometry in C. T.b) y (c. z = 2ax + 2by – a2 + b 2.Bismarck Salvador Traña López__________________________________________ UNI Considere dos tangentes planas del paraboloide analizado en la Seccion (5. Schwarzkopf. [2] M. M.

Related Interests