声振论坛

 找回密码
 我要加入

QQ登录

只需一步,快速开始

查看: 2504|回复: 2

[Fortran] [分享]fortran绘图、界面功能简介

[复制链接]
发表于 2015-10-30 22:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?我要加入

x
本帖最后由 NASA 于 2015-10-30 22:04 编辑

对于fortran的绘图、界面功能,我仅仅做一个简单的罗列,这样方便大家的讨论:
1.利用fortran的扩充函数绘图,下面是一个简单的例子,是http://www.programfan.com上面有人贴出的;
       Visual Fortran中有提供绘图功能。Visual Fortran的绘图功能不完全是以扩充函数的类型存在,使用它的绘图功能必须在选择Project类型时,选择Standard Graphics或QuickWin模式。
Visual Fortran的QuickWin及Standard Graphics模式在简单的绘图使用上会比较方便,它的绘图函数功能比较多样,不过效率会比较差,而且不支持动画功能。
       Standard Graphics和QuickWin模式在绘图方面的使用方法完全相同,它们都是调用相同的函数来绘图。差别在于Standard Graphics只能打开一个窗口来绘图、QuickWin模式则可以打开多个窗口来绘图。QuickWin模式下可以有菜单及对话窗的功能,Standard Graphics则不行。Standard Graphics模式的程序代码可以原封不动直接转换到QuickWin模式下使用,但是QuickWin的程序代码并不一定可以直接拿到Standard Graphics模式下使用。
       下面这个程序会在屏幕上画出一条斜线、一个方形及一个椭圆。编译程序时,请选择Fortran Standard Graphics or QuickWin Application这个模式。这个程序可以在Standard Graphics或QuickWin模式下使用。打开好Project后,再把下面的程序加入Project中来编译。
  1. 1.! 简单的绘图范例
  2. 2.! By Perng 1997/9/19
  3. 3.program Plot_Demo
  4. 4.! 使用Visual Fortran的绘图功能时需要module dflib
  5. 5.use DFLIB   
  6. 6.implicit none
  7. 7.  type(xycoord) :: t
  8. 8.  integer :: result
  9. 9.  call MoveTo(10,10,t)  ! 把目前绘图的位置移动到坐标(10,10)
  10. 10.  result=LineTo(100,50) ! 从(10,10)到(100,50)间绘一条直线
  11. 11.  ! 画一个左上角为(110,10), 右下角为(150,50)的实心方形
  12. 12.  result=Rectangle( $GFILLINTERIOR, 110,10, 150, 50 )
  13. 13.  ! 画一个可以放入在(10,60)--(150,100)方形当中的空心椭圆
  14. 14.  result=Ellipse($GBORDER, 10, 60, 150, 100)
  15. 15.end program Plot_Demo
复制代码

使用Standard Graphics模式时,会出现一个绘图窗口来画图。使用QuickWin模式时,除了绘图窗口外,还有内定的菜单可以使用。File菜单中的Print可以把图形显示出,Save可以把绘图结果储存成*.BMP图文件。
       使用Visual Fortran的绘图功能时,打开窗口的工作是自动完成的。程序代码只需要直接调用绘图函数就可以进行绘图,下面对程序中所使用的绘图函数做一些介绍:
subroutine MoveTo(x,y,t)
使用这个子程序时,要先把屏幕想像成一张画纸,程序会使用一只画笔在屏幕上画画。MoveTo(x,y,t)可以把这只画笔移动到画纸上的(x,y)坐标处,参数t则会返回移动之前的画笔所在位置(这个参数其实没有什么用,不过既然有规定就一定要把它放入)。
请注意,原点(0,0)是位在窗口的左上角,x坐标轴向右为正,y坐标轴向下为正。
integer(2) function LineTo(x,y)
这个函数可以把画笔从目前的位置到(x,y)处画一条直线。返回值如果不为0,代表函数运行不正常。
integer(2) function Rectangle( control, x1, y1, x2, y2 )
这个函数可以在(x1,y1)、(x2,y2)两个端点间画出一个方形。control值可以用来设定是要画出一个实心方形或是只有外框而已。在范例中把control的值用$GFILLINTERIOR来代入,表示要画实心。$GFILLINTERIOR定义在MODULE DFLIB里面。
integer(2) function Ellipse(control,x1,y1,x2,y2)
这个函数会在(x1,y1)、(x2,y2)两端点间所形成的矩形中画椭圆。control的意义同上,在范例中使用$GBORDER,代表只画出外框。
下面这个范例画出SIN函数的图形:
  1.   1.! sin函数的绘图范例
  2.   2.program Plot_Sine
  3.   3. use DFLIB
  4.   4.implicit none
  5.   5.  integer, parameter :: lines=500   ! 用多少线段来画函数曲线
  6.   6.  real(kind=8), parameter :: X_Start=-5.0   ! x轴最小范围
  7.   7.  real(kind=8), parameter :: X_End=5.0      ! x轴最大范围   
  8.   8.  real(kind=8), parameter :: Y_Top=2.0      ! y轴最大范围
  9.   9.  real(kind=8), parameter :: Y_Bottom=-2.0  ! y轴最小范围
  10. 10.  integer :: result         ! 取回绘图函数运行状态
  11. 11.  integer(kind=2) :: color  ! 设定颜色用
  12. 12.  real(kind=8) :: step      ! 循环的增量
  13. 13.  real(kind=8) :: x,y       ! 绘图时使用,每条小线段都连接
  14. 14.  real(kind=8) :: NewX,NewY ! (x,y)及(NewX,NewY)
  15. 15.  real(kind=8), external :: f ! 待绘图的函数
  16. 16.  type(wxycoord) :: wt      ! 返回上一次的虚拟坐标位置
  17. 17.  type(xycoord)  :: t       ! 返回上一次的实际坐标位置
  18. 18.
  19. 19.  ! 设定虚拟坐标范围大小   
  20. 20.  result=SetWindow( .true. , X_Start, Y_Top, X_End, Y_Bottom )
  21. 21.  ! 用索引值的方法来设定颜色
  22. 22.  result=SetColor(2)   ! 内定的2号是应该是绿色
  23. 23.  call MoveTo(10,20,t) ! 移动画笔到窗口的(10,20)
  24. 24.  call OutGText("f(x)=sin(x)")  ! 写出内容
  25. 25.  ! 使用全彩RGB 0-255的256种色阶来设定颜色
  26. 26.  color=RGBToInteger(255,0,0)       ! 把控制RGB的三个值转换到color中
  27. 27.  result=SetColorRGB(color)         ! 利用color来设定颜色
  28. 28.
  29. 29.  call MoveTo_W(X_Start,0.0_8,wt)   ! 画X轴
  30. 30.  result=LineTo_W(X_End,0.0_8)      !
  31. 31.  call MoveTo_W(0.0_8,Y_Top,wt)     ! 画Y轴
  32. 32.  result=LineTo_W(0.0_8,Y_Bottom)   !   
  33. 33.
  34. 34.  step=(X_End-X_Start)/lines        ! 计算小线段间的X间距
  35. 35.  ! 参数#FF0000是使用16进制的方法来表示一个整数
  36. 36.  result=SetColorRGB(#FF0000)        
  37. 37.  ! 开始绘制小线段们
  38. 38.  do x=X_Start,X_End-step,step
  39. 39.    y=f(x)          ! 线段的左端点
  40. 40.    NewX=x+step     
  41. 41.    NewY=f(NewX)    ! 线段的右端点
  42. 42.    call MoveTo_W(x,y,wt)
  43. 43.    result=LineTo_W(NewX,NewY)
  44. 44.  end do
  45. 45.  ! 设定程序结束后,窗口会继续保留
  46. 46.  result=SetExitQQ(QWIN$EXITPERSIST)
  47. 47.end
  48. 48.! 所要绘图的函数
  49. 49.real(kind=8) function f(x)
  50. 50.implicit none
  51. 51.  real(kind=8) :: x
  52. 52.  f=sin(x)
  53. 53.  return
  54. 54.end function f
复制代码

这个程序会以目前Windows分辨率的大小来打开绘图窗口。程序执行后只能够看到窗口的一小部分,读者可以试着按下Alt+Enter来把窗口放大成全屏幕大小,不然看不到全部的图形。使用QuickWin模式时,并不像使用SGL时一样可以得到窗口大小改变的信息,所以QuickWin下的虚拟坐标是对固定分辨率来对应,不会随着窗口大小改变而缩放图形。
把这个程序中新使用的绘图函数做一个介绍
integer(2) function SetWindow( invert, x1,y1, x2,y2 )
用来设定虚拟坐标,invert的值是用来指定Y轴向上为正或为负。invert=.true.时向上为正,invert=.false.时向下为负。(x1,y1)、(x2,y2)则使用双精度浮点数来定义绘图范围两端的虚拟坐标值。
integer(2) function SetColor(index)
使用索引值的方法来设定所要使用的颜色。
subroutine OutGText( text )
调用这个子程序可以在目前画笔的位置上写出text字符串。
integer(4) function RGBToInteger(R,G,B)
前面有提过,全彩模式中,RGB三种色光可以各自有256种色阶变化,所以一个颜色需要使用3 bytes的空间来做记录。但是FORTRAN中通常一个整数使用4 bytes的空间来做记录,如果分别使用3个变量来记录一个颜色值会很浪费空间,因为这3个变量都只会使用到最低的8个位,其它地方都不会使用。
这个函数可以重新组合R G B这三个传入的整数,取出这三个整数中最低8个位的数值,把它重新安排到返回值color中。color中的第0~7 bits用存放原本的R,8~15 bits会存放原本的G,16~23 bits会存放原本的B,剩下第24~31 bits的空间则不会使用。
integer(2) function SetColorRGB( color )
用RGB方法来设定颜色,参数color中的第0~7个bits用来设定红光,第8~15 bits用来设定绿光,第16~23 bits用来设定蓝光,其它位不使用。在范例当中曾使用SetColorRGB(#FF0000)来设定颜色,在Visual Fortran中以#符号开头的数字,代表一个16进制的数字。
16进制数值在0~9时和10进制数字相同,但是接在9下面的数字为A、B、C、D、E、F。其中A等于10进制的10,B=11,C=12.....,同理可推得1016=16,FF16=255。使用16进制的系统可以比较容易来操作这种需要控制到位内容的数值。正规的FORTRAN 90写法应该用Z”FF0000”来设定16进制的数值,第5章的最后一节有介绍这个方法。在此顺便范例一下Visual Fortran的扩充语法。
2.利用科学绘图软件包PLPlot、PGPLOT等
PLplot是一个用于多种编程语言(C, C++, Fortran, Java, Python, Perl etc.)的跨平台(Unix, Linux, Dos, Windows, Mac OS, OS/2 etc.)的科学绘图程序包,完全免费,源代码开放。如果你用ABSoft Pro Fortran,该程序包已经包括在内。如果你用别的平台,你可以用这些源代码建立自己的库文件。
http://plplot.sourceforge.net/
http://keihanna.dl.sourceforge.n ... 5.3.0-printable.pdf
http://keihanna.dl.sourceforge.n ... plplot-5.3.0.tar.gz
http://www.astro.caltech.edu/%7Etjp/pgplot/
上面的连接不一定能连接上,你可以到北大天网资源里面搜一下。
3.利用绘图软件包Matfor
大家可以看看http://www.softwarechn.com/ancad/ancad_index.htm是关于他的简单介绍。
具体的直接去网站http://www.ancad.com可以下载软件。
4.用OPENGL库绘图
关于这个vf的帮助里面有例子,但是要绘制三维图形的话,首先得知道一些图形学的基础知识。
5.windowsGDI绘图
这个还是API编程那一部分,比较麻烦。
回复
分享到:

使用道具 举报

 楼主| 发表于 2015-10-30 22:02 | 显示全部楼层
对于fortran的程序界面方面,也简单做一个罗列:
1.混合编程:
用fortran做核心计算,然后利用VB、VC等做界面,这是大家认可的。具体的可以参考彭国伦、唐章宏等人写的书;
2.利用fortran的扩展功能
在上面的帖子里面已经给出例子,在QUICKWIN模式下可以利用原有的菜单,也可以自己订制菜单和对话框,如果程序仅仅需要一些简单的菜单和对话框的话,这个是不错的选择;唯一不足的就是缺少工具条的制作,当然如果调用API函数的话应该能够实现吧(探讨)。
3.利用API函数做界面
下面给出一个简单的例子,形成简单的菜单和模态对话框。从程序看,这个方法需要的代码比较多,相比较QUICKWIN工程中利用fortran的扩展功能而言,这个方法做界面就复杂一些。
  1. module hh
  2. integer hInst
  3. integer hDlg
  4. end module hh
  5. integer function WinMain( hInstance, hPrevInstance, lpszCmdLine, nCmdShow )
  6. !DEC$ IF DEFINED(_X86_)
  7. !DEC$ ATTRIBUTES STDCALL, ALIAS : '_WinMain@16' :: WinMain
  8. !DEC$ ELSE
  9. !DEC$ ATTRIBUTES STDCALL, ALIAS : 'WinMain' :: WinMain
  10. !DEC$ ENDIF
  11. !包含有用的模块
  12. use user32
  13. use dfwin
  14. use hh
  15. USE clipinc
  16. integer hInstance      !定义句柄
  17. integer hPrevInstance  !定义句柄
  18. integer nCmdShow
  19. integer lpszCmdLine
  20. !*****************************************************************
  21. interface
  22. integer*4 function MainWndProc ( hwnd, mesg, wParam, lParam )
  23. !DEC$ IF DEFINED(_X86_)
  24. !DEC$ ATTRIBUTES STDCALL, ALIAS : '_MainWndProc@16' :: MainWndProc
  25. !DEC$ ELSE
  26. !DEC$ ATTRIBUTES STDCALL, ALIAS : 'MainWndProc' :: MainWndProc
  27. !DEC$ ENDIF
  28. integer*4 hwnd
  29. integer*4 mesg  
  30. integer*4 wParam
  31. integer*4 lParam
  32. end function
  33. end interface
  34. !******************************************************************
  35. type (T_WNDCLASS)       wc   
  36. type (T_MSG)            mesg
  37. integer                 hWnd,COLOR
  38. character*100 lpszClassName,lpszAppName,lpszMenuName
  39. COLOR=9 !这个用来改变窗口的背景颜色
  40. lpszCmdLine = lpszCmdLine
  41. nCmdShow = nCmdShow
  42. lpszClassName ="Generic"C
  43. lpszAppName ="窗口程序,非模态对话框"C
  44. lpszMenuName="menumenu"C
  45. if(hPrevInstance .eq. 0) then
  46.      wc%lpszClassName = LOC(lpszClassName)
  47.      wc%lpfnWndProc = LOC(MainWndProc)
  48.      wc%style = IOR(CS_VREDRAW , CS_HREDRAW)
  49.      wc%hInstance = hInstance
  50.      wc%hIcon = LoadIcon( hInstance, "MYICON")
  51.      wc%hCursor = LoadCursor( hInstance, "MYCURSOR" )
  52.      wc%hbrBackground = ( COLOR_WINDOW+COLOR )
  53.      wc%lpszMenuName = LOC(lpszMenuName)
  54.      wc%cbClsExtra = 0
  55.      wc%cbWndExtra = 0
  56.      i1 = RegisterClass(wc)
  57. end if
  58. hWnd = CreateWindowEx(  0, lpszClassName,                      &
  59.                         lpszAppName,                           &
  60.                         INT(WS_OVERLAPPEDWINDOW),              &
  61.                         CW_USEDEFAULT,                         &
  62.                         0,                                     &
  63.                         CW_USEDEFAULT,                         &
  64.                         0,                                     &
  65.                         NULL,                                  &
  66.                         NULL,                                  &
  67.                         hInstance,                             &
  68.                         NULL                                   &
  69.                         )
  70. hInst=hInstance  
  71. i = ShowWindow( hWnd, SW_SHOWNORMAL)
  72. do while( GetMessage (mesg, NULL, 0, 0))
  73.    if(IsDialogMessage(hDlg,mesg)==0)then
  74.    i =  TranslateMessage( mesg )
  75.    i =  DispatchMessage( mesg )
  76.    endif
  77. end do
  78. WinMain = mesg%wParam
  79. end
  80. !*********************************以下是窗口处理函数*************
  81. integer function MainWndProc (hWnd, mesg, wParam, lParam)
  82. !DEC$ IF DEFINED(_X86_)
  83. !DEC$ ATTRIBUTES STDCALL, ALIAS : '_MainWndProc@16' :: MainWndProc
  84. !DEC$ ELSE
  85. !DEC$ ATTRIBUTES STDCALL, ALIAS : 'MainWndProc' :: MainWndProc
  86. !DEC$ ENDIF
  87. use user32
  88. use dfwin
  89. use hh
  90. USE clipinc
  91. !*****************************************************************
  92. interface
  93. logical function DialogFunc ( hdWnd, mesg, wParam, lParam )
  94. !DEC$ IF DEFINED(_X86_)
  95. !DEC$ ATTRIBUTES STDCALL, ALIAS : '_DialogFunc@16' :: DialogFunc
  96. !DEC$ ELSE
  97. !DEC$ ATTRIBUTES STDCALL, ALIAS : 'DialogFunc' :: DialogFunc
  98. !DEC$ ENDIF
  99. integer*4 hdWnd
  100. integer*4 mesg  
  101. integer*4 wParam
  102. integer*4 lParam
  103. end function
  104. end interface
  105. !******************************************************************
  106. integer hWnd, mesg, wParam, lParam
  107.    select case ( mesg )
  108.          case(WM_COMMAND)
  109.         select case(LOWORD(wParam))
  110.                   case(IDM_OPEN)
  111.                     hDlg=CreateDialog(hInst, LOC("AboutBox"C),hWnd,LOC(DialogFunc))
  112.       case(IDM_DIALOG)
  113.                     call PostQuitMessage( 0 )
  114.      end select
  115.          case (WM_DESTROY)
  116.                   call PostQuitMessage( 0 )
  117.          case default
  118.                MainWndProc = DefWindowProc( hWnd, mesg, wParam, lParam )
  119.       return
  120.    end select
  121. end
  122. !**********************对话框窗口函数***********************
  123. logical function DialogFunc( hdWnd, mesg, wParam, lParam )
  124. !DEC$ IF DEFINED(_X86_)
  125. !DEC$ ATTRIBUTES STDCALL, ALIAS : '_DialogFunc@16' :: DialogFunc
  126. !DEC$ ELSE
  127. !DEC$ ATTRIBUTES STDCALL, ALIAS : 'DialogFunc' :: DialogFunc
  128. !DEC$ ENDIF
  129. use user32
  130. use dfwin
  131. USE clipinc
  132. use hh
  133. integer hdWnd, mesg, wParam, lParam
  134. integer*4 i
  135. logical logresult,F,T
  136. character*100 string
  137. F=10   !T的值为TRUE
  138. select case (mesg)
  139.     case (WM_COMMAND)
  140.         select case(LOWORD(wParam))
  141.                   case(IDOK)
  142.          logresult=DestroyWindow(hdWnd)
  143.          DialogFunc=T
  144.          RETURN
  145.       case(IDCANCEL)
  146.          logresult=DestroyWindow(hdWnd)
  147.          DialogFunc=T
  148.          RETURN
  149.                   case(IDC_LIST1)
  150.          if(HIWORD(wParam)==LBN_DBLCLK)THEN
  151.       i=SendDlgItemMessage(hdWnd,IDC_LIST1,LB_GETCURSEL,0,0)
  152.       write(string,"('你已经选择了第',I3,'项!')")i
  153.          i=MessageBox(hdWnd,string,"提示框",MB_OK)
  154.       ENDIF
  155.          DialogFunc=T
  156.          RETURN
  157.       case(IDC_SELECT)
  158.          i=SendDlgItemMessage(hdWnd,IDC_LIST1,LB_GETCURSEL,0,0)
  159.       if(i==LB_ERR)THEN
  160.          write(string,"('你没有作出选择!')")
  161.       else
  162.          write(string,"('你已经选择了第',I3,'项!')")i
  163.       endif
  164.          i=MessageBox(hdWnd,string,"提示框",MB_OK)
  165.          DialogFunc=T
  166.          RETURN
  167.       case(IDC_EDITOK)
  168.          i=GetDlgItemText(hdWnd,IDC_EDIT,string,100)
  169.                      i=MessageBox(hdWnd,string,"你输入的内容为:",MB_OK)
  170.          DialogFunc=T
  171.          RETURN         
  172.         end select
  173.     case(WM_INITDIALOG)
  174.   i=SendDlgItemMessage(hdWnd,IDC_LIST1,LB_ADDSTRING,0,LOC("计算机"C))
  175.   i=SendDlgItemMessage(hdWnd,IDC_LIST1,LB_ADDSTRING,0,LOC("物  理"C))
  176.   i=SendDlgItemMessage(hdWnd,IDC_LIST1,LB_ADDSTRING,0,LOC("数  学"C))
  177.   i=SendDlgItemMessage(hdWnd,IDC_LIST1,LB_ADDSTRING,0,LOC("语  文"C))
  178.   i=SendDlgItemMessage(hdWnd,IDC_LIST1,LB_ADDSTRING,0,LOC("英  语"C))
  179.   i=SendDlgItemMessage(hdWnd,IDC_LIST1,LB_ADDSTRING,0,LOC("历  史"C))
  180.   i=SendDlgItemMessage(hdWnd,IDC_LIST1,LB_ADDSTRING,0,LOC("地  理"C))
  181.   i=SendDlgItemMessage(hdWnd,IDC_LIST1,LB_ADDSTRING,0,LOC("生  物"C))
  182.   DialogFunc=T
  183.   RETURN
  184. end select
  185. DialogFunc=F
  186. RETURN
  187. end
复制代码

4.用图形界面库XFT
对于习惯只用fortran编程,不会也没有时间学习VC, VB等进行界面变成的朋友,这里有一个十分好的用fortran编写界面的库XFT,其主页在http://www.xeffort.com/xeffort/home.htm ; 。该库封装了用于界面编程的windows API函数,包括XFTFile(文件处理), XFTGDI(图形设备接口), XFTWND(窗口), XFTReg(注册表), XFTMDI(多文档界面), XFTMenu(菜单), XFTCtrl(控制条), XFTApp(应用程序), XFTDialog(对话框)。所有的程序均为free的,源程序open,有详细的文档。(来自SIMWE)
大概看了一下这一部分,基本上还是API的模式,个人觉得(探讨)。
5.用FORTRAN95的Windows编程接口Winteracter
http://www.winteracter.com
 楼主| 发表于 2015-10-30 22:05 | 显示全部楼层
Winteracter
FORTRAN95的Windows编程接口

Winteracter.doc

54 KB, 下载次数: 0

您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

QQ|小黑屋|Archiver|手机版|联系我们|声振论坛

GMT+8, 2024-5-6 13:34 , Processed in 0.174009 second(s), 21 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表