unit Plt; { A simple graphics library, with simultaneous screen and Postscript output. } { Last edited by J. Stolfi on 93-04-20. } { Change by C.H.Q. Forster on 95-01-11 (removed PostScript Features)} interface { The routines below can be used to paint two-dimensional diagrams consisting of lines, points, and shaded triangles. The drawing and painting commands below are both executed on the screen and written to a disk file in Postscript format. The file can be sent directly to any Postscript printer, to produce a full-resolution copy of the final drawing. Waring: dont try to use this package to show animated drawings on the screen; if you do, you may run out of disk space. For this unit, the X axis points to the right, the Y axis points up. All dimensions and Cartesian coordinates correspond to MILLIMETERS on the printed image. For the screen image, the coordinates are automatically scaled so that exactly the same points are visible on the screen and on the paper. } const plt_x_max = 100.0; plt_y_max = 100.0; { The plotting window (the visible part of the drawing plane) is a rectangle measuring (2 * x_max) by (2 * y_max) millimeters. The origin is at the CENTER of the plotting window. Thus, a point (X,Y) is visible only if -x_max <= X <= +x_max and -y_max <= Y <= +y_max. } procedure plt_begin_drawing(file_name: string; user_name: string; page: integer); { Initializes the Postscript file and the screen device. The Postscript file will have the given /file_name/. When that file is printed, the given /user_name/ will appear at the bottom of the page. This routine MUST be called (once) before any other drawing commands. } procedure plt_end_drawing; { Finishes the current drawing, and closes the file. MUST be called (once) after the last drawing command. } procedure plt_draw_point(x, y: real; size: real; grey: real); { Plots a point (x y), as a circle with diameter /size/. } procedure plt_draw_segment( x1, y1: real; x2, y2: real; width: real; grey: real ); { Plots the line segment from (x1 y1) to (x2 y2), using a pen with given width and color. Setting /width/=0 means a 1-pixel-wide line. } procedure plt_paint_triangle( x1, y1: real; x2, y2: real; x3, y3: real; grey: real ); { Paints the interior of the given triangle with the given color. } procedure plt_paint_plane(grey: real); { Paints the whole plotting area with the given color. } procedure plt_add_caption(s: string); { Prints the caption /s/, left-justified, under the drawing. Each new call adds a new line to the caption. } implementation uses {PSHacks,} GrHacks; const max_width = 300.0; { Maximum point size and line width in mm. } var { cur_file: PSHacks.PS_File; } { The current Postscript output file. } { cur_file_name: string;} { Name of current Postscript file. } { file_is_open: boolean;} { /true/ if a drawing is in progress. } cmd_count: Longint; { Count of drawing commands in file. } procedure err_msg(caller: string; msg: string); begin writeln('*** plt_', caller, ': ', msg); { if file_is_open then begin writeln(' file = ', cur_file_name, ' command count = ', cmd_count) end; } halt(1) end; var cur_grey: real; { Current color. } cur_pen_size: real; { Current pen size. } procedure new_command(caller: string); begin { if not file_is_open then err_msg(caller, 'begin_drawing was not called'); } inc(cmd_count); end; procedure set_pen_size(caller: string; size: real); begin if (size < 0.0) or (size > max_width) then err_msg(caller, 'invalid point size.'); if size <> cur_pen_size then begin cur_pen_size := size; { ps_set_pen(cur_file, cur_pen_size, 0.0, 0.0); } gr_set_pen(cur_pen_size) end; end; procedure set_grey(caller: string; grey: real); begin if (grey < 0.0) or (grey > 1.0) then err_msg(caller, 'invalid grey level.'); if grey <> cur_grey then begin cur_grey := grey; { ps_set_color(cur_file, cur_grey); } gr_set_color(cur_grey) end; end; procedure plt_begin_drawing(file_name: string; user_name: string; page: integer); var driver, mode, errcode: integer; begin { Initialize Postscript drawing file } { if file_is_open then err_msg('begin_drawing', 'drawing already in progress'); assign(cur_file, file_name); rewrite(cur_file); cur_file_name := file_name; } cmd_count := 0; { file_is_open := true; } cur_grey := 0; cur_pen_size := 0.0; { ps_begin_file(cur_file); ps_begin_page(cur_file, -plt_x_max, +plt_x_max, -plt_y_max, +plt_y_max, user_name, page ); ps_set_color(cur_file, cur_grey); ps_set_pen(cur_file, cur_pen_size, 0.0, 0.0); } { Initialize screen graphics } gr_begin_drawing( -plt_x_max, +plt_x_max, -plt_y_max, +plt_y_max ); gr_set_color(1.0); gr_paint_plane; gr_set_color(cur_grey); gr_set_pen(cur_pen_size); end; procedure plt_end_drawing; begin new_command('end_drawing'); { ps_end_page(cur_file); ps_end_file(cur_file); close(cur_file); file_is_open := false; } gr_end_drawing; end; procedure plt_draw_point(x, y: real; size: real; grey: real); label 999; { End of procedure. } begin new_command('draw_point'); set_pen_size('draw_point', size); set_grey('draw_point', grey); { Clip coordinates: } if abs(x) > plt_x_max + size/2.0 then goto 999; if abs(y) > plt_y_max + size/2.0 then goto 999; { ps_draw_point(cur_file, x, y); } gr_draw_point(x, y); 999: end; procedure plt_draw_segment( x1, y1: real; x2, y2: real; width: real; grey: real ); var lim: real; label 999; { End of procedure. } begin new_command('draw_segment'); set_pen_size('draw_segment', width); set_grey('draw_segment', grey); { Reject segment if obviously outside window: } lim := plt_x_max + width/2; if (x1 < -lim) and (x2 < -lim) then goto 999; if (x1 > +lim) and (x2 > +lim) then goto 999; lim := plt_y_max + width/2; if (y1 < -lim) and (y2 < -lim) then goto 999; if (y1 > +lim) and (y2 > +lim) then goto 999; { Plot it: } { ps_draw_segment(cur_file, x1, y1, x2, y2); } gr_draw_segment(x1, y1, x2, y2); 999: end; procedure plt_paint_plane(grey: real); begin new_command('paint_plane'); set_grey('draw_segment', grey); { ps_paint_plane(cur_file); } gr_paint_plane; end; procedure plt_paint_triangle( x1, y1: real; x2, y2: real; x3, y3: real; grey: real ); var lim: real; label 999; { End of procedure. } begin new_command('paint_triangle'); set_grey('paint_triangle', grey); { Clip traingle to window: } lim := plt_x_max; if (x1 < -lim) and (x2 < -lim) and (x3 < -lim) then goto 999; if (x1 > +lim) and (x2 > +lim) and (x3 > +lim) then goto 999; lim := plt_y_max; if (y1 < -lim) and (y2 < -lim) and (y3 < -lim) then goto 999; if (y1 > +lim) and (y2 > +lim) and (y3 > +lim) then goto 999; { Plot it: } { ps_paint_triangle(cur_file, x1, y1, x2, y2, x3, y3); } gr_paint_triangle(x1, y1, x2, y2, x3, y3); 999: end; procedure plt_add_caption(s: string); begin new_command('add_caption'); { ps_add_caption(cur_file, s); } end; begin { file_is_open := false } end.