(* Copyright (C) 1989, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* Last modified on Fri Jun 26 18:51:54 PDT 1992 by harrison *) (* modified on Mon Nov 18 23:09:06 PST 1991 by gnelson *) (* modified on Thu Nov 2 18:28:27 1989 by muller *) (* modified on Mon Oct 2 10:21:21 1989 by kalsow *) (* modified on Fri Jun 3 16:22:22 PDT 1988 by glassman *) (* modified on Thu Aug 13 18:24:20 PDT 1987 by luca *) (* modified on Thu Mar 5 17:17:13 1987 by msm *) (* A "RealRect.T" is a set of points lying in a rectangle with its sides parallel to the coordinate axes. The directions of the screen are named after the compass points, with north at the top. A rectangle "rect" contains a point "pt" if | pt.h `is in` [rect.west .. rect.east - 1] AND | pt.v `is in` [rect.north .. rect.south - 1] We impose the restriction that if a rectangle contains no points, then it must be equal as a record to "RealRect.Empty". *) INTERFACE RealRect; IMPORT Axis, Interval, Point; TYPE T = RECORD west, east, north, south: REAL END; TYPE Edge = {W, E, N, S}; TYPE Vertex = {NW, NE, SW, SE}; CONST Empty = T {0.0, 0.0, 0.0, 0.0}; (* An empty rectangle *) CONST Full = T {FIRST(REAL), LAST(REAL), FIRST(REAL), LAST(REAL)}; (* The biggest possible rectangle *) (* --- Initialization --- *) PROCEDURE FromEdges(w, e, n, s: REAL): T; (* If "w >= e" or "n >= s" return "Empty", else return "T{w,e,n,s}". *) PROCEDURE FromAbsEdges(h1, h2, v1, v2: REAL): T; (* Return | FromEdges(MIN(h1,h2), MAX(h1,h2), | MIN(v1,v2), MAX(v1,v2)) *) PROCEDURE FromR2(READONLY p: R2.T): T; (* Return the rectangle whose only element is "p". *) PROCEDURE FromCorners(READONLY p, q: R2.T): T; (* Return "FromAbsEdges(p.h,q.h,p.v,q.v)". *) PROCEDURE FromCorner( READONLY p: R2.T; hor, ver: CARDINAL): T; (* Return "FromEdges(p.h, p.h+hor, p.v, p.v+ver)". *) PROCEDURE FromSize(hor, ver: REAL): T; (* Return "FromCorner(Point.Origin,hor,ver)". *) PROCEDURE Center(READONLY r: T; READONLY p: Point.T): T; (* If "r" is empty then return "Empty" else return a rectangle "s" such that "Congruent(r, s)" and "Middle(s)=p". *) PROCEDURE FromIntervals (READONLY hor, ver: Interval.T): T; (* Return "FromEdges(hor.lo,hor.hi,ver.lo,ver.hi)". *) PROCEDURE FromAxes (axis: Axis.T; READONLY n, m: Interval.T): T; (* If axis=Hor then FromIntervals(n,m), else FromIntervals(m,n) *) (* --- Selection --- *) PROCEDURE NorthWest(READONLY r: T): Point.T; (* Return "Point.T{r.west,r.north}". *) PROCEDURE NorthEast(READONLY r: T): Point.T; (* Return "Point.T{r.east,r.north}". *) PROCEDURE SouthWest(READONLY r: T): Point.T; (* Return "Point.T{r.west,r.south}". *) PROCEDURE SouthEast(READONLY r: T): Point.T; (* Return "Point.T{r.east,r.south}". *) PROCEDURE GetVertex (v: Vertex; READONLY r: T): Point.T; (* the point corresponding to the vertex v of r; origin if r is empty *) PROCEDURE HorSize(READONLY r: T): CARDINAL; (* Return "r.east - r.west". *) PROCEDURE VerSize(READONLY r: T): CARDINAL; (* Return "r.south - r.north". *) PROCEDURE Size (a: Axis.T; READONLY r: T): CARDINAL; (* HorSize(r) if a=Hor; VerSize(r) if a=Ver *) PROCEDURE DiagSizeSquare (READONLY r: T): CARDINAL; (* HorSize(r)**2+VerSize(r)**2 *) PROCEDURE Middle(READONLY r: T): Point.T; (* Return "Point.T{r.west+r.east DIV 2, r.north+r.south DIV 2}". *) PROCEDURE PickEdge (READONLY r: T; READONLY p: Point.T): Edge; (* Return the edge of r closest to p (one of them if not unique) *) PROCEDURE PickVertex (READONLY r: T; READONLY p: Point.T): Vertex; (* Return the vertex of r closest to p (one of them if not unique) *) PROCEDURE Project(READONLY r: T; READONLY p: Point.T): Point.T; (* Return the element of "r" that is closest to "p". This is a checked runtime error if "r" is empty. *) (* --- Transformation --- *) PROCEDURE Add(READONLY r: T; READONLY p: Point.T): T; (* Return | FromEdges(r.west+p.h, r.east+p.h, | r.north+p.v,r.south+p.v) *) PROCEDURE Sub(READONLY r: T; READONLY p: Point.T): T; (* Return "Add(r, Point.Minus(p))". *) PROCEDURE Move (READONLY r: T; READONLY p: Point.T): T; (* increment r.e and r.w by p.h; increment r.n and r.s by p.v *) PROCEDURE MoveH (READONLY r: T; h: INTEGER): T; (* increment r.e and r.w by h *) PROCEDURE MoveV (READONLY r: T; v: INTEGER): T; (* increment r.n and r.s by v *) PROCEDURE MoveHV (READONLY r: T; h, v: INTEGER): T; (* increment r.e and r.w by h, r.n and r.s by v *) PROCEDURE Scale (READONLY r: T; num, den: INTEGER): T; (* scale a rectangle by a fraction *) PROCEDURE Change (READONLY r: T; dw,de,dn,ds: INTEGER): T; (* If "r" is empty return "Empty", else return the rectangle "FromEdges(r.west+dw, r.east+de, r.north+dn, r.south+ds)". *) PROCEDURE Inset(READONLY r: T; n: INTEGER): T; (* Return "Change(r, n, -n, n, -n)". *) PROCEDURE Transpose(READONLY r: T; ax := Axis.T.Ver): T; (* If "r" is empty or if "ax = Axis.Hor", then return "r", else return "T{r.north, r.south, r.west, r.east}". *) PROCEDURE MoveEdge (READONLY r: T; e: Edge; dn: INTEGER): T; (* If r is empty return empty, else move the edge e of r by dn in the positive direction of the axis perpendicular to it *) PROCEDURE MoveVertex (READONLY r: T; v: Vertex; READONLY dp: Point.T): T ; (* If r is empty return empty, else move the vertex v of r by dp in the northwest-southeast direction *) PROCEDURE Stretch (READONLY r: T; axis: Axis.T; lo, hi: INTEGER): T; (* If r is empty return empty, else change the interval of r determined by axis. *) PROCEDURE Join(READONLY r, s: T): T; (* Return the smallest rectangle containing both "r" and "s". *) PROCEDURE Meet(READONLY r, s: T): T; (* Return the largest rectangle contained in both "r" and "s". *) PROCEDURE Extend (READONLY r: T; READONLY p: Point.T): T; (* Returns Join(r,FromPoint(p)) *) PROCEDURE Chop (hv: Axis.T; READONLY r: T; n: INTEGER; VAR (*out*) s, t: T) ; (* Chop a rectangle in two. If hv=Ver, s and t become the top and bottom parts of r resp. If hv=Hor, s and t become the left and right parts of r resp. *) TYPE Partition = ARRAY [0..4] OF T; PROCEDURE Factor( READONLY r, s: T; VAR (*out*) f: Partition; dh, dv: INTEGER) ; (* Partition "r" into "5" pieces "f[0]..f[4]" where "f[2] = Meet(r,s)", and the other rectangles in "f" partition the set difference "r-s". *) (* The order of "f" is such that if "i *) PROCEDURE Eq (READONLY a, b: T): BOOLEAN; (* == RETURN (a = b) *) PROCEDURE Hash (READONLY a: T): INTEGER; (* == RETURN a suitable hash value *) END Rect.