(* Copyright (C) 1995 UNICAMP. See notice at the end of this file. *) INTERFACE PSPlot; (* Version 95-04-16-stolfi *) (* Medium-level tools to generate PostScript files. This module provides tools for creating two flavors os PostScript files: Encapsulated PostScript (EPS), suitable for inclusion in other documents; and plain Postscript (PS), which can be sent directly to a printer. For more information and examples, see the comments further down. *) TYPE Axis = {X, Y}; BOOL = BOOLEAN; LONG = LONGREAL; TYPE EPSFile <: PubEPSFile; (* An Encapsulated PostScript (EPS) file contains a single figure, meant to be included in other documents. To create such a file, do | WITH f = NEW(EPSFile).open("foo.eps", ...) DO | f.segment(...); | f.circle(...) | ... | f.close() | END; *) PubEPSFile = File OBJECT METHODS open(name: TEXT; xSize, ySize: LONG := 150.0d0): EPSFile; (* Opens an Encapsulated PostScript file with the given name, and writes the file header and procedure sets. The extension ".eps" is recommended. The nominal drawing area will be a rectangle "xSize" by "ySize" in millimeters. *) END; TYPE PSFile <: PubPSFile; (* A plain PostScript (PS) file is meant to be sent to a printer, and may contain several pages, with several figures per page. To create one, do | WITH f = NEW(PSFile).open("foo.ps", ...) DO | (* Page 1: *) | f.beginPage() | f.beginDrawing(...); | f.segment(...); | ... | f.endDrawing(); | f.beginDrawing(...) | f.circle(...) | f.endDrawing(); | f.endPage(); | (* Page 2: *) | f.beginPage(); | f.beginDrawing(); | ... | f.endDrawing(); | ... | f.endPage(); | (* More pages: *) | ... | f.close() | END; *) PubPSFile = File OBJECT METHODS open( name: TEXT; xPageSize: LONG := LetterXSize; yPageSize: LONG := LetterYSize; ): PSFile; (* Opens a plain (i.e. multi-page, non-encapsulated) PostScript file with the given name, and writes the file header and procedure sets. The extension ".ps" is recommended. *) beginPage(); (* Starts a new page: writes page header line, etc. *) endPage(); (* Finishes the current page: Writes page trailer line, etc. *) beginDrawing( xSize, ySize: LONG := 150.0d0; xCenter := LetterXSize/2.0d0; yCenter := LetterYSize - LetterXSize/2.0d0; ); (* Starts a new drawing on the current page. Sets the drawing area to the specified rectangle (in millimeters from the lower left corner of page). *) endDrawing(); (* Finishes the current drawing. *) caption ( txt: TEXT; font: TEXT := "Courier"; size: REAL := 10.0; xAlign: REAL := 0.0; ); (* Prints a caption text just below the drawing area. The text will be left-justified if "xAlign=0", centered if "xAlign=0.5", and right-justified if "xAlign=1". For multi-line captions, use multiple calls and/or embedded newlines. *) END; TYPE File <: PubFile; (* Methods shared by plain and Encapsulated Postscript files. *) PubFile = OBJECT METHODS setScale(axis: Axis; min, max: LONG); (* Sets the scale of client coordinates along the given axis. Except where noted otherwise, all "axis" coordinates below are assumed to lie in the interval "[min_max]", which gets mapped to the corresponding dimension of the drawing area. *) setLineWidth(width: REAL); setLineColor(READONLY color: Color); setLineSolid(); setLineDashed(READONLY pattern: ARRAY OF REAL; skip: REAL := 0.0); (* Sets the color, line width, and dash length/space pattern for line drawing. The color also applies to text labels. Width and dash lengths are in millimeters, irrespective of current scale. *) setFillColor(READONLY color: Color); (* Sets the color to be used for filling the interior of closed figures (circles, rectangles, etc.). *) segment(xa, ya, xb, yb: LONG); (* Draws a segment from "(xa,ya)" to "(xb,yb)", using the current line parameters. *) setTextColor(READONLY color: Color); (* Sets the color to be used for labels and captions. The "color" must be visible. *) label( txt: TEXT; x, y: LONG; xAlign, yAlign: REAL := 0.0; angle: REAL := 0.0; font: TEXT := "Courier"; size: REAL := 10.0; ); (* Prints "txt" tilted by "angle" with its reference point at "(x,y)". The parameters "xAlign" and "yAlign" are the coordinates of the reference point relative to the text's bounding box: "(0,0)" means the lower left corner, "(1,1)" the upper right corner, "(0.5,0.5)" the center, etc. The "font" must be a Postscript font; the "size" is the nominal font size in points. The text must not include newlines. *) (* The methods below will paint the interior of the figure with the current "fill" color, and then draw the outline with the current "line" parameters (color, pen width, and dash pattern). Use the "Invisible" color to prevent either of these from happening. *) rectangle(xlo, xhi, ylo, yhi: LONG); (* The rectangle "[xlo..xhi] x [ylo..yhi]". *) triangle(xa, ya, xb, yb, xc, yc: LONG); (* The triangle "(xa,ya), (xb,yb), (xc,yc)". *) circle(xc,yc: LONG; radius: REAL); (* The circle with center "(xc,yc)" (in client coordinates) and given radius (in millimeters, irrespective OF current scale). *) ellipse(xc,yc, xa,ya, xb,yb: LONG); (* The ellipse which corresponds to the unit circle in the affine frame with origin "(xc,yc)" and basis vectors "(xa,ya), (xb,yb)". *) coordLine(axis: Axis; coord: LONG); (* Draws a reference line perpendicular to the given axis at the given coordinate value. *) setGridSize(xn, yn: CARDINAL); (* Implicitly divides the drawing area into an array of "xn" by "yn" cells, for use by the methods "gridCell" and "gridLines" below. The cells are numbered left to right from 0 to "xn-1", and bottom to top from 0 to "yn-1". *) gridCell(xi, yi: CARDINAL); (* Paints the specified cell of the cell grid. *) gridLines(); (* Draws the all cell grid lines with the current line parameters. *) frame(); (* Draws a frame around the plotting area. *) comment(txt: TEXT); (* Writes "txt" to the file, as a comment *) close(); (* MUST be called to write the file trailers and close the file. *) END; CONST (* Standard paper dimensions in mm: *) LetterXSize = 8.5d0 * 25.4d0; LetterYSize = 11.0d0 * 25.4d0; TYPE Color = ARRAY [0..2] OF REAL; (* RGB in the range [0__1]. If any components are negative, the color is interpreted as "invisible" (wholly transparent). *) CONST Invisible = Color{-1.0, -1.0, -1.0}; (* An invisible color. *) Black = Color{0.0, 0.0, 0.0}; Red = Color{1.0, 0.0, 0.0}; Yellow = Color{1.0, 1.0, 0.0}; Green = Color{0.0, 1.0, 0.0}; Cyan = Color{0.0, 1.0, 1.0}; Blue = Color{0.0, 0.0, 1.0}; Magenta = Color{1.0, 0.0, 1.0}; White = Color{1.0, 1.0, 1.0}; PROCEDURE Gray(v: REAL): Color; (* A gray color with given brightness. *) END PSPlot. (* This module aims to provide only the most basic drawing commands, in a simple interface. It is not meant to be a complete Postscript interface (see the "dps" package for that), nor a replacement for data graphing tools (like "gnuplot"). Some things that should be added to this package: * Other geometric primitives: Beziers, circular and elliptical arcs, polygons, (with open array arguments?), incremental path construction, etc. * A "text" primitive that prints a given text in a specified rectangle, with atomatic line breaking, justification, etc. * A "landscape" argument to "PSFile.open". Note that because of the defaults, "xPageSize" and "yPageSize" should probably be interpreted before "landscape". * PSFile.open should write "xPageSize" and "yPageSize" as the appropriate Postscript structured comment. *) (****************************************************************************) (* *) (* Copyright (C) 1995 Universidade Estadual de Campinas (UNICAMP) *) (* *) (* Authors: *) (* Jorge Stolfi - CS Dept, UNICAMP *) (* *) (* This file can be freely used, distributed, and modified, provided that *) (* this copyright and authorship notice is included in every copy or *) (* derived version. *) (* *) (* DISCLAIMER: This software is offered ``as is'', without any guarantee *) (* as to fitness for any particular purpose. Neither the copyright *) (* holder nor the authors or their employers can be held responsible for *) (* any damages that may result from its use. *) (* *) (****************************************************************************)