Silverfrost Forums

Welcome to our forums

Animation control - use of %dl

4 Jun 2020 8:54 #25558

I often use %pl or %gr to develop simple animations. These generally run for a fixed period at a fixed speed after the user invokes the start callback. I have been thinking that it would be useful for the user to adjust the speed, or stop and then restart at some point during the animation. Discovering the %dl format code the other day, I came up with the following – which provides the required functionality. I’m just wondering if others have a better way of achieving the same end result? Ken

module t
use clrwin
implicit none
private ; public build_gui
integer, parameter :: dp = kind(1.d0), gw = 800, gh = 800, npts(1:2) = (/2,2/)
real(kind=dp)      :: x(1:2)=0.d0, y(1:2)=0.d0, limits_x(1:2) = (/-2.d0,2.d0/), limits_y(1:2) = (/-2.d0,2.d0/)
logical            :: run = .false.,  forward = .true.
integer(kind=7)    :: win_handle
real(kind=dp)      :: speed = 0.08d0, speed_not_running = 5.d0
contains
  integer function build_gui()
  integer, save :: iw
    iw = winio@('%mn[Exit]&','exit')
    iw = winio@('%hw&',win_handle)
    iw = winio@('%fn[Tahoma]&')
    call winop@('%pl[native, independent, x_array, n_graphs=2, width=3, smoothing=5]')
    call winop@('%pl[colour=red,    link=lines, pen_style=0, symbol=6,  symbol_size=6]')
    call winop@('%pl[colour=red,    link=none, pen_style=1, symbol=0,  symbol_size=6]') !To force display to show 4 quad.
    call winop@('%pl[x_axis=@,y_axis=@,dx=1.0,dy=1.0,margin=100]')
    iw = winio@('%bf%pl%`bf&',gw,gh,npts,x,y,limits_x,limits_y)
    iw = winio@('%ts%ob[invisible]%^tt[Start]%2nl%^tt[Stop]%2nl%^tt[Slower]%2nl%^tt[Normal]%2nl%^tt[Faster]%2nl%^tt[Reverse]%cb&', &
                  0.8d0,start_cb,stop_cb,slow_cb,normal_cb,fast_cb,reverse_cb)
    iw = winio@('%dl',speed_not_running,calc_cb)
    build_gui = 2
  end function build_gui

  integer function start_cb()
  integer i
    run = .true. ; i = normal_cb() ; start_cb = 2
  end function start_cb

  integer function stop_cb()
  integer i
    run = .false. ; i = speed_not_running_cb() ; stop_cb = 2
  end function stop_cb

  integer function speed_not_running_cb()
  call CHANGE_TIMER_INTERVAL@( win_handle, speed_not_running ) ; speed_not_running_cb = 2
  end function speed_not_running_cb

  integer function fast_cb()
    speed = speed/2.d0 ; call CHANGE_TIMER_INTERVAL@( win_handle, speed ) ; fast_cb = 2
  end function fast_cb

  integer function normal_cb()
    speed = 0.05d0 ; call CHANGE_TIMER_INTERVAL@( win_handle, speed ) ; normal_cb = 2
  end function normal_cb

  integer function slow_cb()
    speed = speed*2.d0 ; call CHANGE_TIMER_INTERVAL@( win_handle, speed ) ; slow_cb = 2
  end function slow_cb

  integer function reverse_cb()
    if (forward) then ; forward = .false. ; else if (.not. forward) then ; forward = .true. ; end if ; reverse_cb = 2
  end function reverse_cb

  integer function calc_cb()
  real(kind=dp), save :: theta, d_theta
  logical, save :: first = .true.
    if (first) then ; d_theta = 4.d0*atan(1.0)/180.d0 ; theta = 0.d0 ; first = .false. ; end if
    if (run) then
      x(2) = cos(theta) ;  y(2) = sin(theta) ; call simpleplot_redraw@()
      if (forward) then ; theta = theta + d_theta
      else              ; theta = theta - d_theta ; end if
    end if
    calc_cb = 2
  end function calc_cb
end module t

program main
use t, only : build_gui
i = build_gui()
end program main
4 Jun 2020 9:43 #25561

You can stop the flicker on the axes as follows but further work would be needed to avoid the cursor flickering.

      i = SendMessage(win_handle, WM_SETREDRAW, 0, 0)
      call simpleplot_redraw@()
      i = SendMessage(win_handle, WM_SETREDRAW, 1, 0)

SendMessage requires 'use mswin'. The cursor can be switched off with

      i = ShowCursor(0)
5 Jun 2020 1:52 #25576

Thanks for the tips Paul.

https://youtu.be/STM-0GAWZk8

Ken

5 Jun 2020 2:48 #25577

Amazing!

5 Jun 2020 3:14 #25578

That is very impressive!

5 Jun 2020 6:14 #25582

What would very benefit Clearwin in our times of online presentations, Youtube and video for everything is the utility for automatic saving of series of graphics files to mp4. That is the major trend and Matlab has it by the way and our students showing many animations during their oral talks on the conferences.

6 Jun 2020 5:49 #25583

Dan

If you have not already done this, I suggest that you try a Zoom session with 'Share screen' and recording. The recording can be saved and you get the video with very little effort. There are YouTube tutorials on how to do use Zoom if you have any problems.

6 Jun 2020 12:10 #25584

Ken,

That's brilliant.

One observation is that the yellow vector is a bit less obvious than some of the other colours. I'm working on a project at the moment where another engineer has used yellow for some notes on a drawing and I can hardly read them. I think that you get a better effect with a little bit of red in it, but not so far as it turns orange.

Eddie

6 Jun 2020 4:34 #25585

Thanks Eddie,

Goldenrod is the colour that's needed I think.

One thing I did notice was that the position of the q axis label appears to jump when crossing the horizontal axis. A little bit of investigation this afternoon, and I can now see that rotate_font@ also changes the height of the font and at that particular position angular position it is at its smallest.

module t
use clrwin
implicit none
private ; public gui
integer, parameter :: dp = kind(1.d0)
real(kind=dp)      :: ang=-30.d0
contains

integer function gui()
integer, save :: iw
  iw = winio@('%mn[Exit]&','exit')
  iw = winio@('%gr[white]&',600,600)
  iw = winio@('%^tt[next]&',next_Cb)
  iw = winio@(' ')
  gui = 2
end function gui

integer function next_cb()
real(kind=dp) x, y
integer ix(1:5), iy(1:5)
integer w, d
character(len=18) :: STR = 'This is some text'
character(len=3) nst
!  call select_font@('Consolas')
  call select_font@('Times')   
!  call select_font@('Courier')      !###### Rotate font does not like Courier 
  call SIZE_IN_PIXELS@( 30, 10)
  call set_line_width@(2)
  call draw_filled_rectangle@(0,0,600,600,rgb@(255,255,255)) ! Clear graphics area
  x = 400.d0*cos(deg_to_rad_dp(ang))
  y = 400.d0*sin(deg_to_rad_dp(ang))
  call draw_line_between@(300, 300, nint(300.d0+x), nint(300.d0 - y), rgb@(0,0,0))
  call rotate_font@(ang)
  call draw_characters@(STR,300,300, rgb@(0,0,0))
  call GET_TEXT_SIZE@( STR, w, d )
  ix(1) = 300 ; iy(1) = 300
  ix(2) = 300 + nint(dble(w)*cos(deg_to_rad_dp(ang))) 
  iy(2) = 300 - nint(dble(w)*sin(deg_to_rad_dp(ang)))
  ix(3) = ix(2) - nint(dble(d)*cos(deg_to_rad_dp(90.d0-ang)))
  iy(3) = iy(2) - nint(dble(d)*sin(deg_to_rad_dp(90.d0-ang)))
  ix(4) = ix(3) - nint(dble(w)*cos(deg_to_rad_dp(ang))) 
  iy(4) = iy(3) + nint(dble(w)*sin(deg_to_rad_dp(ang)))
  ix(5) = ix(1) ; iy(5) = iy(1)
  call DRAW_POLYLINE@(IX,IY,5,rgb@(255,0,0))
  write(nst,'(I3)') d
  call rotate_font@(0.d0)
  call draw_characters@('Text height '//nst,30,30, rgb@(0,0,0))
  ang = ang + 10.d0
  next_cb = 2
end function next_cb

function deg_to_rad_dp (deg)
real (kind = dp), intent(in) :: deg
real (kind = dp)  deg_to_rad_dp
  deg_to_rad_dp = deg * ((4.d0 * atan(1.d0) )/180.d0)
end function deg_to_rad_dp
    
end module t

program main
use t , only : gui
i = gui()
end program main
6 Jun 2020 7:26 #25586

Paul,

That Zoom suggestion is interesting. Unfortunately it does fit only quick almost realtime simulations with instant plotting like Ken showed above.

In the vast amount of other cases the user gets the data outputs from one per second or per minute to one per hour or even per day, and only at that times he can get one PNG or JPG snapshot. Hence the utility is required which will step by step gather all graphics snapshots into MP4 as the simulation proceeds.

There exist post-processing apps which do that, they allow to gather files into one place and then generate MP4. There also exist online services where you send your JPG files and get MP4 video. But often they have limitations like not more than 50MB total etc

As you can see this is a bit of a headache, as everything of such sort has to be done by the codes automatically. Around 1995 i wrote PCX/BMP graphics file animator using Salford FTN77 Fortran. Today we can use other graphics formats but MP4 beats them all as the final total file size is tremendously smaller and the speed visualization fps much faster and video smoother

7 Jun 2020 10:52 #25590

I could not resist the temptation of making the %pl callback do just a little more.

https://youtu.be/dLJvhZ2IYzM

Ken

8 Jun 2020 4:47 #25592

Quoted from John-Silver

.... is this 'Zoom' a third party program or embedded in ftn95 ?

John, I'd wish this would be a part of Clearwin so that we call it from the FTN95 and it makes you video automatically out of picture files also generated by the same code. So when the code ends it produces you not just the numbers, not just the still pictures, not just the screen shots, but also the videos. In the modern days if you do not generate nice looking videos nobody buy your stuff even if you will try publish supergeneral theory of relativity. Teaching, online journals, different meetings and conferences all require videos

Zoom is the program many now use for video conferencing, remotely teaching at schools and universities.

8 Jun 2020 5:04 #25593

P.S. Since i am with this company's compiler almost from its start I'll remind all the one of its slogans. Something like:

You do not need to learn C/C++ or assembler, you do not need third party graphics programs and headaches to connect them to your code, you do not need to scratch your head how to make modern programs for Windows, you will get all of this and a lot more with this Fortran

Please login to reply.