Here’s what it does:
-
Enter an algorithm in RLIP.
-
Each time you call one of the symbol functions it adds the matching symbol to a list of symbols to draw.
-
The program just draws from that list of circles.
As with all my projects it depends on rouziclib for all the heavy lifting so it needs to be in your include path.
The way you make the drawing calculator show anything on screen is by calling functions that match a symbol. But first the colour function should be called at least once to set a colour. Its 3 arguments are red-green-blue in linear values in the 0 to 1 range (numbers outside of that range do something too). For instance: d v = colour red grn blu or d v = colour 0.6 0 0.4. Due to RLIP not currently accepting functions that do not return a value all of these functions return a dummy value which must be assigned to a dummy variable, in the examples shown it’s v (d in d v means v is declared as a double).
Here are the currently available symbol functions:
-
line <pos X of point A> <pos Y> <pos X of point B> <pos Y> <blur size>+ A line is simply define by the coordinates of a point A and point B, plus the size of a blur, which by default for a thin line should be 0. -
rect <pos X> <pos Y> <width> <height> <offset X> <offset Y>The rectangle is defined by a position, the size of the rectangle independent of its position and an X-Y offset where X of 0 means the position sets the left edge, 1 sets the right edge, 0.5 centres the rectangle around the position, and same with the Y offset: 0 is the bottom edge, 1 is the top edge, 0.5 centres the rectangle. For instance
d v = rect x y 3 3 .5 .5will make a square 3 units wide and tall centred on positionsxandy. -
quad <pos X of point A> <pos Y> <pos X of point B> <pos Y> <pos X of point C> <pos Y> <pos X of point D> <pos Y> <blur size> -
circle <pos X of centre> <pos Y> <radius of the circle> -
number <pos X of centre> <pos Y> <scale of the glyphs> <value to show> <max number of digits to show> <alignment>For instance
d v = number 0 0 1 pi 7 9will show3.141593. The alignment argument decides of the printing layout: 1 is centred around the position, 0 makes the position define the left edge of the text, 2 defines the right edge, adding 8 makes digits be monospaced, adding 4 makes all glyphs monospaced. Therefore 9 means centred with monospaced digits and is a good default. -
text <pos X> <pos Y> <scale of the glyphs> <alignment> <first text value> <second text value>Much like the
numberfunction,textdisplays text. The weird part is how the text data is stored: as two numbers between 0 and almost 253-1, or 988, using base98 encoding (the alternatives were base39 and base59). For instance "c0 = " is written3+98(30+98(27+98(42+98(27)))).3is the 3rd letter of the alphabet 'c',30is '0',27is a space,42is '='. The simplest way to encode text is to write the first character’s value, then paste+98()and press the left arrow key once, then enter the second character’s value, paste+98()again, press the left arrow key and so forth. One value reliably holds 8 characters, if more are needed a second value can be entered for another 8 characters. The values for each character of this base98 encoding are detailed below:0 1 2 3 4 5 6 7 8 9 line break
a
b
c
d
e
f
g
h
i
10 11 12 13 14 15 16 17 18 19 j
k
l
m
n
o
p
q
r
s
20 21 22 23 24 25 26 27 28 29 t
u
v
w
x
y
z
space
_
tab
30 31 32 33 34 35 36 37 38 39 0
1
2
3
4
5
6
7
8
9
40 41 42 43 44 45 46 47 48 49 .
:
=
<
>
+
-
*
/
|
50 51 52 53 54 55 56 57 58 59 ,
A
B
C
D
E
F
G
H
I
60 61 62 63 64 65 66 67 68 69 J
K
L
M
N
O
P
Q
R
S
70 71 72 73 74 75 76 77 78 79 T
U
V
W
X
Y
Z
;
!
?
80-81 82 83 84 85 86 87 88 89 two bytes of °
'
"
(
)
[
]
{
}
90 91 92 93 94 95 96 97 #
$
&
@
\
^
%
~
Example:
d v = colour 1 0.8 0.6
v = circle 0 -1 1
v = quad -.8 -1 0 -.2 .8 -1 0 -1.8 .75
v = colour 1 0.2 0
v = line 0 -28/12 8/12 -4 0.01
v = line 0 -28/12 -8/12 -4 0.01
v = quad -1 -20/12 0 -25/12 1 -20/12 0 -28/12 0
v = colour 0.6 0 0.4
v = rect 0 1.5 4.25 1 .5 .5
v = colour -0.6 0 -0.4
v = number 0 1.5 7/12 2pi 7 9
v = colour -1 -0.8 -0.6
v = text 0 -1 7/12 9 32+98(16+98(9)) 0The interface is zoomable as explained here. Basically by clicking the middle mouse button you enter the zoom-scroll mode so you can zoom (using the scroll wheel) and adjust the selection with more precision. You exit that mode by clicking the middle mouse button again or better yet reset the view by holding the middle mouse button for at least half a second.
This one creates a 3D sphere with bokeh with two coloured areas. Adjust the knob for variable k0 for how the dots spin up the sphere, angle to make it rotate and k1 to adjust camera focus.
d i = 0
i_loop:
expr d north = (i-0.5)/2
expr d west = (i * k0 + 0.25)%1
expr d westr = (west - angle)%1
expr d p.x = cos_tr_d2(westr) * cos_tr_d2(north)
expr d p.y = cos_tr_d2(north-0.25)
expr d p.z = cos_tr_d2(westr-0.25) * cos_tr_d2(north)
expr d rad = abs(p.z-k1) * 0.02
expr d m = .00003/sq(rad)
expr m = m*erfr(p.z*3)
// Colours
expr d spot_a = 8*exp(-sqadd((north-0.1)*40, (west-0.3)*20))
expr d spot_b = exp(-sqadd((north+0.05)*20, (west-0.5)*20))
expr d red = 0.13*m + spot_a*m + spot_b*4*m
expr d grn = (0.13 + spot_a)*m (1 - spot_b)^20 + spot_b*.04*m
expr d blu = (0.5 + spot_b)*m (1 - spot_b)^20 + spot_b*.04*m
// Draw circle
d v = colour red grn blu
v = circle p.x p.y rad
i = add i .0008
i i_cond = cmp i <= 1
if i_cond goto i_loopAdapted from this tweet. Click "Animate" to animate it.
d num_curves = 512
d iter = 400
d t = mul time 0.025
d radm = 0.004
d r = 2pi/235
d tr = 1/(2pi)
d i = 0
i_loop:
d p.x = 0
d p.y = 0
d j = 0
j_loop:
// Position
expr d a = i*r + t + p.x
expr d b = i + t + p.y
expr p.x = cos_tr_d2(a*tr-0.25) + cos_tr_d2(b*tr-0.25)
expr p.y = cos_tr_d2(a*tr) + cos_tr_d2(b*tr)*0.1
// Radius
expr d rad = radm * (1 - (j / iter))
// Colour
expr d red = sq(i / num_curves)
expr d grn = sq(0.5+0.5*cos_tr_d2(j/200+0.25))
expr d blu = sq(1-(i/num_curves+j/iter)/2)
// Draw circle
d v = colour red grn blu
v = circle p.x p.y rad
j_end:
inc1 j
i j_cond = cmp j < iter
if j_cond goto j_loop
i = add i 3.86
i i_cond = cmp i < num_curves
if i_cond goto i_loopNaturally you can simply loop through a variable x, calculate a y from it, and for each iteration of x draw a quadrilateral.
expr d r = colour(1/8, 1, 1/8)
d th = .04 // half thickness of the curve
d x_step = 0.005
d x0 = 0/0
d y0 = 0/0
d x = -40
loop_x:
d y = 0
// Loop through frequencies and sum them to y
d freq = 0
loop_freq:
expr y = y + cos(2pi*x*freq)*erfr(freq*k0-k1)
freq = add freq 0.01
i c_freq = cmp freq < 0.5
if c_freq goto loop_freq
// Control vertical scale
y = mul y 0.5
// Draw quad
i c = isnan y0
if c goto skip_drawing
expr r = quad(x0, y0+th, x, y+th, x, y-th, x0, y0-th, 0)
skip_drawing:
x0 = x
y0 = y
x = add x x_step
i c_x = cmp x < 40
if c_x goto loop_xI needed to create a 256-colour palette for some data visualisation so I experimented with colouring a grid of circles until I was happy with the formula.
d i = 0
i_loop:
expr d t = (255-i)*0.2
expr d m = sqrt(i/255)
// Colours
expr d red = (1-abs(cos_tr_d2(0.16 * t-0.25))) * m
expr d grn = (1-abs(cos_tr_d2(0.02 * t-0.25))) * (i/255)
expr d blu = (1-abs(cos_tr_d2(0.15 * t-0.25))) * m
// Draw palette
expr d p.x = i%16
expr d p.y = floor(i/16)
d v = colour red grn blu
v = circle p.x p.y 0.46
// Draw side graph
p.x = mad red 8 16.5
p.y = mad blu 8 3
v = circle p.x p.y 0.08
i = add i 1
i i_cond = cmp i < 256
if i_cond goto i_loop



