!  Graphics routines
!
!  a True BASIC(tm) product
!
!  ABSTRACT
!  A library of general purpose graphics routines
!  for use in user programs.
!
!  Copyright (c)1985, True BASIC, Inc.

EXTERNAL

SUB frame                         ! Frame window
    ASK window x1,x2,y1,y2
    BOX LINES x1,x2,y1,y2
END SUB

SUB axes                          ! Draw axes
    ASK window x1,x2,y1,y2
    PLOT x1,0;x2,0
    PLOT 0,y1;0,y2
END SUB

SUB ticks(x,y)                    ! Axes with ticks, x and y units apart
    ASK screen u1,u2,v1,v2
    ASK window x1,x2,y1,y2
    PLOT x1,0;x2,0
    PLOT 0,y1;0,y2
    LET p1 = abs(v2-v1)*200       ! Pixels vertical
    LET p2 = abs(u2-u1)*320       ! Pixels horizontal
    LET r = min(p1/50,p2/50)      ! Small fraction
    LET r = max(r,2)+.5           ! At least 2, avoid round error
    LET d1 = r/p1*abs(y2-y1)      ! For x
    LET d2 = r/p2*abs(x2-x1)      ! For y
    CALL mark(x1,x,1,d1)
    CALL mark(x2,x,1,d1)
    CALL mark(y1,y,2,d2)
    CALL mark(y2,y,2,d2)

    SUB mark(u2,us,c,d)           ! Does one tick
        IF u2=0 then EXIT SUB
        FOR u = 0 to u2 step sgn(u2)*us
            IF c=1 then
               PLOT u,-d;u,d
            ELSE
               PLOT -d,u;d,u
            END IF
        NEXT u
    END SUB

END SUB


SUB polygon(x1,x2,y1,y2,n)        ! n-sided, in box

    LET c1 = (x1+x2)/2            ! Center
    LET c2 = (y1+y2)/2
    LET r1 = abs(x2-x1)/2         ! Radius
    LET r2 = abs(y2-y1)/2
    LET delta = 2*pi/n            ! Angle step
    FOR i = 0 to n
        LET a = i*delta
        LET x = c1 + r1*cos(a)
        LET y = c2 + r2*sin(a)
        PLOT x,y;
    NEXT i
    PLOT

END SUB

SUB bars(data(),n)                ! Bar graph of data

    LET low,high = data(1)        ! Scale
    FOR i = 2 to n
        LET x = data(i)
        IF x<low then LET low = x
        IF x>high then LET high = x
    NEXT i
    LET low = min(low,0)
    LET high = max(high,0)
    IF high = low then LET high = high + 1
    LET range = max(abs(high),abs(low))
    LET r = int(log10(range))
    LET s = 10^r
    CALL divide(high,s,q,r)
    IF r>0 then LET high = (q+1)*s
    CALL divide(low,s,q,r)
    LET low = q*s

    LET n2 = max(n,8)             ! Coordinates
    ASK screen u1,u2,v1,v2
    LET pix = abs(u2-u1)*320      ! Horizontal pixels
    LET left = -32                ! 4 characters
    LET w = int((pix+left)/n2)    ! Pixels per bar
    LET w1 = int(w/3)
    LET w2 = int(w/6)
    LET delta = (high-low)/16
    SET WINDOW left,n2*w,low-delta/2,high
    SET COLOR "white"
    PLOT 0,0;n*w,0
    PLOT 0,low;0,high
    SET COLOR "red"
    FOR i = 1 to n
        BOX AREA (i-1)*w+w1,i*w-w2,0,data(i)
    NEXT i
    LET f$ = ">###"
    IF high>0 then PLOT TEXT, at left,high-delta: using$(f$,str$(high)[1:4])
    PLOT TEXT, at left,0-delta/2: using$(f$,"0")
    IF low<0 then PLOT TEXT, at left,low: using$(f$,str$(low)[1:4])

END SUB

SUB arc(x0,y0,r,a1,a2)            ! Arc of circle, between angles a1, a2

    OPTION ANGLE degrees
    LET da = 3
    LET cda = cos(da)
    LET sda = sin(da)
    LET x = r*cos(a1)
    LET y = r*sin(a1)
    PLOT x+x0, y+y0;
    FOR a = a1+da to a2 step da
        LET xp = x*cda - y*sda
        LET y  = y*cda + x*sda
        PLOT xp+x0, y+y0;
        LET x  = xp
    NEXT a
    PLOT x0+r*cos(a2), y0+r*sin(a2)    !guarantee closure

END SUB


SUB fplot(a,b)                    ! Plot function f from a to b

    DIM temp(0 to 64,2)
    DECLARE DEF f
    LET delta = (b-a)/64
    LET y1 = +1e100
    LET y2 = -1e100
    FOR i = 0 to 64
        LET x = a + i*delta
        LET y = f(x)
        IF y<y1 then LET y1 = y
        IF y>y2 then LET y2 = y
        LET temp(i,1) = x
        LET temp(i,2) = y
    NEXT i
    SET WINDOW a,b,y1,y2
    MAT PLOT LINES: temp
END SUB
