Roundrect

El programa 'roundrect' imprime un rectángulo con bordes difuminados (ver figura 1) sobre una superficie gráfica de la biblioteca SDL.

Este documento explica los criterios y estrategias que se adoptaron para desarrollar el programa.

Figura 1

figura 1

¿Como funciona?

La implementación del programa surge de la interpretación geométrica de una circunferencia, específicamente del teorema de Pitagoras. Por esa razón, la forma mas sencilla de comprender el funcionamiento del programa es analizar la estrategia geométrica y luego estudiar el código del programa.

El resultado gráfico está compuesto por una circunferencia dividida en 4 arcos (cuadrantes), que se conectan mediante rectas entre sí (figura 1).

De esta manera el problema inicial se reduce a imprimir los arcos de circunferencia aislados e interconectarlos mediante rectas.

La impresión de rectas no requiere un minucioso análisis previo, posiblemente todas las soluciones al ejercicio implementen la misma metodología:

[...]

for (i = 0; i < ancho; i ++)
	put_pixel (screen, x + i, y, color)

[...]

Soluciones alternativas:

En cambio, la impresión de las esquinas del rectángulo, puede realizarse de muchas maneras diferentes:

Todas las estrategias son válidas, incluso, ninguna es potencialmente mas rápida que otra, la eficiencia de cada solución dependerá en mayor medida de su implementación 1. Por ejemplo, el manejo de funciones trigonométricas no es necesariamente 'lento' si se pre-calculan sus valores inicialmente y se reutilizan constantemente.

Aplicando una estrategia:

Para desarrollar esta solución he utilizado parte del teorema de Pitagoras, partiendo de la ecuación:

r^2 = x^2 + y^2

donde:

es posible construir el arco de circunferencia, asegurando que el punto (x,y) pertenece al gráfico de la curva si verifica la ecuación con un 'r' fijo: "los puntos de una circunferencia se encuentran a la misma distancia del centro"

Un ejemplo, paso a paso:

La figura 2, muestra el seguimiento de impresión de una curva.

Figura 2

figura 2

El proceso comienza imprimiendo el primer punto de la circunferencia en (0, R), en este caso (0, 10), ya que el radio elegido para el ejemplo es 10.

El siguiente punto se encontrará a derecha del primero 2, con x = 1, pero se desconoce su coordenada de posición 'y'. Para ello se busca un valor de 'y' que verifique la ecuación del teorema, y se asegura que el punto (x, y) pertenece al gráfico de la curva.

x^2 + y^2 = r^2
      y^2 = r^2 - x^2
      y   = sqrt (r^2 - x^2)

donde 'x' y 'r' son valores conocidos.

Simetría:

Esta aproximación, donde se asegura que el siguiente punto está a derecha del actual, será válida únicamente para el primer tramo de curva (ver 2). El resto de la curva se obtiene por simetría, evitando resolver nuevamente la ecuación del teorema.

Gráficamente la simetría actúa de "espejo" reflejando las curvas restantes.

En la figura 2 se destacan los puntos que obtenemos mediante la ecuación de Pitagoras de color 'celeste', los puntos que se obtienen por simetría de color 'gris' y el punto que pertenece al eje de simetría de color 'rojo'.

Código fuente:

En la función 'roundrect' se utilizan algunas variables auxiliares para facilitar el cálculo de posiciones, la figura 3 muestra la utilidad geométrica de cada una.

Figura 3

figura 3

Para imprimir las esquinas del rectángulo se calculan las posiciones de cada punto dentro del primer arco de circunferencia, específicamente entre 45 y 90 grados.

A medida que se imprimen estos puntos, el resto de los cuadrantes se imprimen respetando el concepto de simetría.

[...]

for (x = 0; x < y; x ++)
{
	y = (int) sqrt (radio * radio - x * x);

	/* primer cuadrante */
	put_pixel (screen, xb + x, ya - y, color);
	put_pixel (screen, xb + y, ya - x, color);

	/* segundo cuadrante */
	put_pixel (screen, xa - x, ya - y, color);
	put_pixel (screen, xa - y, ya - x, color);

	/* tercer cuadrante */
	put_pixel (screen, xa - x, yb + y, color);
	put_pixel (screen, xa - y, yb + x, color);

	/* cuarto cuadrante */
	put_pixel (screen, xb + x, yb + y, color);
	put_pixel (screen, xb + y, yb + x, color);
}

[...]

El ciclo de repetición (for) termina cuando se alcanza el eje de simetría, marcado con color 'rojo' en la figura 2. Nótese que en ese punto, 'x' tiene el mismo valor que 'y'.

Por último se imprimen las rectas que conectan a los tramos de circunferencia.

Notas al pie:

1 - "dependerá de su implementación...": es mi humilde opinión; considero que la habilidad mas importante de los programadores es su capacidad para proponer, analizar y valorar las diferentes formas de solucionar cada problema. Desmerecer 'a-priori' las alternativas de solución no fomentan el aprendizaje.

2 - "a derecha del primer punto...": esta afirmación sólo se cumple en una parte del primer cuadrante, entre los 45 y 90 grados.


Hugo Ruscitti
26 de Agosto 2005
www.losersjuegos.com.ar