<> <> <> <> DIRECTORY Imager, PadGraphics, Real, RealFns, SV2d, SVLines2d, SVVector2d; PadGraphicsImpl: PROGRAM IMPORTS Imager, Real, RealFns, SVLines2d, SVVector2d EXPORTS PadGraphics = BEGIN Path: TYPE = SV2d.Path; Point2d: TYPE = SV2d.Point2d; Polygon: TYPE = SV2d.Polygon; Vector2d: TYPE = SV2d.Vector2d; squareSide: REAL _ 6.0; globalOutline: Imager.Trajectory; ScreenToPad: PUBLIC PROC [screenPoint: Point2d, origin: Point2d, scalar: REAL _ 1] RETURNS [padPoint: Point2d] = { <> 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: Imager.Context, padPoint: Point2d, origin: Point2d] = { screenPoint: Point2d; screenPoint _ PadToScreen[padPoint, origin]; globalOutline _ Imager.MoveTo[[screenPoint[1], screenPoint[2]]]; }; DrawTo: PUBLIC PROC [dc: Imager.Context, padPoint: Point2d, origin: Point2d] = { screenPoint: Point2d; screenPoint _ PadToScreen[padPoint, origin]; globalOutline _ Imager.LineTo[globalOutline, [screenPoint[1], screenPoint[2]]]; Imager.MaskStroke[dc, globalOutline, 1, square]; }; MirrorMoveTo: PUBLIC PROC [dc: Imager.Context, padPoint: Point2d, origin: Point2d] = { screenPoint: Point2d; padPoint[1] _ -padPoint[1]; screenPoint _ PadToScreen[padPoint, origin]; globalOutline _ Imager.MoveTo[[screenPoint[1], screenPoint[2]]]; }; MirrorDrawTo: PUBLIC PROC [dc: Imager.Context, padPoint: Point2d, origin: Point2d] = { screenPoint: Point2d; padPoint[1] _ -padPoint[1]; screenPoint _ PadToScreen[padPoint, origin]; globalOutline _ Imager.LineTo[globalOutline, [screenPoint[1], screenPoint[2]]]; Imager.MaskStroke[dc, globalOutline, 1, square]; }; DrawPathNeighborHood: PUBLIC PROC [dc: Imager.Context, path: Path, index: NAT, origin: Point2d] = { <> <> <> DrawSquare[dc, squareSide, path[index], origin]; IF index>0 THEN { MoveTo[dc, path[index-1], origin]; DrawTo[dc, path[index], origin]; }; IF index> <> <> MirrorDrawSquare[dc, squareSide, path[index], origin]; IF index>0 THEN { MirrorMoveTo[dc, path[index-1], origin]; MirrorDrawTo[dc, path[index], origin]; }; IF index> <> <> <> 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: Imager.Context, poly: Polygon, index: NAT, origin: Point2d] = { <> <> <> <> 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: Imager.Context, path: Path, origin: Point2d, scalar: REAL _ 1] = { <> <> outline: Imager.Trajectory; << _ Graphics.NewPath[path.len];>> screenPoint: Point2d; IF path.len <= 1 THEN RETURN; screenPoint _ PadToScreen[path[0], origin, scalar]; outline _ Imager.MoveTo[[screenPoint[1], screenPoint[2]]]; FOR i: NAT IN [1..path.len) DO screenPoint _ PadToScreen[path[i], origin, scalar]; outline _ Imager.LineTo[outline, [screenPoint[1], screenPoint[2]]]; ENDLOOP; Imager.MaskStroke[dc, outline, 0, round]; }; DrawPolygon: PUBLIC PROC [dc: Imager.Context, poly: Polygon, origin: Point2d, scalar: REAL _ 1] = { <> <> 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]]; }; 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]; globalOutline _ Imager.MoveTo[[screenPoint[1], screenPoint[2]]]; screenPoint _ PadToScreen[rightPoint, origin]; globalOutline _ Imager.LineTo[globalOutline, [screenPoint[1], screenPoint[2]]]; Imager.MaskStroke[dc, globalOutline, 0, square]; screenPoint _ PadToScreen[topPoint, origin]; globalOutline _ Imager.MoveTo[[screenPoint[1], screenPoint[2]]]; screenPoint _ PadToScreen[bottomPoint, origin]; globalOutline _ Imager.LineTo[globalOutline, [screenPoint[1], screenPoint[2]]]; Imager.MaskStroke[dc, globalOutline, 0, square]; }; DrawSquare: PUBLIC PROC [dc: Imager.Context, side: REAL, center: Point2d, origin: Point2d] = { delta: REAL _ side/2.0; screenPoint: Point2d; square: Imager.Trajectory; <> screenPoint _ PadToScreen[[center[1]-delta, center[2]-delta], origin]; square _ Imager.MoveTo[[screenPoint[1], screenPoint[2]]]; screenPoint _ PadToScreen[[center[1]-delta, center[2]+delta], origin]; square _ Imager.LineTo[square, [screenPoint[1], screenPoint[2]]]; screenPoint _ PadToScreen[[center[1]+delta, center[2]+delta], origin]; square _ Imager.LineTo[square, [screenPoint[1], screenPoint[2]]]; screenPoint _ PadToScreen[[center[1]+delta, center[2]-delta], origin]; square _ Imager.LineTo[square, [screenPoint[1], screenPoint[2]]]; Imager.MaskStrokeClosed[dc, square, 0]; }; MirrorDrawSquare: PUBLIC PROC [dc: Imager.Context, side: REAL, center: Point2d, origin: Point2d] = { delta: REAL _ side/2.0; screenPoint: Point2d; square: Imager.Trajectory; <> center[1] _ -center[1]; screenPoint _ PadToScreen[[center[1]-delta, center[2]-delta], origin]; square _ Imager.MoveTo[[screenPoint[1], screenPoint[2]]]; screenPoint _ PadToScreen[[center[1]-delta, center[2]+delta], origin]; square _ Imager.LineTo[square, [screenPoint[1], screenPoint[2]]]; screenPoint _ PadToScreen[[center[1]+delta, center[2]+delta], origin]; square _ Imager.LineTo[square, [screenPoint[1], screenPoint[2]]]; screenPoint _ PadToScreen[[center[1]+delta, center[2]-delta], origin]; square _ Imager.LineTo[square, [screenPoint[1], screenPoint[2]]]; Imager.MaskStrokeClosed[dc, square, 0]; }; Draw2dVector: PUBLIC PROC [dc: Imager.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 Circle: PUBLIC PROC [dc: Imager.Context, originX, originY, radius: REAL] = { <> <0, so>> <<(1-cos(theta/2) < z/r. -cos(theta/2) < z/r - 1. cos(theta/2) > (1 - z/r). Theta/2 < ArcCos[1 - z/r]. Theta < 2*ArcCos[1 - z/r]. Let z = 0.5.>> cosine, sine, rcosine, rsine, lastRsine, lastRcosine: REAL; z: REAL = 0.5; deltaTheta, theta, lastTheta: REAL; numberOfTimesGoesIn: NAT; cosine _ 1-z/radius; sine _ RealFns.SqRt[1-cosine*cosine]; deltaTheta _ RealFns.ArcTanDeg[sine, cosine]; <> numberOfTimesGoesIn _ Real.FixC[45.0/deltaTheta]; deltaTheta _ 45.0/(numberOfTimesGoesIn + 1); lastTheta _ 0; lastRsine _ 0; lastRcosine _ radius; FOR i: NAT IN [1..numberOfTimesGoesIn+1] DO theta _ lastTheta + deltaTheta; rsine _ radius*RealFns.SinDeg[theta]; rcosine _ radius*RealFns.CosDeg[theta]; DrawLine[dc, originX + lastRcosine, originY + lastRsine, originX + rcosine, originY + rsine]; DrawLine[dc, originX + lastRsine, originY + lastRcosine, originX + rsine, originY + rcosine]; DrawLine[dc, originX + lastRcosine, originY - lastRsine, originX + rcosine, originY - rsine]; DrawLine[dc, originX + lastRsine, originY - lastRcosine, originX + rsine, originY - rcosine]; DrawLine[dc, originX - lastRcosine, originY + lastRsine, originX - rcosine, originY + rsine]; DrawLine[dc, originX - lastRsine, originY + lastRcosine, originX - rsine, originY + rcosine]; DrawLine[dc, originX - lastRcosine, originY - lastRsine, originX - rcosine, originY - rsine]; DrawLine[dc, originX - lastRsine, originY - lastRcosine, originX - rsine, originY - rcosine]; lastTheta _ theta; lastRsine _ rsine; lastRcosine _ rcosine; ENDLOOP; }; -- end of Circle centerLine: SV2d.TrigLine _ SVLines2d.CreateEmptyTrigLine[]; LineSandwich: PUBLIC PROC [dc: Imager.Context, fromX, fromY, toX, toY: REAL] = { leftFirst, leftSecond, rightFirst, rightSecond: Point2d; <> <> 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]]; <> Imager.SetColor[dc, Imager.black]; -- black globalOutline _ Imager.MoveTo[[leftFirst[1], leftFirst[2]]]; globalOutline _ Imager.LineTo[globalOutline, [leftSecond[1], leftSecond[2]]]; Imager.MaskStroke[dc, globalOutline, 0, butt]; <> Imager.SetColor[dc, Imager.white]; -- white globalOutline _ Imager.MoveTo[[fromX, fromY]]; globalOutline _ Imager.LineTo[globalOutline, [toX, toY]]; Imager.MaskStroke[dc, globalOutline, 0, butt]; <> Imager.SetColor[dc, Imager.black]; -- black globalOutline _ Imager.MoveTo[[rightFirst[1], rightFirst[2]]]; globalOutline _ Imager.LineTo[globalOutline, [rightSecond[1], rightSecond[2]]]; Imager.MaskStroke[dc, globalOutline, 0, butt]; }; DrawLine: PRIVATE PROC [dc: Imager.Context, fromX, fromY, toX, toY: REAL] = { <> globalOutline _ Imager.MoveTo[[fromX, fromY]]; globalOutline _ Imager.LineTo[globalOutline, [toX, toY]]; Imager.MaskStroke[dc, globalOutline, 0, square]; }; END.