Quick
index
main
eev
eepitch
maths
angg
blogme
dednat6
littlelangs
PURO
(C2,C3,C4,
 λ,ES,
 GA,MD,
 Caepro,
 textos,
 Chapa 1)

emacs
lua
(la)tex
maxima
git
lean4
agda
forth
squeak
icon
tcl
tikz
fvwm
debian
irc
contact

Eev and (My)Qdraw

My main page on Maxima is here.
This page is about my extensions to Ted Woollett's Qdraw, a drawing package for Maxima.
I'm calling my extensions "MyQdraw". Its examples use eepitch blocks and test blocks.
The animations below were created with MyQdraw:

1. Maxima by Example
2. The "load"s
3. The core of MyQdraw
3.1. Eight functions
3.2. The rest of the core
4. Animations


1. Maxima by Example

One of the best places for learning Maxima from examples is a (free) book whose name is - ta-daaa! - Maxima by Example. It is divided into chapters, and my script to download a local copy of it is here. Its chapter 13 is about Qdraw, that is a front-end to Maxima's draw2d command (see also the Maxima Workbook).

This page is about my current extensions to Qdraw. I'm calling my extensions "MyQdraw" - a bad name, chosen on purpose to indicate that this is not a mature package.


2. The "load"s

The examples in this page will suppose that you have downloaded myqdraw from its git repository, with something like this:

* (eepitch-shell)
* (eepitch-kill)
* (eepitch-shell)
# (find-fline "/tmp/myqdraw/")
rm -Rv /tmp/myqdraw/
mkdir  /tmp/myqdraw/
cd     /tmp/myqdraw/
git clone https://github.com/edrx/myqdraw .

and that you have two lines like these ones in your init file:

load_qdraw  () := load("/tmp/myqdraw/qdraw.mac");
load_myqdraw() := load("/tmp/myqdraw/myqdraw3.mac");

I use definitions that point to the directory ~/myqdraw/ - they are here.


3. The core of MyQdraw

Initially "myqdraw" was just this one-liner:

myqdraw([drargs]) := apply('qdraw, flatten([drargs]));

Here's why. The program below produces these two images:

Its call to `qdraw' produces the image at the left and its call to `myqdraw' produces the image at the right. Here is the code:

* (eepitch-maxima)
* (eepitch-kill)
* (eepitch-maxima)
load_qdraw();

P  : [cos(t), sin(2*t)];
ts : [0, %pi/4, %pi/2];

define(P(t),   P);
define(Pt(t),  diff(P,t));
define(Ptt(t), diff(P,t,2));

qdraw(xr(-4,4),yr(-4,4),
      para(P[1],P[2], t,0,2*%pi, lc(orange)),
      vector(P(0),    Pt(0),      hl(0.1),lc(red)),
      vector(P(%pi/4),Pt(%pi/4),  hl(0.1),lc(red)),
      vector(P(0),    Ptt(0),     hl(0.1),lc(forest_green)),
      vector(P(%pi/4),Ptt(%pi/4), hl(0.1),lc(forest_green))
     );

myqdraw([drargs]) := apply('qdraw, flatten([drargs]));
myqdraw(xr(-4,4),yr(-4,4),
        para(P[1],P[2], t,0,2*%pi, lc(orange)),
        makelist(vector(P(t),Pt (t), hl(0.1),lc(red)), t, ts),
        makelist(vector(P(t),Ptt(t), hl(0.1),lc(forest_green)), t, ts)
     );

The `qdraw' in it is called - and it needs to be called - with all its drawing commands "at the same level", but `myqdraw' flattens its list of drawing commands and then passes the flattened version to qdraw. The qdraw and the myqdraw above are called like this:

qdraw(xr(_),
      yr(_),
      para(_),
      vector(_),
      vector(_),
      vector(_),
      vector(_));
myqdraw(xr(_),
        yr(_),
        para(_),
        [vector(_),
         vector(_),
         vector(_)],
        [vector(_),
         vector(_),
         vector(_)]);

For complex drawings I found `myqdraw' much easier to use.

After a while I saw that it would be good karma to also include some debugging functions. `qdraw' is a kind of preprocessor - first it calls `qdraw1' to transform its drawing commands into a list of drawing commands in the syntax of `draw2d', and then it calls `draw2d'. In this program

* (eepitch-maxima)
* (eepitch-kill)
* (eepitch-maxima)
load_myqdraw();
a_circle : para(cos(t), sin(t), t,0,2*%pi);
qdraw  (a_circle);
qdraw1 (a_circle);
qdraw1v(a_circle);

the `qdraw' just draws a circle, and the `qdraw1' doesn't draw anything, it just returns this list of drawing commands for `draw2d':

[ip_grid_in = [10, 10], grid = true, nticks = 100, key = "", 
line_width = 3, transparent = true, point_size = 3, point_type = 7, 
label_alignment = left, head_type = nofilled, head_angle = 30, 
head_length = 0.5, parametric(cos(t), sin(t), t, 0, 2 %pi), xaxis = true, 
xaxis_width = 2, yaxis = true, yaxis_width = 2]

and the `qdraw1v' - a function that I defined - returns that list of drawing commands for `draw2d' "formatted vertically", like this:

ip_grid_in = [10,10]
grid = true
nticks = 100
key = ""
line_width = 3
transparent = true
point_size = 3
point_type = 7
label_alignment = left
head_type = nofilled
head_angle = 30
head_length = 0.5
parametric(cos(t),sin(t),t,0,2*%pi)
xaxis = true
xaxis_width = 2
yaxis = true
yaxis_width = 2


3.1. Eight functions

So, qdraw.mac defines these two main functions:

  • `qdraw1', that just translates the qdraw commands to draw2d commands, and
  • `qdraw', that does that translation and calls draw2d to draw the result.

Let me invent some new verbs:

  • `qdraw1' "qtranslates"
  • `qdraw' qtranslates and draws the result - or, in short: "qdraws".

This part of myqdraw-core.mac complement those two functions with six new ones to build this cube,

qdraw ------ myqdraw
   | \         |   \
   | qdraw1    |  myqdraw1
   |   |       |      |
qdrawv |---- myqdrawv |
     \ |          \   |
     qdraw1v ---- myqdraw1v

where:

  • `qdraw' qdraws,
  • `qdraw1' qtranslates,
  • `qdrawv' formats vertically,
  • `qdraw1v' qtranslates and formats vertically,
  • `myqdraw' flattens and then qdraws,
  • `myqdraw1' flattens and qtranslates,
  • `myqdrawv' flattens and formats vertically,
  • `myqdraw1v' flattens, qtranslates and formats vertically.


3.2. The rest of the core


4. Animations

Qdraw is easy to extend. I generated the animation below

with these files:

(find-myqdraw "myqdraw3.mac")
(find-myqdraw "topdf1.mac")
(find-myqdraw "mkanim1.sh")
(find-myqdraw "bezier2.mac")

Click on the animation to enlarge it; click here to see it in flipbook format.