MODULE Xform2; (* Procedures for transforming 2-D points. *) IMPORT R2; (* \subsection{Point Transformations} *) (* The following procedures transform 2-D points into 2-D points. *) PROC res := Translate(q, p) IS res := R2.Plus(p, q) END; (* "res" is the point "p" translated by the vector "q". *) PROC res := Scale(scale, p) IS IF VAR sx, sy, px, py IN scale = (sx, sy) AND p = (px, py) -> res := (sx * px, sy * py) END FI END; (* "res" is the point "p" scaled about the origin by the scale factor "scale", which must be a pair of real numbers representing the x- and y-scale factors. *) PROC res := Rotate(theta, p) IS IF VAR px, py, cos = COS(theta), sin = SIN(theta) IN p = (px, py) -> res := (cos * px - sin * py, sin * px + cos * py) END FI END; (* "res" is the point "p" rotated by "theta" radians about the origin. *) (* \subsection{Transformation Closures} *) (* The following procedures produce closures that transform 2-D points into 2-D points. There is also a procedure for composing closures functionally. In the comments for the following procedures, we write "cl(p)" as a shorthand for "APPLY(cl, p)", where "cl" denotes a closure with one IN parameter and one OUT parameter. *) PROC cl := TranslateCl(q) IS cl := CLOSE(Translate, q) END; (* "cl" is a closure such that "cl(p)" evaluates to "Translate(q, p)". *) PROC cl := ScaleCl(scale) IS cl := CLOSE(Scale, scale) END; (* "cl" is a closure such that "cl(p)" evaluates to "Scale(scale, p)". *) PROC cl := RotateCl(theta) IS cl := CLOSE(Rotate, theta) END; (* "cl" is a closure such that "cl(p)" evaluates to "Rotate(theta, p)". *) PRIVATE PROC res := ComposeClsProc(cl2, cl1, p) IS res := APPLY(cl2, APPLY(cl1, p)) END; PROC cl := ComposeCls(cl2, cl1) IS cl := CLOSE(ComposeClsProc, cl2, cl1) END; (* Set "cl" to a closure such that "cl(p)" is equivalent to "cl2(cl1(p))". *)