|
Sections: Introduction
|
General programming rules
|
Using variables
|
Drawing simple objects
|
More geometry
|
Advanced programming
|
Now what?
|
|
Introduction
g2d is an intuitive language that allows you to create, manipulate, and draw 2D geometrical objects, by creating sets of written statements (or instructions) named programs.
As you will see, g2d supports several levels of complexity. You can as well program a fast drawing knowing very few instructions, and you can later get familiar with more advanced features when you want to make a more sophisticated picture.
If you are already familiar with a programming language (Basic, FORTRAN, Pascal, C, C++) or with a scripting language, your learning curve will be very steep, while you will appreciate several unique features that you may have missed in other languages.
|
|
General programming rules
-
Write one (or zero) instruction per line: you cannot group several instructions in one line.
-
Except around keywords, as in for i=1 to n do x=x*i, spaces are optional. You can add spaces and tabs to indent lines if you find it convenient. You can add spaces wherever you find that they improve your program's legibility.
C = circle ( intersect ( L1 , L2 ) , || u || )
-
All text after a double-slash // and until the end of the line is not considered as part of an instruction. This is called a comment, you can use comments to provide information in your program. You can also comment out lines to make them temporarily inactive.
// uncomment lines below to make huge red stroke // penwidth(10) // pencolor(red)
- Functions and commands take parameters. Parameters follow the command, grouped between parentheses, and separated with commas.
draw(segment(polar(1,45°),(cos(a),y0)))
Using variables
You store values or objects in variables. A variable may be any string (except a reserved term) starting with a letter and containing only letters and digits (not underscore). g2d ignores cases: if your program defines a point A, then a real number a, the latter will override the former, so the reference to the point will be lost.
You assign a value to a variable with the equal sign =
n = 10
r = 1/n
Ang1 = 60°
Defining a (simple) variable just consists in assigning it a value for the first time.
|
Drawing simple objects
The basic entity is the 2D point or 2D vector (g2d makes no difference between a point and a vector). Using points and vectors, you will define more complex objects.
A point or a vector is an array of two numbers. To define an array, use parentheses, and separate the components of the array with a comma.
P1 = (1,1)
M = (cos(Ang1),sin(Ang1))
The origin O and the two unit vectors ux, uy are preset, as if your program started with the following lines.
O = (0,0)
ux = (1,0)
uy = (0,1)
To plot a single point, use the mark command.
mark(P1)
|
To draw crosses larger than the default size, this example uses ticksize(2) and tickpenwidth(2).
|
|
The next step is to draw lines. The commands to make lines are: line, ray, and segment. They make, respectively, an infinite line, a semi-infinite line, and a line segment. You define any of these objects by providing two points. (For a ray, the first point is its origin.) The axes Ox and Oy are preset, as if your program included the following lines.
Ox = line(O,ux)
Oy = line(O,uy)
If you use line, ray, or segment without storing its result into a variable, g2d understands that you want to draw the object: this is named implicit drawing.
segment(O,ux) // implicitly draws the segment
Otherwise, you draw the object by explicitly using the draw command.
S = segment(O,uy)
draw(S)
You can use the mark command with lines: to mark the endpoints of a segment, to tick a segment, or to mark angles.
mark(ux,O,uy) // mark a right angle
|
The axes use penwidth(1/2), while the two segments use penwidth(2). The text uses textfont("Arial") and textsize(12).
|
|
Like you made lines or segments by providing two points, you define other geometrical objects by providing appropriately points and values.
To make a circle or a disk, provide the center and the radius to the commands circle or disk: circle(C,r), disk(C,r).
circle((-1, 1), 1/3)
c0 = circle(O,1/4)
fillcolor(yellow)
drawfill(c0)
Alternately, you can define a circle or a disk by providing three (non colinear) points.
circle((2/3,1),(4/3,1),(1,2/3))
Three points may also define an arc: arc(P1, P2, P3). Or you can define an arc by providing its center, its radius, and two angles. The arc is drawn counterclockwise.
arc(O,1,225°,-45°)
Circles and disks really behave the same, except when implicitly drawn: circle draws the boundary, disk draws the inside. To draw both the boundary and the inside, you have to use the drawfill command (with either object.)
|
The arrows on the axes are given by arrow(2*ux, 0) and arrow(2*uy, 90°). The units are marked with mark(ux, Ox) and mark(uy, Oy).
|
|
To draw text, use the name command, and provide it with a location (a point) and with a string (text between double-quotes).
name(ux - uy, "x = -y")
By default, name will use the location as the bottom left corner of the text. To offset the text, use a bracketed positional parameter: prefix the string with one or two letters between brackets [...]. The letters may be: l for left, r for right, t for top, b for bottom, and h for here (centered).
name(O, "[lb]O")
To make a superscript, use hat ^. To make a subscript, use underscore _. To group several characters as a subscript or superscript, use braces: "a_{i+j}". To write a greek letter, prefix its English name with backslash \; for upper case greek letters, capitalize the letter's name. You can also enter most of the LaTeX mathematical symbols.
name(ux+uy,"[h]\alpha^2 \equiv \pi^2/16")
The language includes advanced features to print text easily: smart naming and auto naming. When you use the smartname command instead of name, the text will print shifted in the direction opposite to the center of the figure.
Auto naming consists, when calling name (or smartname), in passing several points but only one string: the program will affect that name to the first point, and will compute "logically" the names of the other points.
polygon(A, B, C, D)
smartname(A, B, C, D, "P_1")
If the string ends with a number, the number is incremented. Otherwise, the first letter of the name is incremented.
|
A strong blue line: penwidth(2), pencolor(blue).
When you know how to use arrays, you can write simply smartname(A, "P_1") and have all the points named.
|
More geometry
You can define other kinds of geometrical objects than lines and circles: you can make ellipses, polygons and curves. For an ellipse, provide the center and the major and minor half-axes. brokenline, curve, polygon and potato are very similar: all four commands take a list of points as their parameter. polygon and potato are closed, curve and potato are smooth.
Another route to make a new geometrical object is to apply a geometrical operator to an existing object or to existing objects. The most basic operators are the translation and the rotation: you can apply translate(theObject, anOffset), rotate(theObject, aCenter, anAngle), and rescale(theObject, aScale) to any geometrical object. Other commands to make new geometrical objects from existing ones include parallel, project, symmetric and intersect.
E1 = ellipse(O, ux + 2 * uy, ux / 2)
E2 = symmetric(E1, Oy)
EE = intersect(E1, E2)
fill(EE)
draw(E1, E2)
|
|
Advanced programming
When you want make more than a short program, you will probably want to use lists of numbers, or of objects: those are arrays.
You store an array in an ordinary variable, for instance A. To refer to an element of the array, you suffix the variable's name with the desired index between brackets: u = A[1], A[i] = pi/2. The size of an array A is size(A).
Unlike in most other languages, you decide whether the array is 0- or 1-based. If you declare an array A of size N, you can use either A[0] ... A[N-1], or A[1] ... A[N]. Actually the array is periodic: if you assign values to A[0] ... A[N-1], your program can use A[N], which refers to the exact same element as A[0].
You already declare arrays: a point is really a 2-array, and a color is a 3-array. For points you use the implicit declaration: M = (3, 2). To declare an array of any size, you can use implicit declaration, which consists in affecting a value to each of its elements, grouped between parentheses and separated with commas. You can store any kind of item in an array.
A = (Ox, Oy, line(O, ux + uy), line(O, ux - uy))
Or you can use explicit declaration, in which case the values of the elements may be assigned later. The explicit declaration consists in writing the name of the array, followed by its size between brackets: A[4]
V[5]
for i = 1 to 5 do V[i] = c + polar(r, 90° + 4*pi * i/5)
|
You may want to use advanced declaration, which makes an array with all its elements already assigned a value. This uses the array command. The first argument of array is the array's size.
array(N, xmin, xmax) returns N evenly spaced values from xmin to xmax.
array(N, xmin, xmax, random) returns N random numbers.
array(N, "[formula]") returns N values computed after a formula.
array(N, ("[Xformula]", "[Yformula]")) returns N points whose coordinates are computed after formulae: you are really generating a curve, that you can view with the curve command.
curve(array(200,("sin(2*a)","sin(3*a)")))
In the formula, use i (the integer index), x (runs from -1 to 1), or a (from -pi to pi).
|
|
|
If your program involves several copies of the same block of lines, or very similar blocks, you can make the block into a separate subroutine, and replace each block with a call to the subroutine. You declare a subroutine with the function keyword, which must be balanced with an end line. A subroutine may return a value (the subroutine is then really a function): terminate the subroutine with return followed by the value to return.
global r
function star5(c)
V[5]
for i = 1 to 5 do V[i] = c + polar(r, 90° + 4*pi * i/5)
fill(polygon(V))
end
background(blue / 3)
fillcolor(yellow)
r = 0.1
for i = 1 to 20 do star5(array(2, -2,2, random))
If your subroutine has to share some variables with the rest of the program, declare those variables as global in the first lines of the program with the global keyword: global scale, r, NMax.
|
The program is indented for better legibility only. Indenting is optional: g2d does not need the program to be indented. Indent your program only if you find it helpful.
|
|
The structure to repeat the same instructions several times is named a loop: indexed loop or conditional loop. In an indexed loop, the iterations are controlled by an index assuming integer values between two bounding values. The indexed loop uses the for keyword. You can make a one-liner loop with the do keyword.
for i = 1 to 3 do draw(C[i])
To include several instructions in a loop, encapsulate them between a for line and an end line.
for i = 1 to 3
draw(C[i])
fill(D[i])
end
Conditional loops use the repeat while or repeat until keyword. They require encapsulation between the repeat line and an end line.
repeat until (i * i > 50)
draw(C[i])
i = i + 1
end
|
|
If you use subroutines, or loops, you probably have to program tests.
A test uses the if keyword. Enclose the boolean expression between parentheses.
You can write a one-line conditional instruction.
if ((i mod 2) = 0) then draw(C)
Or you can do conditional branching. Here the if line must be balanced with an end line.
if ((i mod 3) = 0) then
draw(C)
else if ((i mod 3) = 1) then
fill(C)
else
drawfill(C)
end
|
Now what?
-
Probably you will find it easier to make your first g2ds by copying from existing examples. The main page includes a link to the list of the examples. When you copy a g2d program - and depending on your browser - you may be copying additional white spaces. This is not a problem, g2d supports optional spaces in the programs.
-
When you do not know the name for a command, use the thematic list in the main page. That list displays all the commands, in small characters. Each command is really a link to the section where that command is explained in all details in the Language Reference for g2d.
-
If you feel easier so, you may want to read the Language Reference right now.
|