--- title: "3 Axis Bar Chart" id: 56040 type: "computer_media" slug: "3axis" url: "http://localhost/computer_media/3axis/" markdown_url: "http://localhost/computer_media/3axis.md" published_at: "2024-07-14T20:36:24+00:00" modified_at: "2026-03-30T21:40:50+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/07/SCR-20240714-ohgx.png" excerpt: "A 3D bar chart with solid bars, isometric projection, and a painter's-algorithm draw order renders a cosine-based mathematical surface in vivid color." 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/" genre: - name: "Graphics" slug: "graphics" taxonomy: "genre" url: "http://localhost/type/graphics/" media_contents: - id: 56041 title: "CATUG Tape 0.0 0001" type: "computer_media" url: "http://localhost/computer_media/catug-tape-0-0-0001/" - id: 55021 title: "Long Island Sinclair Timex (LIST) User Group Library Tape #2" type: "computer_media" url: "http://localhost/computer_media/list-lib-2/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive#:~:text=3AXIS%20(198x)(TS2068)(US)(Program).zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/07/SCR-20240714-ohgx.png" media_type_tags: "Graphics" --- This program renders a three-dimensional bar chart with solid bars arranged along two horizontal axes, using the mathematical function z=(4+2*COS(x/20))*(y/10+1) to determine bar heights. The chart is drawn using an isometric-style projection with two direction vectors: dx1/dy1 (10,5) for the x-axis direction and dx2/dy2 (8,4) for the y-axis direction. Bars are constructed by drawing their front face, side face, and top parallelogram as separate geometric elements, using INVERSE 1 mode to erase overlapping portions before redrawing clean edges. The grid is laid out first via a subroutine at line 400, then bars are drawn back-to-front (x and y decremented) to achieve a natural painter’s-algorithm hidden-surface effect. The program uses INK 6, PAPER 1, and BORDER 2 for a yellow-on-blue color scheme. *** ## Program Analysis ### Program Structure The program is organized into three distinct sections: initialization and main loop (lines 100–230), a grid-drawing subroutine (lines 400–480), and a bar-drawing subroutine (lines 500–780). Line 999 references a `MOVE` command, indicating a TS2068-specific save operation alongside the standard `SAVE` at line 998. | Lines | Role | | --- | --- | | 100–115 | Comments and display setup (INK, PAPER, BORDER, CLS) | | 120–150 | Projection constants: origin (`cx`, `cy`), axis direction vectors | | 160–230 | Main logic: draw grid, then iterate bars back-to-front | | 400–480 | Grid subroutine: draws isometric x and y axis lines | | 500–780 | Bar subroutine: draws front face, side face, and top face | ### Mathematical Function and Projection The bar height is computed as `z=INT((4+2*COS(x/20))*(y/10+1))`. Here `x` ranges 0–100 in steps of 20 and `y` ranges 0–90 in steps of 15, producing a 6×7 grid of bars with heights modulated by a cosine wave along the x-axis and linearly scaled by y. The isometric projection uses two axis vectors stored in constants: `dx1=10, dy1=5` for the x-axis and `dx2=8, dy2=4` (with negated x) for the y-axis. The screen origin is at `cx=128, cy=16`. A point at grid coordinates (x, y, z) maps to screen position `(cx+x-y, cy+x/2+y/2+z)`. ### Painter’s Algorithm for Hidden Surfaces The main loop iterates x from 100 down to 0 and y from 90 down to 0. This back-to-front ordering ensures that bars closer to the viewer (smaller x, smaller y) are drawn last and naturally overwrite bars behind them, implementing a painter’s algorithm without any depth buffer. ### Bar Drawing Technique Each bar is rendered in four stages within the subroutine at line 500: 1. **Front face** (lines 510–540): Draws `z` parallel lines along the x-axis direction using `DRAW dx1,dy1`, stacked vertically. 2. **Side face erasure** (lines 550–600): Uses `INVERSE 1` to erase pixels that would overlap the y-axis side, preventing artifacts on the front-face strokes. 3. **Side face outline** (lines 610–650): Draws the left-side parallelogram as a closed four-segment outline with explicit `DRAW` commands. 4. **Top face** (lines 660–780): Erases the top area with `INVERSE 1` before drawing the top parallelogram as a clean four-segment outline. ### Use of INVERSE Mode `INVERSE 1` (lines 550 and 660) is used as an erase operation before drawing clean geometry. Because the Spectrum’s `DRAW` XORs pixels in INVERSE mode, running the same strokes inverted removes previously drawn pixels, allowing the program to overdraw regions without leaving stray marks from earlier rendering passes. ### Notable Anomalies - Line 690 computes the top-erasure plot position as `cy+z+(x+y+n)/2` rather than the expected `cy+x/2+y/2+z`. The term `(x+y+n)/2` is mathematically equivalent to `x/2+y/2+n/2`, introducing a small `n/2` drift per iteration. This is likely an approximation or minor bug in the erasure sweep. - Line numbers jump from 480 to 500 and include a gap at 690 (skipping 680), suggesting the program was edited in place with some lines removed. - The grid subroutine reuses variable `x` (lines 400–430) and `y` (lines 440–470) as loop counters, which is harmless since the grid is drawn before the main chart loop begins. ### Variable Summary | Variable | Purpose | | --- | --- | | `cx, cy` | Screen origin of the chart | | `dx1, dy1` | X-axis direction vector (10, 5) | | `dx2, dy2` | Y-axis direction vector magnitude (8, 4) | | `x, y` | Grid coordinates (also reused in grid subroutine) | | `z` | Computed bar height in pixels | | `n` | Loop counter within bar face drawing | ## Source Code ``` 100 REM 3 axis chart with solid bars 110 REM z=(4+2*COS (x/20))*(y/10+1) 115 INK 6: PAPER 1: BORDER 2: CLS 120 LET cx=128: LET cy=16 130 LET dx1=10: LET dy1=5 140 LET dx2=8: LET dy2=4 150 REM Draw x,y grid 160 GO SUB 400 165 REM Draw chart 170 FOR x=100 TO 0 STEP -20 180 FOR y=90 TO 0 STEP -15 190 LET z=INT ((4+2*COS (x/20))*(y/10+1)) 195 REM Draw bar 200 GO SUB 500 210 NEXT y 220 NEXT x 230 STOP 390 REM x,y grid subroutine 400 FOR x=0 TO 100 STEP 20 410 PLOT cx+x,cy+x/2 420 DRAW -100,50 430 NEXT x 440 FOR y=0 TO 90 STEP 15 450 PLOT cx-y,cy+y/2 460 DRAW 110,55 470 NEXT y 480 RETURN 500 REM Bar drawing subroutine 505 REM Draw face of bar 510 FOR n=0 TO z-1 520 PLOT cx+x-y,cy+x/2+y/2+n 530 DRAW dx1,dy1 540 NEXT n 545 REM Erase side of bar 550 INVERSE 1 560 FOR n=0 TO z-1 570 PLOT cx+x-y,cy+x/2+y/2+n 580 DRAW -dx2,dy2 590 NEXT n 600 INVERSE 0 605 REM Draw side of bar 610 PLOT cx+x-y,cy+x/2+y/2 620 DRAW -dx2,dy2 630 DRAW 0,z 640 DRAW dx2,-dy2 650 DRAW 0,-z 655 REM Erase top of bar 660 INVERSE 1 670 FOR n=0 TO dx2-1 690 PLOT cx+x-y-n,cy+z+(x+y+n)/2 700 DRAW dx1,dy1 710 NEXT n 720 INVERSE 0 725 REM Draw top of bar 730 PLOT cx+x-y,cy+x/2+y/2+z 740 DRAW dx1,dy1 750 DRAW -dx2,dy2 760 DRAW -dx1,-dy1 770 DRAW dx2,-dy2 780 RETURN 998 SAVE "3AXIS" LINE 1: STOP 999 OUT 244,1: MOVE "3DAXIS.BAS",1 ```