GGBuiltinShapesImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Last edited by Bier on June 23, 1986
Contents: The regular polygons and other commonly requested shapes.
Pier, April 24, 1987 0:10:21 am PDT
Bier, February 18, 1987 11:04:00 pm PST
DIRECTORY
GGBasicTypes, GGBoundBox, GGBuiltinShapes, GGModelTypes, GGOutline, GGSegment, GGSegmentTypes, GGTransform, GGSlice, GGTraj, Vectors2d, ImagerColor, RealFns, Rope;
GGBuiltinShapesImpl: CEDAR PROGRAM
IMPORTS GGBoundBox, GGOutline, GGSegment, GGSlice, GGTraj, GGTransform, Vectors2d, ImagerColor, RealFns
EXPORTS GGBuiltinShapes = BEGIN
DefaultData: TYPE = GGModelTypes.DefaultData;
Outline: TYPE = GGModelTypes.Outline;
Point: TYPE = GGBasicTypes.Point;
Segment: TYPE = GGSegmentTypes.Segment;
SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator;
Slice: TYPE = GGModelTypes.Slice;
SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor;
Traj: TYPE = GGModelTypes.Traj;
Vector: TYPE = GGBasicTypes.Vector;
Problem: PUBLIC SIGNAL [msg: Rope.ROPE] = CODE;
PolygonInCircle: PUBLIC PROC [sideCount: NAT, origin: Point, radius: REAL, defaults: DefaultData] RETURNS [outline: Outline] = {
The bottom-most edge of the returned polygon will be horizontal. The polygon will be inscribed inside the circle with radius "radius" centered at "origin".
traj: Traj;
theta0, theta, deltaTheta, sin, cos: REAL;
lastPoint, thisPoint: Point;
success: BOOL;
seg: Segment;
deltaTheta ← 360.0/sideCount;
theta0 ← -90.0 + deltaTheta/2.0;
sin ← RealFns.SinDeg[theta0];
cos ← RealFns.CosDeg[theta0];
thisPoint ← Vectors2d.Add[Vectors2d.Scale[[cos, sin], radius], origin];
traj ← GGTraj.CreateTraj[thisPoint];
lastPoint ← thisPoint;
FOR i: NAT IN [1..sideCount-1] DO
theta ← theta0 + i*deltaTheta;
sin ← RealFns.SinDeg[theta];
cos ← RealFns.CosDeg[theta];
thisPoint ← Vectors2d.Add[Vectors2d.Scale[[cos, sin], radius], origin];
seg ← GGSegment.MakeLine[lastPoint, thisPoint, NIL];
GGSegment.SetDefaults[seg, defaults];
success ← GGTraj.AddSegment[traj, hi, seg, lo];
IF NOT success THEN SIGNAL Problem[msg: "Couldn't add segment"];
lastPoint ← thisPoint;
ENDLOOP;
sin ← RealFns.SinDeg[theta0];
cos ← RealFns.CosDeg[theta0];
thisPoint ← Vectors2d.Add[Vectors2d.Scale[[cos, sin], radius], origin];
seg ← GGSegment.MakeLine[lastPoint, thisPoint, NIL];
GGSegment.SetDefaults[seg, defaults];
GGTraj.CloseWithSegment[traj, seg, lo];
outline ← GGOutline.CreateOutline[traj, ImagerColor.ColorFromGray[0.5]];
outline.class.setStrokeJoint[outline, outline.class.newParts[outline, NIL, topLevel].parts, defaults.strokeJoint];
outline.class.setFillColor[outline, defaults.fillColor];
};
Box: PUBLIC PROC [origin: Point, sideLength: REAL, defaults: DefaultData] RETURNS [slice: Slice] = {
halfSide: REAL ← sideLength/2.0;
box: GGBoundBox.BoundBox ← GGBoundBox.CreateBoundBox[origin.x-halfSide, origin.y-halfSide, origin.x+halfSide, origin.y+halfSide];
sliceD: SliceDescriptor ← GGSlice.MakeBoxSlice[box, ul, GGTransform.Identity[] ];
completeSliceD: SliceDescriptor ← sliceD.slice.class.newParts[sliceD.slice, NIL, slice];
slice ← sliceD.slice;
GGSlice.SetDefaults[slice, completeSliceD.parts, defaults];
};
Circle: PUBLIC PROC [origin: Point, radius: REAL, defaults: DefaultData] RETURNS [slice: Slice] = {
outerPoint: Point ← [origin.x + radius, origin.y];
sliceD: SliceDescriptor ← GGSlice.MakeCircleSlice[origin, outerPoint];
completeSliceD: SliceDescriptor ← sliceD.slice.class.newParts[sliceD.slice, NIL, slice];
slice ← sliceD.slice;
GGSlice.SetDefaults[slice, completeSliceD.parts, defaults];
};
Polygon: PUBLIC PROC [sideCount: NAT, origin: Point, sideLength: REAL, defaults: DefaultData] RETURNS [outline: Outline] = {
The bottom-most edge of the returned polygon will be horizontal. The polygon will be inscribed inside a circle centered at "origin". Each side of the polygon will have length "sideLength".
};
KnotchedLine: PUBLIC PROC [p0, p1: Point, segmentCount: NAT] RETURNS [outline: Outline] = {
Returns a trajectory with "segmentCount" straight line segments, all of the same length. The entire trajectory is a single straight line, from point p0 to p1. All of its segments are collinear. Knotched lines are useful as rulers.
delta: Vector;
lastPoint, thisPoint: Point;
traj: Traj;
seg: Segment;
success: BOOL;
delta ← Vectors2d.Scale[Vectors2d.Sub[p1, p0], 1.0/segmentCount];
lastPoint ← p0;
traj ← GGTraj.CreateTraj[lastPoint];
THROUGH [1..segmentCount-1] DO
thisPoint ← Vectors2d.Add[lastPoint, delta];
seg ← GGSegment.MakeLine[lastPoint, thisPoint, NIL];
success ← GGTraj.AddSegment[traj, hi, seg, lo];
IF NOT success THEN SIGNAL Problem[msg: "Couldn't add segment"];
lastPoint ← thisPoint;
ENDLOOP;
thisPoint ← p1;
seg ← GGSegment.MakeLine[lastPoint, thisPoint, NIL];
success ← GGTraj.AddSegment[traj, hi, seg, lo];
IF NOT success THEN SIGNAL Problem[msg: "Couldn't add segment"];
outline ← GGOutline.CreateOutline[traj, ImagerColor.ColorFromGray[0.5]];
};
END.