CDPolygonsCommands.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
by Christian Jacobi, March 30, 1985 12:19:40 pm PST
last edited by Christian Jacobi, April 11, 1985 9:16:26 am PST
DIRECTORY
CD,
CDApplications,
CDCommandOps,
CDMenus,
CDOps,
CDOrient,
CDPolygons,
CDSequencer,
Real,
Rope,
TerminalIO;
CDPolygonsCommands:
CEDAR
PROGRAM
IMPORTS CDApplications, CDCommandOps, CDMenus, CDOps, CDOrient, CDPolygons, CDSequencer, Real, TerminalIO =
BEGIN
PList: TYPE = LIST OF CD.DesignPosition;
DrawPolygonComm:
PROC [comm: CDSequencer.Command] =
BEGIN
ob: CD.ObPtr;
offset: CD.DesignPosition;
p1: CD.DesignPosition ← comm.sPos; --from
p2: CD.DesignPosition ← comm.pos; --to
points: LIST OF CD.DesignPosition;
TerminalIO.WriteRope["Draw a polygon\n"];
IF ABS[p1.x-p2.x]<4 THEN p2.x ← p1.x+10;
IF ABS[p1.y-p2.y]<4 THEN p2.y ← p1.y+10;
points ← LIST[p1, p2, [p2.x, p1.y]];
[ob, offset] ← CDPolygons.CreatePolygon[points, comm.l];
IF ob=NIL THEN TerminalIO.WriteRope[" not done\n"]
ELSE CDOps.AddAnObject[comm.design, ob, offset]
END;
DistanceSq:
PROC[p1, p2:
CD.Position]
RETURNS [
REAL] =
--returns th square of the distance
BEGIN
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]
END;
Distance:
PROC [p1, p2:
CD.Position]
RETURNS [
REAL] =
BEGIN
RETURN [Real.SqRt[DistanceSq[p1, p2]]]
END;
DistancePairP:
PROC[p1, p2, p:
CD.Position]
RETURNS [
REAL] =
--returns some bad hack representing distance
BEGIN
RETURN [ABS[Distance[p1, p]+Distance[p2, p]-Distance[p2, p1]]]
END;
StretchPoints:
PROC [points: PList, from, to:
CD.DesignPosition]
RETURNS [new: PList←
NIL] =
BEGIN
pos: INT ← 0;
cnt: INT ← 0;
dmin: REAL ← LAST[INT];
FOR p: PList ← 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: PList ← points, p.rest
WHILE p#
NIL
DO
new ← CONS[p.first, new];
ENDLOOP;
END;
IncludePoint:
PROC [points: PList, from, to:
CD.DesignPosition]
RETURNS [new: PList←
NIL] =
BEGIN
after: INT ← 0;
cnt: INT ← 0;
dmin: REAL ← LAST[INT];
last: CD.DesignPosition;
d: REAL;
FOR p: PList ← 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: PList ← points, p.rest
WHILE p#
NIL
DO
new ← CONS[p.first, new];
ENDLOOP;
END;
RemovePoint:
PROC [points: PList, from, to:
CD.DesignPosition]
RETURNS [new: PList←
NIL] =
--to is ignored
BEGIN
pos: INT ← 0;
cnt: INT ← 0;
dmin: REAL ← LAST[INT];
FOR p: PList ← 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.WriteRope["degenerated polygon not created\n"];
FOR p: PList ← points, p.rest
WHILE p#
NIL
DO
new ← CONS[p.first, new];
ENDLOOP;
END;
OrientedPoints:
PROC [ap:
CD.ApplicationPtr]
RETURNS [copy: PList←
NIL] =
--ap must be application of a polygon object
BEGIN
pp: CDPolygons.PolygonPtr = NARROW[ap.ob.specificRef];
FOR p: PList ← pp.points, p.rest
WHILE p#
NIL
DO
orientedP:
CD.DesignPosition = CDOrient.MapPoint[
pointInCell: p.first,
cellSize: ap.ob.size,
cellInstOrient: ap.orientation,
cellInstPos: ap.location].pointInWorld;
copy ← CONS[orientedP, copy];
ENDLOOP;
END;
StretchPolygonComm:
PROC [comm: CDSequencer.Command] =
BEGIN
ap: CD.ApplicationPtr;
p: PROC [points: PList, from, to: CD.DesignPosition] RETURNS [PList];
r: Rope.ROPE;
SELECT comm.a
FROM
$MovePolygonPoint => {p ← StretchPoints; r ← "stretch polygon"};
$AddPolygonPoint => {p ← IncludePoint; r ← "add point to polygon"};
$RemovePolygonPoint => {p ← RemovePoint; r ← "remove point from polygon"};
ENDCASE => {
TerminalIO.WriteRope["unknown command\n"];
RETURN
};
ap ← CDCommandOps.TheApplication[comm, r];
IF ap#
NIL
THEN {
WITH ap.ob.specificRef
SELECT
FROM
t: CDPolygons.PolygonPtr => {
offset: CD.DesignPosition;
ob: CD.ObPtr;
oldPoints: PList ← OrientedPoints[ap];
newPoints: PList ← p[oldPoints, comm.sPos, comm.pos];
[ob: ob, offset: offset] ← CDPolygons.CreatePolygon[newPoints, ap.ob.layer];
IF ob=
NIL
THEN {
TerminalIO.WriteRope[" not done\n"];
RETURN
};
CDOps.DelayedRedraw[comm.design, CDApplications.ARectO[ap]];
ap.ob ← ob;
ap.orientation ← CD.original;
ap.location ← offset;
CDOps.DelayedRedraw[comm.design, CDApplications.ARectO[ap], FALSE];
}
ENDCASE => TerminalIO.WriteRope["selected ob is not polygon; not done\n"];
};
END;
CDSequencer.ImplementCommand[$DrawPolygon, DrawPolygonComm];
CDSequencer.ImplementCommand[$MovePolygonPoint, StretchPolygonComm];
CDSequencer.ImplementCommand[$AddPolygonPoint, StretchPolygonComm];
CDSequencer.ImplementCommand[$RemovePolygonPoint, StretchPolygonComm];
[] ← CDMenus.CreateMenu["Polygons", $PolygonMenu];
CDMenus.CreateEntry[$PolygonMenu, "draw polygon", $DrawPolygon];
CDMenus.CreateEntry[$PolygonMenu, "add point", $AddPolygonPoint];
CDMenus.CreateEntry[$PolygonMenu, "move point", $MovePolygonPoint];
CDMenus.CreateEntry[$PolygonMenu, "remove point", $RemovePolygonPoint];
CDMenus.ImplementMenuCommand[$PolygonMenu, $PolygonMenu];
END.