This program draws Bézier curves through a user-defined set of control points on the screen. The user inputs the number of corners and their X/Y coordinates; the subroutine at line 510 then computes 60 points along a degree-(n) Bernstein polynomial curve using the standard binomial-coefficient recurrence relation. The program optionally overlays the control polygon (the “frame”) on top of the curve. Arrays C and D store the 120-element X and Y coordinate buffers for the computed curve points, which are then plotted individually rather than connected with DRAW commands.
Program Analysis
Program Structure
The program is divided into two functional parts: an input and setup section (lines 1–190) and a curve-computation/rendering subroutine (lines 510–740). Line 400’s STOP acts as a guard between the main code and the subroutine, preventing fall-through. The subroutine is called via GO SUB 510 at line 190 and returns at line 740.
- Lines 1–10: REM header and variable/array initialization.
a=60sets the number of curve sample points. Arraysx(20)andy(20)hold control point coordinates;b(20)holds Bernstein basis values;c(120)andd(120)hold computed curve X/Y positions. - Lines 100–180: User input loop — prompts for the total number of corners
g, then iterates to collect each control point, plotting each as it is entered. - Lines 510–740: Bézier curve computation and rendering subroutine.
Mathematical Technique: Bernstein Basis Recurrence
The subroutine implements an nth-degree Bézier curve (where n = g − 1) using the Bernstein polynomial basis. Rather than computing binomial coefficients directly, it uses the recurrence relation at line 560:
b(i+1) = (g-i)/i * j/(1-j) * b(i)
This is a standard multiplicative recurrence for the ratio of successive binomial terms, scaled by the parameter ratio j/(1-j). The seed value b(1) = (1-j)^n at line 550 is the first Bernstein basis polynomial B(0,n). This approach avoids computing factorials or large integers, making it numerically efficient for BASIC.
The parameter j runs from 0 to 1 across a=60 steps (lines 530–540), and the curve points are accumulated as weighted sums of the control points (lines 590–620).
Array Sizing and Constraints
| Array | Size | Purpose |
|---|---|---|
x(20), y(20) | 20 | Control point coordinates (max 20 corners) |
b(20) | 20 | Bernstein basis values per sample step |
c(120), d(120) | 120 | Computed curve point coordinates |
The curve arrays are sized at 120 but only 60 entries (indices 1 to a=60) are used. This is a conservative over-allocation; halving the array sizes to 60 would save memory without affecting correctness.
Rendering
After computing the curve, the user is prompted at line 650 to choose between curve-only (c) or frame and curve (f). The control polygon is drawn using PLOT/DRAW pairs at lines 680–700. The curve itself is rendered by individually PLOTting each precomputed point at lines 710–730 — no DRAW is used between curve points, so the curve appears as a series of discrete dots rather than connected line segments.
Notable Techniques and Idioms
- The boundary points are set directly:
c(1)=x(1),d(1)=y(1)(line 510) andc(a)=x(g),d(a)=y(g)(line 640), ensuring the curve passes exactly through the first and last control points without relying on floating-point evaluation atj=0orj=1(which would cause a divide-by-zero in the recurrence atj=1). - The loop at line 530 runs from
e=2 TO a-1, deliberately skipping the endpoints already set — a clean guard against the singularity atj=1where1-j=0would cause a division error. - Input for the first point at line 120 uses a dual-variable
INPUTstatement, then copies values into the array inside the loop (line 140), reusing a single pass for both first and subsequent points.
Bugs and Anomalies
- The input comparison at line 660 checks for lowercase
"c"only. If the user types uppercaseC, the condition fails and the frame is drawn regardless of intent. Similarly, any input other than lowercasecwill trigger frame drawing, meaning theF/fdistinction in the prompt is cosmetic — onlycis actually tested. - The curve is plotted as isolated pixels (line 720 uses
PLOTonly), so at low curvature or large screen distances between sample points, gaps may appear in the rendered curve. - There is no bounds check on
g; entering more than 20 corners would cause a subscript error when accessingx(i)ory(i).
Content
Source Code
1 REM curve program
10 LET a=60: DIM x(20): DIM y(20): DIM b(20): DIM c(120): DIM d(120)
100 INPUT "total number of corners: ";g
110 LET n=g-1
120 INPUT "first coordinates: x=";x;" y=";y
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
180 NEXT i
190 GO SUB 510
400 STOP
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
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
