animate.tcl 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075
  1. #!/bin/sh
  2. # the next line restarts using wish \
  3. # exec $GRASS_WISH "$0" "$@"
  4. ##########################################################################
  5. #
  6. # animate.tcl
  7. #
  8. # animates one or more series of raster maps in GRASS 6 TclTk GUI
  9. # Author: Glynn Clements and Michael Barton (Arizona State University)
  10. #
  11. # September 2007
  12. #
  13. # COPYRIGHT: (C) 1999 - 2007 by the GRASS Development Team
  14. #
  15. # This program is free software under the GNU General Public
  16. # License (>=v2). Read the file COPYING that comes with GRASS
  17. # for details.
  18. #
  19. ##########################################################################
  20. namespace eval GmAnim {
  21. variable view1; # maps to animate in frame 1
  22. variable view2; # maps to animate in frame 2
  23. variable view3; # maps to animate in frame 3
  24. variable view4; # maps to animate in frame 4
  25. variable first; # first time animation is run (0 1)
  26. variable cnt; # number of maps to animate
  27. variable tmpfile; # temp file for storing images
  28. variable tmpregion; # temp region file for setting PPM resolution
  29. variable numviews; # number of animation views to show (1-4)
  30. variable numframes; # number of individual frames in an animation
  31. variable vframes; # array holding number of frames in each view
  32. variable step; # turn frame by frame step on (step=1) or off (step=0)
  33. variable speed; # set delay between display of each animation frame
  34. variable stop; # stop continuous animation play (stop=1)
  35. variable direction; # 1=forward, -1=backward
  36. variable rewind; # if rewind=1, return to frame 1
  37. variable prevframe; # number of previous frame
  38. variable currframe; # number of currently displayed frame
  39. variable nframes; # total number of frames in a view
  40. variable ncols; # columns in current region; for setting window size
  41. variable nrows; # rows in current region; for setting window size
  42. variable scale; # scale value for setting size of window and animation images
  43. variable icols; # initial columns in window
  44. variable irows; # initial rows in window
  45. variable vcols; # columns in view window
  46. variable vrows; # rows in view window
  47. variable pnmres; # resolution needed in region to create pnm file of proper size
  48. variable vres; # base region resolution; modify to change pnm image size
  49. variable oldres1; # nsres for current region
  50. variable oldres2; # ewres for current region
  51. variable pic_array; # array holding all rendered images
  52. variable vfiles; # array holding list of all maps for each view
  53. variable label_pos
  54. variable border; # border separating views in multiview window
  55. variable anim_can; # TclTk canvas where animation is drawn
  56. variable cb_loop; # control button for looping
  57. variable cb_swing; # control button for swing
  58. variable minframes; # minimum number of frames among all views; animation must stop at this number
  59. global shownames; # if shownames = 1, print file name in window
  60. global loop;
  61. global swing;
  62. global anim_prog; # increments progress bar
  63. set border 2
  64. set cnt 0
  65. set numviews 1
  66. set first 0
  67. set step 0
  68. set speed 100
  69. set stop 1
  70. set direction 1
  71. set rewind 0
  72. set prevframe 0
  73. set currframe 1
  74. set nframes 0
  75. set loop 0
  76. set swing 0
  77. set shownames 0
  78. set view1 ""
  79. set view2 ""
  80. set view3 ""
  81. set view4 ""
  82. set tmpregion ""
  83. # create file for temporary image output
  84. if {[catch {set tmpfile [exec g.tempfile pid=[pid]]} error]} {
  85. GmLib::errmsg $error [G_msg "Error creating tempfile"]
  86. }
  87. }
  88. ########################################################
  89. # Animation control button procedures
  90. proc GmAnim::cmd_rewind {} {
  91. variable step
  92. variable stop
  93. variable rewind
  94. set step 0
  95. set stop 1
  96. set rewind 1
  97. GmAnim::do_run
  98. }
  99. proc GmAnim::cmd_rplay {} {
  100. variable step
  101. variable stop
  102. variable direction
  103. variable currframe
  104. variable prevframe
  105. global anim_prog
  106. set anim_prog 0
  107. set step 0
  108. set stop 0
  109. set direction -1
  110. set currframe [expr $prevframe + $direction]
  111. }
  112. proc GmAnim::cmd_stepb {} {
  113. variable step
  114. variable direction
  115. variable currframe
  116. variable prevframe
  117. variable nframes
  118. variable anim_prog
  119. if {$currframe == $nframes } {set anim_prog 0}
  120. set step 1
  121. set direction -1
  122. set currframe [expr $prevframe + $direction]
  123. GmAnim::do_run
  124. }
  125. proc GmAnim::cmd_stop {} {
  126. variable stop
  127. set stop 1
  128. }
  129. proc GmAnim::cmd_stepf {} {
  130. variable step
  131. variable direction
  132. variable currframe
  133. variable prevframe
  134. variable anim_prog
  135. if {$currframe == 1 } {set anim_prog 0}
  136. set step 1
  137. set direction 1
  138. set currframe [expr $prevframe + $direction]
  139. GmAnim::do_run
  140. }
  141. proc GmAnim::cmd_play {} {
  142. variable step
  143. variable stop
  144. variable direction
  145. variable currframe
  146. variable prevframe
  147. global anim_prog
  148. set anim_prog 0
  149. set step 0
  150. set stop 0
  151. set direction 1
  152. set currframe [expr $prevframe + $direction]
  153. }
  154. proc GmAnim::cmd_loop {} {
  155. global swing
  156. global loop
  157. variable stop
  158. variable cb_swing
  159. $cb_swing deselect
  160. set swing 0
  161. }
  162. proc GmAnim::cmd_swing {} {
  163. global loop
  164. global swing
  165. variable stop
  166. variable cb_loop
  167. $cb_loop deselect
  168. set loop 0
  169. }
  170. proc GmAnim::cmd_slower {} {
  171. variable speed
  172. if {$speed > 1} {
  173. if {$speed < 200000} {
  174. set speed [expr $speed * 3]
  175. }
  176. } else {
  177. set speed 1
  178. }
  179. }
  180. proc GmAnim::cmd_faster {} {
  181. variable speed
  182. if {$speed > 1} {
  183. set speed [expr $speed / 3]
  184. }
  185. }
  186. proc GmAnim::cleanup {} {
  187. variable numviews
  188. variable numframes
  189. variable vfiles
  190. variable pic_array
  191. variable oldres1
  192. variable oldres2
  193. variable tmpregion
  194. variable view1
  195. variable view2
  196. variable view3
  197. variable view4
  198. global anim_prog
  199. global devnull
  200. # close all windows and delete temporary image file
  201. catch {if { [winfo exists .animwin] } {
  202. destroy .animwin
  203. }}
  204. catch {if { [winfo exists .animmaps_win] } {
  205. destroy .animmaps_win
  206. }}
  207. catch {if { [file exists $tmpfile] } {
  208. file delete -force $tmpfile
  209. }}
  210. set numviews 1
  211. set numframes 0
  212. catch {set view1 ""}
  213. catch {set view2 ""}
  214. catch {set view3 ""}
  215. catch {set view4 ""}
  216. if {[array exists vfiles]} {
  217. array unset vfiles
  218. }
  219. if {[array exists pic_array]} {
  220. array unset pic_array
  221. }
  222. set anim_prog 0
  223. catch {unset env(WIND_OVERRIDE)}
  224. if {[file exists $tmpregion]} {
  225. catch [exec g.remove region=$tmpregion --q 2> $devnull]
  226. }
  227. }
  228. proc GmAnim::make_buttons {anim_tb} {
  229. global bgcolor
  230. global iconpath
  231. global loop
  232. global swing
  233. global shownames
  234. variable cb_loop
  235. variable cb_swing
  236. set selclr #88aa88
  237. # make button images
  238. image create photo img_rast -file "$iconpath/element-cell.gif"
  239. image create photo img_rewind -file "$iconpath/gui-rewind.gif"
  240. image create photo img_rplay -file "$iconpath/gui-rplay.gif"
  241. image create photo img_stepb -file "$iconpath/gui-stepb.gif"
  242. image create photo img_stop -file "$iconpath/gui-stop.gif"
  243. image create photo img_stepf -file "$iconpath/gui-stepf.gif"
  244. image create photo img_play -file "$iconpath/gui-play.gif"
  245. image create photo img_loop -file "$iconpath/gui-loop.gif"
  246. image create photo img_swing -file "$iconpath/gui-swing.gif"
  247. image create photo img_snail -file "$iconpath/gui-snail.gif"
  248. image create photo img_rabbit -file "$iconpath/gui-rabbit.gif"
  249. image create photo img_exit -file "$iconpath/gui-exit.gif"
  250. #Create button bars
  251. set bbox0 [ButtonBox $anim_tb.bbox0 -spacing 0 ]
  252. # Select maps
  253. $bbox0 add -command GmAnim::sel_maps -image img_rast \
  254. -highlightthickness 0 -takefocus 0 -relief link -borderwidth 1 \
  255. -highlightbackground $bgcolor -activebackground $bgcolor\
  256. -helptext [G_msg "Select maps to animate"]
  257. pack $bbox0 -side left -anchor w
  258. set sep0 [Separator $anim_tb.sep0 -orient vertical ]
  259. pack $sep0 -side left -fill y -padx 5 -anchor w
  260. set bbox1 [ButtonBox $anim_tb.bbox1 -spacing 0 ]
  261. # Rewind
  262. $bbox1 add -command GmAnim::cmd_rewind -image img_rewind \
  263. -highlightthickness 0 -takefocus 0 -relief link -borderwidth 1 \
  264. -highlightbackground $bgcolor -activebackground $bgcolor\
  265. -helptext [G_msg "Rewind animation"]
  266. # Replay
  267. $bbox1 add -command GmAnim::cmd_rplay -image img_rplay \
  268. -highlightthickness 0 -takefocus 0 -relief link -borderwidth 1 \
  269. -highlightbackground $bgcolor -activebackground $bgcolor \
  270. -helptext [G_msg "Replay animation"]
  271. # Step backwards
  272. $bbox1 add -command GmAnim::cmd_stepb -image img_stepb \
  273. -highlightthickness 0 -takefocus 0 -relief link -borderwidth 1 \
  274. -highlightbackground $bgcolor -activebackground $bgcolor \
  275. -helptext [G_msg "Step backwards through animation"]
  276. # Stop
  277. $bbox1 add -command GmAnim::cmd_stop -image img_stop \
  278. -highlightthickness 0 -takefocus 0 -relief link -borderwidth 1 \
  279. -highlightbackground $bgcolor -activebackground $bgcolor \
  280. -helptext [G_msg "Stop animation"]
  281. # Step forwards
  282. $bbox1 add -command GmAnim::cmd_stepf -image img_stepf \
  283. -highlightthickness 0 -takefocus 0 -relief link -borderwidth 1 \
  284. -highlightbackground $bgcolor -activebackground $bgcolor \
  285. -helptext [G_msg "Step forwards through animation"]
  286. # Play
  287. $bbox1 add -command GmAnim::cmd_play -image img_play \
  288. -highlightthickness 0 -takefocus 0 -relief link -borderwidth 1 \
  289. -highlightbackground $bgcolor -activebackground $bgcolor \
  290. -helptext [G_msg "Play animation"]
  291. pack $bbox1 -side left -anchor w
  292. set sep1 [Separator $anim_tb.sep1 -orient vertical ]
  293. pack $sep1 -side left -fill y -padx 5 -anchor w
  294. set bbox2 [ButtonBox $anim_tb.bbox2 -spacing 0 ]
  295. # Slower
  296. $bbox2 add -command GmAnim::cmd_slower -image img_snail \
  297. -highlightthickness 0 -takefocus 0 -relief link -borderwidth 1 \
  298. -highlightbackground $bgcolor -activebackground $bgcolor \
  299. -helptext [G_msg "Slower animation"]
  300. # Faster
  301. $bbox2 add -command GmAnim::cmd_faster -image img_rabbit \
  302. -highlightthickness 0 -takefocus 0 -relief link -borderwidth 1 \
  303. -highlightbackground $bgcolor -activebackground $bgcolor \
  304. -helptext [G_msg "Faster animation"]
  305. pack $bbox2 -side left -anchor w
  306. # Loop
  307. set cb_loop [checkbutton $anim_tb.loop -command "GmAnim::cmd_loop" -image img_loop \
  308. -variable loop -offvalue 0 -onvalue 1 -relief flat \
  309. -borderwidth 1 -indicatoron false -bg $bgcolor -selectcolor $selclr \
  310. -activebackground $bgcolor -highlightbackground $bgcolor ]
  311. DynamicHelp::register $cb_loop balloon [G_msg "Continuously loop through animation"]
  312. # Swing
  313. set cb_swing [checkbutton $anim_tb.swing -command "GmAnim::cmd_swing" -image img_swing \
  314. -variable swing -offvalue 0 -onvalue 1 -relief flat \
  315. -borderwidth 1 -indicatoron false -bg $bgcolor -selectcolor $selclr \
  316. -activebackground $bgcolor -highlightbackground $bgcolor ]
  317. DynamicHelp::register $cb_swing balloon [G_msg "Run animation alternately forward and backward"]
  318. pack $cb_loop $cb_swing -side left -anchor w
  319. # Show names
  320. set cb_names [checkbutton $anim_tb.names -text "Names" \
  321. -variable shownames -offvalue 0 -onvalue 1 -relief flat \
  322. -borderwidth 1 -indicatoron false -bg $bgcolor -selectcolor $selclr \
  323. -activebackground $bgcolor -highlightbackground $bgcolor \
  324. -pady 4 -padx 2]
  325. DynamicHelp::register $cb_names balloon [G_msg "Show map names in animation window"]
  326. pack $cb_names -side left -anchor w
  327. set sep2 [Separator $anim_tb.sep2 -orient vertical ]
  328. pack $sep2 -side left -fill y -padx 5 -anchor w
  329. set bbox3 [ButtonBox $anim_tb.bbox3 -spacing 0 ]
  330. # Quit
  331. $bbox3 add -command "destroy .animwin" -image img_exit \
  332. -highlightthickness 0 -takefocus 0 -relief link -borderwidth 1 \
  333. -highlightbackground $bgcolor -activebackground $bgcolor \
  334. -helptext [G_msg "Quit animation"]
  335. pack $bbox3 -side left -anchor w
  336. set helpbtn [Button $anim_tb.help -text [G_msg "Help"] \
  337. -image [image create photo -file "$iconpath/gui-help.gif"] \
  338. -command "spawn g.manual --q gm_animate" \
  339. -background $bgcolor -borderwidth 1 \
  340. -helptext [G_msg "Help"]]
  341. pack $anim_tb -side left -anchor w -expand yes -fill x
  342. pack $helpbtn -side right -anchor e
  343. }
  344. ########################################################
  345. # select maps to animate
  346. proc GmAnim::select_map { view } {
  347. variable view1
  348. variable view2
  349. variable view3
  350. variable view4
  351. variable first
  352. append tmpvar $view
  353. set mapvar [set $tmpvar]
  354. set m [GSelect cell multiple title [G_msg "Select maps"] parent "."]
  355. if { $m != "" } {
  356. set mlist [split $m @]
  357. set m0 [lindex $mlist 0]
  358. if {$mapvar == ""} {
  359. set GmAnim::$view $m0
  360. } else {
  361. set m ",$m0"
  362. append GmAnim::$view $m
  363. }
  364. }
  365. set GmAnim::first 1
  366. }
  367. ########################################################
  368. proc GmAnim::sel_maps {} {
  369. # window for selecting maps and frames to animate
  370. global iconpath
  371. global bgcolor
  372. variable view1
  373. variable view2
  374. variable view3
  375. variable view4
  376. # Create raster map input window
  377. set mapswin [toplevel .animmaps_win]
  378. wm title $mapswin [ G_msg "Maps for Animation" ]
  379. # put it in the middle of the screen
  380. update idletasks
  381. set winWidth [winfo reqwidth $mapswin]
  382. set winHeight [winfo reqheight $mapswin]
  383. set scrnWidth [winfo screenwidth $mapswin]
  384. set scrnHeight [winfo screenheight $mapswin]
  385. set x [expr ($scrnWidth - $winWidth) / 2-250]
  386. set y [expr ($scrnHeight - $winHeight) / 2]
  387. wm geometry $mapswin +$x+$y
  388. wm deiconify $mapswin
  389. # keep this on top somehow
  390. # Heading
  391. set row [ frame $mapswin.heading ]
  392. Label $row.a -text [G_msg "Select maps to animate in one or more frames (1 frame required)"] \
  393. -fg MediumBlue
  394. Button $row.b -text [G_msg "Help"] \
  395. -image [image create photo -file "$iconpath/gui-help.gif"] \
  396. -command "spawn g.manual --q gm_animate" \
  397. -background $bgcolor -helptext [G_msg "Help"]
  398. pack $row.a -side left
  399. pack $row.b -side right -anchor e
  400. pack $row -side top -fill both -expand yes
  401. # Frame 1
  402. set row [ frame $mapswin.view1 ]
  403. Label $row.a -text [G_msg "Maps for frame 1 (required): "]
  404. Button $row.b -image [image create photo -file "$iconpath/element-cell.gif"] \
  405. -highlightthickness 0 -takefocus 0 -relief raised -borderwidth 1 \
  406. -command "GmAnim::select_map view1"
  407. Entry $row.c -width 35 -text $view1 \
  408. -textvariable GmAnim::view1
  409. pack $row.c $row.b $row.a -side right
  410. pack $row -side top -fill both -expand yes
  411. # Frame 2
  412. set row [ frame $mapswin.view2 ]
  413. Label $row.a -text [G_msg "Maps for frame 2 (optional): "]
  414. Button $row.b -image [image create photo -file "$iconpath/element-cell.gif"] \
  415. -highlightthickness 0 -takefocus 0 -relief raised -borderwidth 1 \
  416. -command "GmAnim::select_map view2"
  417. Entry $row.c -width 35 -text $view2 \
  418. -textvariable GmAnim::view2
  419. pack $row.c $row.b $row.a -side right
  420. pack $row -side top -fill both -expand yes
  421. # Frame 3
  422. set row [ frame $mapswin.view3 ]
  423. Label $row.a -text [G_msg "Maps for frame 3 (optional): "]
  424. Button $row.b -image [image create photo -file "$iconpath/element-cell.gif"] \
  425. -highlightthickness 0 -takefocus 0 -relief raised -borderwidth 1 \
  426. -command "GmAnim::select_map view3"
  427. Entry $row.c -width 35 -text $view3 \
  428. -textvariable GmAnim::view3
  429. pack $row.c $row.b $row.a -side right
  430. pack $row -side top -fill both -expand yes
  431. # Frame 4
  432. set row [ frame $mapswin.view4 ]
  433. Label $row.a -text [G_msg "Maps for frame 4 (optional): "]
  434. Button $row.b -image [image create photo -file "$iconpath/element-cell.gif"] \
  435. -highlightthickness 0 -takefocus 0 -relief raised -borderwidth 1 \
  436. -command "GmAnim::select_map view4"
  437. Entry $row.c -width 35 -text $view4 \
  438. -textvariable GmAnim::view4
  439. pack $row.c $row.b $row.a -side right
  440. pack $row -side top -fill both -expand yes
  441. set row [ frame $mapswin.buttons ]
  442. Button $row.a -text [G_msg "OK"] -width 8 -bd 1 \
  443. -command "GmAnim::create_viewlist 1" -default active
  444. Button $row.b -text [G_msg "Cancel"] -width 8 -bd 1 \
  445. -command "destroy .animmaps_win"
  446. Button $row.c -text [G_msg "Apply"] -width 8 -bd 1 \
  447. -command "GmAnim::create_viewlist 0"
  448. pack $row.a $row.b $row.c -side right -padx 5
  449. pack $row -side bottom -pady 3 -padx 5 -expand 0 -fill none -anchor e
  450. }
  451. ########################################################
  452. proc GmAnim::create_viewlist { closeval } {
  453. # Create a list of the entries for each view
  454. variable view1
  455. variable view2
  456. variable view3
  457. variable view4
  458. variable numviews
  459. set viewlist {}
  460. if { $view1 == "" } {
  461. tk_messageBox -type ok -icon warning -parent .animmaps_win \
  462. -message [G_msg "You must select maps to animate for frame 1"] \
  463. -title [G_msg "No maps selected"]
  464. return
  465. }
  466. # creat list of views with maps to animate
  467. set viewlist $view1
  468. if { $view2 != "" } {
  469. lappend viewlist $view2
  470. }
  471. if { $view3 != "" } {
  472. lappend viewlist $view3
  473. }
  474. if { $view4 != "" } {
  475. lappend viewlist $view4
  476. }
  477. if { $closeval == 1 } { destroy .animmaps_win }
  478. GmAnim::parse_viewmaps $viewlist
  479. }
  480. ########################################################
  481. proc GmAnim::parse_viewmaps {viewlist} {
  482. # create lists of maps for each view and calculate frames for each fiew
  483. variable vfiles
  484. variable numviews
  485. variable numframes
  486. variable vframes
  487. variable first
  488. variable pic_array
  489. variable scale
  490. variable vres
  491. variable ncols
  492. variable nrows
  493. variable icols
  494. variable irows
  495. variable vcols
  496. variable vrows
  497. global anim_prog
  498. # Reset variables
  499. set numviews 0
  500. set numframes 0
  501. if {[array exists vfiles]} {array unset vfiles}
  502. if {[array exists vframes]} {array unset vframes}
  503. if {[array exists pic_array]} {array unset pic_array }
  504. set anim_prog 0
  505. incr anim_prog
  506. set allmaps [exec g.mlist rast]
  507. foreach view $viewlist {
  508. set maps {}
  509. set groups [split $view ,]
  510. foreach group $groups {
  511. # parse series of maps with suffix number in range (x-y)
  512. if {[string match *(* $group]} {
  513. set series [split $group {(-)}]
  514. set start [lindex $series 1]
  515. set end [lindex $series 2]
  516. if {$start == ""} {
  517. set first 1
  518. } else {
  519. set first $start
  520. }
  521. if {$end == ""} {
  522. set last $first
  523. } else {
  524. set last $end
  525. }
  526. for {set mapnum $first} {$mapnum < [expr $last+1]} {incr mapnum} {
  527. set map [lindex $series 0]
  528. if {$start != ""} {append map $mapnum}
  529. lappend maps $map
  530. }
  531. } else {
  532. # parse maps as glob/regexp pattern
  533. foreach map $allmaps {
  534. if {[string match $group $map]} {lappend maps $map}
  535. }
  536. }
  537. }
  538. set vfiles($numviews) $maps
  539. set vframes($numviews) [llength $maps]
  540. if {$numframes < $vframes($numviews)} {set numframes $vframes($numviews)}
  541. incr numviews
  542. incr anim_prog
  543. update
  544. }
  545. set first 1
  546. GmAnim::do_run
  547. }
  548. ########################################################
  549. proc GmAnim::do_run {} {
  550. # procedure that displays maps in an animation and controls the animation
  551. global loop
  552. global swing
  553. global anim_prog
  554. global shownames
  555. variable first
  556. variable vfiles
  557. variable vframes
  558. variable pic_array
  559. variable label_pos
  560. variable numviews
  561. variable nframes
  562. variable step
  563. variable stop
  564. variable rewind
  565. variable currframe
  566. variable prevframe
  567. variable direction
  568. variable speed
  569. variable anim_can
  570. variable cnt
  571. # if the animation is just starting, then first export the maps to PPM
  572. # files and create img files for displaying in the canvas
  573. if {$first} {
  574. set first 0
  575. set step 1
  576. set nframes [GmAnim::load_files]
  577. if {$nframes == -1} {
  578. set stop 1
  579. return
  580. }
  581. set currframe [expr $direction > 0 ? 1 : $nframes]
  582. set prevframe $currframe
  583. }
  584. if {$rewind} {
  585. set rewind 0
  586. set currframe 1
  587. set direction 1
  588. set step 1
  589. set anim_prog 0
  590. }
  591. if {$stop == 1 && $step == 0} {
  592. return
  593. }
  594. if {$swing} {
  595. if {$currframe == $nframes } {
  596. set anim_prog 100
  597. set direction -1
  598. set anim_prog 0
  599. } elseif { $currframe == 1} {
  600. set anim_prog 100
  601. set direction 1
  602. set anim_prog 0
  603. }
  604. } elseif {$loop} {
  605. if {$currframe == $nframes} {
  606. set anim_prog 100
  607. set currframe 1
  608. set anim_prog 0
  609. }
  610. } elseif {$currframe == $nframes || $currframe == 1} {
  611. # If we've reached the beginning or the end, then stop the animation
  612. if {$currframe == $nframes && $direction == 1} {set anim_prog 100}
  613. if {$currframe == 1 && $direction == -1} {set anim_prog 100}
  614. set stop 1
  615. }
  616. # This is the main loop for displaying animation images and labels
  617. if {$currframe <= $nframes && $currframe >= 1} {
  618. $anim_can delete all
  619. $anim_can create image 0 0 -anchor nw -image $pic_array($currframe)
  620. # draw labels
  621. if {$shownames > 0} {
  622. for {set i 0} {$i < $numviews} {incr i} {
  623. set x [expr $label_pos($i,0) + 5]
  624. set y [expr $label_pos($i,1) - 3]
  625. if { $currframe > $vframes($i) } {
  626. set lblframe [expr $vframes($i) - 1]
  627. } else {
  628. set lblframe [expr $currframe - 1]
  629. }
  630. set s [lindex $vfiles($i) $lblframe]
  631. $anim_can create text $x $y -text $s -fill black -anchor sw
  632. }
  633. }
  634. set prevframe $currframe
  635. }
  636. incr currframe $direction
  637. incr anim_prog
  638. if {$step} {
  639. set step 0
  640. set stop 1
  641. }
  642. }
  643. ########################################################
  644. proc GmAnim::load_files {} {
  645. # exports maps to ppm and creates array of images to display in canvas
  646. variable numframes
  647. variable vframes
  648. variable numviews
  649. variable ncols
  650. variable nrows
  651. variable scale
  652. variable icols
  653. variable irows
  654. variable vcols
  655. variable vrows
  656. variable pic_array
  657. variable vfiles
  658. variable label_pos
  659. variable tmpfile
  660. variable border
  661. variable anim_can
  662. variable cnt
  663. variable minframes
  664. global anim_prog
  665. set vrows $nrows
  666. set vcols $ncols
  667. set irows $nrows
  668. set icols $ncols
  669. # set vrows & vcols to the size for each sub-image
  670. if { $numviews > 1 } {
  671. set vrows [expr int($vrows * $scale / 2.0)]
  672. set vcols [expr int($vcols * $scale / 2.0)]
  673. }
  674. # create an image or composite image for each frame (use max number of frames from all views)
  675. for {set cnt 0} {$cnt < $numframes} {incr cnt} {
  676. # create the main image that will fill the canvas
  677. set img [image create photo -width $ncols -height $nrows]
  678. # store the image in an array
  679. set pic_array([expr $cnt + 1]) $img
  680. # set region resolution to control size of pnm image if needed
  681. if {$scale != 1.0 || $numviews > 1} {
  682. GmAnim::switch_res 1
  683. }
  684. # create a subimage for each view shown. For single view animations, the subimage
  685. # is the same size as the main image. For multiview animations, the subimage is
  686. # 25% of the main image.
  687. for {set vnum 0} {$vnum < $numviews} {incr vnum} {
  688. if {$icols == $vcols} {
  689. set vxoff $border
  690. set vyoff [expr $irows == $vrows ? $border : $border + $vnum * ($border + $vrows)]
  691. } elseif {$irows == $vrows} {
  692. set vxoff [expr $icols == $vcols ? $border : $border + $vnum * ($border + $vcols)]
  693. set vyoff $border
  694. } else { # 4 views
  695. # set offset for each subimage in multi-image view
  696. set vxoff [expr $vnum % 2 ? $border : $vcols + 2 * $border]
  697. set vyoff [expr $vnum > 1 ? $vrows + 2 * $border : $border]
  698. }
  699. # set label positions
  700. if {! $cnt} {
  701. set label_pos($vnum,0) $vxoff
  702. set label_pos($vnum,1) [expr $vyoff + $vrows - 1]
  703. }
  704. if { $cnt < $vframes($vnum)} {
  705. set name [lindex $vfiles($vnum) $cnt]
  706. } else {
  707. # if a view has fewer frames than the maximum, just use the
  708. # last frame over again
  709. set name [lindex $vfiles($vnum) [expr $vframes($vnum) - 1]]
  710. }
  711. # export the map to a PPM file
  712. if {[catch {exec r.out.ppm input=$name output=$tmpfile --q} error]} {
  713. GmLib::errmsg $error
  714. return -1
  715. }
  716. # create the subimage for each view
  717. set subimg [image create photo -file $tmpfile]
  718. file delete $tmpfile
  719. # copy the subimage to the main image, placing it with the offsets as needed
  720. $img copy $subimg \
  721. -to $vxoff $vyoff [expr $vxoff + $vcols] [expr $vyoff + $vrows]
  722. # delete the subimage
  723. image delete $subimg
  724. incr anim_prog
  725. }
  726. # reset region to original resolution
  727. if {$scale != 1.0 || $numviews > 1 } {
  728. GmAnim::switch_res 0
  729. }
  730. # clear the canvas and display the main image with 1-4 subimages
  731. $anim_can delete all
  732. $anim_can create image 0 0 -anchor nw -image $img
  733. update
  734. incr anim_prog
  735. }
  736. return $cnt
  737. }
  738. ########################################################
  739. proc GmAnim::cmd_idle {} {
  740. # timer - iterates through animation if stop=0 at
  741. # intervals set by "speed"
  742. variable stop
  743. variable speed
  744. variable step
  745. if { !$stop && !$step } {GmAnim::do_run}
  746. after $speed GmAnim::cmd_idle
  747. }
  748. ########################################################
  749. proc GmAnim::switch_res { switch } {
  750. # set region to new temp resolution for pnm scaling if switch=1
  751. # reset region to original resolution if switch = 0
  752. variable scale
  753. variable vres
  754. variable numviews
  755. variable oldres1
  756. variable oldres2
  757. variable tmpregion
  758. global env
  759. global devnull
  760. # calculate region resolution needed for pnm output
  761. set res_scale1 [expr 1.0/ $scale]
  762. set res_scale2 [expr 1.3 * $res_scale1]
  763. set res_scale4 [expr 2.0 * $res_scale1]
  764. # either a 1 view window or a 4 view window
  765. if {$numviews == 1} {
  766. set pnmres [expr 1.0 * $vres * $res_scale1]
  767. } else {
  768. set pnmres [expr 1.0 * $vres * $res_scale4]
  769. }
  770. set tmpregion "tmpanimregion"
  771. append tmpregion [pid]
  772. if { $switch == 1 } {
  773. # set temp region file for changing resolution
  774. if {[catch {set region [exec g.region -u save=$tmpregion --o --q]} error]} {
  775. GmLib::errmsg $error
  776. }
  777. if {[catch {set env(WIND_OVERRIDE) $tmpregion} error]} {
  778. GmLib::errmsg $error
  779. }
  780. # change resolution
  781. if {[catch [exec g.region res=$pnmres] error]} {
  782. GmLib::errmsg $error
  783. }
  784. } else {
  785. # switch back to original region
  786. if {[catch {unset env(WIND_OVERRIDE)} error]} {
  787. GmLib::errmsg $error
  788. }
  789. if {[file exists $tmpregion]} {
  790. catch [exec g.remove region=$tmpregion --q 2> $devnull]
  791. }
  792. }
  793. }
  794. ########################################################
  795. proc GmAnim::main {} {
  796. # main window for displaying and controling animation
  797. variable ncols
  798. variable nrows
  799. variable scale
  800. variable vcols
  801. variable vrows
  802. variable vres
  803. variable oldres1
  804. variable oldres2
  805. variable border
  806. variable speed
  807. variable anim_can
  808. global anim_prog
  809. # set initial canvas geometry to match region
  810. if {[catch {set region [exec g.region -ugp]} error]} {
  811. GmLib::errmsg $error
  812. }
  813. set reglist [split $region "\n"]
  814. foreach line $reglist {
  815. set line [string trim $line]
  816. set key [lindex [split $line "="] 0]
  817. switch $key {
  818. nsres {set oldres1 [lindex [split $line "="] 1]}
  819. ewres {set oldres2 [lindex [split $line "="] 1]}
  820. rows {set vrows [lindex [split $line "="] 1]}
  821. cols {set vcols [lindex [split $line "="] 1]}
  822. }
  823. }
  824. set vres [expr $oldres1 > $oldres2 ? 1.0 * $oldres1 : 1.0 * $oldres2]
  825. set nrows $vrows
  826. set ncols $vcols
  827. # short dimension
  828. set sdim [expr {$nrows > $ncols ? "ncols" : "nrows"}]
  829. set longdim [expr $nrows > $ncols ? $nrows : $ncols]
  830. set scale 1.0
  831. set max 900
  832. set min 600
  833. if {[array get env XGANIM_SIZE] != ""} {
  834. set max $env(XGANIM_SIZE)
  835. set min $env(XGANIM_SIZE)
  836. }
  837. if {$longdim > $max} { # scale down
  838. set scale [expr 1.0 * $max / $longdim]
  839. } elseif {$longdim < $min} { # scale up
  840. set scale [expr 1.0 * $min / $longdim]
  841. }
  842. # set nrows & ncols to the size of the combined - views image
  843. set nrows [expr int($nrows * $scale)]
  844. set ncols [expr int($ncols * $scale)]
  845. # add to nrows & ncols for borders
  846. set nrows [expr int($nrows + (1 + ($nrows/$vrows)) * $border)]
  847. set ncols [expr int($ncols + (1 + ($ncols/$vcols)) * $border)]
  848. # create file viewing frame
  849. toplevel .animwin
  850. wm title .animwin [G_msg "Animation Window"]
  851. set anim_fr [MainFrame .animwin.mf \
  852. -textvariable GmAnim::msg \
  853. -progressvar anim_prog -progressmax 100 -progresstype incremental]
  854. $anim_fr showstatusbar progression
  855. set mf_frame [$anim_fr getframe]
  856. # toolbar creation
  857. set anim_tb [$anim_fr addtoolbar]
  858. #MapToolBar::create $map_tb
  859. # canvas creation
  860. set anim_can [canvas $mf_frame.canvas \
  861. -borderwidth 0 -closeenough 10.0 -relief groove \
  862. -width $ncols -height $nrows ]
  863. # setting geometry
  864. place $anim_can -in $mf_frame -x 0 -y 0 -anchor nw
  865. pack $anim_can -fill both -expand yes
  866. # indicator creation
  867. # set anim_ind [$anim_fr addindicator -textvariable animstatus \
  868. # -width 33 -justify left -padx 5 -bg white]
  869. pack $anim_fr -fill both -expand yes
  870. # create animation control buttons
  871. GmAnim::make_buttons $anim_tb
  872. # bindings for closing window
  873. bind .animwin <Destroy> "GmAnim::cleanup"
  874. update
  875. # start animation timer
  876. after $speed GmAnim::cmd_idle
  877. }
  878. ########################################################
  879. #GmAnim::main