Using the ThingLab Reproduction

A ThingLab browser for the currently committed main branch is available here: https://borning.pages.cs.washington.edu/thinglab/. This is automatically updated on each commit.

A goal of the reproduction is to keep the look and feel of the original, so the new ThingLab browser is (almost entirely) monochrome, with a very simple layout. The window has five panes at the top for categories, things, formats, tools, and arguments. It starts out with the Quadrilateral demo selected in "categories" and "things". There are several formats available in which to view it -- the browser starts out with "picture" selected. The tool "move" with the argument "point" is selected, which gives you a point attached to the cursor that you can use to move points in the picture. The tools and arguments are verb/direct object, so "move a point", "insert a midpoint line", or "delete a line". The "merge" tool is like "move" except that the thing being moved is sticky and will merge with another thing if you drop it nearby. The "edit" tool with the argument "point" or "line" will open up a little structure editor. A few things have specialized editors; for example editing a Text thing pops up a text editor, and editing a Switch toggles the switch on each click. (The "tools pane" was called the "messages pane" in the original.)

Besides the "picture" format, "picture (annotated)" is the picture again, with small annotations on some things -- the geometric things in particular -- to indicate the presence of constraints. This format also shows a light dot at the point that is the center of a circle (which is otherwise invisible, unless you merge something else with it). The "structure" format lists the thing's parts, constraints, merges, etc. The "values" format lists the values of all the parts, bottoming out in primitives like numbers.

You can construct a new thing using the blue-shaded "Define new thing ...." button. The other blue-shaded button "Commands and Settings" pops up a window with controls to file in or file out a user-defined thing, or to enable/disable some of the solvers (see below). If you mess something up, just reload the browser window, and you have a fresh start (and of course you have also lost your work, unless you file it out first).

Some suggested things to experiment with

Quadrilateral Experiment with the quadrilateral demo that is displayed on startup: move some of the points, or try selecting "move line" instead. The quadrilateral that is selected on startup demonstrates a geometric theorem: that if you take an arbitrary quadrilateral, bisect each side and draw lines between the midpoints, you get a parallelogram. Experiment with the quadrilateral: move some of the points, or try selecting "move line" instead. For a curious effect, add anchors to one or more midpoints (using "insert" and "Anchor"), and then move a corner. An ordinary "move" and "point" can't move the anchor -- it's got a one-way constraint on its attachment point. The only way to move an anchor is by "move" and "anchor". (If you anchor all four midpoints, you can't even move one of the anchors any more -- you need to delete another anchor first.)

Bounded Quadrilateral; Chain The bounded quadrilateral is exactly the same as the ordinary quadrilateral, except that it is constrained to lie within a bounding frame. The bounding frame is read-only with respect to the quadrilateral parts that lie inside it. Or try the chain -- try moving one end, or merging the two ends using the "merge" tool and then moving other points. You can also insert an anchor to nail down some point.

Number Things These include the numeric operators Plus, Minus, Times, and Divide, number printers, constants, and thermometers. I first envisioned electrical things, then later number things, so the number things have a feel like constructing an electrical circuit diagram. This is fun for examples like the temperature converter, but gets out of hand for more complex expressions. But it did lead to the itch to construct a complete programming language around constraints.

Bridges and Springs In contrast to the original ThingLab (and to Sketchpad), the constraints here represent forces and Hooke's Law explicitly. The pin joints constrain the sum of the forces acting on that joint to be 0. (This is a static simulation; dynamics is left for future work.) Springs are internally the same as beams, just with a different picture.

Also try some of the things in other categories. Hopefully most of them are self-explanatory. A couple of issues that may not be obvious: select "move" and "point" to move the top of the thermometer in the Thermometers example, or the wiper on the potentiometer. To edit the text in a number printer, select "edit" and "text". To flip a switch, select "edit" and "switch" -- each click flips the switch.

UI differences from the original ThingLab

The browser is very much like the one in the original ThingLab, with a few minor changes. The category pane is new -- all the things used to just be in one big list. The annotated picture format is also new. Claude put in constraint annotations on objects with constraints at one point. This seemed potentially useful so I left it, although moved it from the basic picture format into a new format for annotated pictures. (Sketchpad had something like this after all.) There is a new "rotate" tool (I wanted to have a traditional-looking Wheatstone bridge). The "edit" tool is generalized from the original -- it used to be only "edit text".

"Define new thing ..." used to be done using the "as subclass template" format, and ThingLab would in fact define a new class for a new thing, along with a prototypical instance. (Smalltalk was a more dynamic language than is Javascript/Typescript.) This is handled in a temporary way in the reproduction -- I plan to return to the question of how to handle classes versus prototypes, masters versus classes, instantiation, dynamic updating, and so on, and redesign this part later. File in and file out was handled in the original by selecting bits of Smalltalk code and evaluating it.

The cooperating solvers architecture is new and so are the controls for it.

Both the original ThingLab and the reproduction have the concepts of inserters and constrainers, but unfortunately they don't work as well in the reproduction. Smalltalk running on the Alto gave the programmer control over the cursor position, so that it could be jumped to a new location under program control. Modern browsers alas don't support this. Having this capability was essential for inserters to work correctly, and so in the reproduction often there is only one inserter rather than two or three as in the original. Here is an example. One of the kinds of NumberThing is a Plus, with three NumberLeads coming out of it ending in NumberNodes. Call them a, b, and c, so that the constraint is a+b=c. In the original ThingLab, all three were inserters. The user would first position c, with the entire Plus moving at the same time, potentially merging c with another number node. Then the cursor would jump to a, which could be positioned and perhaps merged, and finally it would jump to the third inserter b. Without the ability to jump the cursor, you place c, then the cursor starts moving a -- but alas a moves right on top of c. Not good. For this reason, Plus only declares c as an inserter in the reproduction. There are only a few things for which the lack of jumping is tolerable -- in particular lines and wires still let you position end1 and then end2, and a circle lets you position the center and then set the radius. (Circle is new for the reproduction -- the original didn't have circles.) Most things however just have one inserter. Incidentally, the ST78 version of ThingLab running in a modern browser has the same problem with no jumping, and similarly cuts down the number of inserters for most things.

Hard and soft constraints; cooperating solvers

The big difference from the original ThingLab (besides being written in a different language) is that the reproduction incorporates subsequent work on formalizing hard and soft constraints, change over time, and new constraint solvers. It currently includes three solvers: DeltaBlue (which handles local propagation constraints), Cassowary (which handles linear equalities and inequalities), and relaxation (which handles numeric constraints that can provide an error function, including nonlinear constraints). Relaxation can handle any set of constraints that Cassowary can, but is much slower. Cassowary and relaxation can handle cycles, whereas DeltaBlue cannot. But DeltaBlue can handle non-numeric constraints, for example a constraint relating a number and a string that represents that number, whereas Cassowary and relaxation are both limited to real-valued numbers.

There are sets of constraints that arise naturally in ThingLab that require a combination of solvers to be solved. This was handled in an ad hoc way in ThingLab; the reproduction handles this with a cooperating solvers architecture that puts this on a solid foundation. You can experiment with enabling or disabling any of the solvers by using the checkboxes that are displayed when you press the "Commands and Settings" button. For example, the Quadrilateral's constraints can be solved by any of DeltaBlue, Cassowary, or relaxation. The Wheatstone bridge needs DeltaBlue for the constraints that relate a string to a voltage, current, or resistance; and either Cassowary or relaxation for the constraints represnting the physical laws (Ohm's Law, Kirchhoff's Law) -- since these constraints are all linear, Cassowary can be used. On the other hand, the square root thing needs relaxation when the square is edited; Cassowary can't handle it.

I'll write a longer description of the cooperating solvers architecture later.

Running locally

See the README.md file in the source code repo for directions for running locally on your own machine.

If you previously defined a new thing and filed it out, you can later add the file to the directory additional-things/ and it will be loaded automatically. The repo includes some pre-defined things to get started. Some of the unit tests rely on the Quadrilateral being in that directory, but otherwise you can add or delete things as you wish.

back to ThingLab then and now