10

Doodling With Lines

Back in the 1980s I had a Spirograph, a toy that lets you draw various designs based on repeating geometry, and here it seems I figured out that I could get a similar effect by tweaking the earlier rotating cubes code. The first two demos set up the geometry, and the third finishes it.

PATTERN1

Four points, four edges, BGI, a bar() erase and a double-edge retrace wait. With the Z portion of SetPoints commented out, the fourth edge collapses to length zero.

JUAN

Byte for byte the same program with the four braces removed. Points 1 and 2 separate, all four edges have length, the determinant can go negative and the shape turns through itself. I have no idea why this file name, of all of them, bears my own first name.

DOODLE

The minified one, and it is a different program in three ways. (1) bar() becomes setviewport(215,135,425,345,clipon) and the helper g() offsets every point by +105 instead of ±320/239∓, so the figure is drawn inside the viewport's own coordinates. Incidentally, y is no longer flipped, so it turns the other way. (2) clearing is now behind if d then clearviewport, and d is a global boolean that is never assigned, so Turbo Pascal starts it false. The screen never clears and the figure accumulates. That is the doodle, and press D to switch it off. (3) the retrace wait loses its first edge (one repeat until instead of two) so it can catch the tail of a blank rather than the start. One more artifact of the compression: if RegisterBGIDriver(…)<0 then; - the halt was deleted and the empty then left behind. And the wrap test fires at 361 with a step of 6, so the cycle is 61 frames and the 6° orientation is drawn twice running.

PATTERN1.PAS

1995-09-22 01:28 · 1,929 bytes · The z values are the commented-out ones.

uses crt,graph,bgidriv;var c,ci:array[1..4,1..3]of integer;
  rotation: ARRAY[1..3,1..3] OF real;
  driver, mode: integer;
  x, y, k: integer;
  ch: char;
  incx, incy: boolean;

PROCEDURE Rotatec;VAR a,b:byte;BEGIN FOR b:=1TO 4DO FOR a:=1TO 3DO
ci[b,a]:=Trunc((rotation[a,1]*c[b,1])+(rotation[a,2]*c[b,2])
+(rotation[a,3]*c[b,3]));END;

PROCEDURE SetRotation (xangle, yangle: integer);
VAR x, y: real;
BEGIN
  x:=xangle*(pi/180);y:=yangle*(pi/180);
  rotation[1,1]:=cos(y);rotation[1,2]:=0;
  rotation[1,3]:=-sin(y);rotation[2,1]:=sin(x)*sin(y);
  rotation[2,2]:=cos(x);rotation[2,3]:=sin(x)*cos(y);
  rotation[3,1]:=cos(x)*sin(y);
  rotation[3,2]:=-sin(x);
  rotation[3,3]:=cos(x)*cos(y);
END;

PROCEDURE Line3d (x1, y1, x2, y2: integer);
BEGIN Line(x1+320,239-y1,x2+320,239-y2);
END;

PROCEDURE SetPoints;
BEGIN
  c[1,1]:=-60;c[1,2]:=-60;{c[1,3]:=-60;}
  c[2,1]:=-60;c[2,2]:=-60;{c[2,3]:=60;}
  c[3,1]:=60;c[3,2]:=-60;{c[3,3]:=-60;}
  c[4,1]:=-60;c[4,2]:=60;{c[4,3]:=-60;}
END;

PROCEDURE Drawc;
BEGIN  setcolor(15);
repeat until(port[$3da]and 8)=0;repeat until(port[$3da]and 8)<>0;
      Line3d(ci[1,1],ci[1,2],ci[2,1],ci[2,2]);
      Line3d(ci[2,1],ci[2,2],ci[3,1],ci[3,2]);
      Line3d(ci[3,1],ci[3,2],ci[4,1],ci[4,2]);
      Line3d(ci[4,1],ci[4,2],ci[1,1],ci[1,2]);END;

BEGIN ClrScr;
  if RegisterBGIDriver(@EGAVGADriverProc) < 0 then halt(1);
  driver:=detect;Initgraph(driver,mode,'');
  SetPoints;setfillstyle(0,0);
  x:=0; y:=0; ch:=' ';
  incx:=true; incy:=true;
  REPEAT
    IF x>=361 THEN x:=0; IF INCX=true THEN Inc(x,6);
    IF y>=361 THEN y:=0; IF INCY=true THEN Inc(y,6);
    SetRotation(x,y);
    Rotatec;
    bar(215,135,425,345);
    Drawc;
    IF Keypressed THEN
      BEGIN
        ch:=readkey;
        case (UpCase(ch))of 'X':INCX:=NOT(INCX);'Y':INCY:=NOT(INCY);end;
      END;
  UNTIL Ord(ch)=27;  CloseGraph;  TextMode(co80);  ClrScr;END.
JUAN.PAS

1995-09-22 14:17 · 1,869 bytes · Identical but for those four values.

uses crt,graph,bgidriv;
const p=4;
var c,ci:array[1..p,1..3]of integer;
  rotation: ARRAY[1..3,1..3] OF real;
  driver, mode: integer;
  x, y, k: integer;
  ch: char;
  incx, incy: boolean;

PROCEDURE Rotatec;VAR a,b:byte;BEGIN FOR b:=1TO p DO FOR a:=1TO 3DO
ci[b,a]:=Trunc((rotation[a,1]*c[b,1])+(rotation[a,2]*c[b,2])
+(rotation[a,3]*c[b,3]));END;

PROCEDURE SetRotation (xangle, yangle: integer);
VAR x, y: real;
BEGIN
  x:=xangle*(pi/180);y:=yangle*(pi/180);
  rotation[1,1]:=cos(y);rotation[1,2]:=0;
  rotation[1,3]:=-sin(y);rotation[2,1]:=sin(x)*sin(y);
  rotation[2,2]:=cos(x);rotation[2,3]:=sin(x)*cos(y);
  rotation[3,1]:=cos(x)*sin(y);
  rotation[3,2]:=-sin(x);
  rotation[3,3]:=cos(x)*cos(y);
END;

PROCEDURE Line3d (x1, y1, x2, y2: integer);
BEGIN Line(x1+320,239-y1,x2+320,239-y2);
END;

PROCEDURE SetPoints;
BEGIN
  c[1,1]:=-60;c[1,2]:=-60;c[1,3]:=-60;
  c[2,1]:=-60;c[2,2]:=-60;c[2,3]:=60;
  c[3,1]:=60;c[3,2]:=-60;c[3,3]:=-60;
  c[4,1]:=-60;c[4,2]:=60;c[4,3]:=-60;
END;

PROCEDURE Drawc;
BEGIN  setcolor(15);
repeat until(port[$3da]and 8)=0;repeat until(port[$3da]and 8)<>0;
      Line3d(ci[1,1],ci[1,2],ci[2,1],ci[2,2]);
      Line3d(ci[2,1],ci[2,2],ci[3,1],ci[3,2]);
      Line3d(ci[3,1],ci[3,2],ci[4,1],ci[4,2]);
      Line3d(ci[4,1],ci[4,2],ci[1,1],ci[1,2]);END;

BEGIN ClrScr;if RegisterBGIDriver(@EGAVGADriverProc)<0 then halt(1);
driver:=detect;Initgraph(driver,mode,'');SetPoints;setfillstyle(0,0);
x:=0;y:=0;ch:=' ';incx:=true;incy:=true;REPEAT IF x>=361 THEN x:=0;
IF INCX=true THEN Inc(x,6);IF y>=361 THEN y:=0; IF INCY=true THEN Inc(y,6);
SetRotation(x,y);Rotatec;bar(215,135,425,345);Drawc;IF Keypressed THEN
      BEGIN
        ch:=readkey;
        case (UpCase(ch))of 'X':INCX:=NOT(INCX);'Y':INCY:=NOT(INCY);end;
      END;UNTIL Ord(ch)=27;  CloseGraph;  TextMode(co80);  ClrScr;END.
DOODLE.PAS

1995-09-22 15:20 · 1,236 bytes · if d then - and d is never set.

uses crt,graph,bgidriv;var c,p:array[1..4,1..3]of integer;r:ARRAY[1..3,1..3]OF
real;x,y,k,l:integer;ch:char;a,b,d:boolean;v,w:real;PROCEDURE g(a,b,c,d:
integer);BEGIN Line(a+105,b+105,c+105,d+105);END;BEGIN if RegisterBGIDriver(
@EGAVGADriverProc)<0 then;x:=detect;Initgraph(x,y,'');c[1,1]:=-60;c[1,2]:=-60;
c[1,3]:=-60;c[2,1]:=-60;c[2,2]:=-60;c[2,3]:=60;c[3,1]:=60;c[3,2]:=-60;c[3,3]:=
-60;c[4,1]:=-60;c[4,2]:=60;c[4,3]:=-60;setcolor(15);x:=0;y:=0;ch:=' ';a:=true;
b:=true;REPEAT IF x>=361THEN x:=0;IF a THEN inc(x,6);IF y>360THEN y:=0;IF b
THEN Inc(y,6);v:=x*(pi/180);w:=y*(pi/180);r[1,1]:=cos(w);r[1,2]:=0;r[1,3]:=
-sin(w);r[2,1]:=sin(v)*sin(w);r[2,2]:=cos(v);r[2,3]:=sin(v)*cos(w);r[3,1]:=cos
(v)*sin(w);r[3,2]:=-sin(v);r[3,3]:=cos(v)*cos(w);FOR l:=1TO 4DO FOR k:=1TO 3DO
p[l,k]:=Trunc((r[k,1]*c[l,1])+(r[k,2]*c[l,2])+(r[k,3]*c[l,3]));setviewport(215
,135,425,345,clipon);if d then clearviewport;repeat until(port[$3da]and 8)<>0;
g(p[1,1],p[1,2],p[2,1],p[2,2]);g(p[2,1],p[2,2],p[3,1],p[3,2]);g(p[3,1],p[3,2],
p[4,1],p[4,2]);g(p[4,1],p[4,2],p[1,1],p[1,2]);IF Keypressed THEN BEGIN ch:=
readkey;case(UpCase(ch))of 'X':a:=NOT(a);'Y':b:=not(b);'D':d:=not(d);end;END;
UNTIL ord(ch)=27;asm mov ah,0;mov al,3;int 16;end;END.