############################################################################
#
#	File:     drip.icn
#
#	Subject:  Program to demonstrate color map animation
#
#	Author:   Gregg M. Townsend
#
#	Date:     May 31, 1994
#
############################################################################
#
#   This file is in the public domain.
#
############################################################################
#
#  usage:  drip [-n ncolors] [-c correlation] [-d delay] [window options]
#
#     drip uses color map animation to simulate the spread of colored
#  liquid dripping into the center of a pool.
#
#     ncolors is the number of different colors present at one time.
#
#     correlation (0.0 to 1.0) controls the similarity of two consecutive
#  colors.  It probably doesn't meet a statistician's strict definition
#  of the term.
#
#     delay is the delay between drops, in milliseconds.  This may not be
#  needed; speed seems to vary greatly among different X servers, even on
#  the same machine.
#
############################################################################
#
#  Requires:  Version 9 graphics
#
############################################################################
#
#  Links: evmux, options, optwindw, random
#
############################################################################


link evmux
link options
link optwindw
link random

global opttab

procedure main(args)
   local win, mono, w, h, m, d
   local a, r, i, xscale, yscale, rad, xctr, yctr, xrad, yrad
   local cindex, cspec, ncolors, bg

   # process options
   opttab := options(args, winoptions() || "n+d+c.")
   /opttab["B"] := "black"
   /opttab["W"] := 512
   /opttab["H"] := 512
   /opttab["M"] := -1
   /opttab["d"] := 50
   /opttab["n"] := 32
   /opttab["c"] := 0.8
   win := optwindow(opttab, "cursor=off", "echo=off")
   w := opttab["W"]
   h := opttab["H"]
   m := opttab["M"]
   ncolors := opttab["n"]
   d := opttab["d"]

   # calculate radius of circle and limit number of colors to that
   r := h / 2
   r >:= w / 2
   xscale := (w / 2.0) / r
   yscale := (h / 2.0) / r
   ncolors >:= r

   # get background color as string of 3 integers (works faster that way)
   bg := ColorValue(win, opttab["B"])

   # allocate a set of mutable colors, initialized to the background
   cindex := list()
   every 1 to ncolors do
      put(cindex, NewColor(win, bg))
   if *cindex = 0 then
      stop("can't allocate mutable colors")
   if ncolors >:= *cindex then
      write(&errout, "proceeding with only ", ncolors, " colors")

   # make list of radii, with a minimum difference of 1
   # try to equalize the *areas* of the rings, not their widths
   a := &pi * r * r
   rad := list(ncolors)
   every i := 1 to *rad do
      rad[i] := integer(sqrt((a * i) / (ncolors * &pi)) + 0.5)
   every i := 1 to *rad-1 do
      rad[i] >:= rad[i+1] - 1

   # draw nested circles (in different mutable colors all set to the background)
   xctr := m + w / 2
   yctr := m + h / 2
   every i := *rad to 1 by -1 do {
      Fg(win, cindex[i])
      xrad := xscale * rad[i]
      yrad := yscale * rad[i]
      FillArc(win, xctr - xrad, yctr - yrad, 2 * xrad, 2 * yrad)
      }
   WFlush(win)

   # install a sensor to exit on q or Q
   quitsensor(win)

   # drip colors into the center and watch them spread,
   # checking for events each time around
   cspec := list(ncolors, bg)
   repeat {
      while *Pending(win) > 0 do
         evhandle(win)
      if d > 0 then {
         WFlush(win)
         delay(d)
         }
      pull(cspec)
      push(cspec, newcolor())
      every i := 1 to *cspec do
         Color(win, cindex[i], cspec[i])
      }

end


#  newcolor -- return a new color spec somewhat close to the previous color

procedure newcolor()
   static r, g, b, c

   initial {
      randomize()
      r := ?32767
      g := ?32767
      b := ?32767
      c := integer(32767 - 32767 * opttab["c"])
      c <:= 1
      }

   r +:= ?c - c/2 - 1;  r <:= 0;  r >:= 32767
   g +:= ?c - c/2 - 1;  g <:= 0;  g >:= 32767
   b +:= ?c - c/2 - 1;  b <:= 0;  b >:= 32767
   return (r + 32768) || "," || (g + 32768) || "," || (b + 32768)
end
