Skip to content

Latest commit

 

History

35 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Michel Rouzic’s drawing calculator

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.

screenshot1.png

Usage

Symbol functions

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 .5 will make a square 3 units wide and tall centred on positions x and y.

  • 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 9 will show 3.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 number function, text displays 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 written 3+98(30+98(27+98(42+98(27)))). 3 is the 3rd letter of the alphabet 'c', 30 is '0', 27 is a space, 42 is '='. 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)) 0

How to zoom

The 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.

Full screen

You can press Alt-Return to switch between full screen or windowed mode.

Example formulas

Bokeh 3D sphere

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.

screenshot2.png
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_loop

Bubble universe

Adapted from this tweet. Click "Animate" to animate it.

screenshot3.png
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_loop

Graphing calculator

Naturally you can simply loop through a variable x, calculate a y from it, and for each iteration of x draw a quadrilateral.

screenshot4.png
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_x

Palette generation

I 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.

screenshot5.png
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

About

Draw symbols placed according to a formula you enter

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages