numbas-extension-eukleides

Numbas Eukleides extension

This extension is a port of the Eukleides geometrical drawing language into Numbas’ JME system. In order to be compatible with JME, this version occasionally works differently to the original Eukleides language. The basic flow of constructing points and then drawing them has been retained, but some of the syntax is different.

Basic concepts

The function eukleides creates a diagram which you can include anywhere in a Numbas question.

A diagram consists of a list of objects, drawn into a frame which is shown on screen. The boundaries of the frame are automatically determined, or you can give explicit values.

The basic objects in a diagram are:

Drawing modifiers change how an object is drawn, for example changing the colour or size. Modifiers can be applied to single objects, lists of objects, or even chained together to create reusable styles.

Coordinates

All coordinates in Eukleides diagrams are specified in terms of the frame and then transformed onto the browser’s coordinates. The bottom-left of the diagram has coordinates (min_x,min_y) and the top-right of the diagram has coordinates (max_x,max_y). The positive horizontal direction is right, and the positive vertical direction is up.

Angles are measured anti-clockwise. The bearing 0 points right. Angles can be given in radians, e.g. rad(pi/4), or degrees, e.g. degrees(45).

Accessibility

It’s important that diagrams are accessible to as many people as possible. The Eukleides extension provides a variety of ways of doing this. It tries to do as much as it can automatically to improve accessibility, but you should bear accessibility in mind when designing diagrams.

Screenreaders

Users who can’t see the diagram might access it through a screenreader.

The first argument to the eukleides function is a title for the diagram, which a screenreader will read out. This title should briefly identify the diagram and describe its contents, for example, “A circle inscribed in a square”, or “Bar chart showing number of customers against month”.

The Web Accessibility Initiative has a good tutorial on describing complex images.

The user can then navigate inside the diagram to have individual objects described.

Eukleides automatically adds a text description to each object in the diagram. At minimum, this is just the name of the object, for example ‘line’ or ‘circle’. If the object is defined in terms of points which have been labelled, those will be used: “triangle through A, B, C” for example.

The object’s colour and drawing style will also be described, for example “gray dotted line segment through A, B”.

The text descriptions are designed not to reveal any information which is not visually obvious. If you add the verbose modifier to an object, information such as coordinates and angles will be used to provide a more precise description of the object.

While these descriptions can give a rough idea of the contents of a diagram, information such as relative positions or implicit meanings of objects will be missing. You can manually set the description for an object with the description function. For example, a circle inscribed in a square will just be described as “circle”; “circle inscribed in square A B C D” would be a more helpful description.

Colours

Eukleides provides a variety of colour schemes which have been designed to maximise accessibility, considering colour vision deficiency and other vision impairments. Most of these colour schemes are drawn from ColorBrewer.

The variables color1 to color6 are assigned to a set of colours which should be easily distinguishable by almost all sighted people, including those with colour vision deficiency.

The functions qualitative_color_scheme, sequential_color_scheme and divergent_color_scheme return lists of colours designed for different uses:

You can select other colours with the color() modifier, which accepts any colour specification accepted by CSS, such as hexadecimal format, RGB or HSL. You should not use other colours without considering contrast and CVD. The WebAIM link constrast checker is a good first port of call to check whether a pair of colours can be easily distinguished against each other and the background.

It’s a good idea to use aspects other than colour, such as the dotted and dashed modifiers, to distinguish objects.

Animation and interactivity

Eukleides diagrams can be made dynamic in several ways.

The variable time represents the number of seconds since the diagram was created. Diagrams which contain references to time are continually redrawn with updated values for time.

The variables mousex and mousey represent the position of the mouse cursor, or the position of the last touch on touchscreen devices, in diagram coordinates. When the mouse moves, the diagram is redrawn with update values of these variables.

A point on the diagram can be made draggable by applying the modifier draggable() to it when drawing it. Any other free variables in the diagram are interpreted as free parameters, and given the initial value of 0. You can explicitly give initial values for free variables in a dictionary as the last argument to the eukleides function.

When the user moves a draggable point, the system tries to position it as close as possible to the mouse by changing the values of the free variables. It does this by repeatedly picking values for the variables, redrawing the diagram, and measuring the distance between the drawn point and the cursor. A gradient descent algorithm homes in on the best solution within a few iterations.

The great advantage of this system is that you don’t need to explicitly provide a mapping between target coordinates and the free variables in your diagram. The algorithm will find a solution, even if the position of the dragged point is calculated indirectly.

Note: The solver algorithm assumes that draggable points move continuously, so will fail if the point’s position can only take discrete values. A workaround is to have a draggable point which can move continuously, and a second non-interactive point which takes the position you really want.

By default, moving a draggable point can affect any of the free variables in a diagram. You can give the draggable function an optional list of variable names that it’s allowed to affect.

How to construct a diagram

The basic template for a Eukleides diagram is the following:

eukleides("A diagram",[
  point(1,0)
, point(1,1) .. point(4,0)
])

The first argument of the eukleides function is a title, and the second argument is a list of objects to draw.

The great power of Eukleides lies in its ability to construct geometrical objects from other objects. In order to achieve this, use the let function to temporarily assign names to objects so you can refer back to them:

eukleides("A triangle",
  let(
    a, point(1,0)
  , b, point(3,1)
  , c, point(2,3)
  , [
      a..b..c filled color1
    , a..b..c
    ]
  )
)

The example above constructs three points, draws a filled triangle with those vertices, and then draws its outline.

There are several functions which construct common polygons, given a mixture of points and side lengths or angles.

eukleides("A right-angled triangle",
  let(
    [a,b,c], right(2,3)
  , [
      a..b..c
    , a,b,c
    ]
  )
)

The example above constructs a right-angled triangle with side lengths 2 and 3. The function right returns a set of points, which are assigned the names a, b and c. We then draw the outline of the triangle, and dots at each of the points.

Note that constructing an object doesn’t mean it’s automatically drawn. The second argument of eukleides evaluates to a list of objects to be drawn - you can draw objects more than once, in different styles, or not at all.

You can use vectors to translate any object in a diagram.

eukleides("A parallelogram",
  let(
    u, vector(1,0)
  , v, vector(1,2)
  , a, point(0,0)
  , [
      a, a+u, a+v, (a+u..a..a+v) open
    ]
  )
)

The example above translates the point a by two different vectors.

When you repeat a construction, you can often make your code easier to read by using the map function:

eukleides("Three congruent parallelograms",
  let(
    u, vector(1,0)
  , v, vector(1,2)
  , a, point(0,0)
  , b, point(4,2)
  , c, point(-1,3)
  , map(
      [x, x+u, x+v, (x+u..x..x+v) open]
    , x
    , [a,b,c]
    )
  )
)

Drawing modifiers change aspects of how objects are drawn, such as colour or shading style. When drawing an object, just write the modifier immediately afterwards to apply it. A modified object becomes a drawing data type, which collects up the object(s) being drawn with the modifiers, so you can’t use the result in further constructions. To minimise the inconvenience, we try to apply modifiers last: for example, (origin red) .. point(2,0) doesn’t work, but origin .. point(2,0) red does - the line segment is constructed before the red modifier is applied.

You can specify the bounding box of the diagram by providing the coordinates of the bottom-left and top-right of the box after the description:

eukleides("Axes and a point at (8,3)", -1,-1, 10,5,
  [ line(origin,deg(0))
  , line(origin,deg(90))
  , point(8,3)
  ]
)

If you don’t specify the bounding box, then Eukleides automatically picks one, containing all of the drawn elements.

Use in Numbas

To include a Eukleides diagram in a Numbas question, first enable the Eukleides extension. Then, create a variable whose definition is the code for your diagram, i.e. eukleides(title,objects). In the following, suppose the variable is called diagram.

To show the diagram to the student, type {diagram} in a content area, such as the question statement, a part prompt, or the advice. The diagram will be inserted into the content at this point.

The definition of your diagram can refer to other question variables, but any values set interactively by the diagram (all free variable names in the diagram’s definition) can’t be used by other question variables - the values of question variables are only evaluated once, when the question is created.

Reference

Data Types

angle
An angle. The positive direction is anti-clockwise, and 0 points right.
point
A single point.
line
An infinite line.
point set
An ordered list of points, interpreted as a line segment, an outline, or a polygon, depending on context.
circle
A circle, defined by its centre point and radius.
conic
A conic curve: an ellipse, hyperbola or parabola.
drawing
A collection of drawing modifiers, applied to a list of objects.
angle label
A curve showing the angle defined by three points.

Drawing modifiers

Colours: black, color1, color2, color3, color4, color5, color6, darkgray, gray, lightgray, white

arrow
Draw an arrow on line segments and angle labels, in the direction specified by forth or back.
arrows
Draw arrows on both ends of line segments and angle labels.
back
When half is applied, draw lines and curves in the backward direction. Arrows on line segments are drawn on the first point. Arrows on angle labels are drawn pointing clockwise.
bold
Text is drawn in boldface.
box
Points are drawn as solid squares.
closed
Point sets are drawn as closed polygons - the last point is joined to the first.
cross
Points are drawn as x shapes.
dashed
Lines are drawn with a dashed pattern, and filled shapes are drawn with stripes.
disc
Points are drawn as hollow discs.
dot
Points are drawn as solid dots.
dotted
Lines and filled shapes are drawn with a dotted pattern.
double
Segments and angle labels are marked with a double dash. If dotted is also applied, angle labels will instead be labelled with two dots.
entire
Draw lines and conics as far as possible in both directions.
filled
Point sets are drawn as filled polygons.
forth
When half is applied, draw lines and curves in the forward direction. Arrows on line segments are drawn on the last point. Arrows on angle labels are drawn pointing anti-clockwise.
full
Lines are drawn as continuous lines. This is the default.
half
Only draw lines and curves in the direction specified. The default is forwards.
italic
Text is drawn in italic style.
noarrow
Do not draw an arrow on segments or angle labels. This is the default.
nospoilers
Accessible descriptions will not give any information not explicitly given in the visual rendering.
open
Point sets are drawn as open paths.
origin
The point at coordinates (0,0).
plus
Points are drawn as + shapes.
right
Draw angle labels as right angles.
simple
Segments and angle labels are marked with a single dash.
transparent
Set the opacity to 0.5.
triple
Segments and angle labels are marked with a triple dash. If dotted is also applied, angle labels will instead be labelled with three dots.
verbose
Accessible descriptions give information not explicitly given in the visual rendering, such as coordinates and bearings.

Functions

*
+
-
  • - n: angleangle

    Flip the direction of the given angle.

..
/
altitude
  • altitude (A: point, B: point, C: point)line

    The line containing the first point and perpendicular to the segment between the second and third.

angle
angle_between
arc
  • arc (circle: circle, from: angle, to: angle)circle

    An arc of the given circle between the given angles.

  • arc (conic: conic, from: angle, to: angle)conic

    The portion of the given conic between the given arguments.

area
argument
  • argument (v: vector)angle

    Direction of the given vector.

  • argument (line: line)angle

    Direction angle of the given line.

  • argument (conic: conic)angle

    The direction of the given conic.

  • argument (conic: conic, p: point)angle

    Polar angle of the given point with respect to the center of the given conic.

barycenter
  • barycenter (points: point set, weights: list)point

    The barycenter of the given polygon.

bisector
  • bisector (A: point, B: point, C: point)line

    The bisector of the angle formed by the given points, and containing the second.

  • bisector (l1: line, l2: line)line

    The bisector of the two given lines.

cardinality
  • cardinality (set: point set)number

    Number of vertices in the given polygon.

center
  • center (set: point set)point

    The isobarycenter (centre of gravity) of the given polygon.

  • center (circle: circle)point

    The center of the given circle.

  • center (conic: conic)point

    The center of the given conic.

circle
  • circle (center: point, r: number)circle

    A circle centered at the given point and with the given radius.

  • circle (set: point set)circle

    The circle with the given segment as a diameter.

  • circle (A: point, B: point, C: point)circle

    The circle through the given points.

color
conic
deg
  • deg (degrees: number)angle

    Construct an angle in degrees.

degrees
  • degrees (v: angle)number

    Convert an angle to a number of degrees.

description
  • description (description: string)drawing

    Set the accessible description for the object being drawn.

distance
  • distance (a: point, b: point)number

    Distance between two points.

  • distance (l: line, p: point)number

    Distance between the given line and point.

  • distance (p: point, l: line)number

    Distance between the given point and line.

divergent_color_scheme
  • divergent_color_scheme (n: integer)list

    Get a list of colours for a divergent data set.

divergent_color_schemes
  • divergent_color_schemes (n: integer)list

    Get a list of colour schemesfor a divergent data set.

draggable
eccentricity
  • eccentricity (conic: conic)number

    The eccentricity of the given conic.

ellipse
  • ellipse (v: point, a: number, b: number, d: angle)conic

    An ellipse with the given center, major and minor axis, and rotated by the given angle.

equilateral
  • equilateral (p1: point, p2: point)list

    equilateral ([p1: point], l1: number, [orientation: angle])list

    Create an equilateral triangle from the given points. Can give up two two vertices; if fewer than two vertices are given must give the length of the first side and optionally the orientation of the first side.

eukleides
foci
  • foci (conic: conic)list

    The foci of the given conic.

font
group
homothetic
  • homothetic (p: point, origin: point, k: number)point

    Homothecy (reduction or dilation) of the first point with respect to the second, and the given scale.

  • homothetic (line: line, origin: point, k: number)line

    Homothecy (reduction or dilation) of a line with respect to the given point and scale factor.

  • homothetic (conic: conic, origin: point, k: number)conic

    Homothecy (reduction or dilation) of a conic with respect to the given point and scaling factor.

hsl
  • hsl (h: number, s: number, l: number)drawing

    Set the colour, in HSL format. H is between 0 and 360; S and L are between 0 and 1.

hsla
hyperbola
  • hyperbola (v: point, x: number, y: number, a: angle)conic

    A hyperbola with the given center, real and imaginary axis, and rotated by the given angle.

incircle
  • incircle (A: point, B: point, C: point)circle

    The circle inscribed in the triangle defined by the given points.

intersection
  • intersection (l1: line, l2: line)point

    The intersection point of two lines.

  • intersection (l: line, set: point set)point set

    All points at which the line intersects the perimeter of the given point set.

  • intersection (l: line, c: circle)point set

    All points at which the line intersects the given circle.

  • intersection (l: line, c: conic)point set

    All points at which the tline intersects the given conic.

  • intersection (s1: point set, s2: point set)point set

    All points at which the perimeters of the two point sets intersect.

  • intersection (c1: circle, c2: circle)point set

    The points of intersection of the two circles.

  • intersection (s: point set, c: circle)point set

    All points of intersection of the perimeter of the point set with the given circle.

isobarycenter
  • isobarycenter (set: point set)point

    The isobarycenter (centre of gravity) of the given polygon.

isosceles
  • isosceles (p1: point, p1: point, l2: number | a1: angle)list

    isosceles ([p1: point], [p2: point], [l1: number, l2: number | a1: angle, [orientation: angle]])list

    Create an isosceles triangle from the given points. Can give up to two vertices; one other length or angle; and the orientation of the first side if fewer than two vertices given.

label
line
  • line (origin: point, angle: angle)line

    A line with the given origin and direction.

  • line (A: point, B: point)line

    A line containing the two given points.

  • line (origin: point, u: vector)line

    A line with the given origin and direction vector.

  • line (set: point set)line

    A line containing the given segment.

list
  • list (ps: point set)list

    Convert a set of points to a list of points.

major
  • major (conic: conic)number

    The major axis of the given conic.

median
  • median (A: point, B: point, C: point)line

    The line containing the first point and passing through the midpoint of the segment between the second and third.

midpoint
minor
  • minor (conic: conic)number

    The minor axis of the given conic.

opacity
  • opacity (opacity: number)drawing

    Set the opacity. 0 is invisible and 1 is solid.

orthocenter
parabola
  • parabola (v: point, a: number, d: angle)conic

    A parabola with the given summit and parameter, rotated by the given angle.

  • parabola (A: point, l: line)conic

    A parabola with the given focus and directrix.

parallel
  • parallel (line: line, p: point)line

    A line parallel to the given line and containing the given point.

  • parallel (set: point set, p: point)line

    A line parallel to the given segment and containing the given point.

parallelogram
  • parallelogram (p1: point, p2: point, p3: point)list

    parallelogram (p1: point, p2: point, [l2: number, a1: angle])list

    parallelogram ([p1: point], [l1: number, l2: number, a1: angle, [orientation: angle]])list

    Create a parallelogram from the given points. Can give up to three vertices. If fewer than two vertices given, must give the length of the first side, one more side and an angle, and optionally the orientation of the first side.

perimeter
  • perimeter (set: point set)number

    Total length of the given polygon's edges.

perpendicular
  • perpendicular (line: line, p: point)line

    A line perpendicular to the given line and containing the given point.

  • perpendicular (set: point set, p: point)line

    A line perpendicular to the given segment and containing the given point.

perpendicular_bisector
  • perpendicular_bisector (set: point set)line

    The perpendicular bisector of the given segment.

point
  • point (x: number, y: number)point

    A point at the given coordinates.

  • point (r: number, a: angle)point

    A point at the given polar coordinates.

  • point (set: point set, t: number)point

    A point along the first edge of the given polygon.

  • point (line: line, t: number)point

    A point on the given line, the given distance away from its origin.

  • point (circle: circle, a: angle)point

    A point on the given circle at the given angle.

  • point (conic: conic, t: number)point

    A point with the given argument on the given conic.

point_with_abscissa
  • point_with_abscissa (line: line, x: number)point

    A point on the given line with the given abscissa, with respect to the implicit coordinate system.

point_with_ordinate
  • point_with_ordinate (line: line, y: number)point

    A point on the given line with the given ordinate, with respect to the implicit coordinate system.

polygon
  • polygon (points: list of multiple point)point set

    Construct a polygon from the given list of points.

  • polygon (n: number, origin: point, r: number, a: angle)point set

    A regular polygon with the given number of sides and circumradius, with center at the given point and rotated by the given angle.

projection
  • projection (A: point, l: line)point

    The projection of point A onto line l.

  • projection (A: point, l1: line, l2: line)point

    The projection of point A in the direction of line l2 onto line l1.

qualitative_color_scheme
  • qualitative_color_scheme (n: integer)list

    Get a list of colours for a qualitative data set.

qualitative_color_schemes
  • qualitative_color_schemes (n: integer)list

    Get a list of colour schemes for a qualitative data set.

rad
  • rad (radians: number)angle

    Construct an angle in radians.

rectangle
  • rectangle (p1: point, p2: point, [l2: number])list

    rectangle ([p1: point], [l1: number, l2: number, [orientation: angle]])list

    Create a rectangle from the given points. Can give up to two vertices. If fewer than two vertices given, must give the length of the first side. Must give the length of one more side and optionally the orientation of the first side.

reflect
rgb
rgba
right
  • right (p1: point, p2: point, [l2: number | a1: angle], [orientation: angle])list

    right ([p1: point], [p2: point], [l1: number, [l2: number | a1: angle], [orientation: angle]])list

    Create a right-angled triangle from the given parameters. Can give up to two vertices; one other length or angle; and the orientation of the first side if fewer than two vertices given.

rotate
  • rotate (p: point, origin: point, angle: angle)point

    Rotate the first point the given angle around the second.

  • rotate (v: vector, a: angle)vector

    Rotate a vector by the given angle.

  • rotate (line: line, origin: point, angle: angle)line

    Rotate a line by the given angle around the given point.

  • rotate (set: point set, origin: point, a: angle)point set

    Rotation of a polygon by the given angle around the given point.

  • rotate (conic: conic, origin: point, a: angle)conic

    Rotate a conic by the given angle around the given point.

segment
  • segment (set: point set, p: point)point set

    A segment from the first point of the given polygon to the given point.

sequential_color_scheme
  • sequential_color_scheme (n: integer)list

    Get a list of colours for a sequential data set.

sequential_color_schemes
  • sequential_color_schemes (n: integer)list

    Get a list of colour schemes for a sequential data set.

size
square
  • square (p1: point, p2: point)list

    square ([p1: point], [l: number, [orientation: angle]])list

    Create a square from the given points. Can give up to two vertices. If fewer than two vertices given, must give the length of the first side and can optionally give the orientation of the first side.

symmetric
  • symmetric (p: point, origin: point)point

    180° rotation of the first point around the second.

  • symmetric (line: line, p: point)line

    180° degree rotation of a line around the given point.

  • symmetric (set: point set, p: point)point set

    180° degree rotation of the given polygon around the given point.

  • symmetric (conic: conic, p: point)conic

    180° rotation of the given conic around the given point.

tangent
  • tangent (circle: circle, a: angle)line

    A line tangent to the given circle at the given heading.

  • tangent (conic: conic, t: number)line

    A line tangent to the given conic at the given argument.

text
triangle
vector
  • vector (set: point set)vector

    Vector from the first point of the polygon to the second.

  • vector (line: line)vector

    Unit vector in the direction of the given line.

x
y