-- File: MiscImpl.mesa
-- Last Edited by: CSChow, February 1, 1985 0:42:38 am PST
--Documentation will come later after consolidating the design --
DIRECTORY
Graphics USING[Context, Path, NewPath, LineTo, MoveTo, DrawTo, SetCP, SetStipple, DrawStroke, DrawArea],
IPConstants,
Misc;
MiscImpl: CEDAR PROGRAM
IMPORTS Graphics
EXPORTS Misc = BEGIN OPEN Misc;
WindCreate: PUBLIC PROC[min, max: INT] RETURNS [Window]={
RETURN [NEW[WindowRep←[span: IntlCreate[min, max], curtains: NIL]]]};-- WindCreate--
WindAddCurtain: PUBLIC PROC[w: Window, curtain: Interval]={
-- curtain is unioned (in Set theory's sense) with previous curtains
newCurtainHd, newCurtainTl: LIST OF Interval;
IF curtain = NIL THEN RETURN;
newCurtainHd ← newCurtainTl ← CONS[NIL, NIL];
FOR c: LIST OF Interval ← w.curtains, c.rest UNTIL c = NIL DO
IF IntlIntersect[curtain, c.first] # NIL OR (c.first.max + 1 = curtain.min) OR (curtain.max + 1 = c.first.min) THEN {curtain ← IntlMakeBIntl[curtain, c.first]; LOOP};
IF c.first.max < curtain.min THEN {
newCurtainTl.rest ← CONS[c.first, NIL]; newCurtainTl ← newCurtainTl.rest; LOOP};
IF c.first.min > curtain.max THEN {
newCurtainTl.rest ← CONS[curtain, c]; EXIT};
REPEAT
FINISHED => {newCurtainTl.rest ← LIST[curtain]}
ENDLOOP;
w.curtains ← newCurtainHd.rest;
};-- WindAddCurtain--
WindIsCovered: PUBLIC PROC[w: Window] RETURNS [BOOL]={
--Window is covered iff union of all Intervals contain it
IF w.curtains = NIL THEN RETURN [w.span = NIL];
FOR c: LIST OF Interval ← w.curtains, c.rest UNTIL c = NIL DO
IF IntlIntersect[c.first, w.span] # NIL THEN RETURN [IntlContainp[c.first, w.span]]
ENDLOOP;
RETURN [FALSE]
};--WindIsCovered --
WindPassesIntl: PUBLIC PROC[w: Window, intl: Interval] RETURNS [BOOL]={
--TRUE <=> interval is contained in window and doesnt intersects any curtains
IF NOT IntlContainp[w.span, intl] THEN RETURN [FALSE];
FOR c: LIST OF Interval ← w.curtains, c.rest UNTIL c = NIL DO
IF IntlIntersect[c.first, intl] # NIL THEN RETURN [FALSE]
ENDLOOP;
RETURN [TRUE]};-- WindPassesIntl--
WindCurtainsCoverIntl: PUBLIC PROC[w: Window, intl: Interval] RETURNS [BOOL] ={
-- TRUE <=> In the union of all previous curtains, 1 of them contains the interval
FOR c: LIST OF Interval ← w.curtains, c.rest UNTIL c = NIL DO
IF IntlIntersect[c.first, intl] # NIL THEN RETURN [IntlContainp[c.first, intl]]
ENDLOOP;
RETURN [FALSE]
};--WindCurtainCoversIntl--
RectSubtractFailure: PUBLIC ERROR [r1, r2: Rect]= CODE;
RectCreate: PUBLIC PROC [xMin, yMin, xMax, yMax: INT] RETURNS[Rect]= {
IF xMin > xMax OR yMin> yMax THEN {RETURN[NIL]};
RETURN [NEW[RectRep ← [x: IntlCreate[xMin, xMax], y: IntlCreate[yMin, yMax]]]]
}; --RectCreate --
RectCopy: PUBLIC PROC[r: Rect] RETURNS [Rect] ={
IF r = NIL THEN RETURN [NIL];
RETURN [NEW[RectRep ←[x: IntlCopy[r.x], y: IntlCopy[r.y]] ]]
}; --RectCopy--
RectOneOf: PUBLIC PROC[r: Rect] RETURNS[MiscOneOf] ={
IF r = NIL THEN RETURN [empty];
SELECT IntlOneOf[r.x] FROM
interval => {SELECT IntlOneOf[r.y] FROM
interval => RETURN[rect];
point => RETURN[interval];
ENDCASE => ERROR};
point => {SELECT IntlOneOf[r.y] FROM
interval => RETURN[interval];
point => RETURN[point];
ENDCASE => ERROR};
ENDCASE => ERROR}; --RectOneOf--
RectIntersect: PUBLIC PROC [r1, r2: Rect] RETURNS[Rect]= {
xI, yI: Interval;
IF r1 = NIL OR r2 = NIL THEN RETURN[NIL];
xI ← IntlIntersect[r1.x, r2.x];
yI ← IntlIntersect[r1.y, r2.y];
IF xI = NIL OR yI = NIL THEN RETURN[NIL];
RETURN[NEW[RectRep ← [x: xI, y: yI]]];
}; -- RectIntersect--
RectContainp: PUBLIC PROC [r1, r2: Rect] RETURNS[BOOL]= {
IF r2 =NIL THEN RETURN [TRUE];
IF r1 = NIL THEN RETURN [r2 = NIL];
RETURN[IntlContainp[r1.x, r2.x] AND IntlContainp[r1.y, r2.y]];
}; -- RectContainp--
RectContainPt: PUBLIC PROC[r: Rect, xCoord, yCoord: INT] RETURNS [BOOL] ={
IF r = NIL THEN RETURN [FALSE];
RETURN [IntlContainPt[r.x, xCoord] AND IntlContainPt[r.y, yCoord]]};--RectContainPt--
RectArea: PUBLIC PROC[r: Rect] RETURNS[NAT] ={
IF r = NIL THEN RETURN [0];
RETURN [IntlLength[r.x] * IntlLength[r.y]]}; --RectArea--
RectMakeBRect: PUBLIC PROC [r1, r2: Rect] RETURNS[Rect]= {
IF r1 = NIL THEN RETURN [RectCopy[r2]];
IF r2 = NIL THEN RETURN [RectCopy[r1]];
RETURN [NEW[RectRep ← [x: IntlMakeBIntl[r1.x, r2.x], y: IntlMakeBIntl[r1.y, r2.y]]]];
}; -- RectMakeBBox--
RectSubtract: PUBLIC PROC [r1, r2: Rect] RETURNS[Rect]= {
ri: Rect;
IF r1 = NIL OR r2 = NIL THEN RETURN [RectCopy[r1]];
IF RectContainp[r2, r1] THEN RETURN[NIL];
IF r1.x.max < r2.x.min OR r2.x.max < r1.x.min OR r1.y.max < r2.y.min OR r2.y.max < r1.y.min THEN RETURN [RectCopy[r1]];
ri ← RectIntersect[r1, r2];
IF IntlContainp[ri.x, r1.x] THEN {RETURN [NEW[RectRep ←[x: r1.x, y: IntlSubtract[r1.y, ri.y! IntlSubtractFailure => GOTO subtractFailed]]]]};
IF IntlContainp[ri.y, r1.y] THEN {RETURN [NEW[RectRep ←[x: IntlSubtract[r1.x, ri.x ! IntlSubtractFailure =>GOTO subtractFailed], y: r1.y]]]};
GOTO subtractFailed;
EXITS
subtractFailed => RETURN WITH ERROR RectSubtractFailure[r1, r2];
}; -- RectSubtract--
RectPaint: PUBLIC PROC[r: Rect, context: Graphics.Context, xOffset, yOffset: REAL, scaleFactor: REAL ← 1.0, stipple: CARDINAL ← IPConstants.Gray, noFill: BOOLFALSE] ={
originX, originY: REAL;
spanX, spanY: REAL;
SELECT RectOneOf[r] FROM
rect => {path: Graphics.Path ← Graphics.NewPath[];
originX ← xOffset + scaleFactor * r.x.min;
originY ← yOffset + scaleFactor * r.y.min;
spanX ← xOffset + scaleFactor * r.x.max;
spanY ← yOffset + scaleFactor * r.y.max;
Graphics.MoveTo[path, originX, originY, FALSE];
Graphics.LineTo[path, spanX, originY];
Graphics.LineTo[path, spanX, spanY];
Graphics.LineTo[path, originX, spanY];
Graphics.LineTo[path, originX, originY];
IF noFill
THEN {Graphics.DrawStroke[context, path]}
ELSE {Graphics.SetStipple[context, stipple]; Graphics.DrawArea[context, path]}};
interval, point => {delta: INT ← 1;
originX ← xOffset + scaleFactor * (r.x.min - delta);
originY ← yOffset + scaleFactor * (r.y.min - delta);
spanX ← xOffset + scaleFactor * (r.x.max + delta);
spanY ← yOffset + scaleFactor * (r.y.max + delta);
Graphics.SetStipple[context, IPConstants.Black];
Graphics.SetCP[context, originX, originY];
Graphics.DrawTo[context, spanX, originY];
Graphics.DrawTo[context, spanX, spanY];
Graphics.DrawTo[context, originX, spanY];
Graphics.DrawTo[context, originX, originY];};
empty => NULL;
ENDCASE => ERROR;
}; --RectPaint--
x: PUBLIC PROC [r: Rect] RETURNS [Misc.Interval] ={
RETURN [IF r = NIL THEN NIL ELSE r.x]}; --x--
y: PUBLIC PROC[r: Rect] RETURNS [Misc.Interval] = {
RETURN [IF r = NIL THEN NIL ELSE r.y]}; --y--
xMin: PUBLIC PROC [r: Rect] RETURNS[INT]= {RETURN[r.x.min]}; --xMin --
yMin: PUBLIC PROC [r: Rect] RETURNS[INT]= {RETURN [r.y.min]}; -- yMin--
xMax: PUBLIC PROC [r: Rect] RETURNS[INT]= {RETURN [r.x.max]}; -- xMax--
yMax: PUBLIC PROC [r: Rect] RETURNS[INT]= {RETURN [r.y.max]}; --yMax --
IntlSubtractFailure: PUBLIC ERROR [i1, i2: Interval]= CODE;
IntlCreate: PUBLIC PROC [min, max: INT] RETURNS[Interval]= {
IF min> max THEN {RETURN[NIL]};
RETURN[NEW[IntervalRep ← [min, max]]];
}; -- IntlCreate--
IntlCopy: PUBLIC PROC[i: Interval] RETURNS[Interval] ={
IF i = NIL THEN RETURN [NIL];
RETURN [NEW[IntervalRep ← [i.min, i.max]]]}; --IntlCopy--
IntlOneOf: PUBLIC PROC[i: Interval] RETURNS[MiscOneOf] ={
IF i = NIL THEN RETURN [empty];
SELECT i.min FROM
< i.max => RETURN[interval];
i.max => RETURN[point];
ENDCASE => ERROR;}; --IntlOneOf--
IntlMakeBIntl: PUBLIC PROC[i1, i2: Interval] RETURNS[Interval] ={
IF i1 = NIL THEN RETURN [IntlCopy[i2]];
IF i2 = NIL THEN RETURN [IntlCopy[i1]];
RETURN [NEW[IntervalRep ← [MIN[i1.min, i2.min], MAX[i1.max, i2.max]]]]
}; --IntlMakeBIntl--
IntlContainp: PUBLIC PROC [i1, i2: Interval] RETURNS[BOOL]= {
IF i2 = NIL THEN RETURN [TRUE];
IF i1 = NIL THEN RETURN [i2 = NIL];
IF i1.min <= i2.min AND i2.max <= i1.max THEN {RETURN[TRUE]} ELSE {RETURN[FALSE]}}; -- IntlRectContainp--
IntlContainPt: PUBLIC PROC[i: Interval, p: INT] RETURNS[BOOL]= {
IF i = NIL THEN RETURN [FALSE];
RETURN [i.min <= p AND p<= i.max ]};--IntlContainPt--
IntlLength: PUBLIC PROC[i: Interval] RETURNS[NAT] ={
IF i = NIL THEN RETURN [0];
RETURN [i.max - i.min]}; --intlLength--
IntlIntersect: PUBLIC PROC [i1, i2: Interval] RETURNS[Interval]= {
IF i1 = NIL OR i2 = NIL THEN RETURN [NIL];
RETURN[IntlCreate[MAX[i1.min, i2.min], MIN[i1.max, i2.max]]]}; -- IntlIntersect--
IntlSubtract: PUBLIC PROC [i1, i2: Interval] RETURNS[Interval]= {
IF i1 = NIL OR i2= NIL THEN RETURN [IntlCopy[i1]];
IF IntlContainp[i2, i1] THEN RETURN[NIL];
IF i1.max < i2.min OR i2.max < i1.min THEN RETURN [IntlCopy[i1]];
IF i1.min < i2.min AND i2.max < i1.max THEN {RETURN WITH ERROR IntlSubtractFailure[i1, i2]};
IF i1.min <= i2.max AND i2.max < i1.max THEN RETURN [NEW[IntervalRep ← [i2.max + 1, i1.max]]];
IF i1.min < i2.min AND i2.min <= i1.max THEN RETURN[NEW[IntervalRep ← [i1.min, i2.min - 1]]];
ERROR;
}; --IntlSubtract --
--Raise IntlSubtractFailure-
min: PUBLIC PROC [i: Interval] RETURNS [INT]= {RETURN[i.min]}; --min --
max: PUBLIC PROC [i: Interval] RETURNS [INT]= {RETURN[i.max]}; --max --
END.
--ChangeLog:
-- January 2, 1985 10:28:57 pm PST
-- (1) Add "IF r = NIL THEN RETURN [FALSE]; " to RectContainPt
-- (2) Add IF r = NIL THEN NIL ELSE r.<x/y> to x and y