FORTRAN在DOS下的编程技术相信早以为大家熟悉。有关FORTRAN90方面的书籍也不少见,因此这里不再赘述。以下主要以最新的DVF5.0讲述有关FORTRAN图形编程的方法。
Microsof 公司推出了支持32位的FORTRAN POWER STATION1.0 到FORTRAN POWER STATION4.0编译器后将其卖给了DEC公司。DEC随即推出了DVF5.0(Digital Visual FORTRAN 5.0),其工作环境与MFC5.0完全一致,最近DEC又推出了DVF6.0(Digital Visual FORTRAN 6.0,其工作环境与MFC6.0完全一致。
FORTRAN在DOS下的编程技术相信早以为大家熟悉。有关FORTRAN90方面的书籍也不少见,因此这里不再赘述。以下主要以最新的DVF5.0讲述有关FORTRAN图形编程的方法。
1 DVF 概述
2 QuickWin Application
3 Win32 Application
4 OpenGL
1 DVF概述
1. 1 安装
1) 在安装选项中,注意选择 /Samples,这里包含了DVF的丰富例子。
2) 要拷贝 /Msdn 子目录,这里包含了API及OPENGL函数的帮助。
3) 可以网上下载升级。
1.2 语言
1) 书写格式
● 不受列的限制,可自由书写。
● 注释在任何地方由'!'开始。
● 续行在行尾加'&'。
2) 动态数组
● 优点:动态数组的维界在程序执行过程中随时可按需要变化,数据需要占多少内存,就可在程序中动态地分配给数组多少内存;如果该数组以后不再使用,又可释放该数组,把该数组占用的内存归还给系统另作他用。这样可以节约使用内存,提高内存使用效率。动态数组主程序与子程序。
● 语句:
? 属性说明语句
ALLOCATABLE
? 分配语句
ALLOCATE(数组名1(形状描述),数组名2(形状描述),…[STAT=变量 名])
? 释放语句
DEALLOCATE(动态数组名1,动态数组名2,…[STAT=变量名])
● 例子程序1
REAL(8),ALLOCATABLE::X(:),Y(:),Z(:)
INTEGER(4)::NODE
READ(*,*) NODE
ALLOCATE (X(1:NODE),Y(1:NODE),Z(1:NODE))
DO I=1,NODE
X(I)=1.0
Y(I)=1.0
Z(I)=I
END DO
DO I=1,NODE
WRITE(*,*) X(I),Y(I),Z(I)
END DO
DEALLOCATE(X,Y,Z)
END
3) 模块
● 优点:模块是一种在主程序单元之外独立编写的程序单元。模块程序单元内没有可执行语句,除了说明语句外,最多包含模块过程。主要作用是供其他程序单元引用,即数据的共享与模块过程的复制。包含了COMMON与INCLUDE的全部功能。
● 语句:
a 模块的编写
MODULE 模块名
类型说明部分
[CONTAINS]
[模块过程1]
…
[模块过程N]
END MODULE [模块名]
b 模块的引用
USE 模块1,模块2,…,模块n
● 例子程序2:
! 模块***************************************
MODULE MYDATA
INTEGER NODE,NEL
END MODULE MYDATA
!*******************************************
!主程序*************************************
USE MYDATA
NODE=100
NEL=90
WRITE(*,*)"IN MAIN PROGRAM :"
WRITE(*,*)"NODE=",NODE
WRITE(*,*)"NEL=",NEL
CALL SUBPROGRAM()
END
!*******************************************
!子程序*************************************
SUBROUTINE SUBPROGRAM()
USE MYDATA
WRITE(*,*)"IN SUBPROGRAM :"
WRITE(*,*)"NODE=",NODE
WRITE(*,*)"NEL=",NEL
END SUBROUTINE
!*******************************************
1.2 开发环境
1) 建立新文件、新项目
● "File" → "New" → "Files"
文件类型:
a 固定格式
b 自由格式
● "File" → "New" → "Projects"
项目类型:
a Win32 Console Application:
基于命令行的程序(字符界面)。
b Standard Graphics Application:
单窗口单任务绘图应用程序,易学易用。
c Quick Win Application
多窗口单任务绘图应用程序,易学易用。
d Win32 Application
多窗口多任务应用程序,有固定的程序结构,复杂难学。
2) 建立资源文件
● "Insert" → "Resource"
资源文件类型:
a 加速键
b 对话框
c 图象
d 菜单
2 Quick Win Application
2.1 画图
1) 例子程序3
SUBROUTINE PLOT_JU()
USE DFLIB
TYPE (XYCOORD) POS
OPEN(8,FILE='USER',TITLE='矩形')
I=SETBKCOLOR(3)
CALL CLEARSCREEN($GCLEARSCREEN)
I=SETCOLORRGB(#FFFFFF)
I=RECTANGLE($GFILLINTERIOR,100,100,300,300)
END
2) 注意点:
● 必需包含DFLIB库。
● 子窗口用 OPEN(窗口号,FILE='USER') 打开。
● 用QuickWin编写的绘图程序不能被Win32 Application引用。
2.2 菜单
1) 编辑菜单
2) 菜单的应用
例子程序4
LOGICAL(4) FUNCTION INITIALSETTINGS()
USE DFLIB
LOGICAL(4) RESULT
EXTERNAL PLOT_TYPE
RESULT=APPENDMENUQQ(1,$MENUENABLED,'画图(&P)'C,PLOT_TYPE)
INITIALSETTINGS=.TRUE.
END FUNCTION INITIALSETTINGS
2.3 对话框
1) 编辑对话框
2) 对话框的应用
例子程序5
SUBROUTINE PLOT_TYPE(L)
USE DIALOGM
IMPLICIT NONE
INCLUDE 'RESOURCE.FD'
LOGICAL RET,L
TYPE(DIALOG)DLG
EXTERNAL PLOT
RET=DLGINIT(IDD_PLOT_TYPE,DLG)
RET=DLGSET(DLG,IDC_PLOT_S1,'图形类型:')
RET=DLGSET(DLG,IDC_PLOT_L1,2,DLG_NUMITEMS)
RET=DLGSET(DLG,IDC_PLOT_L1,'矩形'C,1)
RET=DLGSET(DLG,IDC_PLOT_L1,'圆'C,2)
RET=DLGSETSUB(DLG,IDOK,PLOT)
RET=DLGMODAL(DLG)
CALL DLGUNINIT(DLG)
RETURN
END SUBROUTINE
SUBROUTINE PLOT(DLG,CONTROL_NAME,CALLBACKTYPE )
USE DFLOGM
INCLUDE 'RESOURCE.FD'
TYPE (DIALOG) DLG
INTEGER CONTROL_NAME,CALLBACKTYPE,LOCAL_CALLBACKTYPE
INTEGER VALUE
LOGICAL RET
LOCAL_CALLBACKTYPE = CALLBACKTYPE
RET=DLGGET(DLG,IDC_PLOT_L1,VALUE,1)
SELECT CASE (VALUE)
CASE(1)
CALL PLOT_JU()
CASE(2)
CALL PLOT_YUAN()
CASE DEFAULT
END SELECT
CALL DLGEXIT(DLG)
END SUBROUTINE
3 Win32 Application
3.1 概念
1) 窗口
是Windows应用程序基本的操作单元,是应用程序与用户之间交互的接口环境,也是系统管理应用程序的基本单位。
2) 事件驱动
Windows程序设计围绕事件或消息的产生驱动运行处理函数。
3) 消息
Windows应用程序通过发送和接收统一格式的消息与其他应用程序和Windows系统进行信息交换。
4) 对象与句柄
Windows系统通过句柄标识不同的对象和同类对象中不同的实例。
3.2 程序结构
1) WinMain函数
● WinMain函数是应用程序的入口函数,其功能是完成一系列的定义和初始 化工作,并产生消息循环。
● 例子程序6
2) 窗口函数
● 定义了应用程序对接收到的不同消息的响应,是消息处理分支控制语句的 集合。
● 例子程序7
3.3 菜单
例子程序8
3.4 对话框
例子程序9
INTEGER*4 FUNCTION FILE_INPUT(HWND, MESSAGE, WPARAM, LPARAM)
!DEC$ IF DEFINED(_X86_)
!DEC$ ATTRIBUTES STDCALL, ALIAS : '_FILE_INPUT@16' ::FILE_INPUT
!DEC$ ELSE
!DEC$ ATTRIBUTES STDCALL, ALIAS : 'FILE_INPUT' ::FILE_INPUT
!DEC$ ENDIF
USE DFWINA
USE MYDATA
INTEGER*4 HWND, MESSAGE, WPARAM, LPARAM,H
LOGICAL BRET
CHARACTER*30 STR
SELECT CASE (MESSAGE)
CASE (WM_INITDIALOG)
STR='对话框实例'
H=GETDLGITEM(HWND,1201)
I=SENDMESSAGE(H,CB_ADDSTRING ,0,LOC(STR(1:10)))
RETURN
CASE (WM_COMMAND)
SELECT CASE (LOWORD(WPARAM))
CASE (IDCANCEL)
I = ENDDIALOG (HWND, 1)
FILE_INPUT=TRUE
RETURN
CASE (IDOK)
I = ENDDIALOG (HWND, 1)
FILE_INPUT=TRUE
RETURN
END SELECT
END SELECT
FILE_INPUT= FALSE
RETURN
END
3.5 GDI绘图
例子程序10
SUBROUTINE PLOT(HDC)
USE DFWINA
USE MYDATA
USE DFWIN
INTEGER HDC,HFONT
LOGICAL BRET
ID_PLOT=1
IF (PLOT_TYPE==1) THEN
BRET= SELECTOBJECT(HDC, HPEN(1))
BRET=ARC(HDC,300,200,700,600,300,200,300,200)
BRET=SETTEXTCOLOR(HDC,RGB(0,0,0))
BRET=SETBKCOLOR(HDC,RGB(255,255,255))
H=65
LINE_W=50
CALL FONT(H,LINE_W,HFONT)
BRET=SELECTOBJECT(HDC,HFONT)
BRET=TEXTOUT(HDC,320,400,'GDI画图例子1',12)
BRET=DELETEOBJECT(HFONT)
ELSE
BRET= SELECTOBJECT(HDC, HPEN(2))
BRET=ARC(HDC,300,200,700,600,300,200,300,200)
BRET=SETTEXTCOLOR(HDC,RGB(255,100,0))
BRET=SETBKCOLOR(HDC,RGB(255,255,255))
H=65
LINE_W=50
CALL FONT(H,LINE_W,HFONT)
BRET=SELECTOBJECT(HDC,HFONT)
BRET=TEXTOUT(HDC,320,400,'GDI画图例子2',12)
BRET=DELETEOBJECT(HFONT)
END IF
END SUBROUTINE
SUBROUTINE FONT(H,LINE_W,HFONT)
USE DFWINA
INTEGER HFONT
HFONT=CREATEFONT(H,0,0,0,LINE_W,0,0,0,ANSI_CHARSET, &
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, &
DEFAULT_PITCHIFF_DONTCARE,"大号字")
END
SUBROUTINE PEN()
USE DFWINA
USE MYDATA
HPEN(1)=CREATEPEN(PS_SOLID,7,RGB(255,0,0))
HPEN(2)=CREATEPEN(PS_SOLOD,7,RGB(0,255,0))
END
3.6 未解决的问题
● 工具栏的使用。
4 三维计算机图形库OpenGL
4.1 概述
1) Quick Win、GDI、OpenGL 比较
Quick Win GDI OpenGL
类型 平面 平面 三维
速度 慢 慢 快
程度 简单 较复杂 复杂
2) 注意点
● QuickWin Application和 Win32 Application都能用OpenGL绘图。
● 要连接 opengl32.lib glu32.lib glaux.lib 。
3) 编写OpenGL程序的基本步骤
建模→设置视点→设置光照→绘制场景→屏幕窗口
4.2 OpenGL 实现的功能
● 基本几何要素。
例子程序11
………………………….
………………………….
integer ret
CALL READDATA()
call fauxinitdisplaymode(IOR(IOR(AUX_SINGLE,AUX_INDEX),AUX_DEPTH))
call fauxinitposition(0,0,700,700)
ret=fauxinitwindow("曲面"c)
call myinit()
call fauxreshapefunc(LOC(myreshape))
call fauxmainloop(loc(display))
end
!***************************************************************************
subroutine myreshape(w,h)!重新计算 模型,取景变换,投影变换
!DEC$ IF DEFINED(_X86_)
!DEC$ ATTRIBUTES STDCALL, ALIAS : '_myReshape@8' :: myReshape
!DEC$ ELSE
!DEC$ ATTRIBUTES STDCALL, ALIAS : 'myReshape' :: myReshape
!DEC$ ENDIF
use dfopngl
use mydata
integer(4) w,h
call fglViewPort(0, 0, W,H)
call fglmatrixmode(GL_PROJECTION)
call fglloadidentity()
callfgluperspective(BIAO_APH+10.,DBLE(w)/DBLE(h),BIAO_S- BIAO_R*1.01,BIAO_S+BIAO_R)
call fglmatrixmode(GL_MODELVIEW)
call fglloadidentity()
CALL FGLTRANSLATEF(X_EYE,Y_EYE,Z_EYE)
end subroutine
!*****************************************************************************
subroutine myinit()!明暗处理方式
!DEC$ IF DEFINED(_X86_)
!DEC$ ATTRIBUTES STDCALL, ALIAS : '_myinit@0' :: myinit
!DEC$ ELSE
!DEC$ ATTRIBUTES STDCALL, ALIAS : 'myinit' :: myinit
!DEC$ ENDIF
use dfopngl
use mydata
A=252./255.
B=22./255.
C=16./255.
CALL FAUXSETONECOLOR(30,A,B,C)
…………………
CALL FAUXSETONECOLOR(59,A,B,C)
CALL FGLCLEARINDEX(REAL(29))
CALL FGLSHADEMODEL(GL_SMOOTH)
call fgldepthfunc(GL_LEQUAL)
call fglenable(GL_DEPTH_TEST)
CALL FGLDISABLE(GL_DITHER)
end subroutine
!****************************************************************************
subroutine display()
!DEC$ IF DEFINED(_X86_)
!DEC$ ATTRIBUTES STDCALL, ALIAS : '_display@0' :: display
!DEC$ ELSE
!DEC$ ATTRIBUTES STDCALL, ALIAS : 'display' :: display
!DEC$ ENDIF
use dfopngl
use mydata
external drawmyobjects
call fglclear(GL_COLOR_BUFFER_BIT)!清除视见区的缓冲区
call fglclear(GL_DEPTH_BUFFER_BIT)
call fglRotatef(-55, 1.0, 0.0, 0.0)
call fglRotatef(-45, 0.0, 0.0, 1.0)
call drawmyobjects()
CALL FGLEND()
end subroutine
!***************************************************************************
subroutine drawmyobjects()
use dfopngl
use mydata
DO I=1,NODE
call fglbegin(GL_POLYGON)
CALL FGLINDEXI(59-(Z_NODE(1,I)+400)/30.-2)
call fglvertex3f(x_NODE(1,I),y_NODE(1,I),z_NODE(1,I))
CALL FGLINDEXI(59-(Z_NODE(2,I)+400)/30.-2)
call fglvertex3f(x_NODE(2,I),y_NODE(2,I),z_NODE(2,I))
CALL FGLINDEXI(59-(Z_NODE(3,I)+400)/30.-2)
call fglvertex3f(x_NODE(3,I),y_NODE(3,I),z_NODE(3,I))
CALL FGLINDEXI(59-(Z_NODE(4,I)+400)/30.-2)
call fglvertex3f(x_NODE(4,I),y_NODE(4,I),z_NODE(4,I))
call fglend()
END DO
end subroutine
● 材质、光照处理。
例子程序12
………………………
………………………
real(4):: ambient(4)
real(4):: diffuse(4)
real(4):: position(4)
real(4):: mat_ambient1(4)
real(4):: mat_diffuse1(4)
REAL(4)::SPOT_DIR(3)
data ambient/0.0,0.0,0.0,1.0/
data diffuse/1.0,1.0,1.0,1.0/
data position/-30.,30.0,30.,1.0/
data mat_ambient1/0.0,0.5,1.0,1.0/
data mat_diffuse1/0.0,0.5,1.0,1.0/
DATA SPOT_DIR/1.0,-1.0,-1.0/
call fglenable(GL_DEPTH_TEST)
call fgldepthfunc(GL_LESS)
call fgllightfv(GL_LIGHT0,GL_AMBIENT,loc(ambient))
call fgllightfv(GL_LIGHT0,GL_DIFFUSE,loc(diffuse))
call fgllightfv(GL_LIGHT0,GL_POSITION,loc(position))
CALL FGLLIGHTF(GL_LIGHT0,GL_SPOT_CUTOFF,APHADD)
CALL FGLLIGHTFV(GL_LIGHT0,GL_SPOT_DIRECTION,LOC(SPOT_DIR))
call fglenable(GL_LIGHTING)
call fglenable(GL_LIGHT0)
call fglmaterialfv(GL_FRONT,GL_AMBIENT,loc(mat_AMBIENT1))
call fglmaterialfv(GL_FRONT,GL_DIFFUSE,loc(mat_diffuse1))
……………………..
…………………….
● 混合、反走样。
● 纹理。
…………………………………..
…………………………………..
CALL FGLTEXIMAGE2D(GL_TEXTURE_2D,0,3,4,4,&
0,GL_RGB,GL_UNSIGNED_BYTE,LOC(CHE))
CALL FGLTEXPARAMETERF(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT)
CALL FGLTEXPARAMETERF(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT)
CALL FGLTEXPARAMETERF(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_linear)
CALL FGLTEXPARAMETERF(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_linear)
CALL FGLTEXENVF(GL_TEYTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL)
CALL FGLENABLE(GL_TEXTURE_2D)
…………………………..
…………………………..
CALL FGLTEXCOORD2F(0.0,0.0);CALL FGLVERTEX2F(-2.0,-1.0)
CALL FGLTEXCOORD2F(0.0,2.);CALL FGLVERTEX2F(-2.0,1.0)
CALL FGLTEXCOORD2F(2.,2.);CALL FGLVERTEX2F(0.0,1.0)
CALL FGLTEXCOORD2F(2.,0.0);CALL FGLVERTEX2F(0.0,-1.0)
…………………………..
……………………………..
● 选择与反馈。
4.3 未解决的问题
● 图形的打印。
● 写汉字。