Curve

Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Demo, Graphics

This program draws Bézier curves on screen by accepting a series of control-point coordinates from the user and computing the curve using the Bernstein polynomial basis. Up to 20 corner (control) points are supported, stored in arrays x() and y(). The curve is evaluated at 50 evenly spaced parameter values (controlled by variable a=50), calculating blending coefficients iteratively in array b() to avoid expensive factorial computation. Users can optionally overlay the polygonal control frame before rendering the smooth curve, and a menu system lets them list, edit, store, or re-render the current set of control points. POKEs to addresses 23730–23731 adjust a system variable, likely setting the printer buffer or similar system parameter.


Program Analysis

Program Structure

The program is organized around a top-level menu at line 40 that dispatches via a computed GO TO (f*100) at line 50, routing to one of four sections based on user input:

  1. Lines 100–190: Input mode — collect control points and trigger curve computation.
  2. Lines 200–320: Alter mode — list, fix, or redraw control points (dispatched via GO TO (200+h*30)).
  3. Lines 400: Quit (STOP).
  4. Lines 500–740: Subroutines — curve computation (510–640), draw routine (650–740), and coordinate validation (750–760).

A secondary menu at line 20 handles CLS, COPY (printer dump), or continuation, serving as a post-render hub before returning to the alter menu.

Bézier Curve Algorithm

The curve is computed using the Bernstein polynomial form of a Bézier curve. For n+1 control points, parameter j steps from 0 to 1 across a=50 sample points. The blending weights b(i) are built iteratively at line 560:

b(i+1) = (g-i)/i * j/(1-j) * b(i)

This recurrence relation avoids computing binomial coefficients directly and is numerically efficient in BASIC. The anchor points are set explicitly: c(1)=x(1), d(1)=y(1) and c(a)=x(g), d(a)=y(g), ensuring the curve passes exactly through the first and last control points.

Key Variables

VariablePurpose
aNumber of curve sample points (50)
gTotal number of control points entered
ng−1 (degree of the Bézier curve)
x(i), y(i)Control point coordinates (up to 20)
b(i)Bernstein blending weights at current parameter value
c(e), d(e)Computed curve point coordinates
jParameter value along the curve (0 to 1)
eLoop index across sample points

Notable Techniques

  • Computed GO TO: Both GO TO (f*100) at line 50 and GO TO (200+h*30) at line 220 act as jump tables, a common BASIC idiom for menu dispatch without long IF-THEN chains.
  • Iterative Bernstein weights: Rather than computing each binomial coefficient from scratch, the recurrence at line 560 builds the next weight from the previous, reducing computation significantly for higher-degree curves.
  • Coordinate validation subroutine: Lines 750–760 enforce screen bounds (x: 0–255, y: 0–175) via a loop with an INPUT prompt, preventing PLOT from receiving out-of-range values that would cause an error.
  • Frame + curve toggle: Lines 650–700 optionally draw the polygonal control hull using PLOT/DRAW before the sampled curve points are plotted, giving the user a visual reference for the control structure.
  • INK 7 / INK 0 toggling: Lines 290, 300, and 320 toggle ink color around PLOT calls using USR 26727 and USR 26715 — these USR calls with PLOT are suspicious and may be intended as machine code calls or are bugs resulting from a misuse of USR in a PLOT context.
  • System variable POKEs: POKE 23730,30: POKE 23731,231 at line 10 writes to the ZX Spectrum system area (RASP/PIP area or similar), likely adjusting a system parameter at startup.

Bugs and Anomalies

  • Lines 290, 300, and 320 use PLOT 175,USR 26727 and PLOT 175,USR 26715. USR in this context calls a machine code routine and returns a value, so these PLOT statements would plot at coordinates derived from the machine code return value — almost certainly not the intended behavior. These lines may be remnants of an unfinished or ported section.
  • Line 200 dispatches with GO TO (200+h*30) for values 1–4, targeting lines 230, 260, 290, and 320 respectively. However, the “old” option (h=3) lands at line 290 and the “both” option (h=4) at line 320, both of which contain the suspicious PLOT/USR constructs noted above.
  • In the Bernstein weight loop (line 560), if j=1 (i.e., 1-j=0), a division by zero would occur. This is avoided in practice because the loop runs from e=2 TO a-1, so j never actually reaches 1; the endpoints are set manually.
  • The b() array is dimensioned to 20 at line 10 but is indexed up to n+1 (equal to g), so the limit of 20 control points is consistent with the array bounds.

Content

Appears On

Track the OSCAR 10 satellite, design Bézier curves interactively, take a geography quiz on a hand-drawn map of North America, or hear the Olympic fanfare — LIST Library Tape 2 is a well-curated selection of practical and creative programs.
A focused supplement to the LIST library — play 3D Tic-Tac-Toe with three difficulty levels, design smooth curves with an interactive Bézier tool, and inspect or load machine code byte by byte.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

    1 REM COPY BORDER !@ GO SUB VAL <> COPY @! BORDER GO SUB VAL <>x
   10 LET a=50: DIM x(20): DIM y(20): DIM b(20): DIM c(100): DIM d(100): POKE 23730,30: POKE 23731,231: GO TO 40
   20 INPUT "1)cls 2)copy 3)continue  ";t: IF t=1 THEN CLS 
   30 IF t=2 THEN COPY 
   40 INK 0: INPUT "1)begin 2)alter 3)store 4)quit";f
   50 GO TO (f*100)
  100 INPUT "total number of corners:  ";g
  110 IF g>20 THEN INPUT "MUST be <=20...try again:";g: GO TO 110
  120 LET n=g-1: INPUT "first coordinates: x=";x;" y=";y: GO SUB 750
  130 FOR i=1 TO n+1
  140 LET x(i)=x: LET y(i)=y
  150 PLOT x,y: IF i=n+1 THEN GO TO 180
  160 INPUT "next coordinates: x=";x;" y=";y
  170 GO SUB 750
  180 NEXT i
  190 GO SUB 510: GO TO 20
  200 INPUT "1)list 2)fix 3)old 4)both 5)MM";h
  210 IF h=5 THEN GO TO 20
  220 GO TO (200+h*30)
  230 CLS : PRINT "corner:  (x)    (y)"
  240 FOR i=1 TO n+1: PRINT "   ";i;")";TAB 10;x(i);TAB 17;y(i)
  250 NEXT i: GO TO 200
  260 INPUT "alter corner __? (0 if done)";i
  270 IF i=0 THEN GO SUB 500: GO TO 200
  280 INPUT "new coordinates: x=";x(i);" y=";y(i): GO TO 260
  290 INK 7: PLOT 175,USR 26727: INK 0: GO TO 200
  300 INK 7: PLOT 175,USR 26715: INK 0: GO TO 200
  320 INK 7: PLOT 175,USR 26727: INK 0: GO SUB 650: GO TO 20
  400 STOP 
  500 CLS 
  510 LET c(1)=x(1): LET d(1)=y(1)
  530 FOR e=2 TO a-1
  540 LET j=((e-1))/(a-1): LET b(1)=(1-j)^n
  550 FOR i=1 TO n
  560 LET b(i+1)=(g-i)/i*j/(1-j)*b(i)
  570 NEXT i
  580 LET c(e)=0: LET d(e)=0
  590 FOR i=1 TO n+1
  600 LET c(e)=c(e)+b(i)*x(i)
  610 LET d(e)=d(e)+b(i)*y(i)
  620 NEXT i
  630 NEXT e
  640 LET c(a)=x(g): LET d(a)=y(g)
  650 INPUT "C)curve only F)frame & curve";z$
  660 IF z$="c" THEN GO TO 710
  670 FOR i=1 TO n
  680 PLOT x(i),y(i)
  690 DRAW x(i+1)-x(i),y(i+1)-y(i)
  700 NEXT i
  710 FOR e=2 TO a-1
  720 PLOT c(e),d(e)
  730 NEXT e
  740 RETURN 
  750 IF x<=255 AND x>=0 AND y<=175 AND y>=0 THEN RETURN 
  760 INPUT "HEY!...x<256,y<176! x=";x;" y=";y: GO TO 750

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top