File Format

Let's begin by looking at a simple example. The following is a text version of the diagram that demonstrates that the three medians of a triangle meet at a point.

.geometry "version 0.2";
v1 = .free(-0.404517, 0.351129, "A");
v2 = .free(0.408624, 0.441478, "B");
v3 = .free(0.0513347, -0.301848, "C");
l1 = .l.vv(v1, v2);
l2 = .l.vv(v2, v3);
l3 = .l.vv(v3, v1);
v4 = .v.vvmid(v1, v2);
v5 = .v.vvmid(v2, v3);
v6 = .v.vvmid(v3, v1);
l4 = .l.vv(v1, v5);
l5 = .l.vv(v2, v6);
l6 = .l.vv(v3, v4);
// Here's a comment.

At present, the first line doesn't do anything---but leave it unchanged. In the future, it may be used for version control, or to signal to future versions of Geometer that the file is ancient and needs to be brought up to date. It can also signal to an older version of geometer that it's trying to read a more modern file, and there might be trouble.

The final line shows you how to put in a comment. The comment text will be saved and rewritten, but it has no effect on the operation of Geometer. The "//" tells Geometer to ignore all the text to the end of the line.

The rest of the lines in the file are more typical of Geometer commands. Geometer uses a bunch of reserved words, and every reserved word begins with a period (and may contain additional periods). Thus ".geometer", ".free", ".l.vv", and ".v.vvmid" are the reserved words used in this file.

If you're writing your own Geometer program, you cannot accidentally have a conflict with Geometer's reserved words -- even for future versions of Geometer. You cannot use a leading period in your variable names and Geometer promises always to use one. A user identifier begins with a letter (or the underscore character), and is followed by a sequence of letters, digits, or the underscore character. Here are a few valid identifiers:

  Line1 point_A m7 M7 Ma8qWs Iris1000 __7
Upper and lower case are distinguished, so m7 and M7 represent different variables.

The vast majority of Geometer's commands have the form:

[variable] = [command]([required params] [optional params]);
For example, in the second line:
v1 = .free(-0.404517, 0.351129, "A");
the variable is v1, which serves as the internal name of that geometric object. The command is .free, the required parameters are the two floating-point numbers that serve as the point's coordinates, and the display (or external) name, "A", is an optional parameter.

Since these commands will play a huge role in advanced diagrams, it's convenient to have a syntax to describe the command form. This will be covered in detail in the reference section, but a couple of examples should make the form clear:

[P] = .v.ll([L], [L]);
The example above uses the strings [P] and [L] to indicate that any internal point or line name can go in the corresponding slot. Note also that the optional parameters are not listed -- after the final line in the example above, you can add colors, linestyles, external names, et cetera. In addition to [P] for point and [L] for line, circles are represented by [C], angles by [A], and there are a bunch of others that we'll introduce as needed.

Typically, the non-geometric properties are optional. There is a set of default values for each property, and if they are not specified in a command, the default value is used. Here's a list of the defaults (some of which won't make sense to you yet):

Property Default Value
Color.white
Name(none)
Layer.l0on (all layers)
Line type.segment
Line stipple.solidline
Line mark.line0slash
Vertex type .circpoint
Angle type .ring1
Polygon type .outlinepoly

When Geometer writes a text file, it checks the properties of each item, and if they have the default value, it omits them from the output. You may type them as input if you've forgotten what the default is and want to be sure, but if it was a default value, Geometer will not bother to write it on output.

For example, if you type in a line like this:

vert = .free(.123, .456, .white, .segment, .l5);
Geometer will cheerfully parse it and will paint the point white, and draw it as a segment but only on layer 5. When you save the file, however, it will look like this:
vert = .free(.123, .456, .l5);
There's no need to write ".white" or the ".segment" as they are defaults. Geometer does, however, write the non-standard layering specification ".l5".

So don't spend a lot of time working on the formatting of your Geometer files in the editor. As soon as you let Geometer write it out, it will do as it pleases, simplifying as many things as possible and clobbering all of your careful formatting work.

When you type in properties, the order doesn't matter. the following two lines are exactly equivalent from Geometer's point of view:

 l1 = .l.vv(v1, v2, .dashline, .green); 

and

 l1 = .l.vv(v1, v2, .green, .dashline); 

When you write a file, Geometer puts them in some order that may be different from the order you typed them in, but the net result is the same. (The order of the required parameters---in this case v1 and v2---does make a difference. Even here for a line connecting two points, if that line is changed to be displayed as a ray, the origin of the ray is the first point specified, so reversing v1 and v2 would flip the direction of the ray.)

Look in the reference section at the end of this chapter for a concise list of the available property types, and for a complete list of the Geometer commands, together with their features.

In Geometer files, the parameters are separated by commas, and the commands are terminated by a semicolon. There is no need for the commands to occupy a single line; newlines and white space are ignored by Geometer (except, of course, within text strings).

If it isn't obvious already, Geometer tries to use sensible command names. After the leading period, the first part of the name signifies what type of geometric object is being created. After that is another period, followed by the types of things the new item will depend upon. For example, to make a point where two lines intersect, use the command ".v.ll". To make a circle passing through three points, use ".c.vvv".

Sometimes the name includes additional information. To make the line passing through a point and parallel to another given line, use ".l.vlpar". The command to make the perpendicular line also requires a point and a line, so it's name is ".l.vlperp". This convention makes it easy to remember most of the Geometer commands, but if you have a bad memory, there's always the reference section.

Line Widths

The width of the lines used to draw lines, circles, arcs, polygons, conics, and Bézier curves is set to 1.0 by default. It can be set to any positive width with an entry that looks something like this:

line = .l.vv(vert1, vert1, .width=3.0);
The "3.0" above can be replaced by any positive number. Although Geometer's menu entries only allow for a fixed set of widths, any positive width is legal, but non-standard widths must be entered with the text editor. If the width is 1.0, that is the default, and no entry is put in the text version of that primitive.