Author: scruss

  • Ulam Spiral to 2¹⁶ #mathart

    Ulam Spiral to 2¹⁶ #mathart

    Ulam Spiral to 2¹⁶ #mathart

    Instagram filter used: Normal

    View in Instagram ⇒

    Here’s 220, though it looks a little mushy:

    ulam2tothe20-new

  • chip roll frenzy

    chip roll frenzy

    chip roll frenzy

    Instagram filter used: Lo-fi

    Photo taken at: Harry’s Drive In

    View in Instagram ⇒

  • ayaburnie!

    ayaburnie!

    ayaburnie!

    Instagram filter used: Normal

    View in Instagram ⇒

  • tfw …

    tfw …

    tfw ...

    Instagram filter used: Normal

    View in Instagram ⇒

  • Trams of Old Kansas City

    Trams of Old Kansas City

    Trams of Old Kansas City

    Instagram filter used: Normal

    Photo taken at: KC Streetcar

    View in Instagram ⇒

  • A skosh stormy

    A skosh stormy

    A skosh stormy

    Instagram filter used: Lo-fi

    Photo taken at: Liberty, Missouri

    View in Instagram ⇒

  • Melty Sharktooth

    Melty Sharktooth

    Melty Sharktooth

    Instagram filter used: Normal

    View in Instagram ⇒

  • Pastorale

    Pastorale

    Pastorale

    Instagram filter used: Lo-fi

    View in Instagram ⇒

  • TwentyfourSixteen – a 17-segment alpha LCD font

    2416-demo

    Download: TwentyfourSixteen.zip.

    Made in 2016 by Stewart C. Russell – scruss.com

    A mono-spaced font family derived from the HP/Siemens/Litronix DL-2416 17-segment alphanumeric 17 segment LED display matrix.

    Design size: appx 19 pt

    For maximum fidelity, should be displayed/printed red to match the original’s ~640 nm wavelength. This corresponds to RGB #ff2100

    Weights

    Regular only.

    Note that this has a very slight skew (5°) built in.

    Coverage

    ASCII only, upper case.

    Author

    Stewart C. Russell – http://scruss.com/blog/

    Licence

    Dual-licensed CC0/WTFPL (srsly)

    All of the segments. I've stashed this glyph at character code U+007f so you can make up new ones.
    All of the segments. I’ve stashed this glyph at character code U+007f so you can make up new ones.

    also: numbers.zip — just 00-99 as PNG images, after this, made with Pango, like this:

    for f in {00..99}
    do
     pango-view --no-display --background=black --dpi=112 --align=right --foreground='#ff2100' --font='TwentyfourSixteen Regular 48' --hinting=full --output="$f.png" -t "$f"
    done
  • Future stylin’

    Future stylin’

    Future stylin'

    Instagram filter used: Lo-fi

    View in Instagram ⇒

  • Pen plotters: not just output devices …

    Pen plotters were pretty expensive and complex pieces of electromechanical equipment. While they often earned their keep in the CAD office, they also had a function that’s almost forgotten: they could be used as input devices, too.

    As a kid, we sometimes used to drive past the office of Ferranti-Cetec in Edinburgh. They specialized in digitizers: great big desk or wall mounted devices for capturing points from maps and drawings. Here’s one of their 1973 models:

    Ferranti EP210 Freescan Digitiser. Source: Grace's Guide, http://www.gracesguide.co.uk/File:Im1973IME-Ferranti.jpg
    Ferranti EP210 Freescan Digitiser. Source: Grace’s Guide, http://www.gracesguide.co.uk/File:Im1973IME-Ferranti.jpg

    While the technology and size have changed a bit, these huge bits of engineering kit are the ancestors of today’s track pads and touch screens.

    Realizing that their plotters had very precise X-Y indexing and that they had two-way communications to a computer, HP made a drafting sight that fitted in place of a pen on their plotters:

    HP drafting sight, part no 09872-60066
    HP drafting sight, part no 09872-60066.

    This is a very pleasing piece of kit, all metal, thick plastic and polished optical glass. They show up on eBay occasionally, and aren’t cheap. With a bit of coercion, it fits into my HP plotter like this:

    Drafting sight in HP7470A plotter
    Drafting sight in HP7470A plotter

    The image is very bright and clear:

    Drafting sight near an axis label
    Drafting sight near an axis label
    Drafting sight over a point
    Drafting sight over a point, showing cursor dot

    If one has a digitizing sight, one needs to find something to digitize post haste. I’m sure everyone can sense the urgency in that. So I found this, a scan from my undergraduate project writeup (centrifugal pump impeller design ftw, or something), which was probably made on an Amiga or Atari ST:

    It's a graph, with pointy bits on it
    It’s a graph, with pointy bits on it

    I printed this as large as I could on Letter paper, as it’s the only size my HP7470A plotter can take. Now all it needed was a small matter of programming to get the data from the plotter. Here’s a minimally-useful digitizer for HP and compatible serial plotters. Although I ran it on my little HP grit wheel plotter attached to a Raspberry Pi, I developed it with my larger Roland plotter. The only fancy module it needs is pySerial.

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # a really crap HP-GL point digitizer
    #  scruss - 2016
    
    from time import sleep
    from string import strip
    import serial
    
    ser = serial.Serial(port='/dev/ttyUSB1', baudrate=9600, timeout=0.5)
    lbl = ''
    points = []
    labels = []
    k = 0
    retval = 0
    
    ser.write('DP;')                # put in digitizing mode
    while lbl != 'quit':
        ser.write('OS;')
        ret = strip(ser.read(size=5), chr(13))
        print ('Retval: ', ret)
        if ret != '':
            retval = int(ret)
        if retval & 4:              # bit 2 is set; we have a point!
            print ('Have Point! Retval: ', retval)
            retval = 0
            ser.write('OD;')
            pt = strip(ser.read(size=20), chr(13))
            print ('OD point: ', pt)
            lbl = raw_input('Input label [quit to end]: ')
            points.append(pt)
            labels.append(lbl)
            k = k + 1
            ser.write('DP;')        # put in digitizing mode again
        sleep(1)
    ser.close()
    
    f = open('digit.dat', 'w')
    for i in range(k):
        f.write(points[i])
        f.write(',')
        f.write(labels[i])
        f.write('\n')
    f.close()
    

    In the unlikely event that anyone actually uses this, they’ll need to change the serial port details near the top of the program.

    The program works like this:

    1. Move the drafting sight to the point you want to capture using the plotter’s cursor keys, and hit the plotter’s ENTER key
    2. Your computer will prompt you for a label. This can be anything except quit, that ends the program
    3. When you have digitized all the points you want and entered quit as the last label, the program writes the points to the file digit.dat

    I didn’t implement any flow control or other buffer management, so it can crash in a variety of hilarious ways. I did manage to get it to work on the lower trace of that graph, and got these data:

    9649,2428,1,300,0
    357,2428,1,0,0
    357,7217,1,0,0.60
    733,3112,1,first
    826,3167,1,
    968,3256,1,
    1122,3334,1,
    1290,3405,1,
    1588,3583,1,
    1891,3725,1,
    2215,3880,1,
    2526,4051,1,
    2830,4194,1,
    3143,4280,1,
    3455,4516,1,
    4077,4767,1,
    5008,5229,1,
    6543,5954,1,
    8067,6548,1,
    8740,7195,1,
    8740,7195,1,last
    8740,7195,1,quit

    The first two columns are X and Y, in HP-GL units — that’s 1/40 mm, or 1/1016 inches. The third column will always be 1 if you have the sight down. The last columns are the label; if you put commas in them, opening the file as CSV will split the label into columns. I used it to fudge axis points. You’ll also note that the last three lines of data are my valiant attempts to quit the program.

    Assuming the axes are not skewed (they are, very slightly, but shhh) some simple linear interpolation gives you the results below:

     12.1    0.086
     15.1    0.093
     19.7    0.104
     24.7    0.114
     30.1    0.122
     39.7    0.145
     49.5    0.162
     60.0    0.182
     70.0    0.203
     79.8    0.221
     89.9    0.232
    100.0    0.262
    120.1    0.293
    150.2    0.351
    199.7    0.442
    248.9    0.516
    270.7    0.597

    Good enough for a demo.

    (For prettier things to do with plotter digitizing commands, Ed Nisley KE4ZNU has made some rather lovely Superformula patterns)

    If you don’t have a plotter, or even if you do and you don’t have hours to waste mucking about with Python, obsolete optics and serial connections, Ankit Rohatgi’s excellent WebPlotDigitizer (or Engauge, as I found out when this article hit HackerNews in 2021) gets numbers out of graphs quickly. It handles all sorts of graphs rather well.

    Update, 2025: eek, but WebPlotDigitizer is now login-only and has been infested by AI shite. Run away now, run away fast … or try to find an old mirror online, such as WebPlotDigitizer at utk.edu.

  • Clockwatching

    Clockwatching

    Clockwatching

    Instagram filter used: Normal

    View in Instagram ⇒

  • Ellen’s the real weirdo here

    Ellen’s the real weirdo here

    Ellen's the real weirdo here

    Instagram filter used: Clarendon

    Photo taken at: Protolab Makerspace

    View in Instagram ⇒

  • Scripting Inkscape – kinda

    A couple of months back at the GTALUG Graphics session, someone asked if Inkscape – the 2D vector graphics workhorse that everyone seems to use – could be scripted. We pretty much said that it couldn’t. Recently, I found out that it does support a limited form of scripting, and wish to pass this on.

    The key to it is understanding Inkscape’s command verbs. These can be listed using:

    inkscape --verb-list
    
    

    These verbs map to Inkscape commands, and often have names linked to the menu they live in (such as “FileQuit” doing what you’d expect).

    I had a task I had to repeat on many files: convert all the stroked lines to filled paths. You’d need to do this if you are laser engraving a simple drawing, but there are other applications for this too. Here’s a command that would do this for all objects in a drawing, and overwrite the input file:

    inkscape --verb EditSelectAll --verb SelectionUnGroup \
            --verb EditSelectAll --verb SelectionUnGroup \
            --verb EditSelectAll --verb SelectionUnGroup \
            --verb EditSelectAll --verb ObjectToPath \
            --verb EditSelectAll --verb SelectionCombine \
            --verb EditSelectAll --verb StrokeToPath \
            --verb FileSave --verb FileClose \
            --verb FileQuit input.svg
    
    

    What this does:

    1. Selects everything, and ungroups all objects (×3, to break up most nested groups);
    2. Selects everything, and converts all objects to paths (so text, circles, polygons, spirals become paths, the lowest-level SVG object);
    3. Selects everything, and combines everything into one path;
    4. Selects everything, and converts all strokes to filled paths (so a two node straight line 1 mm wide would become a four node filled rectangle 1 mm thick);
    5. Overwrite the input file, close it, and quit.

    The process has some disadvantages:

    1. It opens a window every time. You can’t execute verbs without the GUI opening.
    2. You can’t have another copy of Inkscape open while you do this.
    3. Realistically, you can’t really do anything at your computer until this is done, as it’s popping up windows and shifting focus like crazy. (ssh types can say “heh!” in a smug manner now)
    4. You can’t set parameters to verbs.
    5. It will overwrite the input file.
    6. It clogs up your “File / Recent” menu with all of the files you scripted.