[UP]


Manual Reference Pages  - M_draw (3)

NAME

M_draw(3fm) - [M_draw::INTRO] The M_draw graphics library (LICENSE:PD)

CONTENTS

Description
Library Function Descriptions
Example
Bugs

DESCRIPTION

M_draw is a portable public-domain device-independent graphics library intended for being called from Fortran that is based on VOGLE (from the University of Melbourne) that is loosely based on the Silicon Graphics Iris GL library. It was also partly inspired by the DIGS library developed at the U.S. Naval Academy under the guidance of Prof David Rogers.

Many output devices are available:

o FrameMaker MIF 3.0 (Maker Interchange File) driver.
o Adobe PDF driver.
o HTML5 Canvas driver.
o SVG driver.
o A PCL5/HPGL2 driver that supports prefsize() calls.
o Monochrome PBM (Poskanzer bitmap P1 and P4 formats) and X11 bitmap driver.
o Color PBM (Poskanzer pixmap P3 and P6 formats). If you have the pbmplus package you can use it to make M_draw appear to write any format pbmplus writes (assuming your system supports the popen(3c) function).
o A clear-text CGM (Computer Graphics Metafile) driver.
o A different (color) PostScript driver.
o A driver for Microsoft VML (Vector Markup Language)

M_draw is intended to produce simple graphics composed of line drawings and polygon fills in two and three dimensions. It handles circles, curves, arcs, patches, polygons, and software text in a device independent fashion. Simple hidden line removal is also available via polygon backfacing. Access to hardware text and double buffering of drawings depends on the driver.

M_draw is callable from C and Fortran, and Pascal; but M_draw is only supported in Fortran (the C components are being converted to Fortran).

The original VOGLE source’s ownership statement

      This software is public domain and may be used for any purpose commercial
      or otherwise. It is offered without any guarantee as to its suitability
      for any purpose or as to the sanity of its writers. The authors do ask
      that the source is passed on to anyone that requests a copy, and that
      people who get copies don’t go round claiming they wrote it. Use at your
      own risk.

LIBRARY FUNCTION DESCRIPTIONS

    DEVICE ROUTINES

vinit(device)
  Initialise device
vexit() Reset window/terminal (must be last routine called)
voutput(path)
  Redirect output from *next* vinit to file
vnewdev(device)
  Reinitialize to use new device without changing
vgetdev(device)
  Get name of current device
pushdev(device)
  push current device onto a stack
popdev(device)
  pop device from stack created by pushdev.
getdepth()
  Return number of bit planes (color planes)

    ROUTINES FOR SETTING UP WINDOWS

prefposition(x, y)
  Specify preferred position of window
prefsize(width, height)
  Specify preferred width and height of window
Some devices are basically window oriented - like sunview and X11. You can give M_draw some information on the window that it will use with these routines. These can make your code very device independent. Both routines take arguments which are in device space. (0, 0) is the top left hand corner in device space. To have any effect these routines must be called before vinit. For the X11 device, an entry may be made in your .Xdefaults file or loaded in with the xrdb(1) command:

      xrdb <<\end_of_file
      ! X11 Windows fonts to use for "small" and "large" fonts
      M_draw*smallfont: fixed
      M_draw*largefont: 9x15
      ! title on decoration bar for the window
      M_draw*title: My M_draw program
      ! window geometry and position,
      ! overridden by prefsize(3c) and prefposition(3c)
      M_draw.Geometry: =500x500-10+20
      end_of_file

(where you specify your geometry as you please).

    CLIPPING ROUTINES

clipping(onoff)
  Turn clipping on or off

    COLOR ROUTINES

clear() Clears screen to current color
color(col)
  Set current color mapcolor(indx, red, green, blue) Set color map index

    INTERACTIVE ROUTINES

getkey()
  Return ASCII ordinal of next key typed
checkkey()
  Returns zero if no key is pressed or ASCII ordinal
getstring(bcol, string)
  Read in a string, echoing it in current font
locator(xaddr, yaddr)
  Find out where cursor is
slocator(xaddr, yaddr)
  Find out where cursor is in screen coordinates

    FLUSHING

vsetflush(yesno)
  Set global flushing status
vflush()
  Call device flush or syncronisation routine
On some devices (particularly X11) considerable speedups in display can be achieved by not flushing each graphics primitive call to the actual display until necessary. M_draw automatically delays flushing in the following cases:
 
o Within a callobj() call.
o Within curves and patches.
o Within Hershey software text.
o When double buffering (the flush is only done within swapbuffers).
There are two user routines that can be used to control flushing.

    VIEWPORT ROUTINES

viewport(left, right, bottom, top)
  Specify which part of screen to draw in
pushviewport()
  Save current viewport
popviewport()
  Retrieve last viewport
getviewport(left, right, bottom,top)
  Returns limits of current viewport in screen coordinates
expandviewport()
  use the entire device viewport
unexpandviewport()
  undo expandviewport(3f)
Viewpoint routines alter the current transformation matrix.

    GETTING THE ASPECT DETAILS

getaspect()
  Returns the ratio height over width of the display device.
getfactors(wfact, hfact)
  Returns width over min(width of device, height of device) and height over min(width of device, height of device).
getdisplaysize(w, h)
  Returns width and height of device in device units
Often the screen is not perfectly square and it would be nice to use the extra space without having to turn clipping off. The following routines are provided to get the values needed to adjust the calls to viewport, etc as needed.

    ATTRIBUTE STACK ROUTINES

pushattributes()
  Save the current attributes on the attribute stack.
popattributes()
  Restore attributes to what they were at last pushattributes().
The attribute stack contains details such as current color, filling, hatching, centered, fixedwidth, text height, text width, and the current font. If you need to prevent object calls from changing these, use pushattributes before the call and popattributes after.

    PROJECTION ROUTINES

ortho(left, right, bottom, top,near,far)
  Define x,y,z clipping planes.
ortho2(left, right, bottom, top)
  Define x and y clipping planes.
perspective(fov, aspect, near, far)
  Specify perspective viewing pyramid
window(left, right, bot, top, near,far)
  Specify a perspective viewing pyramid

    PROJECTION AND VIEWPORT ROUTINES

subroutine page (left, right, bottom, top)
  create a window of the specified size and then set the viewport to the largest viewport with that aspect so that output acts much like a page of paper of the specified size without distortion.
All the projection routines define a new transformation matrix, and consequently the world units. Parallel projections are defined by ortho or ortho2. Perspective projections can be defined by perspective and window.

    MATRIX STACK ROUTINES

pushmatrix()
  Save the current transformation matrix on the matrix stack.
popmatrix()
  Reinstall the last matrix pushed

    VIEWPOINT ROUTINES

polarview(dist, azim, inc, twist)
  Specify the viewer’s position in polar coordinates
up(x, y, z)
  Specify the world up.
lookat(vx, vy, vz, px, py, pz,twist)
  Specify the viewer’s position

    MOVE ROUTINES

move(x, y, z)
  Move current graphics position to (x, y, z)
rmove(deltax, deltay, deltaz)
  Relative move
move2(x, y)
  Move graphics position to point (x, y)
rmove2(deltax, deltay)
  Relative move in world units.
smove2(x, y)
  Move current graphics position in screen coordinates (-1.0 to 1.0).
rsmove2(deltax, deltay)
  Relative move in screen units (-1.0 to 1.0).

    LINESTYLE ROUTINES

linewidth()
  set line width in rasters
dashcode()
  set dash pattern length
linestyle()
  set the line dash pattern
Linestyles are specified by giving a nominal length of a single dash and a character string consisting of 1’s and 0’s (zeros) that specify when to draw a dash and when not to draw a dash. Linestyles will follow curves and "go around" corners. If a linestyle is set or reset, the accumulated information as to where on a curve (or line) a dash is to be draw is also reset.

For EXAMPLE, with a nominal view of -1 to 1, setting the dash length to 0.5, and the linestyle to ’11010’ would draw a line(or curve) with a 1.0 unit solid part, followed by a 0.5 unit blank part followed by a 0.5 unit solid part followed by a 0.5 unit blank part. The linestyle would then repeat itself.

The dash sizes are affected by the current viewport/transformation scaling factors, meaning that in perspective, the dashes look smaller the farther away they are.

    DRAW ROUTINES

draw(x, y, z)
  Draw from current graphics position to (x, y, z)
rdraw(deltax, deltay, deltaz)
  Relative draw
draw2(x, y)
  Draw from current graphics position to point (x, y)
rdraw2(deltax,deltay)
  Relative draw
sdraw2(x, y)
  Draw in screen coordinates (-1.0 to 1.0).
rsdraw2(deltax, deltay)
  Relative draw in screen units (-1.0 to 1.0).

    ARCS AND CIRCLES

circleprecision(nsegs)
  Set number of line segments in a circle. Default is 32.
arc(x, y, radius, startang, endang)
  Draw an arc in world units.
sector(x, y, radius, startang,endang)
  Draw a sector. Note: sectors are polygons.
circle(x, y, radius)
  Draw a circle. Note: circles are polygons.
When creating arcs and sectors note that angles are measured in degrees; where zero(0) is the positive X axis in a right-handed Cartesian coordinate system and positive angles sweep counterclockwise. If filling sectors or circles (As described in the section on polygons) hatch pitch is measured in world coordinates and is initially set to 0.1. The initial hatch angle is zero(0).

    CURVE ROUTINES

curvebasis(basis)
  Define a basis matrix for a curve.
curveprecision(nsegs)
  Define number of line segments used to draw a curve.
rcurve(geom)
  Draw a rational curve.
curve(geom)
  Draw a curve.
curven(n, geom)
  Draw n - 3 overlapping curve segments. Note: n must be at least 4.

    RECTANGLES AND GENERAL POLYGON ROUTINES

rect(x1, y1, x2, y2)
  Draw a rectangle.
polyfill(onoff)
  Set the polygon fill flag
polyhatch(onoff)
  Set the polygon hatch flag
hatchang(angle)
  Set the angle of the hatch lines.
hatchpitch(pitch)
  Set the distance between hatch lines.
poly2(n, points)
  Construct an (x, y) polygon from an array of points
poly(n, points)
  Construct a polygon from an array of points
makepoly()
  opens polygon constructed by a series of move-draws and closed by closepoly
closepoly()
  Terminates a polygon opened by makepoly.
backface(onoff)
  Turns on culling of backfacing polygons.
backfacedir(clockwise)
  Sets backfacing direction to clockwise or anti-clockwise
A polygon is composed of a number of coplanar line segments connected end to end to form a closed shape.
In M_draw curves are estimated by a series of line segments, and thus may be included easily into polygons.
Regular
  A polygon with all sides and interior angles the same. Regular polygons are always convex. See Regular Polygons
Irregular
  Each side may a different length, each angle may be a different measure. The opposite of a regular polygon. See Irregular Polygons
Convex All interior angles less than 180 ,and all vertices ’point outwards’ away from the interior. The opposite of concave. Regular polygons are always convex. See Convex Polygons
Concave
  One or more interior angles greater than 180 . Some vertices push ’inwards’ towards the interior of the polygon. The opposite of convex.
Self-intersecting or Crossed
  A polygon where one or more sides crosses back over another side, creating multiple smaller polygons. Most of the properties and theorems concerning polygons do not apply to this shape. It is best considered as several separate polygons. A polygon that in not self-intersecting in this way is called a simple polygon.

    TEXT ROUTINES

font(fontname)
  set the current font
numchars()
  return number of characters in the current SOFTWARE font.
textsize(width, height)
  set maximum size of a character in the current SOFTWARE font.
textang(ang)
  set the SOFTWARE text angle.
fixedwidth(onoff)
  turns fixedwidth mode on or off for SOFTWARE fonts.
getcharsize(c, width, height)
  get the width and height of a character.
getfontdec()
  return size of maximum font descender
getfontsize(width, height)
  get maximum width and height of a character in a font.
drawchar(c)
  draw the character c and update current position.
drawstr(str)
  draw the text in string at the current position.
strlength(str)
  return the length of the string s
boxtext(x, y, l, h, s)
  stretch and draw the SOFTWARE string s so that it fits in the imaginary box
boxfit(x, y, l, h, s)
  resize the SOFTWARE text size so it fits in a box
textjustify(val)
  general text justification
leftjustify()
  left justify text
rightjustify()
  right justify text
topjustify()
  top justify text
bottomjustify()
  bottom justify text
centertext(onoff)
  turns centertext mode on or off for SOFTWARE fonts.
xcentertext()
  center text in the X direction
ycentertext()
  center text in the Y direction
textslant()
  defines the obliqueness of the fonts.
textweight()
  defines the weight of the fonts.
M_draw supports hardware and software fonts. The software fonts are based on the character set digitized by Dr Allen V. Hershey while working at the U. S. National Bureau of Standards. Exactly what hardware fonts are supported depends on the device, but it is guaranteed that the names "large" and "small" will result in something readable. For X11 displays the default large and small fonts used by the program can be overridden by placing the following defaults in the ~/.Xdefaults file:

     draw.smallfont: X11-font-name
     draw.largefont: X11-font-name

It is noted here that hardware text is always assumed to be drawn parallel to the (x, y) plane, using whatever the current z coordinate is. The following software fonts are supported:

      astrology       cursive         cyrillic        futura.l
      futura.m        gothic.eng      gothic.ger      gothic.ita
      greek           markers         math.low        math.upp
      meteorology     music           script          symbolic
      times.g         times.i         times.ib        times.r
      times.rb        japanese

A markers font "markers" is also provided for doing markers - you need to have centertext mode on for this to give sensible results when placing the markers.

If the environment variable "M_DRAW_FONTPATH" is set M_draw looks for the software fonts in the directory given by this value.

the default font is futura.l

    TRANSFORMATION ROUTINES

translate(x, y, z)
  Set up a translation.
scale(x, y, z)
  Set up scaling factors in x, y, and z axis.
rotate(angle, axis)
  Set up a rotation in axis axis where axis is one of ’x’,’y’, or ’z’.
All transformations are cumulative, so if you rotate something and then do a translate you are translating relative to the rotated axes. If you need to preserve the current transformation matrix use pushmatrix(), do the drawing, and then call popmatrix() to get back where you were before.

When doing transformations, ensure your objects remain in the viewing volume or they will be clipped. See routines such as ortho(3) for more information.

    PATCH ROUTINES

patchbasis(tbasis, ubasis)
  Define the t and u basis matrices of a patch.
patchprecision(tseg, useg)
  Set minimum number of line segments making up curves in a patch.
patchcurves(nt, nu)
  Set the number of curves making up a patch.
rpatch(gx, gy, gz, gw)
  Draws a rational patch in the current basis, according to the geometry matrices gx, gy, gz, and gw.
patch(gx, gy, gz)
  Draws a patch in the current basis, according to the geometry matrices gx, gy, and gz.

    POINT ROUTINES

point(x, y, z)
  Draw a point at x, y, z
point2(x, y)
  Draw a point at x, y.
points are drawn with the current color and linewidth. Points are currently device-specific and may appear as circles, squares, or not at all; as they are generated by a zero-length vector using the hardware line style.

    OBJECT ROUTINES

makeobj(n)
  Commence the object number n.
closeobj()
  Close the current object.
genobj()
  Returns a unique object identifier.
getopenobj()
  Return the number of the current object.
callobj(n)
  Draw object number n.
isobj(n)
  Returns non-zero if there is an object of number n.
delobj(n)
  Delete the object number n.
loadobj(n, filename)
  Load the object in the file filename as object number n.
saveobj(n, filename)
  Save object number n into file filename. Does NOT save objects called inside object n.
invokeobj(xt,yt,zt,xs,ys,zs,xr,yr,zr,iobject)
  push environment and do a transformation and then pop environment
Objects are graphical entities created by the drawing routines called between makeobj and closeobj. Objects may be called from within other objects. When an object is created most of the calculations required by the drawing routines called within it are done up to where the calculations involve the current transformation matrix. So if you need to draw the same thing several times on the screen but in different places it is faster to use objects than to call the appropriate drawing routines each time. Objects also have the advantage of being savable to a file, from where they can be reloaded for later reuse. Routines which draw or move in screen coordinates, or change device, cannot be included in objects.

    DOUBLE BUFFERING

backbuffer()
  Draw in the backbuffer. Returns -1 if the device is not up to it.
frontbuffer()
  Draw in the front buffer. This will always work.
swapbuffers()
  Swap the front and back buffers.
Where possible M_draw allows for front and back buffers to enable things like animation and smooth updating of the screen. The routine backbuffer is used to initialise double buffering.

    POSITION ROUTINES

getgp(x, y, z)
  Gets the current graphics position
getgpt(x, y, z, w)
  Gets the current transformed graphics position in world coords.
getgp2(x, y)
  Gets the current graphics position
sgetgp2(x, y)
  Gets the current screen graphics position in screen coords (-1 to 1)

    GENERAL STACK ROUTINES

subroutine pop()
  pop
subroutine push()
  push

EXAMPLE

Sample program:

   program demo_M_draw
   use M_draw
   use M_draw,    only  : D_BLACK,   D_WHITE
   use M_draw,    only  : D_RED,     D_GREEN,    D_BLUE
   use M_draw,    only  : D_YELLOW,  D_MAGENTA,  D_CYAN
   use M_units,    only : cosd, sind
   implicit none
   integer  :: ipaws
   real     :: x1, y1
   integer  :: icolor
   integer  :: i,j

! initialize image call prefsize(400,400) ! set size before starting call vinit(’ ’) ! start graphics using device $M_DRAW_DEVICE call textsize(10.0,10.0) call mapcolor( 0, 255,255,255 ) !white call mapcolor( 1, 255, 0, 0 ) !red call mapcolor( 2, 0,255, 0 ) !green call mapcolor( 3, 255,255, 0 ) !yellow call mapcolor( 4, 0, 0,255 ) !blue call mapcolor( 5, 255, 0,255 ) !magenta call mapcolor( 6, 0,255,255 ) !cyan call mapcolor( 7, 0, 0, 0 ) !black call mapcolor( 8, 0,155, 0 ) call mapcolor( 9, 155,155,155 ) call mapcolor(10, 155,255,255 ) call mapcolor(11, 155,155, 0 ) call mapcolor(12, 0, 0,155 ) call mapcolor(13, 155, 0,155 ) call mapcolor(14, 0,155,155 ) call mapcolor(15, 100,100,100 ) call mapcolor(16, 155,100,100 ) call color(D_BLACK) call clear() ! clear to color 0 call color(D_WHITE)

! map area of virtual world to specified device area ! notice Y-axis for viewport is zero at TOP ! define the virtual world area we want to work in call page(0.0, 400.0, 0.0, 400.0) ! the drawing routines use these world units

! put some colored boxes into pixmap by address ! so show how the pixel map can be edited easily with ! other routines that can manipulate a pixel array. ! The P_pixel array was created when vinit(3f) was called call polyfill(.true.) icolor=1 do i=0,3 do j=0,3 x1=j*100.0 y1=i*100.0 icolor=icolor+1 call color(icolor) call rect(x1,y1,x1+100.0,y1+100.0) enddo enddo call polyfill(.false.)

! draw polar grids call linewidth(100)

call linewidth(100) call color(14) call target(200.0,200.0,200.0)

call linewidth(75) call color(0) call target(100.0,200.0,50.0)

! draw some lines call color(D_RED) call linewidth(200) call line(1.0,1.0,400.0,400.0)

call color(D_BLUE) call linewidth(250) call line(350.0,200.0,350.0,300.0)

! print some text call color(1) call linewidth(125) call font(’futura.l’) call hershey(40.0, 40.0,35.0,’Hello World’,0.0) call color(7) call linewidth(25) call hershey(40.0, 80.0,35.0,’Hello World’,0.0) call linewidth(100) call hershey(40.0,120.0,35.0,’Hello World’,30.0)

call hershey( 40.0,350.0,35.0,’Hello World’,0.0) call font(’futura.m’) call hershey( 40.0,310.0,35.0,’Hello World’,0.0) call font(’times.r’) call hershey( 350.0,400.0,35.0,’Hello World’,90.0) call linewidth(50) call font(’times.i’) call hershey(200.0,120.0,15.0,’Hello World’,20.0)

ipaws=getkey() call vexit()

contains

subroutine target(xc,yc,rc) use M_units, only : cosd, sind real :: xc,yc,rc integer :: i real :: x,y do i=0,360,10 x=rc*cosd(i) y=rc*sind(i) call line(xc,yc,xc+x,yc+y) enddo do i=1,int(rc),10 call circle(xc,yc,real(i)) enddo end subroutine target

subroutine line(x1,y1,x2,y2) real,intent(in) :: x1,y1,x2,y2 call move2(x1,y1) call draw2(x2,y2) end subroutine line

subroutine hershey(x,y,height,itext,theta) real,intent(in) :: x,y real,intent(in) :: height character(len=*),intent(in) :: itext real,intent(in) :: theta call move2(x,y) call textang(theta) call textsize(height,height) call drawstr(itext) end subroutine hershey

end program demo_M_draw

BUGS

Polygon hatching will give unexpected results unless the polygon is initially defined in the X-Y plane.

Double buffering isn’t supported on all devices.

We don’t recommend the use of the smove/sdraw routines.

The yobbarays may be turned on or they may be turned off.

When creating an object, current position and text size are not actually changed so almost any query routine to get position or font size or whatever will not work properly.

If call vexit(3f) and then call vinit(3f) everything should probably be reset to initial values at program startup, such as linewidth, current font, and color. It is currently left up to the output device initialization routine. It should not be. To minimize the issue, call all the push* routines after a vinit(3f) and call all the pop* routines before vexit(3f).

Exactly what attributes should and should not be reset with a vnewdev(3f) is questionable.


M_draw (3) March 11, 2021
Generated by manServer 1.08 from 4e70b8c4-1eda-464d-83a9-80cba3567c34 using man macros.