NB. Script sfn.ijs for creating an animation of growth for:
NB. A Simple Local Cellular Model for Snow Crystal Growth
NB. Cliff Reiter
NB. Creates a sample animation of the model growth
NB. Requires J (www.jsoftware.com) and the Image3 Addon for J

NB. load required scripts
load '~addons/image3/prevare.ijs'
load '~addons/image3/view_m.ijs'

NB. adverb for creating padding around given configurations
Pad=: 1 : 0
([:-(+2&|)@$@]++:@[){.!.m.((+2&|)@$@]+[){.!.m.]
)

NB. replicate pixels
rep=:[##"1

NB. show array as shifted to a hexagonal lattice
hx_sh=:(e.&0 1@(4:|i.@#)|."0 1])@:(2&rep)

NB. periodic extension functions (overriden)
perext2=:({:,],{.)"1@:({:,],{.)
perext2e=:({:,],{.)"1@:(],2&{.)

NB. left and right neighbor lists
lnbr=:(4 0 1 5 7 6 3)&{@,
rnbr=:(4 1 2 5 8 7 3)&{@,

NB. adverb for applying a local function to hexagonal neighborhoods
Hxauto=: 1 : 0
[: ,/ [: 0 2&|: ((2 1 ,:3 3)&(u.@:lnbr ;._3)@:perext2) ,:(2 1,:3 3)&(u.@:rnbr ;._3)@:perext2e
)

NB. find edge locations
ledge=: (-.@{. * +/ > 0:)@:(1&<:)

NB. find receptive locations (ice or edge)
l_i_or_e=: (+/ > 0:)@:(1&<:)

NB. function to give average values
avg=: +/ % #

hxa_edge=: ledge Hxauto

hxa_i_or_e=: l_i_or_e Hxauto

NB. create averging method
dfu_avg=:1 : 0
((1j6#1)+m.*1 6#_6 1)&(+/ . *)
)

hxa_avg =: (%12) dfu_avg Hxauto

NB. applies one step of 
dla=: 3 : 0
0 dla y.
:
e=. hxa_i_or_e y.
z=. hxa_avg y. * -. e
z+e*y.+x.
)

NB. main function for iterating growth model
mk_dla=:1 : 0
200 2000 m. mk_dla  y.
:
b_sf=:({.x.) ({.m.) Pad 1 1$1
s_sf=.#b_sf
'ocir icir'=:(2,2#s_sf){.!.(1)cir <:s_sf
bc_fct=: ({.m.)"_
roomq=: 1: *./ . >  ,@:(icir&*)
fns=.''
k=.0
n=._2+#m.
while. (roomq b_sf )*. k<{:x. do.
   if. 0=10|k do.    NB. every tenth frame
     fn=.y.,'_',(5 nfmt k),'.png'
     (sfP1;sf_vw2 b_sf) write_image fn
      end.
   b_sf=: ((1+n <.k){m.) dla b_sf
   b_sf=:(ocir*bc_fct k)+b_sf*-.ocir
   if. 0 = 100|k do.
     wd 'reset;'
     sf_view b_sf
     end.
   k=.k+1
end.
(k-1),x.
)


NB. makes inner/outer circles for boundary tests/conditions
cir=:3 : 0  NB. assumes y. is odd 
sh=.(1=4|y.){_0.5 0,:0 0.5
hn=.<.-:y.
sq=. ((1 o. 1r3p1)*i:-hn)  ([(+/&*:)"0"0 1$@[ $sh"_ +/ ])i: hn
'o i'=.<./"(1) 0 2{sq
(sq>:o),:sq>:i
)

NB. formatting decimals function
to_o=: {&('o',a.)@:(('.',a.)&i.)

NB. file name function
sfnm=: 3 : 0"1
'sf' sfnm y.
:
x.,'_d',(to_o 6j4 ": y.)
)

NB. makes the file sequence
mk_hxs=:3 : 0"1
200 100000 y. mk_dla pathd,'na' sfnm y.
:
x. y. mk_dla pathd,'na' sfnm y.
)

NB. pallete
sfP1=:(<.0.75*3#"0 i.128),Hue 5r6-2r3*(i.%<:)128

NB. scaling for coloring
sf_c=:3 : 0
<.(y.-1)%(1e_4>.<:>./,y.)%127.999
)

NB. viewing functions
sf_vw=:3 : 0
i=.y.>:1
hx_sh ((-.i)*<.128*y.)+i*128+sf_c y.
)

sf_vw2=:3 : 0
i=.y.>:1
z=.hx_sh ((-.i)*<.128*y.)+i*128+sf_c y.
h=.<. 0.5 + (w=.# z)*1 o. 1r3p1
z {~ <.(w %&<: h ) *i. h
)

sf_view=:3 : 0
800 sf_view y.
:
z=.sf_vw y.
r=.1>.<.0.5+-:x.%#y.
view_image sfP1;r rep z
)

NB. the J path to temporary file space
NB. make such a path explicit if necessary
]path=: >(i.&(<'temp')@{. { {:) |:SYSTEMFOLDERS_j_

NB. create temp directory
NB. delete the files in the directory before 
NB. running with other parameters
1!:5< pathd=:path,dir_sep,'sfn',dir_sep

NB. make the frames
100 2000 mk_hxs 0.45 0.0001

NB. get the images names (animation frames) in the temp directory
fns=:pngs_in pathd

NB. puts those frames into an animation
NB. with 8 frames per second
8 fseq_to_png_mov fns;nm=:pathd,'sfn.mov'

NB. Attempts to run the animation by 
NB. assuming the default J browser has 
NB. the Quicktime pluggin installed. Open
NB. sfn.mov in the temp directory with
NB. Quicktime directly if necessary
open_html nm