Skip to content

s3.gle

Library for 3d drawing and surface plots.

Copyright (c) 2025 Francois Tonneau

License: MIT


LIBRARY SUMMARY


This library, s3.gle, adds to GLE the ability to draw surface plots with

colored facets and colored mesh lines. The library comes with simplified

perspective and viewport settings, along with helper subroutines to draw

lines, plot panes, grid lines, and axis labels on 3D plots.


SUBROUTINE SUMMARY


xrange min max

yrange min max

zrange min max

These subroutines specify the range of x, y, and z values to appear in a 3D

plot.

==========

xaxisrange min max

yaxisrange min max

zaxisrange min max

These subroutines allow you optionally to extend the x, y, or z range that

will appear on the page. Calling zaxisrange with a min value lower than the

lowest z number, for example, will allow you to show the bottom pane of a

surface plot noticeably "below" the visible surface. This can be used to

project a contour map on the bottom pane.

==========

scaling xs ys zs

This subroutine allows you optionally to change the appearance of the

parallelepiped that encloses a 3D plot. Calling 'scaling 1 2 1', for example,

will result in a 3D plot with an apparent y range twice as broad as the x

range.

==========

angles horz vert

This subroutine specifies the angles of rotation (in degrees) used for a 3D

plot. The larger the 'horz' argument, the more the plot will appear to be seen

from the left. The larger the 'vert' argument, the more the plot will appear

to be seen from above.

==========

persp coeff

This subroutine specifies the degree of pseudo-perspective used for plotting.

Setting coeff to 1 means no perspective (i.e., an orthographic projection). A

lower value for coeff (e.g., 0.80) means a stronger perspective.

==========

viewport width height

This subroutine sets the width and the height (in cm) of the viewport for a

3D plot. The subroutine also calibrates the whole 3D -> 2D viewing pipeline,

so it must be called before any drawing attempt -- otherwise your script

may crash with a division-by-zero error.

==========

s3move x y z

This subroutine moves the current drawing point to 3d coordinates x, y, z.

==========

s3line x y z

This subroutine draws a straight line from the current drawing point to 3d

coordinates x, y, z.

==========

s3rect xA yA zA xB yB zB xC yC zC xD yD zD

This subroutine draws a rectangle with corners A, B, C, D; xA, yA, zA, ... are

the 3d coordinates of each corner.

==========

pane id$

This subroutine draws a single plot panel (or wall); id$ is a one-character

string specifying pane position:

'X' : the pane on the left that bears an X axis at its bottom

'Y' : the pane at the front that bears an Y axis at its bottom

'I' : the pane on the right, opposite of 'X'

'J' : the pane on the back, opposite of 'Y'

'B' : the bottom pane

'T' : the top pane

==========

grid id$ first last step

This subroutine draws a horizontal or vertical grid along a plot pane; id$ is

a two-character string that specifies grid type:

"xX" : the x grid on pane X

"zX" : the z grid on pane X

"xI" : the x grid on pane I

"zI" : the z grid on pane I

"yY" : the y grid on pane Y

"zY" : the z grid on pane Y

"yJ" : the y grid on pane J

"zJ" : the z grid on pane J

"xB" : the x grid on pane B

"yB" : the y grid on pane B

"xT" : the x grid on pane T

"yT" : the y grid on pane T,

first : the starting value of the grid

last : the last value of the grid

step : the interval between a grid value and the next

==========

label id$ pos dist text$ adjx adjy

This subroutine draws a label along a plot axis; id$ identifies the axis by

the intersection of two panes:

"XB" : plane X and B

"XT" : plane X and T

"IB" : plane I and B

"IT" : plane I and T

"YB" : plane Y and B

"YT" : plane Y and T

"JB" : plane J and B

"JT" : plane J and T

"XY" : plane X and Y

"YI" : plane Y and I

"IJ" : plane I and J

"JX" : plane J and X

pos : numeric position of the label along the axis

dist : distance in cm between the axis and the label

text$ : value (string or number) of the label

adjx : optional adjustment of label position in the horizontal direction

adjy : optional adjustment of label position in the vertical direction

==========

s3funcsurf f$ fillpal$ linepal$ nx ny xorient yorient

This subroutine produces a surface plot for a specified function.

f$ : name of the function to be plotted; f must accept two numeric

        arguments and return a single numeric value

fillpal$ : name of the palette function for facet coloring; fillpal must

        accept a single numeric argument and return a valid GLE color

        (e.g., "#ff0033"); for transparent facets, use "clear" as value

        for fillpal$

linepal$ : name of the palette function for facet-border coloring; linepal

        must accept a single numeric argument and return a valid GLE color;

        alternatively, using "same" as value for linepal$ will paint facet

        borders with the same color as the facet

xorient and yorient are two numeric parameters (either 1 or -1) that determine

        the order of plotting facets along the xaxis (for xorient) or yaxis

        (for yorient); the default values for xorient and orient are 1 and

        -1, respectively

Note: s3.gle has no z buffering or hidden-surface detection, and draws surface

facets one after the other via a simple painter's algorithm. Depending on the

values of 'horz' and 'vert' in the 'angles' subroutine, switching the sign of

xorient or yorient may be needed to achieve correct rendering.

==========

s3datasurf filename$ fillpal$ linepal$ xorient yorient

This subroutine produces a surface plot from the data file named filename$.

This file contains the matrix of z data to be plotted, with rows and columns

corresponding to successive x and y values, respectively. Note that the values

for x and y do not appear in the data file; rather, their ranges are specified

separately, by calling the 'xrange min max' and 'yrange min max' subroutines.

Also, for technical reasons, the matrix of data must be preceded on the left

by a dummy column of row numbers (e.g.: 0 0 0 ...). Thus, the data file for

a 3 by 3 surface plot should look like:

0 z z z

0 z z z

0 z z z

==========

s3contourlines rawfile$ linepal$ pane$

This subroutine draws the colorized contour lines of a GLE cdata file.

rawfile$ : the base name of the cdata file. If the cdata file is named

        "myfile-cdata.dat", for example, rawfile$ should be "myfile"

linepal$ : name of the palette function for contour coloring; linepal must

        accept a single numeric argument and return a valid GLE color

pane$ : where to draw the colorized contour lines; either "bottom" (the

        default) or "top" (to draw the contour lines on the top pane)

Note: the "myfile-cdata.dat" file used to draw colored contours must have been

generated from a "myfile.z" z file via a 'begin contour ... end' block. Please

see the User Manual for more information about GLE z files, cdata files, and

contour blocks.


IMPLEMENTATION


Plot setup

Pipeline handling


Geometric setup


sub xrange min max
sub yrange min max
sub zrange min max
sub xaxisrange min max
sub yaxisrange min max
sub zaxisrange min max
sub scaling xs ys zs
sub angles horz vert
sub persp coeff

Pipeline stages


Stage 1: input normalization

sub s3xnor x
sub s3ynor y

sub s3znor z
Stage 2: viewpoint rotation

sub s3xrot x y z
sub s3yrot x y z

sub s3zrot x y z
Stage 3: pseudo perspective

sub s3xper x y z

sub s3yper x y z
Stage 4: output normalization

sub s3xg x y z
sub s3yg x y z

Viewport setting


sub viewport width height

Drawing primitives


sub s3move x y z
sub s3line x y z
sub s3rect xA yA zA xB yB zB xC yC zC xD yD zD

Plot panes


sub pane id$

Grid lines


sub s3xintersect xA yA xB yB xC yC xD yD
sub s3yintersect xA yA xB yB xC yC xD yD
sub grid id$ first last step

Axis labels


sub label id$ pos dist text$ adjx adjy

Surface facet


sub s3facet x y dx dy zA zB zC zD fillpal$ linepal$

Surface plot of a function


sub s3funcsurf f$ fillpal$ linepal$ nx ny xorient yorient

Surface plot of a dataset


sub s3datasurf filename$ fillpal$ linepal$ xorient yorient

Contour lines on a plane


sub s3contourlines rawfile$ linepal$ pane$