Tuesday, March 9, 2010

Gráficos con Ruby y SVG

Hace un tiempo me puse a jugar con las diferentes formas de hacer gráficos en Ruby. Una de ellas es usando el paquete Tcl/tk, para pintar sobre un canvas en una ventana. Otra forma más interesante que descubrí después, fue por medio del lenguaje SVG. Se escribe un programa en Ruby que genere un archivo en formato SVG, y cuando este se abre con el browser, se puede apreciar un gráfico.

¿Por qué SVG?
* Porque es uno de los estándares de internet,
* porque se puede utilizar en aplicaciones cliente-servidor por internet,
* porque el nuevo HTML5 también tiene soporte para SVG, y,
* porque los nuevos browsers ya implementan soporte para HTML5 y SVG.

SVG es un lenguaje derivado de XML, declarativo, para hacer gráficos de vectores. Define primitivas para hacer líneas, rectángulos, elipses, círculos, etc, que se pueden utilizar para derivar gráficos complejos. Tiene también incluída la capacidad para hacer fills con efectos de luz y sombras (raster effects), texto, fonts, y animación.

Veamos un ejemplo sencillo:


<?xml version='1.0'?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 
  'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>

<svg width='12cm' height='12cm' viewBox='0 0 1200 1200' 
  xmlns='http://www.w3.org/2000/svg' version='1.1'>

<desc>SVG creado con un programa en Ruby.</desc>

<rect x='1' y='1' width='800' height='800' 
  fill='none' stroke='blue' stroke-width='2'/>

<g stroke='green' transform=' scale(3)'>
  <line x1='50' y1='50' x2='50' y2='100' stroke-width='5'/>
  <line x1='50' y1='50' x2='75' y2='25' stroke-width='5'/>
  <line x1='50' y1='50' x2='100' y2='50' stroke-width='5'/>
  <line x1='50' y1='100' x2='100' y2='100' stroke-width='5'/>
  <line x1='75' y1='25' x2='100' y2='50' stroke-width='5'/>
  <line x1='100' y1='50' x2='100' y2='100' stroke-width='5'/>
  <text x='50' y='120' font-size='20' font-family='Verdana'>
    casa1
  </text>
</g>

<g stroke='blue' transform=' translate(200,0) scale(3)'>
  <line x1='50' y1='50' x2='50' y2='100' stroke-width='5'/>
  <line x1='50' y1='50' x2='75' y2='25' stroke-width='5'/>
  <line x1='50' y1='50' x2='100' y2='50' stroke-width='5'/>
  <line x1='50' y1='100' x2='100' y2='100' stroke-width='5'/>
  <line x1='75' y1='25' x2='100' y2='50' stroke-width='5'/>
  <line x1='100' y1='50' x2='100' y2='100' stroke-width='5'/>
  <text x='50' y='120' font-size='20' font-family='Verdana'>
    casa2
  </text>
</g>

<g stroke='red' transform=' translate(400,0) scale(3)'>
  <line x1='50' y1='50' x2='50' y2='100' stroke-width='5'/>
  <line x1='50' y1='50' x2='75' y2='25' stroke-width='5'/>
  <line x1='50' y1='50' x2='100' y2='50' stroke-width='5'/>
  <line x1='50' y1='100' x2='100' y2='100' stroke-width='5'/>
  <line x1='75' y1='25' x2='100' y2='50' stroke-width='5'/>
  <line x1='100' y1='50' x2='100' y2='100' stroke-width='5'/>
  <text x='50' y='120' font-size='20' font-family='Verdana'>
    casa3
  </text>
</g>

</svg>


En el ejemplo anterior se puede apreciar el uso de las primitivas <rect> para dibujar rectángulos, <line> para líneas, <text> para texto; y, <g> para agrupar primitivas bajo un mismo color. Notar también el uso de la propiedad 'transform' para mover y escalar los dibujos. Los lectores cuidadosos habrán notado que las coordenadas de las líneas de las tres "casas" son las mismas. La diferencia está en el uso de la propiedad 'transform'.

El resultado, cuando se ve este archivo con el browser es el siguiente:




Como se puede apreciar, no es difícil generar SVG desde Ruby. Con un poco de imaginación podemos generar gráficos más "sofisticados" tales como los siguientes:

La "Curva Dragón":




Epitrocoides:




Hipotrocoides:




Buscando, me encontré con estos otros módulos para hacer SVG con Ruby, pero no encontré suficiente información para iniciarme con ellos:
* RCairo
* Ruby/RSVG, parte de Ruby/GTK2 (?)
* SVG::Graph
* ruby-svg
* SVuGy

Referencias:
La especificación de SVG, en w3
Curva Dragón, en la wikipedia
Epitrocoides, en la wikipedia
Hipotrocoides, en la wikipedia

No comments: