-- File: PadGraphicsImpl.mesa
-- Last edited by Bier on December 18, 1982 1:29 am
-- Author: Eric Bier on August 6, 1982 12:30 pm
-- Contents: Simple 2d graphics package for the scratchpad
DIRECTORY
Graphics,
PadGraphics,
Matrix3d,
RealFns,
SVDraw,
SVPolygon2d,
SVVector2d;
PadGraphicsImpl: PROGRAM
IMPORTS Graphics, RealFns, SVDraw, SVVector2d
EXPORTS PadGraphics =
BEGIN
Path: TYPE = SVPolygon2d.Path;
Point2d: TYPE = Matrix3d.Point2d;
Polygon: TYPE = SVPolygon2d.Polygon;
Vector2d: TYPE = SVVector2d.Vector2d;
squareSide: REAL ← 6.0;
ScreenToPad: PUBLIC PROC [screenPoint: Point2d, origin: Point2d, scalar: REAL ← 1] RETURNS [padPoint: Point2d] = {
-- origin is the pad origin in screen coordintates
padPoint[1] ← screenPoint[1] - origin[1];
padPoint[2] ← screenPoint[2] - origin[2];
padPoint ← SVVector2d.Scale[padPoint, 1/scalar];
};
PadToScreen: PUBLIC PROC [padPoint: Point2d, origin: Point2d, scalar: REAL ← 1] RETURNS [screenPoint: Point2d] = {
padPoint ← SVVector2d.Scale[padPoint, scalar];
screenPoint[1] ← padPoint[1] + origin[1];
screenPoint[2] ← padPoint[2] + origin[2];
};
MoveTo: PUBLIC PROC [dc: Graphics.Context, padPoint: Point2d, origin: Point2d] = {
screenPoint: Point2d;
screenPoint ← PadToScreen[padPoint, origin];
Graphics.SetCP[dc, screenPoint[1], screenPoint[2]];
};
DrawTo: PUBLIC PROC [dc: Graphics.Context, padPoint: Point2d, origin: Point2d] = {
screenPoint: Point2d;
screenPoint ← PadToScreen[padPoint, origin];
Graphics.DrawTo[dc, screenPoint[1], screenPoint[2]];
};
MirrorMoveTo: PUBLIC PROC [dc: Graphics.Context, padPoint: Point2d, origin: Point2d] = {
screenPoint: Point2d;
padPoint[1] ← -padPoint[1];
screenPoint ← PadToScreen[padPoint, origin];
Graphics.SetCP[dc, screenPoint[1], screenPoint[2]];
};
MirrorDrawTo: PUBLIC PROC [dc: Graphics.Context, padPoint: Point2d, origin: Point2d] = {
screenPoint: Point2d;
padPoint[1] ← -padPoint[1];
screenPoint ← PadToScreen[padPoint, origin];
Graphics.DrawTo[dc, screenPoint[1], screenPoint[2]];
};
DrawPathNeighborHood: PUBLIC PROC [dc: Graphics.Context, path: Path, index: NAT, origin: Point2d] = {
-- draw three points and 2 edges corresponding to the neighborhood of path[index];
-- path is in pad coordinates.
-- if index is one of the two ends of the path then draw 2 points and 1 edge.
DrawSquare[dc, squareSide, path[index], origin];
IF index>0 THEN {
MoveTo[dc, path[index-1], origin];
DrawTo[dc, path[index], origin];
};
IF index<path.len-1 THEN {
MoveTo[dc, path[index+1], origin];
DrawTo[dc, path[index], origin];
};
};
MirrorDrawPathNeighborHood: PUBLIC PROC [dc: Graphics.Context, path: Path, index: NAT, origin: Point2d] = {
-- draw three points and 2 edges corresponding to the neighborhood of path[index];
-- path is in pad coordinates.
-- if index is one of the two ends of the path then draw 2 points and 1 edge.
MirrorDrawSquare[dc, squareSide, path[index], origin];
IF index>0 THEN {
MirrorMoveTo[dc, path[index-1], origin];
MirrorDrawTo[dc, path[index], origin];
};
IF index<path.len-1 THEN {
MirrorMoveTo[dc, path[index+1], origin];
MirrorDrawTo[dc, path[index], origin];
};
};
DrawPolyNeighborHood: PUBLIC PROC [dc: Graphics.Context, poly: Polygon, index: NAT, origin: Point2d] = {
-- draw three points and 2 edges corresponding to the neighborhood of poly[index];
-- poly is in pad coordinates.
-- poly.len = 2 then draw both points and the edge joining them.
-- if poly.len = 1 then just draw a point.
indexPlusOne, indexMinusOne: NAT;
indexPlusOne ← IF index = poly.len-1 THEN 0 ELSE index + 1;
indexMinusOne ← IF index = 0 THEN poly.len-1 ELSE index - 1;
DrawSquare[dc, squareSide, poly[index], origin];
IF poly.len = 1 THEN RETURN;
MoveTo[dc, poly[indexPlusOne], origin];
DrawTo[dc, poly[index], origin];
IF poly.len = 2 THEN RETURN;
MoveTo[dc, poly[indexMinusOne], origin];
DrawTo[dc, poly[index], origin];
};
MirrorDrawPolyNeighborHood: PUBLIC PROC [dc: Graphics.Context, poly: Polygon, index: NAT, origin: Point2d] = {
-- draw three points and 2 edges corresponding to the neighborhood of poly[index];
-- poly is in pad coordinates.
-- poly.len = 2 then draw both points and the edge joining them.
-- if poly.len = 1 then just draw a point.
indexPlusOne, indexMinusOne: NAT;
indexPlusOne ← IF index = poly.len-1 THEN 0 ELSE index + 1;
indexMinusOne ← IF index = 0 THEN poly.len-1 ELSE index - 1;
MirrorDrawSquare[dc, squareSide, poly[index], origin];
IF poly.len = 1 THEN RETURN;
MirrorMoveTo[dc, poly[indexPlusOne], origin];
MirrorDrawTo[dc, poly[index], origin];
IF poly.len = 2 THEN RETURN;
MirrorMoveTo[dc, poly[indexMinusOne], origin];
MirrorDrawTo[dc, poly[index], origin];
};
DrawPath: PUBLIC PROC [dc: Graphics.Context, path: Path, origin: Point2d, scalar: REAL ← 1] = {
-- poly is in Pad coordinates
-- transform each point to screen coordinates and draw using Graphics.
outline: Graphics.Path ← Graphics.NewPath[path.len];
screenPoint: Point2d;
IF path.len <= 1 THEN RETURN;
screenPoint ← PadToScreen[path[0], origin, scalar];
Graphics.MoveTo[outline, screenPoint[1], screenPoint[2]];
FOR i: NAT IN [1..path.len) DO
screenPoint ← PadToScreen[path[i], origin, scalar];
Graphics.LineTo[outline, screenPoint[1], screenPoint[2]];
ENDLOOP;
Graphics.DrawStroke[dc, outline, 2, FALSE, round];
};
DrawPolygon: PUBLIC PROC [dc: Graphics.Context, poly: Polygon, origin: Point2d, scalar: REAL ← 1] = {
-- poly is in Pad coordinates
-- transform each point to screen coordinates and draw using Graphics.
screenPoint0, screenPoint1, screenPoint2: Point2d;
IF poly.len <= 1 THEN RETURN;
screenPoint0 ← screenPoint1 ← PadToScreen[poly[0], origin, scalar];
FOR i: NAT IN [1..poly.len) DO
screenPoint2 ← PadToScreen[poly[i], origin, scalar];
SVDraw.LineSandwich[dc, screenPoint1[1], screenPoint1[2], screenPoint2[1], screenPoint2[2]];
screenPoint1 ← screenPoint2;
ENDLOOP;
SVDraw.LineSandwich[dc, screenPoint1[1], screenPoint1[2], screenPoint0[1], screenPoint0[2]];
};
CrossHairs: PUBLIC PROC [dc: Graphics.Context, origin: Point2d] = {
leftPoint, rightPoint, topPoint, bottomPoint, screenPoint: Point2d;
leftPoint ← [-1000, 0];
rightPoint ← [1000, 0];
topPoint ← [0, 1000];
bottomPoint ← [0, -1000];
screenPoint ← PadToScreen[leftPoint, origin];
Graphics.SetCP[dc, screenPoint[1], screenPoint[2]];
screenPoint ← PadToScreen[rightPoint, origin];
Graphics.DrawTo[dc, screenPoint[1], screenPoint[2]];
screenPoint ← PadToScreen[topPoint, origin];
Graphics.SetCP[dc, screenPoint[1], screenPoint[2]];
screenPoint ← PadToScreen[bottomPoint, origin];
Graphics.DrawTo[dc, screenPoint[1], screenPoint[2]];
};
DrawSquare: PUBLIC PROC [dc: Graphics.Context, side: REAL, center: Point2d, origin: Point2d] = {
delta: REAL ← side/2.0;
screenPoint: Point2d;
square: Graphics.Path ← Graphics.NewPath[4];
screenPoint ← PadToScreen[[center[1]-delta, center[2]-delta], origin];
Graphics.MoveTo[square, screenPoint[1], screenPoint[2]];
screenPoint ← PadToScreen[[center[1]-delta, center[2]+delta], origin];
Graphics.LineTo[square, screenPoint[1], screenPoint[2]];
screenPoint ← PadToScreen[[center[1]+delta, center[2]+delta], origin];
Graphics.LineTo[square, screenPoint[1], screenPoint[2]];
screenPoint ← PadToScreen[[center[1]+delta, center[2]-delta], origin];
Graphics.LineTo[square, screenPoint[1], screenPoint[2]];
Graphics.DrawStroke[dc, square, 1, TRUE];
};
MirrorDrawSquare: PUBLIC PROC [dc: Graphics.Context, side: REAL, center: Point2d, origin: Point2d] = {
delta: REAL ← side/2.0;
screenPoint: Point2d;
square: Graphics.Path ← Graphics.NewPath[4];
center[1] ← -center[1];
screenPoint ← PadToScreen[[center[1]-delta, center[2]-delta], origin];
Graphics.MoveTo[square, screenPoint[1], screenPoint[2]];
screenPoint ← PadToScreen[[center[1]-delta, center[2]+delta], origin];
Graphics.LineTo[square, screenPoint[1], screenPoint[2]];
screenPoint ← PadToScreen[[center[1]+delta, center[2]+delta], origin];
Graphics.LineTo[square, screenPoint[1], screenPoint[2]];
screenPoint ← PadToScreen[[center[1]+delta, center[2]-delta], origin];
Graphics.LineTo[square, screenPoint[1], screenPoint[2]];
Graphics.DrawStroke[dc, square, 1, TRUE];
};
Draw2dVector: PUBLIC PROC [dc: Graphics.Context, vec: Vector2d, at: Point2d, origin: Point2d] = {
unitVec, vec50: Vector2d;
mag: REAL;
mag ← RealFns.SqRt[vec[1]*vec[1] + vec[2]*vec[2]];
unitVec[1] ← vec[1]/mag;
unitVec[2] ← vec[2]/mag;
vec50[1] ← unitVec[1]*50;
vec50[2] ← unitVec[2]*50;
MoveTo[dc, at, origin];
DrawTo[dc, [at[1]+vec50[1], at[2]+vec50[2]], origin];
}; -- end of Draw2dVector
END.