File: SVDrawImpl.mesa
Last edited by Bier on May 31, 1984 4:10:03 pm PDT
Author: Eric Bier on August 5, 1985 3:21:41 pm PDT
Contents: Some convenience functions to draw shapes not directly available in Cedar Imager
DIRECTORY
Imager,
ImagerPath,
SV2d,
SVDraw,
SVLines2d,
SVVector2d;
SVDrawImpl: PROGRAM
IMPORTS Imager, ImagerPath, SVLines2d, SVVector2d
EXPORTS SVDraw =
BEGIN
Point2d: TYPE = SV2d.Point2d;
Polygon: TYPE = SV2d.Polygon;
globalSandwich: ImagerPath.Trajectory;
DrawLine: PROC [dc: Imager.Context, fromX, fromY, toX, toY: REAL] = {
Imager.MaskVector[dc, [fromX, fromY], [toX, toY]];
};
Cross: PUBLIC PROC [dc: Imager.Context, originX, originY, length: REAL] = {
halfLength: REAL ← length/2.0;
DrawLine[dc, originX-halfLength, originY, originX+halfLength, originY];
DrawLine[dc, originX, originY-halfLength, originX, originY+halfLength];
};
centerLine: SV2d.TrigLine ← SVLines2d.CreateEmptyTrigLine[];
LineSandwich: PUBLIC PROC [dc: Imager.Context, fromX, fromY, toX, toY: REAL] = {
leftFirst, leftSecond, rightFirst, rightSecond: Point2d;
Draw two parallel lines, so that the total width is three screen dots. This requires that we calculate the points with are 1 unit from the given central line segment and normal to that line segment.
Find the left and right segments given the center segment
path: ImagerPath.Trajectory;
SVLines2d.FillTrigLineFromPoints[[fromX, fromY], [toX, toY], centerLine];
leftFirst ← SVLines2d.PointLeftOfTrigLine[1, [fromX, fromY], centerLine];
leftSecond ← SVLines2d.PointLeftOfTrigLine[1, [toX, toY], centerLine];
rightFirst ← SVVector2d.Add[SVVector2d.Sub[[fromX, fromY], leftFirst], [fromX, fromY]];
rightSecond ← SVVector2d.Add[SVVector2d.Sub[[toX, toY], leftSecond], [toX, toY]];
Now draw the left line
path ← ImagerPath.MoveTo[[leftFirst[1], leftFirst[2]]];
path ← ImagerPath.LineTo[path, [leftSecond[1], leftSecond[2]]];
Imager.SetStrokeWidth[dc, 1.0];
Imager.SetStrokeEnd[dc, square];
Imager.MaskStrokeTrajectory[dc, path];
Finally, draw the right line
path ← ImagerPath.MoveTo[[rightFirst[1], rightFirst[2]]];
path ← ImagerPath.LineTo[path, [rightSecond[1], rightSecond[2]]];
Imager.MaskStrokeTrajectory[dc, path];
};
LineSandwich: PUBLIC PROC [dc: Imager.Context, fromX, fromY, toX, toY: REAL] = {
leftFirst, leftSecond, rightFirst, rightSecond: Point2d;
Draw three parallel lines, 2 black with 1 white in between so that the total width is three screen dots. This requires that we calculate the points with are 1 unit from the given central line segment and normal to that line segment.
Find the left and right segments given the center segment
path: ImagerPath.Trajectory;
SVLines2d.FillTrigLineFromPoints[[fromX, fromY], [toX, toY], centerLine];
leftFirst ← SVLines2d.PointLeftOfTrigLine[1, [fromX, fromY], centerLine];
leftSecond ← SVLines2d.PointLeftOfTrigLine[1, [toX, toY], centerLine];
rightFirst ← SVVector2d.Add[SVVector2d.Sub[[fromX, fromY], leftFirst], [fromX, fromY]];
rightSecond ← SVVector2d.Add[SVVector2d.Sub[[toX, toY], leftSecond], [toX, toY]];
Now draw the left line
Imager.SetColor[dc, Imager.black]; -- black
path ← ImagerPath.MoveTo[[leftFirst[1], leftFirst[2]]];
path ← ImagerPath.LineTo[path, [leftSecond[1], leftSecond[2]]];
Imager.SetStrokeWidth[dc, 1.0];
Imager.SetStrokeEnd[dc, square];
Imager.MaskStrokeTrajectory[dc, path];
Now draw the center line
Imager.SetColor[dc, Imager.white]; -- white
path ← ImagerPath.MoveTo[[fromX, fromY]];
path ← ImagerPath.LineTo[path, [toX, toY]];
Imager.MaskStrokeTrajectory[dc, path];
Finally, draw the right line
Imager.SetColor[dc, Imager.black]; -- black
path ← ImagerPath.MoveTo[[rightFirst[1], rightFirst[2]]];
path ← ImagerPath.LineTo[path, [rightSecond[1], rightSecond[2]]];
Imager.MaskStrokeTrajectory[dc, path];
};

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];
};
CrossHairs: PUBLIC PROC [dc: Imager.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];
globalSandwich ← ImagerPath.MoveTo[[screenPoint[1], screenPoint[2]]];
screenPoint ← PadToScreen[rightPoint, origin];
globalSandwich ← ImagerPath.LineTo[globalSandwich, [screenPoint[1], screenPoint[2]]];
Imager.SetStrokeWidth[dc, 0];
Imager.SetStrokeEnd[dc, square];
Imager.MaskStrokeTrajectory[dc, globalSandwich, FALSE];
screenPoint ← PadToScreen[topPoint, origin];
globalSandwich ← ImagerPath.MoveTo[[screenPoint[1], screenPoint[2]]];
screenPoint ← PadToScreen[bottomPoint, origin];
globalSandwich ← ImagerPath.LineTo[globalSandwich, [screenPoint[1], screenPoint[2]]];
Imager.SetStrokeWidth[dc, 0];
Imager.SetStrokeEnd[dc, square];
Imager.MaskStrokeTrajectory[dc, globalSandwich, FALSE];
};
DrawPolygon: PUBLIC PROC [dc: Imager.Context, poly: Polygon, origin: Point2d, scalar: REAL ← 1] = {
poly is in Pad coordinates
transform each point to screen coordinates and draw using Imager.
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];
LineSandwich[dc, screenPoint1[1], screenPoint1[2], screenPoint2[1], screenPoint2[2]];
screenPoint1 ← screenPoint2;
ENDLOOP;
LineSandwich[dc, screenPoint1[1], screenPoint1[2], screenPoint0[1], screenPoint0[2]];
};
END.