--- title: "Curve 2" id: 55006 type: "computer_media" slug: "curve-2" url: "http://localhost/computer_media/curve-2/" markdown_url: "http://localhost/computer_media/curve-2.md" published_at: "2024-06-10T07:03:30+00:00" modified_at: "2026-03-30T21:41:37+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "Enter a set of control points and watch this program compute and plot a smooth Bézier curve, with an optional wireframe overlay showing the control polygon." 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: "Demo" slug: "demo" taxonomy: "genre" url: "http://localhost/type/demo/" - name: "Graphics" slug: "graphics" taxonomy: "genre" url: "http://localhost/type/graphics/" media_contents: - 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" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/06/SCR-20260329-scax.png" media_type_tags: "Demo, Graphics" --- 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. 1. **Lines 1–10:** REM header and variable/array initialization. `a=60` sets the number of curve sample points. Arrays `x(20)` and `y(20)` hold control point coordinates; `b(20)` holds Bernstein basis values; `c(120)` and `d(120)` hold computed curve X/Y positions. 2. **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. 3. **Lines 510–740:** Bézier curve computation and rendering subroutine. ### Mathematical Technique: Bernstein Basis Recurrence The subroutine implements an *n*th-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 `PLOT`ting 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) and `c(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 at `j=0` or `j=1` (which would cause a divide-by-zero in the recurrence at `j=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 at `j=1` where `1-j=0` would cause a division error. - Input for the first point at line 120 uses a dual-variable `INPUT` statement, 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 uppercase `C`, the condition fails and the frame is drawn regardless of intent. Similarly, any input other than lowercase `c` will trigger frame drawing, meaning the `F`/`f` distinction in the prompt is cosmetic — only `c` is actually tested. - The curve is plotted as isolated pixels (line 720 uses `PLOT` only), 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 accessing `x(i)` or `y(i)`. ## 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 ```