HideSweepImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Greene, March 28, 1986 5:00:36 pm PST
DIRECTORY
Buttons USING [Button, ButtonProc, Create],
Commander USING [CommandProc, Register],
Containers USING [Container, Create],
Imager USING [black, Context, Color, ScaleT, MaskFillTrajectory, MaskStrokeTrajectory, SetColor, SetStrokeWidth],
ImagerColor USING [ColorFromRGB, RGB],
ImagerPath USING[LineTo, MoveTo, Trajectory],
FS USING [StreamOpen],
IO USING [Close, GetCedarTokenRope, GetReal, PutF, PutFR, PutRope, real, RIS, STREAM, TokenKind, EndOf],
Menus USING[CreateMenu, AppendMenuEntry, CreateEntry, Menu, ClickProc],
Real USING [Float, Round],
RealFns USING [AlmostZero, SinDeg, CosDeg, SqRt],
Rope USING [Cat, Equal, ROPE],
Sweep,
Vector2 USING [VEC],
ViewerClasses USING [ViewerClass, ViewerClassRec, Viewer, PaintProc, NotifyProc],
ViewerOps USING [CreateViewer, RegisterViewerClass, PaintViewer],
ViewerTools USING [MakeNewTextViewer, SetSelection, SetContents, GetContents];
HideSweepImpl: CEDAR MONITOR
LOCKS my USING my: State
IMPORTS Buttons, Containers, Commander, FS, IO, Imager, ImagerPath, ImagerColor, Menus, Real, RealFns, Rope, Sweep, ViewerOps, ViewerTools =
BEGIN OPEN Sweep;
leafBucketSize: CARDINAL ← 12;
branchingFactor: CARDINAL ← 4;
sticks: BOOLEAN ← FALSE;
surfaces: BOOLEAN ← TRUE;
shade: BOOLEAN ← TRUE;
diffuse: REAL ← .30;
perspective: BOOLEAN ← TRUE;
eye: REAL ← -6.0; --Eye is at (0, 0, eye)
eyeToScreen: REAL ← 1.0;
screenSize: REAL ← .2;
largestEyeToObject: REAL ← 20.0;
Perspective:
PROC [i: Point3]
RETURNS [o: Point3] ~ {
f: REAL ← screenSize * (i[3] - eye) / eyeToScreen;
o[1] ← i[1]/f;
o[2] ← i[2]/f;
o[3] ← (f - screenSize) / ( (1.0 - eyeToScreen/largestEyeToObject) * f)
};
Point3: TYPE = ARRAY [1..3] OF REAL;
Matrix33: TYPE = ARRAY [1..3] OF ARRAY [1..3] OF REAL;
Rotate:
PROC [p: Point3, m: Matrix33 ]
RETURNS [q: Point3] ~ {
FOR i:
CARDINAL
IN [1..3]
DO
q[i] ← 0;
FOR j:
CARDINAL
IN [1..3]
DO
q[i] ← q[i] + m[i][j]*p[j];
ENDLOOP;
ENDLOOP;
};
ScaleTranslate:
PROC [p: Point3]
RETURNS [q: Point3] ~ {
FOR i:
CARDINAL
IN [1..3]
DO
q[i] ← p[i] * 2000.0 --Spots per inch
ENDLOOP;
q[1] ← q[1] + 10000.0; q[2] ← q[2] + 10000.0
};
Dot:
PROC [p, q: Point3]
RETURNS [s:
REAL ← 0.0] ~ {
FOR i:
CARDINAL
IN [1..3]
DO
s ← s + p[i] * q[i];
ENDLOOP;
};
Cross:
PROC [p, q: Point3]
RETURNS [r: Point3] ~ {
FOR i:
CARDINAL
IN [1..3]
DO
n: CARDINAL ← (i MOD 3) + 1;
nn: CARDINAL ← (n MOD 3) + 1;
r[i] ← p[n]*q[nn] - p[nn]*q[n];
ENDLOOP;
};
Sub:
PROC [p, q: Point3]
RETURNS [r: Point3] ~ {
FOR i:
CARDINAL
IN [1..3]
DO
r[i] ← p[i] - q[i];
ENDLOOP;
};
Add:
PROC [p, q: Point3]
RETURNS [r: Point3] ~ {
FOR i:
CARDINAL
IN [1..3]
DO
r[i] ← p[i] + q[i];
ENDLOOP;
};
Facet: TYPE = REF FacetRec;
FacetRec:
TYPE =
RECORD [
a, b, c, n: Point3,
color: ImagerColor.RGB];
Scene: TYPE = LIST OF Facet;
Union:
PROC [a, b:
LIST
OF Facet]
RETURNS [c:
LIST
OF Facet ←
NIL] ~ {
merge according to pointer order, cancel duplicates
t: LIST OF Facet ← NIL;
DO
IF a =
NIL
THEN {
IF b #
NIL
THEN
IF t = NIL THEN c ← b ELSE t.rest ← b;
RETURN};
IF b =
NIL
THEN {
IF a #
NIL
THEN
IF t = NIL THEN c ← a ELSE t.rest ← a;
RETURN};
IF a.first = b.first THEN {a ← a.rest; b ← b.rest} --cancel duplicates
ELSE {
IF
LOOPHOLE[a.first,
LONG
CARDINAL] <
LOOPHOLE[b.first,
LONG
CARDINAL]
THEN {
IF t = NIL THEN {c ← LIST[a.first]; t ← c} ELSE {t.rest ← LIST[a.first]; t ← t.rest};
a ← a.rest}
ELSE {
IF t = NIL THEN {c ← LIST[b.first]; t ← c} ELSE {t.rest ← LIST[b.first]; t ← t.rest};
b ← b.rest};
};
ENDLOOP;
};
Copy:
PROC [a:
LIST
OF Facet]
RETURNS [b:
LIST
OF Facet ←
NIL] ~ {
keep ordering of a
t: LIST OF Facet;
IF a = NIL THEN RETURN ELSE b ← t ← CONS[a.first, NIL];
a ← a.rest;
UNTIL a =
NIL
DO
t.rest ← CONS[a.first, NIL];
a ← a.rest; t ← t.rest;
ENDLOOP;
};
Change:
PROC [a, b:
LIST
OF Facet, x, y:
REAL]
RETURNS [c:
LIST
OF Facet ←
NIL] ~ {
c will reflect order of a toggling elements of b
IF b = NIL THEN RETURN[a];
c ← Copy[a];
UNTIL b = NIL DO
s, p:
LIST
OF Facet;
BEGIN
s ← c; p ← NIL;
DO
IF s = NIL THEN GOTO Insert;
IF s.first = b.first THEN EXIT;
p ← s; s ← s.rest;
ENDLOOP;
IF p = NIL THEN c ← s.rest ELSE p.rest ← s.rest;
EXITS
Insert => {
s ← c; p ← NIL;
IF s #
NIL
THEN
UNTIL InFront[b.first, s.first, x, y]
DO
p ← s; s ← s.rest;
IF s = NIL THEN EXIT;
ENDLOOP;
IF p = NIL THEN c ← CONS[b.first, s] ELSE p.rest ← CONS[b.first, s];
}
END;
b ← b.rest;
ENDLOOP;
};
InFront:
PROC [f,g: Facet, x, y:
REAL]
RETURNS [
BOOLEAN] ~ {
fz, gz: REAL;
IF f.n[3] = 0 THEN RETURN[TRUE]; --f is end on
IF g.n[3] = 0 THEN RETURN[FALSE]; --g is end on
fz ← - ((x - f.a[1])*f.n[1] + (y - f.a[2])*f.n[2])/ f.n[3] + f.a[3];
gz ← - ((x - g.a[1])*g.n[1] + (y - g.a[2])*g.n[2])/ g.n[3] + g.a[3];
RETURN[ fz < gz ];
};
Scale: INT ← 2000;
State: TYPE = REF StateRec;
StateRec: TYPE = MONITORED RECORD [
outer: Containers.Container ← NIL,
menu: Menus.Menu,
fileNameInput, rotateYInput,
inner: ViewerClasses.Viewer,
scene: Scene ← NIL,
output: Graph];
ShowHide: Commander.CommandProc = {
my: State ← NEW[StateRec];
fileNameButton, rotateYButton: Buttons.Button;
my.menu ← Menus.CreateMenu[];
my.menu.AppendMenuEntry[Menus.CreateEntry["Clear", ClearProc, my]];
my.menu.AppendMenuEntry[Menus.CreateEntry["View", ViewProc, my]];
my.outer ← Containers.Create[[
name: "Hide",
menu: my.menu,
scrollable: FALSE]];
fileNameButton ← Buttons.Create[
info:
[name: "Input File Name:",
wx: 10, wy: 10, wh: 15,
parent: my.outer,
border: FALSE],
proc: ForceFileName,
clientData: my];
my.fileNameInput ← ViewerTools.MakeNewTextViewer[[
parent: my.outer,
wx: fileNameButton.wx + fileNameButton.ww + 20,
wy: 10, wh: 15, ww: 500,
scrollable: FALSE,
border: FALSE]];
ViewerTools.SetContents[my.fileNameInput, "[]<>sweep>Test.facets"];
rotateYButton ← Buttons.Create[
info:
[name: "Rotate Around Y:",
wx: 400, wy: 10, wh: 15,
parent: my.outer,
border: FALSE],
proc: ForceRotateY,
clientData: my];
my.rotateYInput ← ViewerTools.MakeNewTextViewer[[
parent: my.outer,
wx: rotateYButton.wx + rotateYButton.ww + 20,
wy: 10, wh: 15, ww: 500,
scrollable: FALSE,
border: FALSE]];
ViewerTools.SetContents[my.rotateYInput, "-60.0"];
my.inner ← ViewerOps.CreateViewer[
flavor: $ShowHide,
info: [wx: 5, wy: 30, wh: 400, ww: 630, parent: my.outer, data: my]];
ViewerOps.PaintViewer[viewer: my.inner, hint: all];
};
ForceFileName: Buttons.ButtonProc
-- [parent: REF ANY, clientData: REF ANY ← NIL, mouseButton: Menus.MouseButton ← red, shift: BOOL ← FALSE, control: BOOL ← FALSE] -- = {
my: State ← NARROW[clientData];
ViewerTools.SetSelection[my.fileNameInput];
};
ForceRotateY: Buttons.ButtonProc
-- [parent: REF ANY, clientData: REF ANY ← NIL, mouseButton: Menus.MouseButton ← red, shift: BOOL ← FALSE, control: BOOL ← FALSE] -- = {
my: State ← NARROW[clientData];
ViewerTools.SetSelection[my.rotateYInput];
};
ClearProc: Menus.ClickProc = {
my: State ← NARROW[clientData];
ClearLocked[my];
ViewerOps.PaintViewer[viewer: my.inner, hint: all];
};
ClearLocked: ENTRY PROC[my: State] ~ {
ENABLE UNWIND => NULL;
DestroyGraph[my.output];
my.output ← NIL;
};
ViewProc: Menus.ClickProc = {
my: State ← NARROW[clientData];
ViewLocked[my];
ViewerOps.PaintViewer[viewer: my.inner, hint: all];
};
HideLine: TYPE = REF HideLineRec;
HideLineRec:
TYPE =
RECORD [
changing: LIST OF Facet
];
HideRegion: TYPE = REF HideRegionRec;
HideRegionRec:
TYPE =
RECORD[
facets: LIST OF Facet ← NIL];
hideInfinityRegion: HideRegion = NEW[HideRegionRec ← [facets: NIL]];
HideCopy: CopyLineProc = {
RETURN[stateIn]
};
HideFlip: FlipLineProc = {
RETURN[stateIn]
};
HideCombine: CombineLineProc = {
s1: HideLine ← NARROW[state1];
s2: HideLine ← NARROW[state2];
sO: HideLine ←
NEW[HideLineRec ← [
changing: Union[s1.changing, s2.changing]]];
RETURN[sO];
};
ViewLocked: ENTRY PROC[my: State] ~ {
ENABLE UNWIND => NULL;
HideStart: StartRegionProc = {
rP: HideRegion ← NARROW[regionPrevious];
lR: HideLine ← NARROW[lineRight.state];
x: REAL ← (lineRight.above.x + lineRight.below.x + lineLeft.below.x) / 3.0;
y: REAL ← (lineRight.above.y + lineRight.below.y + lineLeft.below.y) / 3.0;
rC: HideRegion ← NEW[HideRegionRec ← [facets: Change[rP.facets, lR.changing, x, y] ] ];
FixLineState[rC, lineRight, rP];
RETURN[rC];
};
HideStop: StopRegionProc = {
IF UselessTest[NARROW[lineLeft.state]] THEN RemoveLineFromEndPoints[lineLeft];
};
HideSplit: SplitRegionProc = {
FixLineState[NARROW[regionRight], lineLeft, NARROW[regionPrevious]];
RETURN[regionRight];
};
HideMerge: MergeRegionProc = {
IF UselessTest[NARROW[lineRight.state]] THEN RemoveLineFromEndPoints[lineRight];
RETURN[regionRight];
};
HideLineChange: LineChangeRegionProc = {
IF side = left
THEN {
IF UselessTest[NARROW[lineOld.state]] THEN RemoveLineFromEndPoints[lineOld];
}
ELSE
FixLineState[NARROW[regionCenter], lineNew, NARROW[regionPrevious]];
};
UselessTest:
PROC [line: HideLine]
RETURNS [
BOOL] ~
INLINE {
RETURN[line.changing = NIL]
};
FixLineState:
PROC [regionLeft: HideRegion, lineCenter: Line, regionRight: HideRegion] ~ {
lF: LIST OF Facet ← IF regionLeft.facets = NIL THEN NIL ELSE LIST[regionLeft.facets.first];
rF: LIST OF Facet ← IF regionRight.facets = NIL THEN NIL ELSE LIST[regionRight.facets.first];
lineCenter.state ← NEW[HideLineRec ← [changing: Union[lF, rF]]];
};
input: Graph ← NewGraph[];
workLoad, newWorkLoad: LIST OF Graph ← NIL;
facetCount: LONG CARDINAL;
inputFile: IO.STREAM ← FS.StreamOpen[ViewerTools.GetContents[my.fileNameInput]];
scanScene: Scene;
master: Matrix33;
sin, cos: REAL;
my.scene ← NIL;
UNTIL inputFile.EndOf[]
DO
f: Facet ← NEW[FacetRec];
sep: Rope.ROPE;
f.a[1] ← inputFile.GetReal[];
f.a[2] ← inputFile.GetReal[];
f.a[3] ← inputFile.GetReal[];
sep ← inputFile.GetCedarTokenRope[].token;
IF NOT Rope.Equal[sep, ","] THEN ERROR;
f.b[1] ← inputFile.GetReal[];
f.b[2] ← inputFile.GetReal[];
f.b[3] ← inputFile.GetReal[];
sep ← inputFile.GetCedarTokenRope[].token;
IF NOT Rope.Equal[sep, ","] THEN ERROR;
f.c[1] ← inputFile.GetReal[];
f.c[2] ← inputFile.GetReal[];
f.c[3] ← inputFile.GetReal[];
sep ← inputFile.GetCedarTokenRope[].token;
IF NOT Rope.Equal[sep, "/"] THEN ERROR;
f.color.R ← inputFile.GetReal[];
f.color.G ← inputFile.GetReal[];
f.color.B ← inputFile.GetReal[];
my.scene ← CONS[f, my.scene];
ENDLOOP;
sin ← RealFns.SinDeg[RealFromRope[ViewerTools.GetContents[my.rotateYInput]]];
cos ← RealFns.CosDeg[RealFromRope[ViewerTools.GetContents[my.rotateYInput]]];
master ← [[cos, 0.0, -sin], [0.0, 1.0, 0.0], [sin, 0.0, cos]];
DestroyGraph[my.output]; my.output ← NIL;
scanScene ← my.scene;
facetCount ← 1;
UNTIL scanScene =
NIL
DO
OPEN Real;
of: Facet ← scanScene.first;
nf: Facet ← NEW[FacetRec];
lineState: HideLine ← NEW[HideLineRec ← [LIST[nf]]];
nf.a ← Rotate[of.a, master]; nf.b ← Rotate[of.b, master]; nf.c ← Rotate[of.c, master]; nf.color ← of.color;
nf.n ← Cross[ Sub[nf.b, nf.a], Sub[nf.c, nf.a] ];
IF shade
THEN {
length: REAL ← RealFns.SqRt[ABS[Dot[nf.n, nf.n]]];
cos ← IF RealFns.AlmostZero[length, -50] THEN 0.0 ELSE ABS[nf.n[3]/length];
nf.color.R ← nf.color.R*(cos*(1.0 - diffuse) + diffuse);
nf.color.G ← nf.color.G*(cos*(1.0 - diffuse) + diffuse);
nf.color.B ← nf.color.B*(cos*(1.0 - diffuse) + diffuse);
};
IF perspective
THEN {
nf.a ← Perspective[nf.a]; nf.b ← Perspective[nf.b]; nf.c ← Perspective[nf.c];
nf.n ← Cross[ Sub[nf.b, nf.a], Sub[nf.c, nf.a] ];
};
nf.a ← ScaleTranslate[nf.a]; nf.b ← ScaleTranslate[nf.b]; nf.c ← ScaleTranslate[nf.c];
input ← NewPoint[input, Round[nf.a[1]], Round[nf.a[2]] ];
input ← input.LineTo[Round[nf.b[1]], Round[nf.b[2]], lineState, HideFlip];
input ← input.LineTo[Round[nf.c[1]], Round[nf.c[2]], lineState, HideFlip];
input ← input.LineTo[Round[nf.a[1]], Round[nf.a[2]], lineState, HideFlip];
IF facetCount
MOD leafBucketSize = 0
THEN {
my.output ← Intersect[input, HideCopy, HideCombine, HideFlip];
my.output ← Sweep[my.output, hideInfinityRegion, HideStart, HideStop, HideSplit, HideMerge, HideLineChange];
workLoad ← CONS[my.output, workLoad];
input ← NewGraph[];
};
scanScene ← scanScene.rest;
facetCount ← facetCount + 1;
ENDLOOP;
IF input.points.size #
0
THEN {
my.output ← Intersect[input, HideCopy, HideCombine, HideFlip];
my.output ← Sweep[my.output, hideInfinityRegion, HideStart, HideStop, HideSplit, HideMerge, HideLineChange];
workLoad ← CONS[my.output, workLoad];
input ← NewGraph[];
};
DO
newWorkLoad ← NIL;
UNTIL workLoad =
NIL
DO
input ← NIL;
FOR i:
CARDINAL
IN [1..branchingFactor]
DO
IF workLoad = NIL THEN {IF i = 2 THEN GOTO FreePass ELSE EXIT};
input ← MergeGraphs[input, workLoad.first];
workLoad ← workLoad.rest;
ENDLOOP;
my.output ← Intersect[input, HideCopy, HideCombine, HideFlip];
my.output ← Sweep[my.output, hideInfinityRegion, HideStart, HideStop, HideSplit, HideMerge, HideLineChange];
newWorkLoad ← CONS[my.output, newWorkLoad];
REPEAT
FreePass => {
newWorkLoad ← CONS[input, newWorkLoad];
};
ENDLOOP;
IF newWorkLoad.rest = NIL THEN EXIT ELSE workLoad ← newWorkLoad;
ENDLOOP;
};
EndOfLines:
PROC [in:
LIST
OF Line]
RETURNS [out:
LIST
OF Line] ~
INLINE {
IF in = NIL THEN RETURN[NIL];
UNTIL in.rest =
NIL
DO
in ← in.rest;
ENDLOOP;
RETURN[in];
};
RealFromRope:
PROC [rawRope: Rope.
ROPE]
RETURNS [
REAL] =
INLINE {
OPEN IO;
RETURN [GetReal[RIS[rawRope]]] };
ShowHidePaint: ViewerClasses.PaintProc = {
my:State ← NARROW[self.data];
context.ScaleT[40.0/Scale];
PaintLocked[my, context];
};
TrapRegion: TYPE = REF TrapRegionRec;
TrapRegionRec:
TYPE =
RECORD [
facet: Facet ← NIL,
lastPointSeen: Point ← NIL,
lineLeft, lineRight: Line ← NIL
];
trapInfinityRegion: TrapRegion = NEW[TrapRegionRec ← [facet: NIL]];
PaintLocked: ENTRY PROC [my: State, context: Imager.Context] ~ {
OPEN Imager, ImagerPath;
ENABLE UNWIND => NULL;
TrapStart: StartRegionProc = {
lR: HideLine ← NARROW[lineRight.state];
rR: TrapRegion ← NARROW[regionPrevious];
cF: LIST OF Facet ← Change[IF rR.facet = NIL THEN NIL ELSE LIST[rR.facet], lR.changing, -1.0, -1.0];
IF cF # NIL THEN
RETURN[NEW[TrapRegionRec ← [facet: cF.first, lastPointSeen: lineLeft.above, lineLeft: lineLeft, lineRight: lineRight]]]
ELSE RETURN[trapInfinityRegion];
};
TrapStop: StopRegionProc = {
rC: TrapRegion ← NARROW[regionCenter];
IF rC # trapInfinityRegion
THEN {
PaintTrap[rC.facet.color, rC.lastPointSeen.y, lineLeft.below.y, lineLeft, lineRight];
rC.lineLeft ← rC.lineRight ← NIL;
};
};
TrapSplit: SplitRegionProc = {
rR: TrapRegion ← NARROW[regionRight];
rL: TrapRegion;
point: Point ← lineRight.above;
IF rR # trapInfinityRegion
THEN {
PaintTrap[rR.facet.color, rR.lastPointSeen.y, point.y, rR.lineLeft, rR.lineRight];
rR.lastPointSeen ← point;
rL ← NEW[TrapRegionRec ← [facet: rR.facet, lastPointSeen: point, lineLeft: rR.lineLeft, lineRight: lineLeft]];
rR.lineLeft ← lineRight;
RETURN[rL];
}
};
TrapMerge: MergeRegionProc = {
rL: TrapRegion ← NARROW[regionLeft];
rR: TrapRegion ← NARROW[regionRight];
point: Point ← lineLeft.below;
IF (rL # trapInfinityRegion)
AND (rR # trapInfinityRegion)
THEN {
PaintTrap[rL.facet.color, rL.lastPointSeen.y, point.y, rL.lineLeft, rL.lineRight];
PaintTrap[rR.facet.color, rR.lastPointSeen.y, point.y, rR.lineLeft, rR.lineRight];
rR.lastPointSeen ← point;
rR.lineLeft ← rL.lineLeft;
rL.lineLeft ← rL.lineRight ← NIL;
};
RETURN[IF rL = trapInfinityRegion THEN rL ELSE rR];
};
TrapLineChange: LineChangeRegionProc = {
rC: TrapRegion ← NARROW[regionCenter];
point: Point ← lineNew.above;
IF (rC # trapInfinityRegion)
THEN {
PaintTrap[rC.facet.color, rC.lastPointSeen.y, point.y, rC.lineLeft, rC.lineRight];
rC.lastPointSeen ← point;
IF side = left THEN rC.lineLeft ← lineNew ELSE rC.lineRight ← lineNew;
};
};
PaintTrap: PROC [c: ImagerColor.RGB, aboveY, belowY: INT, lineLeft, lineRight: Line] ~ {
Trapaziods are easy to paint directly, the following is a slightly inacurate, and extremely inefficient way of painting them.
traj: Trajectory;
lowX: INT ← MIN[lineLeft.above.x, lineLeft.below.x];
highX: INT ← MAX[lineRight.above.x, lineRight.below.x];
top: Line ← NEW[LineRec ← [above: NEW[PointRec ← [x: highX, y: aboveY]], below: NEW[PointRec ← [x: lowX, y: aboveY]] ]];
bottom: Line ← NEW[LineRec ← [above: NEW[PointRec ← [x: highX, y: belowY]], below: NEW[PointRec ← [x: lowX, y: belowY]] ]];
topLeft, topRight, bottomLeft, bottomRight: Point;
IF aboveY = belowY THEN RETURN;
[topLeft, ] ← PairIntersection[top, lineLeft];
[topRight, ] ← PairIntersection[top, lineRight];
[bottomLeft, ] ← PairIntersection[bottom, lineLeft];
[bottomRight, ] ← PairIntersection[bottom, lineRight];
traj ← MoveTo[Vfp[topLeft]].LineTo[VfpR[topRight]].LineTo[VfpR[bottomRight]].LineTo[Vfp[bottomLeft]];
context.SetColor[ImagerColor.ColorFromRGB[c]];
MaskFillTrajectory[context, traj];
};
StickStart: StartRegionProc = {
DrawLine[lineRight];
};
StickSplit: SplitRegionProc = {
DrawLine[lineLeft];
};
StickLineChange: LineChangeRegionProc = {
IF side = right THEN DrawLine[lineNew];
};
DrawLine:
PROC [line: Line] ~ {
traj: Trajectory;
traj ← MoveTo[Vfp[line.above]].LineTo[Vfp[line.below]];
context.MaskStrokeTrajectory[traj];
};
Vfp:
PROC [p: Point]
RETURNS [Vector2.
VEC] ~
INLINE {
RETURN[[Real.Float[p.x], Real.Float[p.y]]];
};
VfpR:
PROC [p: Point]
RETURNS [Vector2.
VEC] ~
INLINE {
RETURN[[Real.Float[p.x+1], Real.Float[p.y]]];
};
IF surfaces
THEN
my.output ← Sweep[my.output, trapInfinityRegion, TrapStart, TrapStop, TrapSplit, TrapMerge, TrapLineChange];
IF sticks
THEN {
context.SetColor[Imager.black];
context.SetStrokeWidth[20.0];
my.output ← Sweep[my.output, trapInfinityRegion, StickStart, NilStop, StickSplit, NilMerge, StickLineChange];
};
};
FacetCompile:
PROC [in, out: Rope.
ROPE] ~ {
inputFile: IO.STREAM ← FS.StreamOpen[in];
outputFile: IO.STREAM ← FS.StreamOpen[out, $create];
curve: ARRAY [0..100] OF Point3; position: CARDINAL;
origin, destination: Point3; color: Rope.ROPE;
token: Rope.ROPE; tokenKind: IO.TokenKind;
PutPoint:
PROC [p: Point3] ~ {
outputFile.PutF["%g %g %g", IO.real[p[1]], IO.real[p[2]], IO.real[p[3]]];
};
[tokenKind, token,] ← inputFile.GetCedarTokenRope[];
UNTIL inputFile.EndOf[]
DO
IF tokenKind # tokenID THEN ERROR;
IF Rope.Equal[token, "STRETCH"]
THEN
BEGIN
position ← 0;
DO
curve[position][1] ← inputFile.GetReal[];
curve[position][2] ← inputFile.GetReal[];
curve[position][3] ← inputFile.GetReal[];
[tokenKind, token,] ← inputFile.GetCedarTokenRope[];
IF tokenKind # tokenSINGLE OR (NOT Rope.Equal[token, ","]) THEN EXIT;
position ← position + 1;
ENDLOOP;
IF (tokenKind # tokenID) OR (NOT Rope.Equal[token, "ALONG"]) THEN ERROR;
FOR i:
CARDINAL
IN [1..3]
DO
origin[i] ← inputFile.GetReal[];
ENDLOOP;
[tokenKind, token,] ← inputFile.GetCedarTokenRope[];
IF (tokenKind # tokenSINGLE) OR (NOT Rope.Equal[token, ","]) THEN ERROR;
FOR i:
CARDINAL
IN [1..3]
DO
destination[i] ← inputFile.GetReal[];
ENDLOOP;
[tokenKind, token,] ← inputFile.GetCedarTokenRope[];
IF (tokenKind # tokenSINGLE) OR (NOT Rope.Equal[token, "/"]) THEN ERROR;
color ← "/";
FOR i:
CARDINAL
IN [1..3]
DO
component: REAL ← inputFile.GetReal[];
color ← color.Cat[IO.PutFR[" %g", IO.real[component]]];
ENDLOOP;
IF NOT inputFile.EndOf[] THEN [tokenKind, token,] ← inputFile.GetCedarTokenRope[];
FOR pos:
CARDINAL
IN [0..position]
DO
outputFile.PutRope["
"];
PutPoint[Add[origin, curve[pos]]]; outputFile.PutRope[", "];
PutPoint[Add[origin, curve[(pos + 1) MOD (position + 1)]]]; outputFile.PutRope[", "];
PutPoint[Add[destination, curve[(pos + 1) MOD (position + 1)]]]; outputFile.PutRope[color];
outputFile.PutRope["
"];
PutPoint[Add[destination, curve[pos]]]; outputFile.PutRope[", "];
PutPoint[Add[origin, curve[pos]]]; outputFile.PutRope[", "];
PutPoint[Add[destination, curve[(pos + 1) MOD (position + 1)]]]; outputFile.PutRope[color];
ENDLOOP;
END;
ENDLOOP;
outputFile.Close[];
};
displayerClass: ViewerClasses.ViewerClass ← NEW[ViewerClasses.ViewerClassRec ←
[paint: ShowHidePaint]];
ViewerOps.RegisterViewerClass[$ShowHide, displayerClass];
Commander.Register[key: "ShowHide", proc: ShowHide, doc: "To Debug Hidden Lines"];
END.