19 Funciones para el trazado de líneas
El GDI dispone de un repertorio de funciones para el trazado de líneas bastante completo
Función | Tipo de línea |
---|---|
MoveToEx | Actualiza la posición actual del cursor gráfico, opcionalmente obtiene la posición anterior. |
LineTo | Traza una línea desde la posición actual del cursor al punto indicado. |
ArcTo | Traza un arco de elipse. |
PolylineTo | Traza uno o más trazos de líneas rectas. |
PolyBezierTo | Traza una o más curvas Bézier. |
AngleArc | Traza un segmento de arco de circunferencia. |
Arc | Traza un arco de elipse. |
Polyline | Traza una serie de segmentos de recta que conectan los puntos de un array. |
PolyBezier | Traza una o más curvas Bézier. |
GetArcDirection | Devuelve la dirección de arco del DC actual. |
SetArcDirection | Cambia la dirección del ángulo para el trazado de arcos y rectángulos. |
LineDDA | Traza una línea, pero permite a una función de usuario decidir qué pixels se mostrarán. |
LineDDAProc | Función callback de la aplicación que procesa las coordenadas recibidas de LineDDA. |
PolyDraw | Traza una o varias series de líneas y curvas Bézier. |
PolyPolyLine | Traza una o varias series de segmentos de recta conectados. |
La mayoría de éstas funciones no requieren mayor explicación, sobre todo las que trazan arcos y líneas rectas.
Trazado de arcos, función Arc
Para trazar un arco mediante la función Arc, se parte de una circunferencia inscrita en el rectángulo de borde. Los puntos de inicio y final del arco se obtienen de los cortes de los radios definidos por los puntos de radio de inicio y final:
La función ArcTo es idéntica, salvo que se traza una línea desde la posición actual del cursor gráfico hasta el punto de inicio del arco.
Curvas Bézier
Las curvas Bézier son una forma de definir curvas irregulares mediante métodos matemáticos. Para definir una curva Bézier sólo se necesitan cuatro puntos: los puntos de inicio y final, y dos puntos de control.
En el gráfico se representa una curva Bézier y las líneas auxiliares, que sólo se muestran como ayuda. El punto de inicio y el punto de control 1 refinen una recta que es tangente a la curva en el punto de inicio. La curva tiende a aproximarse al punto de control 1.
Análogamente, el punto de final y el punto de control 2 refinen otra recta, que es tangente a la curva en el punto de final. La curva también tiende a acercarse al punto de control 2.
Las ecuaciones que definen la curva no son demasiado complejas, pero escapan al objetivo de este curso, se estudiaran las curvas de Bézier con detalle en un artículo separado.
Funciones Poly<tipo>
Todas las funciones con el prefijo Poly trabajan de un modo parecido. Se basan en un array de puntos para definir un conjunto de líneas que se trazan una a continuación de otra.
Polyline o PolylineTo trazan un conjunto de segmentos rectos, PolyBezier y PolyBezierTo, un conjunto de curvas Bézier. PolyDraw, varios conjuntos de líneas y curvas Bézier, y PolyPolyline, varios conjuntos de líneas rectas.
Función LineDDA y funciones callback LineDDAProc
LineDDA nos permite personalizar el trazado de segmentos de líneas rectas. Mediante la definición de funciones propias del tipo LineDDAProc, podemos procesar cada punto de la línea y decidir cómo visualizarlo. Podemos cambiar el color, ignorar ciertos puntos, y en general, aplicar la modificación que queramos. Esto nos permite trazar líneas de varios colores o con distintas tramas, etc.
Veamos un ejemplo sencillo, definiremos una función LineDDAProc para trazar líneas que alternen 10 pixels rojos y 10 verdes.
struct DatosDDA1 { int cuenta; HDC hdc; }; VOID CALLBACK FuncionDDA1(int X, int Y, LPARAM datos) { struct DatosDDA1 *dato = (struct DatosDDA1 *)datos; // Función que pinta líneas con 10 pixels alternados rojos y verdes dato->cuenta++; if(dato->cuenta >= 20) dato->cuenta = 0; // Mantenemos cuenta entre 0 y 19 if(dato->cuenta < 10) SetPixel(dato->hdc, X, Y, RGB(0,255,0)); else SetPixel(dato->hdc, X, Y, RGB(255,0,0)); }
Hemos definido una función callback para que muestre cada punto en función de los datos almacenados en una estructura DatosDDA1, diseñada por nosotros. En ella almacenamos un valor "cuenta" que nos ayuda a decidir el color de cada pixel, y un manipulador de DC para poder activar pixels, usando SetPixel, en la ventana:
... struct DatosDDA1 datos = {0, hDC}; LineDDA(10,10, 240,180, FuncionDDA1, (LPARAM)&datos); ...
Ahora podemos llamar a la función LineDDA, indicando los puntos de inicio y final de la línea, la función que usaremos para decidir el color de cada punto, y un puntero a la estructura de datos que esa función necesita.
Ejemplo 17
Basándonos en el último programa de ejemplo, vamos a hacer otro que muestre cada una de éstas funciones y cómo se usan.
Añadiremos un menú para poder ver cada función por separado.
Nombre | Fichero | Fecha | Tamaño | Contador | Descarga |
---|---|---|---|---|---|
Ejemplo 17 | win017.zip | 2004-01-18 | 3532 bytes | 775 |