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: LPNIL] = {
pos, cnt: INT ← 0;
dmin: REALLAST[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: LPNIL] = {
after, cnt: INT ← 0;
dmin: REALLAST[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: LPNIL] = {
--to is ignored
pos: INT ← 0; cnt: INT ← 0;
dmin: REALLAST[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: LPNIL] = {
--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.