Geom2DImpl.Mesa
Last Edited by: Spreitzer, June 9, 1985 1:04:00 pm PDT
some two dimensional geometry, with real numbers
DIRECTORY Imager, ImagerBox, ImagerTransformation, Geom2D, Vector2;
Geom2DImpl:
CEDAR
PROGRAM
IMPORTS Geom2D, ImagerBox, ImagerTransformation, Vector2
EXPORTS Geom2D =
BEGIN OPEN Geom2D;
Singularity: PUBLIC SIGNAL = CODE;
id: PUBLIC Transform ← ImagerTransformation.Translate[[0, 0]];
Project:
PUBLIC
PROC [on, what: Vec]
RETURNS [Vec] =
{l2, d: Number;
l2 ← on.x * on.x + on.y * on.y;
IF l2 = 0 THEN SIGNAL Singularity[];
d ← on.x * what.x + on.y * what.y;
RETURN [[(on.x * d)/l2, (on.y * d)/l2]]};
Displace:
PUBLIC
PROC [p: Vec, a: Rect]
RETURNS [Rect] =
{RETURN [[a.x+p.x, a.y+p.y, a.w, a.h]]};
DirectionOf:
PUBLIC
PROC [p: Vec]
RETURNS [Direction] =
{IF p.Length[] = 0 THEN SIGNAL Singularity[];
RETURN [
IF p.x = 0
THEN [
Y,
SGN[p.y]]
ELSE IF p.y = 0 THEN [X, SGN[p.x]]
ELSE ERROR]};
SGN:
PROC [n: Number]
RETURNS [Dir] =
{RETURN [IF n < 0 THEN -1 ELSE IF n > 0 THEN 1 ELSE 0]};
LineRect:
PUBLIC
PROC [l: Line]
RETURNS [r: Rect] = {
[r.x, r.w] ← MinDelt[l.from.x, l.to.x];
[r.y, r.h] ← MinDelt[l.from.y, l.to.y]};
BloatVec:
PUBLIC
PROC [p: Vec, by: Number]
RETURNS [Rect] =
{RETURN [[p.x-by, p.y-by, by*2, by*2]]};
BloatRect:
PUBLIC
PROC [r: Rect, by: Number]
RETURNS [Rect] =
{RETURN [[r.x-by, r.y-by, r.w+by*2, r.h+by*2]]};
BloatLine:
PUBLIC
PROC [l: Line, by: Number]
RETURNS [r: Rect] =
{r ← BloatRect[LineRect[l], by]};
MinMax:
PROC [a, b: Number]
RETURNS [min, max: Number] =
{IF b < a THEN RETURN[b, a] ELSE RETURN[a, b]};
MinDelt:
PROC [a, b: Number]
RETURNS [min, delta: Number] =
{IF b < a THEN RETURN[b, a-b] ELSE RETURN[a, b-a]};
UnitNormalToward:
PUBLIC
PROC [l: Line, p: Vec]
RETURNS [u: Vec] = {
dx, dy: Number;
e: Number ← (p.x - l.from.x) * (dy ← l.to.y - l.from.y) -
(dx ← l.to.x - l.from.x) * (p.y - l.from.y);
IF e = 0 THEN SIGNAL Singularity[]
ELSE
RETURN [
IF e > 0
THEN Vector2.Unit[[dy, -dx]]
ELSE IF e < 0 THEN Vector2.Unit[[-dy, dx]]
ELSE ERROR];
Parallel:
PUBLIC
PROC [a, b: Vec]
RETURNS [
BOOLEAN] =
{RETURN [a.x * b.y - a.y * b.x = 0]};
In:
PUBLIC
PROC [p: Vec, r: Rect]
RETURNS [
BOOLEAN] =
{RETURN [p.x >= r.x AND p.x <= r.x+r.w AND p.y >= r.y AND p.y <= r.y+r.h]};
SweepRects:
PUBLIC
PROC [a, b: Rect]
RETURNS [Rect] =
{RETURN [[a.x+b.x, a.y+b.y, a.w+b.w, a.h+b.h]]};
UpdateRects:
PUBLIC
PROC [a, b: Rect]
RETURNS [Rect] = {
ab: ImagerBox.Box ← ImagerBox.BoxFromRect[a];
bb: ImagerBox.Box ← ImagerBox.BoxFromRect[b];
RETURN [ImagerBox.RectFromBox[[
MIN[ab.xmin, bb.xmin], MIN[ab.ymin, bb.ymin],
MAX[ab.xmax, bb.xmax], MAX[ab.ymax, bb.ymax]
]]]};
UpdateFRect:
PUBLIC
PROC [a: Rect, f: FRect]
RETURNS [FRect] =
{RETURN [[TRUE, IF f.defined THEN UpdateRects[a, f.r] ELSE a]]};
ExtremaOfRect:
PUBLIC PROC [r: Rect, n: Vec]
RETURNS [min, max: Vec] = {
b: ImagerBox.Box ← ImagerBox.BoxFromRect[r];
e: ExtremaRec ← Extreme[n, [b.xmin, b.ymin],
Extreme[n, [b.xmin, b.ymax],
Extreme[n, [b.xmax, b.ymin],
StartExtreme[n, [b.xmax, b.ymax]]]]];
RETURN [e.minV, e.maxV]};
RotateBy90s:
PUBLIC
PROC [t: Transform, i:
INTEGER]
RETURNS [Transform] =
{
RETURN [
SELECT ((i
MOD 4) + 4)
MOD 4
FROM
0 => t,
2 => t.PostScale[-1],
1 => t.Concat[rotLeft],
3 => t.Concat[rotRight],
ENDCASE => ERROR]};
rotLeft: Transform ← ImagerTransformation.Create[0, -1, 0, 1, 0, 0];
rotRight: Transform ← ImagerTransformation.Create[0, 1, 0, -1, 0, 0];
MapVecs:
PUBLIC
PROC [t: Transform, l: VecList]
RETURNS [n: VecList] =
{prev: VecList ← n ← NIL;
FOR l ← l, l.rest
WHILE l #
NIL
DO
cur: VecList ← LIST[t.Transform[l.first]];
IF prev = NIL THEN n ← cur
ELSE prev.rest ← cur;
prev ← cur;
ENDLOOP};
MapRects:
PUBLIC
PROC [t: Transform, l: RectList]
RETURNS [n: RectList] =
BEGIN
prev: RectList ← n ← NIL;
FOR l ← l, l.rest
WHILE l #
NIL
DO
cur: RectList ← LIST[t.TransformRectangle[l.first]];
IF prev = NIL THEN n ← cur
ELSE prev.rest ← cur;
prev ← cur;
ENDLOOP;
END;
END.