# Functions

##  Bounding Box

###  savebox and restorebox

Functions savebox and restorebox respectively save the current bounding box and restore it.

```def savebbox =
interim bboxmargin := 0;
save _bbox; path _bbox; _bbox = bbox currentpicture;
enddef;
```
```def restorebbox =
setbounds currentpicture to _bbox;
enddef;
```

###  smashdraw and phanthomdraw

Function smashdraw allows drawing things without affecting the current bounding box:

```vardef smashdraw text command =
savebbox;
command;
restorebbox;
enddef;
```

Function phanthomdraw is the opposite of smashdraw, it affects the bounding box as if the drawing command had been executed, however, nothing is drawn.

```vardef phantomdraw text command =
interim bboxmargin := 0;
setbounds currentpicture to bbox image(command) -- bbox currentpicture -- cycle;
enddef;
```

Example:

```draw fullcircle scaled 10 withcolor blue;
smashdraw draw fullcircle scaled 10 shifted (50,50) withcolor red;
phantomdraw draw fullcircle scaled 10 shifted (-50,-50);
```

###  drawbefore

Drawbefore lets you draw things under the current drawing.

```vardef drawbefore text commands =
save pic; picture pic;
pic := currentpicture;
currentpicture := nullpicture;
commands;
enddef;
```

##  Generating shapes

###  polygon

A simple function that returns a regular polygon.

```vardef polygon(expr sides) =
for i = 0 upto sides - 1:
((1,0) rotated (360/sides * i)) --
endfor
cycle
enddef;
```

###  wavepath

Function wavepath generates a wave along a given path. You specify the wavelength and the angle at which the wave should intersect the original path.

```vardef wavepath(expr apath, wavelength, angle) =
for time = 0 step wavelength until arclength apath:
hide(_ta := arctime time of apath;
_tb := arctime (time + wavelength/2) of apath;)
if time > 0: .. fi
point _ta of apath {(direction _ta of apath) rotated angle} ..
point _tb of apath {(direction _tb of apath) rotated -angle}
endfor
if cycle apath: .. cycle fi
enddef;
```

###  cloud

Function cloud generates a cloud-like shape along a given cyclic path, consisting of a given number of segments.

```vardef cloud(expr p, segments) =
save thestep, lasttime, thistime, lastpoint,  thisdir, lastdir, cpath, xpath;
thestep = arclength(p)/segments;
numeric lasttime; lasttime = 0;
cloudangle:=5;
cloudperc:=.1;
for i = 1 upto segments:
hide(
numeric thistime;
pair lastpoint, thispoint, lastdir, thisdir;
path cpath, xpath;
thistime = arctime (i if i < segments: + uniformdeviate(0.2) fi)
*arclength(p) / segments of p;
lastpoint = point lasttime of p;
thispoint = point thistime of p;
lastdir = (direction lasttime of p) rotated (-cloudangle + uniformdeviate(10));
thisdir = (direction thistime of p) rotated (cloudangle + uniformdeviate(10));
cpath = lastpoint{lastdir} .. {thisdir}thispoint;
xpath = subpath (1-cloudperc-uniformdeviate(0.1), 1) of cpath reflectedabout(thispoint, thispoint + (thisdir rotated 90));
lasttime := thistime;
)
cpath -- (reverse xpath) & xpath --
endfor
cycle
enddef;
```

###  rounded rectangle

```vardef roundedrect(expr pa, pb, rdist) =
(xpart pa + rdist, ypart pa) --- (xpart pb - rdist, ypart pa) ..
(xpart pb, ypart pa + rdist) --- (xpart pb, ypart pb - rdist) ..
(xpart pb - rdist, ypart pb) --- (xpart pa + rdist, ypart pb) ..
(xpart pa, ypart pb - rdist) --- (xpart pa, ypart pa + rdist) ..
cycle
enddef;
```