Gráficos con pikchr
En el blog ya he hablado de pikchr
y en ese artículo podéis ver lo
básico del sistema. Lo traigo de nuevo porque escribiendo unos apuntes
para impartir un curso lo he utilizado con profusión y estoy
maravillado de sus posibilidades. Es una de esas herramientas que me
encontré buceando por el mundillo1 de Tcl/Tk, SQLite y Fossil.
Como sabéis, porque lo he contado innumerables veces, suelo generar
mis cosas siempre a partir de texto plano. Concretamente, utilizo el
org-mode
de Emacs para ello. Los bloques de código que proporciona
dicho modo son una herramienta increíble para realizar también los
gráficos utilizando texto plano con herramientas como GraphViz-Dot o
PlantUML. Sin embargo, con dichas herramientas no puedo hacer todos
los gráficos que necesito. En muchas ocasiones recurría a Inkscape
para generar un archivo SVG
e incrustarlo en el documento. Lo que era
un incordio, porque tenía que abrir dicho programa para dibujar y
echaba de menos la agilidad que me proporcionan graphviz
y plantuml
.
Conocía pikchr
, pero no había pasado de hacer algunas pruebas y poco
más.
Por ejemplo, estoy con la documentación de un curso sobre conflicto y negociación. El resumen gráfico en el tema de las fases de un conflicto es el siguiente2:
$fase = 1.25 define flecha { line up 1cm right 1cm \ left 0.25cm up 0cm \ left 0.25cm left 0 \ up 1.2cm left 1cm \ up 0 down 1.2cm left 0 \ up 0 left 0.5cm \ close fill 0xfaafc1 } # Marcos para las fases down box width 10cm height $fase fill 0xacc9e3 box same fill 0xc5d8ef box same as first box box same as 2nd box box same as first box line from 1st box.sw+(0.2,0) up until even with 1st box.n "Fase I" above aligned line from 2nd box.sw+(0.2,0) up until even with 2nd box.n "Fase II" above aligned line from 3rd box.sw+(0.2,0) up until even with 3rd box.n "Fase III" above aligned line from 4th box.sw+(0.2,0) up until even with 4th box.n "Fase IV" above aligned line from 5th box.sw+(0.2,0) up until even with 5th box.n "Fase V" above aligned # Rellenar la Fase I up; move 4.6 right; move 0.2 F1a: box ht 0.3 wid 1.3 rad 6px fill white thickness 1px "Antecedentes" big arrow right 100% F1b: "Condición germen" move 100%; down; move 75% F1c: box ht 0.3 wid 1.24 rad 6px fill 0xaa92ef "Condición necesaria" "No suficiente" spline thin right 0.4 -> from F1b.e to F1c.n color 0x888888 # Rellenar la Fase II F2a: box same as F1a at 3.1cm south of F1a "Personalización" big arrow <- from F2a.ne to F1b.s "percepción" aligned "conflicto" aligned color 0x888888 F2b: box same as F1c at 3.1cm south of F1c "Delimita los temas" "del conflicto" F2c: "Emociones" "Sentimientos" at 3.1cm south of F1b arrow from F2a.e to F2c.w spline thin right 0.5 -> from F2c.e to F2b.n color 0x888888 # Rellenar la Fase III F3a: box same as F2a at 3.1cm south of F2a "Intenciones cta." big arrow <- from F3a.ne to F2c.s "generan" above aligned color 0x888888 F3b: box rad 6px ht 0.2 wid 1 fill 0xaacaff with .c at (4.8cm, -5.3cm) "Intención de competir" small down F3c: box same as F3b "Intención de colaborar" small F3d: box same as F3b "Intención de ceder" small F3e: box same as F3b "Intención de evadirse" small F3f: box same as F3b "Intención de compromiso" small spline -> thin right 1.5cm from F3a.e to F3b.w color 0x888888 spline -> thin right 1.5cm from F3a.e to F3c.w color 0x888888 spline -> thin right 1.5cm from F3a.e to F3d.w color 0x888888 spline -> thin right 1.5cm from F3a.e to F3e.w color 0x888888 spline -> thin right 1.5cm from F3a.e to F3f.w color 0x888888 left; move 0.9cm Cta: "Comportamiento de" "las partes" arrow -> from F3a.se to Cta.n # Rellenar la Fase IV F4a: box same as F3a at 3.1cm south of F3a "Gestión" big arrow <- from F4a.ne to Cta.s "regula" above aligned color 0x888888 F4b: box same as F3b at 0.925cm south of F3f "Ignorar" small down F4c: box same as F4b "Ceder" small F4d: box same as F4b "Imponer" small F4e: box same as F4b "Colaborar" small F4f: box same as F4b "Arbitraje" small F4g: box same as F4b "Negociación" small spline -> thin right 1.5cm from F4a.e to F4b.w color 0x888888 spline -> thin right 1.5cm from F4a.e to F4c.w color 0x888888 spline -> thin right 1.5cm from F4a.e to F4d.w color 0x888888 spline -> thin right 1.5cm from F4a.e to F4e.w color 0x888888 spline -> thin right 1.5cm from F4a.e to F4f.w color 0x888888 spline -> thin right 1.5cm from F4a.e to F4g.w color 0x888888 # Rellenar la Fase V F5a: box same as F4a at 3.1cm south of F4a "Resultados" big F5b: box same as F4b at 0.9cm south of F4g "Perder -- Perder" small down F5c: box same as F5b at .75cm south of F5b.s "Ganar -- Perder" small F5d: box same as F5b at .75cm south of F5c.s "Ganar -- Ganar" small spline -> thin right 1.5cm from F5a.e to F5b.w color 0x888888 spline -> thin right 1.5cm from F5a.e to F5c.w color 0x888888 spline -> thin right 1.5cm from F5a.e to F5d.w color 0x888888 # Colocar flechas gordas # Utilizo un punto invisible para mover el dibujo de la flecha dot at 0.2cm north of F2a.n invisible; flecha dot at 0.2cm north of F3a.n invisible; flecha dot at 0.2cm north of F4a.n invisible; flecha dot at 0.2cm north of F5a.n invisible; flecha
Este gráfico no podría haberlo hecho con graphviz
o con plantuml
.
Incluso con Inkscape me hubiera costado colocar elementos, alinearlos,
poner guías, etc. Sin embargo, con un poco de ayuda de Emacs –sí,
tiene un modo pikchr incluido– he podido ir dibujando, elemento a
elemento todo el dibujo.
Situar elementos en el dibujo
Cuando empecé con pikchr
me resultaba complicado situar elementos en
el dibujo. El modo en que fluye el dibujo limitaba mi forma de
trabajar. Acostumbrado a otras herramientas, donde es la propia
herramienta la que elige dónde situar un elemento u otro, esperaba de
ésta la misma funcionalidad. La tiene, pero ponía a prueba mi
capacidad espacial a la hora de dibujar. El acostumbrarme a situar las
cosas donde quiero, a guiar las líneas y los textos, a utilizar
elementos invisibles para colocarlos y otros truquillos han hecho que
me resulte una herramienta mucho más completa de lo que me pareció al
principio. Puedes ser tan preciso como quieras, puedes dejar que fluya
o forzar la posición, tú eliges.
box "Hola"; arrow; box "Mundo"
Ese código da como resultado:
box "Hola"; arrow; box "Mundo"
Si cambiamos hacia dónde fluye:
down box "Hola"; arrow; box "Mundo" move right box "Hola"; arrow; box "Mundo" move up box "Hola"; arrow; box "Mundo"
down box "Hola"; arrow; box "Mundo" move right box "Hola"; arrow; box "Mundo" move up box "Hola"; arrow; box "Mundo"
Como vemos, dejar el alineamiento al propio flujo de dibujo de
pikchr
presenta algunos inconvenientes, que eran los que me volvía
loco al principio de utilizar la herramienta.
down box "Hola"; arrow; box "Mundo" right box "Hola" at 1.5cm east of 2nd box.e; arrow; box "Mundo" up box "Hola" at 15mm east of 4nd box.e; arrow; box "Mundo"
Podemos apreciar que se puede hacer referencia a los elementos por su orden de aparición para situar el siguiente. Vemos que en el segundo grupo de elementos se hace referencia a la segunda caja para situar la tercera a 1.5cm al este de la misma. Para acotar mejor las distancias y visualizar mejor el espacio, en el resultado he añadido acotaciones:
down box "Hola"; arrow; box "Mundo" right box "Hola" at 1.5cm east of 2nd box.e; arrow; box "Mundo" up box "Hola" at 15mm east of 4nd box.e; arrow; box "Mundo" # Acotamientos para visualizar mejor las medidas X1: line thin color gray down 50% from 2mm south of 2nd box.se X2: line same as X1 from (3nd box, X1.start) arrow <-> from 3/4<X1.start,X1.end> right until even with X2 "1.5cm" above thin color gray assert( last arrow.width == 1.5cm ) X3: line thin color gray down 50% from 2mm south of 4nd box.se X4: line same as X3 from (5nd box, X3.start) arrow <-> from 3/4<X3.start,X3.end> right until even with X4 "15mm" above thin color gray assert( last arrow.width == 15mm )
Si habéis mirado el código para ver las acotaciones, veréis que
también me aseguro que las medidas son correctas con una instrucción
assert
.
Cada elemento dentro del gráfico tiene una serie de propiedades. Las que más vas a utilizar son los puntos de referencia:
# Puntos de situación B1: box rad 5mm color blue thin width 5cm height 3.5cm dot at B1.c color red "c" above dot at B1.nw "nw" above color red dot at B1.n "n" above color red dot at B1.ne "ne" above color red dot at B1.w "w" rjust color red dot at B1.e "e" ljust color red dot at B1.sw "sw" rjust color red dot at B1.s "s" below color red dot at B1.se "se" ljust color red # Acotaciones de ancho, alto y radio X1: line thin color gray down 100% from 20mm south of B1.w X2: line same as X1 from 20mm south of B1.e arrow <-> dashed thin color gray from 3/4<X1.start,X1.end> right until even with X2 "width o wid" above X3: line thin color gray left 100% from 30mm west of B1.n X4: line same as X3 from 30mm west of B1.s arrow <-> dashed thin color gray from 3/4<X3.start,X3.end> down until even with X4 "height o ht" above aligned X5: line thin color gray right 100% from 30mm east of B1.n X6: line thin color gray right 100% from 5mm south of X5.start arrow <-> dashed thin color gray from X5 down until even with X6 "radius o rad" ljust
El resultado del código anteriores es:
# Puntos de situación B1: box rad 5mm color blue thin width 5cm height 3.5cm dot at B1.c color red "c" above dot at B1.nw "nw" above color red dot at B1.n "n" above color red dot at B1.ne "ne" above color red dot at B1.w "w" rjust color red dot at B1.e "e" ljust color red dot at B1.sw "sw" rjust color red dot at B1.s "s" below color red dot at B1.se "se" ljust color red # Acotaciones de ancho, alto y radio X1: line thin color gray down 100% from 20mm south of B1.w X2: line same as X1 from 20mm south of B1.e arrow <-> dashed thin color gray from 3/4<X1.start,X1.end> right until even with X2 "width o wid" above X3: line thin color gray left 100% from 30mm west of B1.n X4: line same as X3 from 30mm west of B1.s arrow <-> dashed thin color gray from 3/4<X3.start,X3.end> down until even with X4 "height o ht" above aligned X5: line thin color gray right 100% from 30mm east of B1.n X6: line thin color gray right 100% from 5mm south of X5.start arrow <-> dashed thin color gray from X5 down until even with X6 "radius o rad" ljust
Y como se puede apreciar para dibujar se utilizan comandos como right
,
up
, down
, left
, es decir: derecha, abajo, arriba, izquierda. Y las
cosas se sitúan south
, north
, east
, west
, es decir: al sur, al norte,
al este o al oeste de un punto. También podemos situarnos en
fracciones de la distancia entre dos puntos utilizando la notación:
fracción<punto1,punto2>
Conclusiones
No hay nada como leerse la documentación y mirar todos los ejemplos que he podido encontrar. Creo que aún no he conseguido sacar toda la chicha que tiene el asunto.
En fin, pikchr
me parece una herramienta bastante completa. Se asemeja
a poder dibujar un SVG
a partir de instrucciones simples, aunque no
tiene todas las cosas que permite un SVG
. Por ejemplo, no soporta
gradientes o colores con canal alfa. Para la muchas de las cosas que
debo dibujar me facilita la vida y si necesito esas otras cosas que no
me proporciona, siempre puedo modificar el resultado desde Inkscape,
por ejemplo, para añadirle fórmulas LaTeX.
Comentarios