A diagram interpreter in XForms

Steven Pemberton, CWI, Amsterdam

The Author

Introduction

I am updating a book on mathematics (Previous edition)

It contains a couple of dozen diagrams.

The previous version was written in LibreOffice.

The new edition is in XHTML+CSS+SVG

SVG

A few shortcomings for this purpose:

Diagrams

The diagrams are often progressive

I needed to be able to easy compare a diagram with the earlier simpler version to make sure they correctly correspond

Solution

Design a domain specific mini-language that supports my abstractions

Write an XForms interpreter that displays each diagram, converting to SVG

Basic Data Structure

<data index="1" xmlns="">
   <diagram title="3+2=5 as arrows">
   ...
   </diagram>
   <diagram title="rectangle of 2×3">
   ...
   </diagram>
</data>

Elements of diagrams

<dot    x="..."  y="..."/>
<line   x1="..." y1="..." x2="..." y2="..." />
<arrow  x1="..." y1="..." x2="..." y2="..." />
<arrow2 x1="..." y1="..." x2="..." y2="..." />
<circle x="..."  y="..." r="..."/>
<text   x="..."  y="...">text</text>
 ...

Interpreter

<trigger>
   <label>prev</label>
   <setvalue ev:event="DOMActivate" ref="@index" value=". - 1"/>
</trigger>
<output ref="@index"/>
<trigger>
   <label>next</label>
   <setvalue ev:event="DOMActivate" ref="@index" value=". + 1"/>
</trigger>
<svg ...>
   <xf:group ref="diagram[position() = ../@index]">
   ...
   </xf:group>
</svg>

Interpreting a diagram

<text x="-10" y="-9" class="text">
   <xf:output ref="@title"/>
</text>
<xf:repeat ref="*">
   <xf:group ref=".[name(.)='line']">
      <line x1="{@x1}" y1="{0-@y1}" 
            x2="{@x2}" y2="{0-@y2}"
            class="line"/>
   </xf:group>
   <xf:group ref=".[name(.)='dot']">
      <circle cx="{@x}" cy="{0-@y}" r="0.05"
              class="dot"/>
       </xf:group>
   <xf:group ref=".[name(.)='arrow']">
   ...

Quick and Dirty

This was a quick and slightly dirty solution for a one-off problem

If I'd have needed it more often, I would have generalised it further, and added more primitives.

But this simple solution served its purpose perfectly well.

Version 2

at="1,2" with 0,0 as default

lines etc either length="" or to=x,y"

general rotation=""

Demo

Source