CDCurvesCommands.mesa
Copyright © 1985, 1986 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, March 30, 1985 12:19:40 pm PST
Last Edited by: Christian Jacobi, January 16, 1987 4:32:13 pm PST
DIRECTORY
CD,
CDInstances,
CDBasics,
CDCurves,
CDOps,
CDPrivate,
CDSequencer,
CDSymbolicObjects,
IO,
PriorityQueue,
Real,
Rope,
TerminalIO;
CDCurvesCommands:
CEDAR
PROGRAM
IMPORTS CDBasics, CDCurves, CDOps, CDSequencer, CDSymbolicObjects, IO, PriorityQueue, Real, Rope, TerminalIO
SHARES CDCurves =
BEGIN
LP: TYPE = LIST OF CD.Position;
DistanceSq:
PROC[p1, p2:
CD.Position]
RETURNS [
REAL] = {
--returns th square of the distance
dx: REAL = Real.Float[p1.x]-Real.Float[p2.x];
dy: REAL = Real.Float[p1.y]-Real.Float[p2.y];
RETURN [dx*dx+dy*dy]
};
Distance:
PROC [p1, p2:
CD.Position]
RETURNS [
REAL] = {
RETURN [Real.SqRt[DistanceSq[p1, p2]]]
};
DistancePairP:
PROC[p1, p2, p:
CD.Position]
RETURNS [
REAL] = {
--returns some bad hack representing distance
RETURN [ABS[Distance[p1, p]+Distance[p2, p]-Distance[p2, p1]]]
};
StretchPoints:
PROC [points:
LP, from, to:
CD.Position]
RETURNS [new:
LP←
NIL] = {
pos, cnt: INT ← 0;
dmin: REAL ← LAST[INT];
FOR p:
LP ← points, p.rest
WHILE p#
NIL
DO
d: REAL = DistanceSq[p.first, from];
cnt ← cnt+1;
IF d<dmin THEN {pos𡤌nt; dmin𡤍};
ENDLOOP;
FOR i:
INT
IN [1..pos)
DO
new ← CONS[points.first, new];
points ← points.rest;
ENDLOOP;
new ← CONS[to, new];
points ← points.rest;
FOR p:
LP ← points, p.rest
WHILE p#
NIL
DO
new ← CONS[p.first, new];
ENDLOOP;
};
IncludePoint:
PROC [points:
LP, from, to:
CD.Position]
RETURNS [new:
LP←
NIL] = {
after, cnt: INT ← 0;
dmin: REAL ← LAST[INT];
last: CD.Position;
d: REAL;
FOR p:
LP ← points, p.rest
WHILE p#
NIL
AND p.rest#
NIL
DO
d ← DistancePairP[p.first, p.rest.first, from];
last ← p.first;
cnt ← cnt+1;
IF d<dmin THEN {after𡤌nt; dmin𡤍};
ENDLOOP;
d ← DistancePairP[points.first, last, from];
IF d<dmin THEN after𡤀
FOR i:
INT
IN [1..after]
DO
new ← CONS[points.first, new];
points ← points.rest;
ENDLOOP;
new ← CONS[to, new];
FOR p:
LP ← points, p.rest
WHILE p#
NIL
DO
new ← CONS[p.first, new];
ENDLOOP;
};
RemovePoint:
PROC [points:
LP, from, to:
CD.Position]
RETURNS [new:
LP←
NIL] = {
--to is ignored
pos: INT ← 0; cnt: INT ← 0;
dmin: REAL ← LAST[INT];
FOR p:
LP ← points, p.rest
WHILE p#
NIL
DO
d: REAL = DistanceSq[p.first, from];
cnt ← cnt+1;
IF d<dmin THEN {pos𡤌nt; dmin𡤍};
ENDLOOP;
FOR i:
INT
IN [1..pos)
DO
new ← CONS[points.first, new];
points ← points.rest;
ENDLOOP;
IF cnt>3 THEN points ← points.rest
ELSE TerminalIO.PutRope["degenerated polygon not created\n"];
FOR p:
LP ← points, p.rest
WHILE p#
NIL
DO
new ← CONS[p.first, new];
ENDLOOP;
};
OffsetInPlace:
PROC [pl: LP, off:
CD.Number] = {
FOR l: LP ← pl, l.rest
WHILE l#
NIL
DO
l.first ← [l.first.x+off, l.first.y+off]
ENDLOOP;
};
OrientedPoints:
PROC [inst:
CD.Instance]
RETURNS [copy:
LP←
NIL] = {
--inst must be instance of a curve object
pl: LP;
WITH inst.ob.specific
SELECT
FROM
cp: CDCurves.CurveSpecific => pl ← cp.points;
ENDCASE => ERROR;
FOR p:
LP ← pl, p.rest
WHILE p#
NIL
DO
orientedP: CD.Position = CDBasics.MapPoint[p.first, inst.trans].pointInWorld;
copy ← CONS[orientedP, copy];
ENDLOOP;
};
FindMarks:
PROC [design:
CD.Design, predicate: CDSymbolicObjects.InstEnumerator←
NIL]
RETURNS [pq: PriorityQueue.Ref] = {
pq ← PriorityQueue.Create[SortPred];
FOR w:
CD.InstanceList ← CDOps.InstList[design], w.rest
WHILE w#
NIL
DO
IF CDSymbolicObjects.IsMark[w.first.ob]
AND (predicate=
NIL
OR predicate[w.first])
THEN
PriorityQueue.Insert[pq, w.first];
ENDLOOP;
};
SelectPMarksComm:
PROC [comm: CDSequencer.Command] = {
cnt: INT ← 0;
FOR w:
CD.InstanceList ← CDOps.InstList[comm.design], w.rest
WHILE w#
NIL
DO
IF CDSymbolicObjects.IsMark[w.first.ob]
AND FromPS[w.first]
THEN
IF ~w.first.selected
THEN {
w.first.selected ← TRUE; cnt ← cnt+1;
CDOps.RedrawInstance[comm.design, w.first, FALSE]
};
ENDLOOP;
TerminalIO.PutF["add-select curve control marks; %g more mark(s) selected\n ", [integer[cnt]]];
MarksStatistic[comm.design];
};
RemOwnerComm:
PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRope[" remove owner of marks\n"];
FOR w:
CD.InstanceList ← CDOps.InstList[comm.design], w.rest
WHILE w#
NIL
DO
IF w.first.selected
AND CDSymbolicObjects.IsMark[w.first.ob]
THEN
CDSymbolicObjects.SetOwner[w.first, NIL];
ENDLOOP;
};
SetOwnerComm:
PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRope[" convert marks to curve control marks\n"];
FOR w:
CD.InstanceList ← CDOps.InstList[comm.design], w.rest
WHILE w#
NIL
DO
IF w.first.selected
AND CDSymbolicObjects.IsMark[w.first.ob]
THEN
IF ~FromPS[w.first] THEN SetOrder[w.first];
ENDLOOP;
};
MarksStatisticComm:
PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRope["count marks: "];
MarksStatistic[comm.design];
};
MarksStatistic:
PROC [design:
CD.Design] = {
oMcnt, pMcnt, oXcnt, notSelPMcnt: INT ← 0;
FOR w:
CD.InstanceList ← CDOps.InstList[design], w.rest
WHILE w#
NIL
DO
IF w.first.selected
THEN {
IF CDSymbolicObjects.IsMark[w.first.ob]
THEN
IF FromPS[w.first] THEN pMcnt ← pMcnt+1
ELSE oMcnt ← oMcnt +1
ELSE oXcnt ← oXcnt + 1
}
ELSE
IF CDSymbolicObjects.IsMark[w.first.ob]
AND FromPS[w.first]
THEN
notSelPMcnt ← notSelPMcnt+1;
ENDLOOP;
TerminalIO.PutF[" %g curve control marks", [integer[pMcnt]]];
IF oMcnt#0 THEN TerminalIO.PutF[" %g other-marks", [integer[oMcnt]]];
IF oXcnt#0 THEN TerminalIO.PutF[" %g other-objects", [integer[oXcnt]]];
TerminalIO.PutRope[" selected"];
IF notSelPMcnt#0 THEN TerminalIO.PutF[" %g curve control marks NOT selected", [integer[notSelPMcnt]]];
TerminalIO.PutRope["\n"];
};
ConvertPSToMarks:
PROC [comm: CDSequencer.Command] = {
i: CD.Instance ← CDOps.TheInstance[comm.design, "split up curve object\n"];
IF i#
NIL
THEN {
IF CDCurves.IsPolygon[i.ob]
OR CDCurves.IsSpline[i.ob]
OR CDCurves.IsFilledCurve[i.ob]
OR CDCurves.IsLine[i.ob]
THEN {
cp: CDCurves.CurveSpecific ← NARROW[i.ob.specific];
cnt: INT ← 0; oldPoints: LP ← OrientedPoints[i];
CDOps.RemoveInstance[comm.design, i];
FOR pl: LP ← oldPoints, pl.rest
WHILE pl#
NIL
DO
r: CD.Rect ← CDBasics.RectAt[[pl.first.x-cp.w/2, pl.first.y-cp.w/2], [0, 0]];
si: CD.Instance ← CDSymbolicObjects.CreateSymInst[denotes: r, layer: i.ob.layer];
SetOrder[si]; si.selected ← TRUE;
CDOps.IncludeInstance[comm.design, si];
ENDLOOP;
}
ELSE TerminalIO.PutRope["selected ob is neither polygon nor spline; not done\n"];
};
};
Selected: CDSymbolicObjects.InstEnumerator ={
RETURN [inst.selected]
};
FromPS: CDSymbolicObjects.InstEnumerator ={
RETURN [CDSymbolicObjects.GetOwner[inst]=$CurveControl]
};
SelectedOrFromPS: CDSymbolicObjects.InstEnumerator ={
RETURN [inst.selected OR CDSymbolicObjects.GetOwner[inst]=$CurveControl]
};
SortPred: PriorityQueue.SortPred = {
RETURN [ Rope.Compare[ CDSymbolicObjects.GetName[NARROW[x]], CDSymbolicObjects.GetName[NARROW[y] ], FALSE] < equal];
};
MarksToPSComm:
PROC [comm: CDSequencer.Command] = {
MarksToPS:
PROC [design:
CD.Design, pq: PriorityQueue.Ref, layer:
CD.Layer, key:
ATOM, w:
CD.Number ← 0] = {
ob: CD.Object; offset: CD.Position; pl: LIST OF CD.Position ← NIL;
SELECT key
FROM
$s => {w ← (w+1)/2*2};
$p => {w ← 0};
$l => {w ← (w+1)/2*2};
$f => {w ← 0};
ENDCASE => ERROR;
FOR c:
INT
IN [0..PriorityQueue.Size[pq])
DO
i: CD.Instance ← NARROW[PriorityQueue.Remove[pq]];
pos: CD.Position ← CDBasics.BaseOfRect[CDSymbolicObjects.Denotes[i]];
pl ← CONS[[pos.x+w/2, pos.y+w/2], pl];
CDOps.RemoveInstance[design, i];
ENDLOOP;
SELECT key
FROM
$s => [ob: ob, offset: offset] ← CDCurves.CreateSpline[pl, w, layer];
$p => [ob: ob, offset: offset] ← CDCurves.CreatePolygon[pl, layer];
$l => [ob: ob, offset: offset] ← CDCurves.CreateLine[pl, w, layer];
$f => [ob: ob, offset: offset] ← CDCurves.CreateFilledCurve[pl, layer];
ENDCASE => ERROR;
IF ob=NIL THEN TerminalIO.PutRope[" not done\n"]
ELSE [] ← CDOps.IncludeObjectI[design, ob, offset];
};
key: ATOM; min: INT;
predicate: CDSymbolicObjects.InstEnumerator;
pq: PriorityQueue.Ref;
TerminalIO.PutRope[" convert marks to "];
IF comm.n<=1
THEN
SELECT comm.key
FROM
$MakeSplineS => {
TerminalIO.PutRope["[0 size spline] "]; comm.key ← $MakeFilledCurveS};
$MakeLineS => {
TerminalIO.PutRope["[0 size line] "]; comm.key ← $MakePolygonS};
$MakeSplineB => {
TerminalIO.PutRope["[0 size spline] "]; comm.key ← $MakeFilledCurveB};
$MakeLineB => {
TerminalIO.PutRope["[0 size line] "]; comm.key ← $MakePolygonB};
ENDCASE => NULL;
SELECT comm.key
FROM
$MakePolygonS => {
TerminalIO.PutRope["polygon (selected)"]; predicate ← Selected; key ← $p; min ← 3};
$MakeSplineS => {
TerminalIO.PutRope["spline (selected)"]; predicate ← Selected; key ← $s; min ← 4; min ← 4};
$MakeLineS => {
TerminalIO.PutRope["line (selected)"]; predicate ← Selected; key ← $l; min ← 2};
$MakeFilledCurveS => {
TerminalIO.PutRope["filled curve (selected)"]; predicate ← Selected; key ← $f; min ← 4};
$MakePolygonB => {
TerminalIO.PutRope["polygon (selected+origin)"]; predicate ← SelectedOrFromPS; key ← $p; min ← 3};
$MakeSplineB => {
TerminalIO.PutRope["spline (selected+origin)"]; predicate ← SelectedOrFromPS; key ← $s; min ← 4};
$MakeLineB => {
TerminalIO.PutRope["line (selected+origin)"]; predicate ← SelectedOrFromPS; key ← $l; min ← 2};
$MakeFilledCurveB => {
TerminalIO.PutRope["filled curve (selected+origin)"]; predicate ← SelectedOrFromPS; key ← $f; min ← 4};
ENDCASE => {TerminalIO.PutRope["failed\n"]; RETURN};
pq ← FindMarks[comm.design, predicate];
IF pq.Size[]<min THEN TerminalIO.PutF[" must use %g or more marks\n", [integer[min]]]
ELSE MarksToPS[comm.design, pq, comm.l, key, comm.n];
};
cnt: INT ← 0;
SetOrder:
PROC [inst:
CD.Instance] = {
CDSymbolicObjects.SetOwner[inst, $CurveControl];
CDSymbolicObjects.SetName[inst, IO.PutFR["CP-%05g", [integer[cnt ← cnt+10]]]];
};
DrawControlMarkComm:
PROC [comm: CDSequencer.Command] = {
inst: CD.Instance;
r: CD.Rect = CDBasics.RectAt[comm.pos, [0, 0]];
TerminalIO.PutRope["draw unnamed control-mark\n"];
inst ← CDSymbolicObjects.CreateSymInst[denotes: r];
SetOrder[inst];
CDOps.IncludeInstance[comm.design, inst];
};
RenameMarkComm:
PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRope["rename and make mark a control mark\n"];
FOR w:
CD.InstanceList ← CDOps.InstList[comm.design], w.rest
WHILE w#
NIL
DO
IF w.first.selected
THEN {
IF CDSymbolicObjects.IsMark[w.first.ob] THEN SetOrder[w.first] ELSE TerminalIO.PutRope[" object is not mark\n"];
RETURN;
}
ENDLOOP;
TerminalIO.PutRope[" no mark found\n"];
};
CDSequencer.ImplementCommand[$DrawPolygonMark, DrawControlMarkComm];
CDSequencer.ImplementCommand[$PolygonRenumber, RenameMarkComm];
CDSequencer.ImplementCommand[$SplitPolygon, ConvertPSToMarks,, doQueueAndMark];
CDSequencer.ImplementCommand[$MakePolygonS, MarksToPSComm,, doQueueAndMark];
CDSequencer.ImplementCommand[$MakePolygonB, MarksToPSComm,, doQueueAndMark];
CDSequencer.ImplementCommand[$MakeLineS, MarksToPSComm,, doQueueAndMark];
CDSequencer.ImplementCommand[$MakeLineB, MarksToPSComm,, doQueueAndMark];
CDSequencer.ImplementCommand[$MakeFilledCurveS, MarksToPSComm,, doQueueAndMark];
CDSequencer.ImplementCommand[$MakeFilledCurveB, MarksToPSComm,, doQueueAndMark];
CDSequencer.ImplementCommand[$MakeSplineS, MarksToPSComm,, doQueueAndMark];
CDSequencer.ImplementCommand[$MakeSplineB, MarksToPSComm,, doQueueAndMark];
CDSequencer.ImplementCommand[$RSelPMarks, SelectPMarksComm,, doQueueAndMark];
CDSequencer.ImplementCommand[$SetOwnMarkP, SetOwnerComm,, doQueueAndMark];
CDSequencer.ImplementCommand[$RemOwnMarkP, RemOwnerComm,, doQueueAndMark];
CDSequencer.ImplementCommand[$MStatC, MarksStatisticComm,, doQueue];
END.