Coronavirus (Covid-19): Latest updates and information
Skip to main content Skip to navigation

DoNaLD - a Definitive Notation for Line Drawings

DoNaLD is a definitive notation for 2D line drawings. It was originally specified in Warwick Computer Science Research Report 086. A subset of the specification was first implemented by Edward Yung and subsequently modified by many other authors. The notation as it stands remains some distance away from what is specified in the research report. One of the objectives of this document is to state what is supported in the current version of DoNaLD.

Variable names and data types

Variable names

x
refers to the variable x in the immediate context
~/x
refers to the variable x in the context one level up
/x
refers to the variable x in the root (topmost) context
x!
refers to an Eden variable
Note:
  • DoNaLD variables need to be declared before use.
  • Eden variables (ending with !) do not need to be declared and would not be type-checked by DoNaLD. To help the type-checker, it is advisible to surround the variable with trunc() or float() to force the expression to int or real type.
  • pi is a predefined constant 3.14159. It cannot be redefined as a variable associated with any context.

Data types

TypeExample
int34
real10.0
char"abc"
booleantrue, false
point{50, 100}, {modulo @ angle}
line[{10,10}, {80, 90}]
circlecircle(centre, radius), circle({500,500}, 400)
ellipseellipse(centre, major, minor)
rectanglerectangle({100, 100}, point1)
imageI!ImageFile("gif", "hill.gif")
labellabel L1, L2
L1 = label("abc", {100,100})
image img
L2 = label(img, {200,100})
openshapeopenshape cross
 within cross {
  line l1, l2
  l1 = [{10, -10}, {-10, 10}]
  l2 = [{10, 10}, {-10, -10}]
}
shapeshape S
S = trans(cross, 100, 200)
graphfunc sqr { return $1 * $1; }
%donald
graph g
within g {
  x<i> = 1.0 + <i>
  f<i> = sqr!(x<i>)
  nSegment = 9
  node = [circle:circle({x<i> * 100, f<i> * 10}, 10);
    label:label("(" // rtos(x<i>, ".0f") // "," // rtos(f<i>, ".0f") // ")", {x<i> * 100, f<i> * 10 + 20})]
  segment = [line:[{x<i-1>*100, f<i-1>*10}, {x<i>*100, f<i>*10}]]
}

Functions

Arithmetic operators and functions

+
-
*
div (division)
mod
sqrt (square root)
log
exp
trunc (convert real to integer)
float (convert an integer to real)
rand (random number generator)
- int rand(int) or real rand(real)
if the argument is an integer, say 10, rand(10) returns a random number ranged from 0 to 9 inclusive;
if the argument is a real, say 1.0, rand(1.0) returns a random number ranged from 0.0 to 1.0 inclusive.

Trigonometric functions

sin
cos
tan
asin
acos
atan
- accept only real arguments

Relational operators

&& (and)
|| (or)
! (not)
<
<=
== (equal)
>
>=

Geometric functions

point midpoint(line)
- mid-point of a line
point intersect(line, line)
- intersection point of two lines
line perpend(point, line)
- the perpendicular line intersecting the point
real dist(point, point)
- distance between two points
bool intersects(line, line)
- whether the lines intersect
bool separates(line, point, point)
- whether the line separates the two points
bool includes(circle, point)
- whether the point is inside the circle
bool incident(line, point)
bool incident(circle, point)
- whether the point coincides with the path
bool pt_betwn_pts(point, point, point)
- whether the 2nd point is within the box bounding the 1st and the 3rd point
bool colinear(point, point, point)
- whether the points are colinear
bool distlarger(point, point, value)
bool distlarger(line, point, value)
bool distsmaller(point, point, value)
bool distsmaller(line, point, value)
- whether the distance from the point to the point/line is larger than or smaller than the specified value

Shape transformations

trans(shape, x, y)
- translate a shape (or openshape)
scale(shape, ratio)
- scale a shape (or openshape) wrt the origin of the coordinate system; would not change the font size or the image size of labels
rot(shape, point, angle)
- rotate a shape round a point by a certain angle

String functions

//
string concatenation
itos(int)
- integer to string conversion
rtos(real, format-string)
- real to string conversion. format-string would be as required by the C function fprintf().

Image functions

Example:
%donald
real xscale, yscale
xscale, yscale = 0.8, 0.8

image zoom, source
source = I!ImageScale(I!ImageFile("gif", "logo.gif"), xscale, yscale)
zoom = I!ImageScale(I!ImageCut(source, 20, 0, 200 * xscale, 200 * yscale), 
	xscale, yscale)

label imgzoom, imgsrc
imgzoom = label(zoom, {500, 200})
imgsrc = label(source, {500, 700})
The images are centred at the specified position (same for string labels). I!functionName denotes a function returning an image. This function is translated to an Eden function named as functionName. The arguments are not fully type-checked, so may sometimes cause a problem. Since this kind of function does not need to be declared beforehand, DoNaLD can easily be extended to make use of image filters chosen by the user. (See examples in $PUBLIC/lib/tkeden/scout.init.e for examples of image filters.)

Other functions

circle(center, radius)
ellipse(center, extreme_point1, extreme_point2)
rectangle(corner1, corner2)
label(string, position)
if boolean_expression then expr else expr
.1, .2
- 1st and 2nd points of a line or 1st and 2nd coordinate of a point, for example:
line l
l = [{0,0}, {100,100}]
point p
p = l.2		# i.e. {100,100}
real x
x = p.1		# i.e. 100
.x, .y
- the projection of a point onto the x- and y- axies, e.g.:
point p, q
p = {100, 200}
q = p.x		# i.e. {100, 0}

Graphs

  • A graph comprises of nSegment number of segments and nSegment + 1 number of nodes. But there may be many visualisations of the same node or segment.
  • x<i> and f<i> have to be defined even though they may not be used in the node/segment definitions.
  • Both node and segment have to be defined. Should no visualisation be associated with either node or segment, define that variable to be []
  • Due to DoNaLD's limitations, once a variable is declared as one type, it cannot be redeclared to another type. So if the first visualisation of the node is a circle, any subsequent redefinition to the node must have the first element declared as a circle. However, you need not give any definition to it.
  • A DoNaLD graph will declare a series of node and segment entities accessible in DoNaLD. The nodes are named as node1_1, node1_2, etc. and the segments are named as segment1_0, segment1_1, etc., where the first number represents which visualisation of the entity and the second number is concerned with which node or segment. You can redefine the individual nodes and segments without any complaint from the system (BUG?).

Attributes

You may like to give a line or a shape a different look, by specifying a wider linewidth or a different colour. Every DoNaLD variable that can be displayed has an attribute variable (an EDEN variable) for you to modify its presentation. Integers, reals, booleans and chars have no immediate graphical representation, hence no attribute variables accompany them. Interestingly enough, openshape does not have attributes either. This is because openshape is not a shape but a collection of shapes. Its subshapes may each have an attribute but the openshape itself has not.

The attribute variables are EDEN variables, and are named after the translated name of the DoNaLD variables in EDEN. The attribute variable name for the DoNaLD variable Obj/line1 would be A_Obj_line1. Attributes are of the form:

"attr1=value1,attr2=value2..."

The set of attributes available may vary from one implementation to another. For tkeden, legal attributes are:

outlinecolor
applicable to: any shape
acceptable values: any X-Windows recognised colour name + transparent
color
applicable to: closed shapes
acceptable values: any X-Windows recognised colour name + transparent. This is the fill colour of the shape. Note that older versions of tkeden had no outlinecolor - color specified both outline and fill colours.
linewidth
applicable to: line, arc, circle, shape
acceptable values: positive integers, 0 = minimum line width
linestyle
applicable to: line
acceptable values: dotted, dashed, solid
arrow
applicable to: line
acceptable values: first, last, both, none followed by 2 spaces)
locus
applicable to: any shape
acceptable values: true, false
fill
applicable to: any shape
acceptable values: solid, hollow

Notes:

  • There must not be any space character in the attribute string.
  • Attributes will affect all the graphical objects within a shape. If the shape is the transformation (rotation, translation or scaling) of an openshape, the attributes given to the shape will override the attributes given to the individual shapes within the openshape.

Viewports

Viewports are workspaces where the graphical objects are placed. For the stand alone usage of DoNaLD, viewport should not be defined. Since Scout, a definitive notation for describing screen layout, has the ability to show different pictures in different (Scout) windows, when DoNaLD is used in conjunction with Scout, viewport is a useful way of separating objects into different pictures. In DoNaLD, the line:

viewport VIEW1

means that from that line onwards the graphical objects to be declared (not defined) will be associated with the viewport VIEW1. All viewports share the same conceptual space, and variables in one viewport can freely make reference to variables in other viewports. Viewports need not be displayed. Hence it is useful to dump intermediate or conceptual objects into a viewport which will not be displayed.

For backward compatibility, declaring DoNaLD variables without first declaring a viewport will create a default viewport displaying on a separate screen. This default viewport is named as DoNaLD.

Comments

DoNaLD uses # as the comment symbol. Comment starts from # to the end of the line.

Escape to EDEN

There are two ways of escaping from DoNaLD to EDEN.

  1. A line beginning with ? will be passed to EDEN directly. Like the DoNaLD comments, this is only for one line escape. The one line escape is particularly useful for defining attributes. For example:
    line cable
    ?A_cable is "linestyle=dotted";	/* this defines the attribute of cable */
    cable = ...		# this is a DoNaLD definition
    

    Not only is this escape method convenient in this case, it also gives the attribute definition a sense of close association with the DoNaLD variable.

  2. Switching to EDEN and back is useful if several EDEN statements are included in a DoNaLD script.
    line cable
    %eden
    A_cable is "linestyle=dotted";	/* this defines the attribute of cable */
    %donald
    cable = ...		# this is a DoNaLD definition
    

Bugs

  • The maximum number of nested openshapes is 128.
  • atan2: DOMAIN error It is a warning message only, does not affect the operation of tkeden. It occurs when the two end-points of an arc are the same.
  • Eden variables in DoNaLD (identifiers ended with !) do not need to be declared and so the type checker may be confused with polymorphic operators such as arithmetic operators. In most cases, you can use trunc() or float() to force the variable to int or real.

(Note: this document was originally titled the "Quick Guide to DoNaLD".)

Example models:

• roomviewerYung1989
• cogRoe1999