\ How to plot a circle?
\ hk  Oct 2026                Tested with noForth
\ Programmeeropgave van Albert Nijhof voor oktober 2026
\ See: http://forth-ig.nl/downloads/2026/Oktober/cirkel-opgave-an.pdf

decimal

32       constant SIDE          \ Size of one side of the plotting grid; max. r = 15
SIDE 2/  constant TLD           \ Translation distance
0  value    x
0  value    y
0  value    r2                  \ r squared
0  value    afw
0  value    afwZ                \ afwijking zuidwaarts
0  value    d                   \ decision variable, for algorithm CK2

create GRID  SIDE dup *  allot  \ Memory for a SIDE x SIDE plotting grid

: 5BITS    ( x -- x' )  hx  1F and ;                    \ 1F   = 31
: 10BITS   ( x -- x' )  hx 3FF and ;                    \ 3F   = 63

: 5BNEGATE ( x -- -x )       negate 5bits ;             \ 5bits negate

: CLEAR    ( -- ) grid  SIDE dup *  bl fill ;           \ Clear the grid with blanks

: POS>ADR  ( pos -- adr   )  10bits grid + ;
: TRANSL   (   n -- n'    )  TLD +  SIDE 1- and ;       \ Translation for grid origin
: XY>HV    ( x y -- h v   )  transl swap transl swap ;  \ Origin to grid centre     
: HV>ADR   ( h v -- adres )  5 lshift +  pos>adr ;

: PLOT     ( x y -- )  xy>hv hv>adr ch @ swap c! ;
: PLOT+    ( x y -- )  >r      \ Plot 4 points in 4 quadrants of a circle 
    dup r@ plot   dup r@ 5bnegate plot            \ (x,y)    (x,-y)
    5bnegate
    dup r@ plot   r> 5bnegate plot ;              \ (-x,y)   (-x,-y)
: PLOT8    ( x y -- )          \ Plot 8 points in 8 octants of a circle
    2dup plot+   swap plot+ ;  \ also: (y,x)  (-y,x)  (-y,x)  (-y,-x)

\ ---------- Print the upside down Cartesian grid (no problem for circles)
0 value HORIZ   0 value VERTI
: FORMAAT ( horiz verti -- )
    3 min 1 max to verti  5 min 1 max to horiz ;

: SPEMIT  ( ch -- )        space emit ;                  \ type a space and a character
: SPTYPE  ( a n -- )       for count spemit next drop ;  \ type n spaced chars of string a
: .GRID ( -- )     \ Print the grid
    grid side    (           -- adr n     )
    for          ( adr n     -- adr       ) 
      dup side   ( adr       -- adr adr n ) 
      cr sptype  ( adr adr n -- adr       ) 
      side +     ( adr       -- adr+n     )
    next drop ;
: .GRID ( -- )     \ Print the grid (for AN)
    grid  side for  dup side  cr sptype  side +  next  drop ;    

\ ---------- Circle plotting algorithms
: <=   > 0= ;
: CK0  ( r -- )         \ Plot a circle with radius r, using the hints of AN.
    clear               \   This is all I could figure out. 7 CK0 looks OK, but as 9 CK0  
    to y                \   produces an octagon I don't think it is optimal.
    0 to x
    0 to afw
    
    x y plot8
    BEGIN x y <= WHILE
        x 1+ to x       \ stap oostwaarts
        x y plot8
        x dup + 1 + afw      +  to afw
        y dup + 1 - afw swap -  to afwZ
        afwZ abs  afw abs  <  IF
            y 1- to y   \ stap zuidwaarts
            y dup + 1 - afw swap -  to afw
        THEN
    REPEAT 
    .grid ;
    
: CK  ( r -- )         \ Plot a circle with radius r, Bresenham midpoint algorithm.
    clear               \   This is optimal, but I would not know how to derive this
    0 to x              \   from the hints of AN.
    dup to y            \ r to y
    dup * to r2         \ r squared to r2
    
    BEGIN x y <= WHILE
        x y plot8
        x 1+ to x
        x dup *  y dup * +  r2 -  abs  to afw
        x dup *  y 1- dup *  +  r2 -  abs  to afwZ
        afwZ afw < IF
            y 1- to y
        THEN
    REPEAT 
    .grid ;
    
: CK2 ( r -- )          \ Plot a circle with radius r, Bresenham midpoint algorithm.
   clear                \   Another implementation of the same algorithm.
   dup to y
   0 to x
   3 swap dup + - to d  \ d is decision variable; initially d = 3 - 2r
   BEGIN
      x y <=
   WHILE
      x y plot8
      d 0 < IF
         d x 4 * + 6 + to d
      ELSE  \ d >= 0
         d x y - 4 * + 10 + to d
         y 1- to y
      THEN
      x 1+ to x
   REPEAT 
   .grid ;
   
: 7CK                   \ Plot a circle with radius 7
    clear
    0 7 plot8   1 7 plot8   2 7 plot8  
    3 6 plot8   4 6 plot8   5 5 plot8 
    .grid ;

   
