--- title: "Surface Plot" id: 55605 type: "computer_media" slug: "surface-plot" url: "http://localhost/computer_media/surface-plot/" markdown_url: "http://localhost/computer_media/surface-plot.md" published_at: "2024-06-30T11:42:55+00:00" modified_at: "2026-03-30T21:45:52+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/06/SCR-20240630-hiat.png" excerpt: "A wireframe 3D surface plotter renders a ripple function using perspective projection math, with hidden-line suppression and precomputed trig for smooth results." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "James Jones" slug: "james-jones" taxonomy: "indiv" url: "http://localhost/indiv/james-jones/" genre: - name: "Demo" slug: "demo" taxonomy: "genre" url: "http://localhost/type/demo/" - name: "Graphics" slug: "graphics" taxonomy: "genre" url: "http://localhost/type/graphics/" - name: "Mathematics" slug: "mathematics" taxonomy: "genre" url: "http://localhost/type/mathematics/" media_contents: - id: 55430 title: "Timex Sinclair Public Domain Library Tape 2004" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-2004/" media_type: "Program" programmers: - name: "James Jones" slug: "james-jones" taxonomy: "indiv" url: "http://localhost/indiv/james-jones/" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/06/SCR-20240630-hiat.png" media_type_tags: "Demo, Graphics, Mathematics" --- This program renders a three-dimensional surface plot of the function z = cos(0.1*(x²+y²)) — a radially symmetric ripple — using a perspective projection onto the screen. The projection math in lines 20–30 implements a standard 3D-to-2D camera transform using rotation angles theta and phi, viewer distance rho, and focal length d, with sine/cosine values precomputed in line 40 for efficiency. The outer loop iterates x from 10 to -10 (reverse order for hidden-line suppression), while the inner loop steps y from -10 to 10, computing each projected screen coordinate via GOSUB. A flag variable fl tracks whether the pen is “up” or “down,” and PLOT/DRAW commands connect consecutive projected points to form the wireframe mesh. The program was converted from the book “[Microcomputer Graphics](https://archive.org/details/microcomputergra0000myer)” by Myers and adapted for the TS2068 by [James N. Jones](http://localhost/indiv/james-jones/) of Amarillo, Texas. *** ## Program Analysis ### Program Structure The program is organized into a small set of functional blocks: 1. **Lines 1–7:** REMs and initialization (BRIGHT, INK, starting pen position). 2. **Line 10:**`GO TO 40` to skip over subroutines. 3. **Lines 20–30:** 3D projection subroutine — computes eye-space coordinates and then screen coordinates. 4. **Line 40:** Camera/view parameter initialization. 5. **Line 50:** Function definition via `DEF FN z(x)`. 6. **Lines 70–150:** Main double loop that iterates over the surface grid and draws it. 7. **Line 9998:**`SAVE` with auto-run. ### The Surface Function The plotted surface is defined in line 50 as `DEF FN z(x)=COS(.1*(x*x+y*y))`. This produces a rotationally symmetric damped cosine ripple (sometimes called a “Mexican hat” approximation). Note that `y` is a free variable in the function definition — it refers to the current value of the global variable `y` from the enclosing loop rather than a formal parameter, which is a common but subtle BASIC idiom. ### 3D Perspective Projection Lines 20 and 30 implement a full 3D-to-2D perspective transform. Line 20 computes eye-space coordinates using a rotation matrix parameterized by `theta` (azimuth) and `phi` (elevation), with precomputed sines and cosines `s1`, `s2`, `c1`, `c2` from line 40. The viewer offset `rho` shifts the scene along the z-axis of eye space. Line 30 applies a perspective divide: `sx = d*xe/ze + cx` and `sy = cy + d*ye/ze`, where `d` is the focal length and `(cx, cy)` is the screen center. This is a standard pinhole camera model. ### Hidden-Line Suppression The outer loop runs x from 10 down to -10 (line 70, `STEP -1`). This reverse ordering is a classic painter’s-algorithm trick for wireframe surface plots: rows closer to the viewer are drawn last and naturally overwrite more distant rows, giving a rudimentary hidden-line effect without any explicit depth buffer. ### Pen-Up / Pen-Down Logic The flag variable `fl` acts as a pen-up indicator. It is reset to 0 at the start of each x-row (line 80) and whenever a projected point falls outside the screen boundary (line 110). When `fl=0`, a `PLOT` lifts and places the pen at the new point (line 120); subsequent in-bounds points are connected with `DRAW` (line 130). However, there is a subtle bug: `fl` is never set to 1 after the initial `PLOT`, so the condition `IF fl=0` on line 120 is always true, meaning every point is PLOTted rather than only the first in a run. The `DRAW` on line 130 still executes unconditionally, so lines are still drawn, but each step first re-PLOTs the current point unnecessarily. ### INK Color Switching Line 136 sets `INK 0` (black) during drawing, while line 145 resets it to `INK 7` (white) between x-rows. Combined with `BRIGHT 1`, this produces a high-contrast white mesh on a black background, with each row’s INK briefly switched to create alternating color effects on the drawn lines. ### Key Variables | Variable | Role | | --- | --- | | `rho` | Viewer distance along optical axis | | `d` | Focal length (perspective scaling) | | `theta` | Azimuth rotation angle (radians) | | `phi` | Elevation rotation angle (radians) | | `cx`, `cy` | Screen center coordinates | | `s1`, `c1` | Precomputed SIN/COS of theta | | `s2`, `c2` | Precomputed SIN/COS of phi | | `sx1`, `sy1` | Previous projected screen point | | `fl` | Pen-up flag (intended; see bug note) | ### Notable Techniques - Trig precomputation in line 40 avoids repeated `SIN`/`COS` calls in the inner loop, significantly improving rendering speed. - The `DEF FN` mechanism is used for the surface function, making it easy to substitute a different z(x,y) formula by editing only line 50. - `GO TO 40` at line 10 skips the subroutine lines, a standard BASIC structure for placing subroutines near the top of the listing. - Screen boundary clipping in line 110 prevents `PLOT`/`DRAW` errors from out-of-range coordinates. ## Source Code ``` 1 REM this proqram 6.4 2 REM draws a surface z=f(x,y) 3 BRIGHT 1 4 LET ink=0 5 LET sx1=0: LET sy1=170 6 INK 7 7 REM converted to T/S 2068 by James N. Jones 2242 Locust Amarillo, Texas 79109 8 REM from the book by Myers Microcomputer Graphics 10 GO TO 40 20 LET xe=-x*s1+y*c1: LET ye=-x*c1*c2-y*s1*c2+z*s2: LET ze=-x*s2*c1-y*s2*s1-z*c2+rho 30 LET sx=d*xe/ze+cx: LET sy=cy+d*ye/ze: RETURN 40 LET rho=30: LET d=350: LET theta=.3: LET phi=1: LET cx=127: LET cy=87: LET s1=SIN (theta): LET s2=SIN (phi): LET c1=COS (theta): LET c2=COS (phi) 50 DEF FN z(x)=COS (.1*(x*x+y*y)) 60 REM color 70 FOR x=10 TO -10 STEP -1 80 LET fl=0 90 FOR y=-10 TO 10 100 LET z=FN z(x): GO SUB 20 110 IF sx<0 OR sx>255 OR sy<0 OR sy>175 THEN LET fl=0: GO TO 140 120 IF fl=0 THEN LET l=1: PLOT sx,sy 130 DRAW (sx1-sx),(sy1-sy) 135 LET sx1=sx: LET sy1=sy 136 INK 0 140 NEXT y 145 INK 7: LET sx1=0: LET sy1=170 150 NEXT x 9998 SAVE "SrfcPlot" LINE 1 ```