f92c68ee9ba765b401d89089616d40ad.ppt
- Количество слайдов: 111
IDL 高级培训 基础篇
基础篇 -语法基础 1. 变量及其属性 • 整型为短整型,注意使用L • 变量的属性是动态改变的 var=5 为整型 var=var*2. 0 变为浮点 • Na. N:!VALUES. F_NAN、!VALUES. D_NAN var=!VALUES. F_NAN,则finite(var)=1
基础篇 -语法基础 2. 数组 IDL是面向矩阵的语言,几乎所有运算都可以在数组上使用。 数组表达:array[n, m] 表示n列m行(与其他语言有别),按行排列, 0为下标起点 数组引用:array[subscript],或(array)[subscript] 下标语法:e、e 0: e 1、e: *、*、array。 array=make_array(10, /integer),sub=indgen(12) 合法的下标表示:array[5, 5]、array[2: 3, 5]、array[*, 4]、array[*, 5: 8]、array[4, 4: *]、 array[sub]、A[[1, 3, 5], 7: 9] reform():array[4, 4: *]为 1列 4行(列向量),reform(array[4, 4: *])则为 4列 1行(行向量) 常数的数组表示:var=5,则var[0]=5(合法!) 赋值:array[[2, 4, 6], 5]=[4, 16, 36] where():array[where(array lt 0)]=-999 数学运算:与普通变量基本相同。 * 和 / :表示两个同维数数组对应元素运算 arr 1=indgen(5)+1,arr 2=arr 1。则:arr 1*arr 2=[1, 4, 9, 16, 25],arr 1/arr 2=[1, 1, 1, 1] # 和 ##:矩阵运算 arr 1(n 1, m)#arr 2(m, n 2)=arr(n 1, n 2),arr 1(n, m 1)##arr 2(m 2, n)=arr(m 2, m 1) 数组串连:arr 1(5, 6),arr 2(5, 2)。则:arr 3=[[arr 1], [arr 2]]为(5, 8) 注意: arr 3=[arr 1, arr 2]不合法!(一维除外)
基础篇 -语法基础 数组常用函数: 其他常用函数:array_equal、rebin()、congrid()、expand()、reverse()
基础篇 -语法基础 3. 结构 一种复合变量,它可以将多种类型的数据存储在一个变量中,对于表示意义相关的数据、程序间 交换数据均非常有意义。 类型及定义 命名结构:dot={PIXEL , x: 128 , y: 236 , color: bytarr(3)},定义后可使用FIXEL定义其他结构 dot 1={PIXEL , x: 58 , y: 46 , color: [255, 0, 255]}、 dot 2={PIXEL , 58 , 46 , [255, 0, 255]}、dot 3= {PIXEL} 匿名结构:person={name: ’jack’ , id: 123456 L},定义后无固定结构,可任意改变 person={name: ’jack’ , id: 123456 L , phone: ’ 123 -4567’} 引用 变量引用:使用变量名或变量在结构中的位置索引。如:dot. x或dot. (0) 数组变量:s={arr: indgen(10)},则s. arr=10将数组所有元素赋值为 10。 结构数组 定义:dotarr=replicate({PIXEL} , 10),或dotarr=replicate(dot , 10) 引用:dotarr[1]. x=10、dotarr. x=10将所有结构的x赋值为 10、dotarr. y=indgen(10) 结构中的变量的类型和(数组)大小 结构定义后,各变量的数据类型以及数组变量的维数均不可改变。当使用中出现不一致时向原类 型转换,不能转换时报错。 var=dot. x*1. 0=128. 0,为浮点,而dot. x=dot仍为整型。 s. arr=-indgen(8)会改变s. arr中前8个元素的值,而s. arr=-indgen(11)会出错。 结构继承 dot 3 d={POINT , INHERITS PIXEL , z: 0} 常用函数 creat_struct()、n_tags()、tag_names()、struct_assign()
基础篇 -语法基础 4. 指针 建立动态数据结构的有效 具,是实现IDL面向对象编程和Widget编程的基本要素之一。 IDL 的指针与其他语言的指针有很大的不同,它不是指向存储的地址而仅仅是一个轻型的指向一 个堆变量的引用(指针变量)。堆变量可以动态分配(数据类型和数组维数),这意味着传递指针 变量就相当于传递动态数据。 Pointer Reference Pointer in Heap Variables Pointer Data • 标量 • 数组 • 结构 指针基本操作 创建:ptr=ptr_new( [initexpr] [, /allocate_heap] [, /no_copy] ) 释放:ptr_free , ptr
基础篇 -语法基础 标量指针 创建:v=5. 5,p=ptr_new(v) 引用:print , p , *p;p 1=p,*p 1=20,print , *p 数组指针 创建:arr=findgen(10),p=ptr_new(arr) 引用:print , (*p)[5] 结构指针 创建:s={name: ’joe’ , age: 40 , height: 180} ,p=ptr_new(s) 引用:print , (*p). name 结构内指针 创建:rec={lon: 120 , lat: 20 , data: ptr_new(findgen(2, 10))} ,p=ptr_new(rec) 引用:* (*p). data=findgen(2, 20) 特殊指针 Null指针:nptr=ptr_new(),仅定义一个指针,并不指向一个堆变量。引用时需重新定义指针。 Empty指针:eptr=ptr_new(/allocate_heap),定义一个指向一个堆变量的指针,但并未定义变 量,引用时可以直接定义变量 指针释放 ptr_free , ptr 相关函数 ptr_valid():ptr_valid(nptr)=0, ptr_valid(eptr)=1 heap_gc:释放没有引用的堆变量 指针数组 ptrarr( d 1, . . . , d 8 [, /allocate_heap] )
基础篇 -编程基础 IDLDE是IDL的集成开发环境,可以使用IDL命令进行交互式命令运行,编写、调试、运行IDL程 序,使用GUI Builer开发用户界面,使用项目管理器管理 程项目等。 1. IDL程序 批处理:由一系列IDL命令组成,以IDL->@batchfile方式运行。批处理文件运行时并不编译,因 此使用控制结构时必须大量使用续行符($), 给书写、理解造成困难。 主程序:与批处理相似,但以end结束,以IDL->. run profile方式运行。主程序运行时先编译,因 此可以正常使用控制结构。 过程:与主程序相似,但以pro proname开始,以end结束。以IDL->proname方式运行(也可以 先运行IDL->. compile proname,编译但不运行)。 函数:与过程相似,但以function fnname开始,以end结束,并以return语句返回一个IDL变量。 以IDL->ret=fnname(para_list)方式运行。 在IDL系统中,一个过程或函数即为一个新的IDL命令。 变量作用范围:批处理和主程序方式的变量为全局变量,可以在IDL开发环境中使用。过程和函数 的变量为局部变量,只在过程和函数运行过程中有效。
基础篇 -编程基础 2. 参数传递 位置参数:在参数列表中按位置列出参数名,严格的顺序限制。通常用于必选参数。 定义:pro batch , para 1 , para 2 , . . . 调用:IDL->batch , para 1 , para 2 , … 关键字参数:关键字参数与位置无关,且可以与位置参数混合位置。通常放在位置参数之后,用 于可选参数。 定义:pro batch , keywordname=keywordsymbol , . . . 调用:IDL->batch , keywordname=keywordsymbol , … IDL->batch , /keywordname 注意:keywordname用于定义,keywordsymbol用于调用。 引用传递和值传递:所有变量为引用传递,其值会被修改。系统变量、下标变量、表达式和常量 均为值传递,原变量的值不被修改。 参数传递了吗?传递了什么? n_params():返回位置参数的个数 keyword_set():关键字参数为不为 0常量或已定义的引用传递时返回 1,否则返回 0 arg_present():关键字参数为引用传递时返回 1(无论是否定义),否则返回 0 n_elements():关键字参数未传递或未定义返回 0,否则返回非 0数
基础篇 -编程基础 3. 错误处理 on_ioerror:当出现I/O错误时,跳转指定的语句。两种用途:跳过错误返回或跳过错误继续。 注意:使用on_ioerror ,null on_error:当程序运行出错时,并不执行一个新的语句,而是指明IDL应该怎样做。 可以设置on_error , 1,或在命令行使用retall catch:格式:catch , error_var。当程序执行到catch语句时,IDL为改模块记录一个错误处理语句, 并将error_var赋值为 0。若程序执行出错,则给error_var赋值相应的错误码,然后跳转到catch后第 一条语句。注意:使用catch , /cancel
基础篇 -编程基础 IDL出错处理示意 Error or Exception is Generated Is it an I/O error? Yes No Is ON_IOERROR routine in use? No Yes Is there an error handler defined by the CATCH routine? Yes Handle error with CATCH-defined error handler and continue program execution. No Handle error as indicated by setting of ON_ERROR routine or use default error handling. Handle error as indicated by ON_IOERROR setting.
基础篇 -编程基础 4. 编译与运行 批处理:@bacthfile,运行 主程序:. run,编译、运行 过程和函数:. compile,编译;->proname,编译、运行。 编译规则:(1)编译到主程序后,编译停止 (2)编译到与文件同名的程序模块时,停止编译 (3)编译到文件末尾或适合其他规则时,停止编译 自动编译规则:当过程或函数出现在命令或代码中时,会自动被编译执行。 (1)过程或函数所在的文件应在当前 作路径和 !Path指定的路径中 (2)过程或函数名与文件名相同 编译函数:resolve_routine、resove_all。可用于程序模块中。. sav:IDL->save,编译后存储为. sav文件,便于发布。但版本间不兼容。
基础篇 -输入输出 1. 常用概念 文件操作:openr,openw,openu,close 逻辑设备号: 1~ 99,直接使用 100~ 128,使用get_lun获取,free_lun释放 常用函数:dilog_pickfile,findfile,filepath 2. 文本文件的格式处理 自由格式:readf,printf,strsplit readf中只接收变量引用,不接收值引用 format语法:format=‘()’,括号内为格式符及其组合 A:[n]a[w],n为重复次数,w为输出宽度 I:[n]i[w]或[n]I[w. m],缺省w=7,特殊用法:i 0 F:[n]f[w. d],缺省w=15 X:[n]X,空格 /:换行符 : :其后的格式不用于最后一项。如每个输出项后加一个‘,’时,最后一项不加。 C:c(),表示日期,接受julian日期。有丰富的子集
基础篇 -输入输出 3. 二进制文件的关连变量处理 基本命令:readu,writeu 关联变量:大型重复单元二进制文件的有效读取手段,可以随机读取。 一个文件可建立多个关联,解决重复单元不一致的情况。 assoc():result=assoc(unit, array_structure [, offset] [, /packed]) 4. 使用与机器无关的数据格式
IDL 高级培训 直接图形篇
直接图形篇 -色彩控制 1. 基本概念 颜色构成:(r, g, b), 每个颜色值在 0~255之间,所以IDL可以表现 256*256种颜色 颜色表:一个颜色表由一个 3列的数组构成,各列分别表示r、g、b值,通常 256行。 索引号:颜色表中的索引位置。可以用来获得颜色的r、g、b值 8位显示器和24位显示器: 8位显示器只能显示 256色,24位则可以显示 256*256色 2. 索引颜色模式和RGB颜色模式 索引颜色模式:通过颜色表的索引号获得颜色的r、g、b值,用于8位显示器。 RGB颜色模式:直接指定颜色的r、g、b值,用于24位显示器。IDL使用一个长整数表示 所有颜色的索引号,c=r+g*256 L+b*256 L。 3. 动态显示和静态显示 动态显示:索引模式将索引号与颜色表中的特定位置连接,称为动态颜色显示。改变颜 色表会影响当前索引号所对应的颜色。通常,8位显示是动态显示 静态显示:RGB模式直接指定颜色本身,称为静态颜色显示。通常 24位显示是静态显示。
直接图形篇 -色彩控制 4. device , decomposed=0|1 decomposed=0:关闭颜色分解,使用索引颜色模式。适用于8位显示和24位显示,但 24位时仍是静态显示。此时,可以使用IDL预设的41个颜色表。 decomposed=1:IDL缺省模式,打开颜色分解,使用RGB颜色模式。只适用于24位显 示。此时,只能使用长整数的全索引。 5. tvlct , r , g , b [, start] [, /get] :(RGB模式) tvlct , r , g , b , /get可以获取当前的颜色表。 tvlct , r , g , b , start可以加载一个颜色表到start指定的入口处。 6. loadct , table 加载IDL预设的41各颜色表之一 7. 创建自己的颜色表 根据颜色表的原理,可以很容易地创建一个 3*n数组作为自己的颜色表,用tvlct加载使用。
直接图形篇 -坐标系 data:数据单位(缺省) dvice:像素单位 normal:归一化坐标,x: 0~1,y: 0~1 一般来说,在输出图形时,3个坐标系同时存在并都可以使用。 例:对于一个一维数组,在未指定坐标系时,IDL会把数组的下标值作为data坐标系 下x轴的值,数组的值作为y值画出曲线。
直接图形篇 -2 D图形 创建自己的标注
直接图形篇 -2 D图形 多坐标系数据集显示
直接图形篇 -2 D图形 画真正的圆
直接图形篇 - 2 D图形 在背景上叠加等值线
直接图形篇 - 2 D图形 等值线图填充中的“黑洞”
直接图形篇 - 添加文本 给图形加文本标注 xyouts , x , y , string , font= True. Type字体设置: (1)DEVICE , SET_FONT=font_str , /TT_FONT , 输出时,使用font=-1|0|1 (2)font=fnont_str Windows环境下True. Type字体设置: font_str='font*modifier 1*modifier 2*. . . modifiern’ • For font weight: THIN, LIGHT, BOLD, HEAVY • For font quality: DRAFT, PROOF • For font pitch: FIXED, VARIABLE • For font angle: ITALIC • For strikeout text: STRIKEOUT • For underlined text: UNDERLINE 注意:并非所有选项在两种方式下均合法!
直接图形篇 -添加文本 使用汉字:font_str=“中文True. Type字体名称” device , set_font=‘隶书’ , /tt_font xyouts , x , y , ‘ ’ , font=1 使自己的字体成为IDL的系统字体:编辑 RSIIDL 54resourcefontsttttfont. map
直接图形篇 - 3 D图形 建立三维坐标系 IDL使用变换矩阵与三维空间的点相乘,实现在二维显示上模拟三维坐标系。该变换 矩阵装入!P. T。实现时,先装入正确的变换矩阵,然后在图形显示前,保证图形命令已 经被变换矩阵乘过。 常用方法:(1)带save关键字的surface命令 surface , data , /nodata , /save (2)在surface后,使用surfr命令 surface , data surfr (3)scale 3命令(scale 3 d:单位立方体) scale 3 [, xrange=vector] [, yrange=vector] [, zrange=vector] [, ax=degrees] [, az=degrees] (4)t 3 d命令 严格、完整、复杂的方法
直接图形篇 - 3 D图形 三维散点图
直接图形篇 - 3 D图形 曲面图 阴影曲面图 图中色彩变化表示光源的方向
直接图形篇 - 3 D图形 用颜色表现另一个数据集的信息 上图为属性数据集 右上、下图为用颜色表示的属性分布信息
直接图形篇 - 3 D图形 用彩色图形叠加表现另一个数据集的信息 左图为属性数据集 右图为用叠加在阴影曲面上的彩色曲面表示属性分布信息
直接图形篇 - 3 D图形 等值线叠加
直接图形篇 - 3 D图形 三维实体创建: shade_volume, value, vertex, polygons scale 3 image=polyshade( vertex, polygons) tv, image
直接图形篇 - 图形定位: !p. region=[x 0, x 1, y 0, y 1](归一化坐标) !p. position=[x 0, x 1, y 0, y 1](归一化坐标) !x|y|z. margin=[p 1, p 2](字符个数,会随charsize改变) 多数图形命令中都带有margin和position关键字,优先级较!变量高 图形位置: 指被坐标轴包围的区域 可以使用!X|Y|Z. margin、 !p. position设置 图形区域 包括图形标题其它注释的区域 可以使用!P. region设置 图形边缘
直接图形篇 - 图形组合显示 如何在一个窗口里显示多个具有不同坐标系的图形? (1)position=[x 0, y 0, x 1, y 1] (2)!Multi=[p 1, p 2, p 3, p 4, p 5] p 1:页面上剩余的部分的数目。通常为 0,表示擦除窗口开始输出 p 2:页面上图形的列数 p 3:页面上图形的行数 p 4:页面上Z方向上叠加的数目 p 5: 0,按行显示; 1,按列显示
直接图形篇 - 图形组合显示 !Y. omargin=[0, 4] !p. multi=[0, 2, 2, 0, 0]
直接图形篇 - 图形组合显示 !Y. omargin=[0, 4] !p. multi=[0, 2, 2, 0, 0]. . . !p. multi=[1, 1, 2, 0, 0]
直接图形篇 - 图形文件读写 作为一个数据分析和可视化的 具,IDL支持大量的图形格式。包括:bmp,geo tiff,interfile, jpeg,pict,png,ppm,srf,tiff,x 11 bitmap,xwd。但从v 5. 4起,不再支持gif。 PNG格式:支持最多 4个通道的8位或 16位数据 单通道数据时,支持调色板 wirte_png , filename , image , [r, g, b]:将图形数据写入PNG文件 其中:(1)如果image为 2维数组,并且提供r、g、b值,则转换为byte以 8位数据写入,否则转 换为 16位无符号整数。 (2)对单通道数据, r、g、b值必须提供,对多通道数据, r、g、b值被忽略 ok=query_png(filename , s):获取PNG文件的属性。 其中:ok=0,不是合法的PNG文件。 s为一个结构,包含PNG文件的属性。若s. has_palette=1,为单通道数据,否则为多通道 数据。 image=read_png(filename [, r, g, b]):读出PNG文件的数据 其中:r, g, b对单通道数据,读出调色板, 否则忽略。 常见用法:write_png , filename , tvrd(true=1) (作为 3通道数据写入) ok=query_png(filename , s). . image=read_png(filename) tv image , /true
直接图形篇 - 图像处理 图像:任何一个二维数组都可以视为一幅图像。 8位图像:总表示为一个二维数组。 24位(真彩色)图像:总表示为一个 3维数组,其中一维为 3。 m*n*3:隔波段扫描(band-interleaved ,true=3) m*3*n:隔行扫描( row-interleaved ,true=2) 3*m*n:隔象素扫描( pixel-interleaved,true=1) 在 8位显示设备上,所有数据要转换位字节类型;在 24位显示设备上,24位图像的r、 g、b值必须转换位字节类型。
直接图形篇 - 图像处理 1. 基本操作 显示:tv和tvscl。两个命令几乎一样,包括可以使用的关键字。都不删除当前窗 口的内容。 tvscl:将图像数据调整为与运行时刻所有可用颜色数目相同的字节数据。通常 用于8位图像 tv:取图像数据本身,作为字节数据显示。如果图像数据以整形和更多位数表示, 则被截断以适合字节类型。因此,图形可能会显示不正确。 在 24位设备上显示图像一般方法: device , decomposed=0 [loadct , ct] tv/tvscl , image(8位图像) tv , image , true=1|2|3(24位图像))
直接图形篇 - 图像处理 2. 调整数据为字节类型并可以使用统一的颜色集 bytscl(image , min= , max= , top=) 如:scale. Image=bytscl(image , min=5 , max=30) 3. 改变图像尺寸 IDL提供了两个改变图像大小的命令:rebin和congrid rebin:新建的图象的大小必须是原始尺寸的整数比例。缺省放大时采用双线性插 值,缩小时采用邻近平均法。sample关键字指定最近邻近采样法。 congrid:新建的图象的大小可以是原始尺寸的任意比例。缺省对三维以下数据采 用最近邻近采样法,三维采用线性插值法。interp关键字指定线性插值法 4. 在窗口中定位图像 (1) tv , image , index:根据图像尺寸,从窗口左上角开始计算位置,逐行至右下角。 (2) tv , image , x , y:指定左下角开始计算的坐标(devic|data|normal)。 利用!d. x_vsize和!d. y_vsize(象素值)计算归一化坐标以确定图像位置和大小。 5. 从窗口中读取图像 8位显示:image=tvrd() 24位显示:image=tvrd(true=1) tvrd命令支持读取指定区域的图像
直接图形篇 - 图像处理 6. 基本图像处理 上图:原始图 中图:hist_equal函数 下图:adapt_hist_equal函数 直方图均衡化:观察图像 中的象素值分布,往往会发 现象素值分布趋于一个较狭 窄的数值范围内。如果将象 素值分散开,使象素值得每 个子范围都有与这些象素值 大约相同的象素,则该图像 的信息内容有可能增加。将 象素分布道整个颜色范围的 过程称为直方图均衡化。
直接图形篇 - 图像处理 负片:将原始图像的显示色板翻转,象素的字节值不变所得到的图像。
直接图形篇 - 图像处理 消除噪声:噪声来自多方面,影响对图像质量。噪声的一般表现形式是随机的具有 极端值的象素(黑白噪声)。 median:计算相邻象素的中间值。这样既可以消除极端值,又不会使大于邻域的部 分图像边缘或特征模糊。
直接图形篇 - 图像处理 平滑:通过将每个象素值与它周 围相邻象素值进行平均来平滑图像。 称为均值或核状平滑。 smooth:在给定的奇数宽度的 范围内通过等加权值实现平滑。 convol:使用给定的方形滤波核 通过卷积实现平滑。 晕光蒙片:将原始图像减去平滑 后的图像。可以定位图像上的边缘 或象素值突然变化的地方 上图:smooth,w=5 中图:smooth,w=3 下图:convol,k=1, 2, 1 2, 8, 2 1, 2, 1
直接图形篇 - 图像处理 边缘增强:通过锐化或微分以增强边缘。 roberts: sobel: convol:使用给定的方形滤波核通过卷积实现。 右图:原始图像 下图:自左至右依次为roberts、sobel、convol
直接图形篇 - 图像处理 7. 频域滤波是图像 和信号处理的常规手段。可以用于平滑图像、锐化图像、降低图像 的模糊程度和恢复图像。 基本步骤:(1)用快速傅立叶变换(FFT)将图像从空间域转换为频率域 (2)将转换后的图像与一个频率滤波器相乘 (3)将滤波后的图像逆变换转换为空间域 方法:filtered_img=fft(img, -1)*filter , 1) img可以是一维矢量,也可以是二维图像 filter为滤波器,用于滤波图像中某些特定频率的一维矢量和二维数组。 创建滤波器: 欧氏距离图(频率图像):r=dist(n [, m]),n和m与实际图像相同 Butterworth频率滤波器: 低通滤波:filter=1/[1+c*(r/r 0)2 n] 高通滤波:filter=1/[1+c*(r 0/r)2 n] 其中:c=1. 0或 0. 414(即当r=r 0时,滤波幅度为 0. 5或 1/sqrt(2)) r 0为滤波器截止频率(实际中使用象素宽度) n为滤波器阶数,通常n=1 通常,低频项代表图像的一般形状,高频项对应图像的细节
直接图形篇 - 图像处理 东海海表面温度图 NOAA 12 2000. 9. 23 20: 40 左图:原始图 中图:低通(w=10) 右图:高通(w=10)
直接图形篇 - 图形窗口输出 IDL支持多种设备输出,并可以简单地在设备之间切换。 set_plot , ’option’:option=win|ps|printer,大小写不敏感。 !d. name:当前设备名。 一般用法: c. Dev. Name=!d. name set_plot , ‘printer’ help , /device set_plot , c. Dev. Name 常用关键字: close_document:刷新输出缓冲区后关闭图形文档,用于从打印机排出打印页。 close_file:刷新输出缓冲区后关闭图形输出文件。 Filename:当输出为文件时地文件名,默认‘idl. option’ landscape:横向输出 portrait:纵向输出,缺省值 xoffset:确定纵向模式下输出窗口左下角(横向模式下ps和printer算法不同) yoffset:确定纵向模式下输出窗口左下角(横向模式下ps和printer算法不同) xsize:确定输出窗口宽度 ysize :确定输出窗口长度 inches:以英寸为单位,缺省为厘米
直接图形篇 - 图形窗口输出 ps 输出的一般方法: img=tvrd(true=1) set_plot , ‘ps’ device, filename=‘. ps’ , color=1 device , xsize= , ysize= , xoffset= , yoffset= tvscl, img , /true device, /close_file set_plot , ‘win’ printer输出的一般方法: ok=dialog_printersetup() img=tvrd(true=1) ratio=float(!d. y_vsize)/!d. x_vsize (printer设备不能自动保持纵横比) set_plot, 'printer' device, get_page_size=spagesize=spagesize/[!d. x_px_cm, !d. x_px_cm] device , xoffset= , yoffset= tvscl , img , /true , /centimeters , xsize= , ysize= *ratio device , /close_document set_plot , ’win’
IDL 高级培训 应用程序构造篇
编程篇 -建立、管理应用程序 IDL有两种应用程序管理方法:主程序和 程 主程序:建立与程序名同名的. pro文件,编译执行。 pro test … end 在这种方式下,根据IDL的自动编译规则,所有被调用的子程序或者与主程序写入 同一个文件并放置在主程序的上部;或者写成与子程序同名的. pro文件,存储在可搜 索的路径下。(子程序指过程或函数) 程:建立若干个. pro文件,每个文件不必与任何子程序同名。指定其中一个过程 为主程序,该过程的名字作为 程执行时首先调用的过程(即 run command)。 在这种方式下,由于程序编写未必遵守IDL的自动编译规则,因此在运行前必须编 译 程中所有的文件。 分发:将源程序编译为. sav文件。 • 主程序方式,需手 编译、存储为. sav文件. compile app_pro resolve_all save, /routines, app_pro , app_sav • 程方式,设置 程属性为形成. sav文件,使用 程菜单项下的build选项即可。
编程篇 -应用程序结构 主程序 Calling Routine Event structure Widget Creation Routine (TLB) Event Handler call xmanager XManger 调用相关子程序 Only if TLB is destoryed
编程篇 -主程序结构 主程序的一般结构: pro app_pro compile_opt idl 2 create top layout base(TLB) create gui base on TLB (initial application) realize TLB collect user information call xmanager [, /NO_BLOCK] end initial application 该过程可以在主程序里进行。但更好的办法是编写单独的过程,用TLB的 notify_realize关键字指定过程名,当realize TLB时执行。 /NO_BLOCK 使用该关键字,主程序运行后,命令行仍然可以使用,主程序自身仍可修改编译, 有利于调试。 compile_opt idl 2 改变默认编译选项,idl 2表示defint 32和strictarr
编程篇 -TLB TLB的三种基本形式 standard TLB: tlb_id=widget_base( group_leader=group $ , uname=’tlb‘ , title=’idl app‘ ) 适用于一般的应用程序,可以单独运行或被调用。group可以不存在。 modal TLB: tlb_id=widget_base( group_leader=group , /modal , uname=’tlb‘ , title=’modal app‘ ) 适用于对话框类的应用程序,通常不可以单独运行,只能被调用。group必须合法。 调用该类程序后,调用者暂时挂起,直至该程序返回。 floating TLB: tlb_id=widget_base( group_leader=group , /floating , uname=’tlb‘ , title=’floating app‘ ) 适用于任务优先类的应用程序,通常不可以单独运行,只能被调用。group必须合 法。调用该类程序后,调用者可以继续运行。该程序总在最前面。
编程篇 -GUI基本组件 容器组件: widget_base:任何GUI组件必须在某BASE组件上实现。一个BASE组件可以包含其 它的BASE。 GUI 组件: widget_draw:图形窗口,所有的图形、图像显示均在此实现 widget_label:标签,不可编辑的文本,可用于提示、说明 widget_button:按钮,分为push button、radio button和checkbox。 可用于命令、单选以及多选 widget_text:文本框,可编辑的文本,可用于用户输入 widget_slider:滑动条,分为水平和垂直,可用于调整预设值 widget_listbox:列表框,用于项目选择 widget_droplist:下拉列表框 widget_table:表格,可编辑的二维数据 组件标识: 每一个组件创建时都会产生一个id,并且可以指定一个uname。这些都是以后检索、 操作这个组件的标识。 True. Type字体设置: draw:使用device , set_font=fnt_str , /tt_font,输出时使用font=1。通常在与用户交 互时使用。 其它:使用font=fnt_str。通常在创建时使用
编程篇 -GUI其他组件 Compound Widgets 组合组件是一组完备、自容、可重用的应用程序,使用时与基本组件大致相同,但 它们是用IDL编写的。所有组合组件得名称都以cw_开始。 组合组件包括一下几类: • Animation(动画) • Color Manipulation(颜色操作) • Data Entry and Display(数据输入输出) • Image Manipulation(图像处理) • Orientation(定位操作) • User Interface(用户界面) 组合组件一般目的是扩充了相应的基本组件的功能。 Dialogs 对话框用于用户界面,可以象组件一样使用,但它不属于组件构造层次。对话框是 modal元素,当调用一个对话框时,其他界面元素暂时刮起直至对话框返回。 对话框包括以下几种: • File and Directory Selection:DIALOG_PICKFILE • Message. DIALOG_MESSAGE • Printing:DIALOG_PRINTJOB、DIALOG_PRINTERSETUP
编程篇 -GUI的构造层次及实现 GUI层次:Every GUI element is over BASE TLB base item GUI实现:指GUI 第一次在屏幕上显示 widget_control , tlb , /realize TLB实现后,所有层次关系属于TLB的组件均实现。 可以使用map=0关键字使某些子层次暂不显示。 base
编程篇 -xmanager Xmanager提供事件循环、监视并发送事件至事件处理程序,直至程序结束。 xmanager , name , widget_id , /just_reg , /no_block , group_leader=widget_id , event_handler=`event_pro’ , cleanup=‘cleanup_pro’ name:创建TLB的过程名 widget_id:TLB的id just_reg:登记一个TLB,但并不进入事件循环 no_block:在程序运行期间仍然允许IDL环境可以使用 group_leader:指定上一层次的widget_id event_handler:指定事件处理程序。缺省为name_event 语法:event_pro , event cleanup:指定程序退出时执行的程序。若指定,拥有最高优先级 语法:clenup_pro , widget_id 程序运行了吗? Result = XREGISTERED( name [, /NO_SHOW] )
编程篇 -事件结构 事件 用户在GUI上的每一个‘认可的’ 操作都会产生一个事件,xmanager将事件信息打包 传给IDL,IDL将事件信息解读后打包成一个结构类型的数据,即事件结构,并把这个 事件结构做为唯一的位置参数发送给事件处理程序。 事件结构是一个命名结构。包括一个结构名、三个公共字段和一些个体字段。 { event_type , id: , top: , handler , … } even_type:标识事件类型。 id:长整数,产生事件的标识符。 top:长整数, id所表示的组件所在的TLB。 handler:长整数,事件处理程序标识符。事实上,由于事件处理程序总与某一 特定的组件相联系,该标识符就是组件标识符。 任何前三个字段定义与上述意义相同的命名字段,都可以认为是IDL的一个事件结构。
编程篇 -事件处理方式 当事件发生时,IDL会从当前组件层次开始,逐层向上查找与该事件相关联的事件处理程序。 handler字段记录该组件的标识。 Event handler TLB A C B D E A F Event handler TLB C B D E G Event occurs here { , id: G , top: A , handler: A , … } F Event handler G Event occurs here { , id: G , top: A , handler: F , … }
编程篇 -为组件指定事件处理程序 1. 由 xmanager 指定的事件处理程序(通常是TLB)处理所有事件。 2. 使用组件创建时的关键字event_pro或event_func为每一个事件单独指定一个处理程序。 注意到:xmanager总会为其直接管理的组件(通常是TLB)指定一个事件处理程序(而 且是一个过程),因此,该组件的事件处理程序不能用event_pro或event_func指定。
编程篇 -事件处理程序可以是过程或函数。 过程:事件处理完毕后被中止,程序等待下一个事件。 函数:由于函数有返回值,如果返回值是一个结构,又恰恰符合IDL事件结构标准,则IDL 会将这个返回值做为一个事件处理。(此乃伪事件,可以用来‘欺骗’IDL) 事件处理程序接受并且只接受一个位置参数,event 事件处理程序基本结构(TLB结构) pro app_pro_event , event uname=widget_info(event. id , /uname) case uname of ‘TLB_uname’: begin if tag_names(event , /structure_name) eq 'widget_kill_request' ) then begin … … (some cleanup work) widget_control , event. top , /destroy return endif end ‘uname 1’: begin … … (do something) end ‘uname 2’: uname 2_event_pro , event (如果已经为uname 2组件指定了该事件处理程序,则该行略去) else: endcase end
编程篇 -数据传递 注意到,对于一个应用程序,IDL所做的只是“捕获”各种组件事件,将事件结构做为 唯一的位置参数传递给事件处理程序,因此,无法通过通常的参数传递的方法交换数 据。 IDL提供了user_value,通过为widget_id“绑定”user_value的方法传递数据。 方法: widget_control , widget_id , set_uvalue=value [, /NO_COPY] 将用户数据绑定到一个组件 widget_control , widget_id , get_uvalue=value [, /NO_COPY] 从一个组件获取用户数据 为TLB绑定用户数据 一般地,在主程序中,xmanager之前,会创建一个结构,该结构的各个字段是用户 在整个应用程序运行期间所需要相互传递的数据。然后把这个结构绑定给TLB。 s. State={ … } widget_control , TLB_id , set_uvalue=s. State 当事件发生时,IDL会把事件结构传递给事件处理程序,事件处理程序可以通过事 件结构的top字段来获得用户数据。 Widget_control , event. top , get_uvalue=s. State 注意到,用户数据的传递是值引用,这就意味着一旦在事件处理程序里改变了用户 数据的值,必须把改变了值的用户数据传回给top才会使改变了的值在其它事件处理程 序里生效。 Widget_control , event. top , set_uvalue=s. State
编程篇 -数据传递 有问题发生 事实上,s. State是一个局部变量,因此当绑定给TLB_ID时,是copy了一份到全局内存。而 当事件处理程序获得用户数据时,又是从全局内存中copy一份到该事件处理程序的局部变量中。 于是,一份数据就有了3份copy。 指定/NO_COPY关键字,就只使用一份。 烦恼: (1)copy一事会给我们带来烦恼。因为一旦no_copy,则当前的用户数据变量就不再有效。 这意味着返回用户数据的命令应该是事件处理程序的最后一行,显然这是不现实的。 (2)事实上,必须返回用户数据才会使修改有效这件事也会给我们带来烦恼,这要求我们 必须时刻保持警惕!是不是精神会有点紧张?: )
编程篇 -数据传递 解决的方法 用一个指针变量可以解决这个问题! (我们不必等IDL把用户数据copy到全局内存,我们有能力自己干!) TLB: s. State={ … } p. State=ptr_new(s. State , /no_copy) widget_control , TLB_id , set_uvalue=p. State EH: widget_control , ebent. top , get_uvalue=p. State 这时,*p. State 就是 s. State 有了指针,我们方便多了! (1)任何修改立即生效,免去返回的烦恼。 (2)由于指针仅仅是“指针”,我们可以在s. State里也设置一些必要的指针,比如数组指针, 这样又可以免去结构数据不能更改数组维数的烦恼。
编程篇 -数据传递 没有免费的午餐! 指针仍然有一个小小的问题。必须在cleanup里将指针释放,否则会引起内存泄漏。 最后 没有证据证明传递 s. State 和 p. State 哪一个更好。 由于用户数据是值传递,这就带给我们可以在愿意的时候随便传递一个“什么”给TLB的便利。 这时,使用p. State未必就比使用s. State更方便。你需要ptr_free() ! 再者,太多的 * 仍然带来麻烦。
编程篇 -数据传递 widget_list 和 widget_droplist 的 uvalue 通常我们在 list 里放置的是带有说明性的字符串数组,然而一旦进入事件循环我们就再也不 会得到这个数组,我们只能得到这个数组的 index 值,即数组下标。 通过绑定字符串数组到 list_id 就可以在需要的时候仍然得到特定的字符串 TLB: widget_control , list. id , set_value = a. Str widget_control , list. id , set_uvalue = a. Str EH: index = widget_info( list_id , /droplist_select ) OR index = widget_info( list_id , /list_select ) widget_control , list. id , get_uvalue = a. Str string = a. Str[index]
编程篇 -操作组件分为两个部分:获取组件属性和设置组件属性 widget_info函数用来获取组件属性,widget_control函数用来设置组件属性 result=widget_info(widget_id , …… ) general: , /uname , find_by_uname=string , /valid_id , /geometry widget_droplist: , /droplist_select widget_list: , /list_select widget_control , widget_id , …… general: , /hourglass ( no widget_id ) , /realize , map=0|1 , sensitive=0|1 , /destroy , get_uvalue= value , send_event={…} widget_base: , cancel_button=button_id (for modal) , /iconify widget_draw: , draw_xsize=int , draw_ysize=int , get_draw_view=var , set_draw_view=[x, y] widget_droplist: , set_droplist_select=integer , set_value=value widget_list: , set_list_select=value , set_value=value widget_slider: , set_slider_max=value , set_slider_min=value widget_text: , editable=0|1 , get_value=var: except base、droplist、listbox , set_value=var: except base、draw
编程篇 -draw事件 TLB: w. Draw=widget_draw( tlb_id , uname=‘w. Draw’ , /button_events , /motion_events , /viewport_events , /expose_events , retain=0|1|2 , …) EH: widget_info(event. id , /uname)=‘w. Draw’ tag_names(event, /structure_name)=‘WIDGET_DRAW’ event={ WIDGET_DRAW , ID: 0 L , TOP: OL , HANDLER: 0 L , TYPE: 0 , X: 0 L , Y: 0 L , PRESS: 0 B , RELEASE: 0 B , CLICKS : 0 , MODIFIERS: 0 L} event. TYPE: 0 mouse press 1 mouse release 2 mouse motion 3 viewport moved (scrollbars) 4 visibility changed (exposed) event. X & event. Y mouse coordinate , device event. PRESS for mouse press left 1 mouse left event. RELEASE for mouse release 2 mouse middle 4 mouse right event. CLICKS 1 mouse clicks 2 mouse double clicks event. MODIFIERS keyboard modifier key state when mouse event 1 shift 2 control 4 capslock 8 alt(win)
编程篇 -table_resize事件 改变窗口大小,一般来说,对draw的影响最大,draw应该随窗口的改变而改变,draw中的内 容也应该随之改变。 TLB: tlb=widget_base( uname=‘tlb’ , /tlb_size_events , … ) EH: w. Draw=widget_info(event. top find_by_uname=‘w. Draw’) (get new xsize , ysize of draw) widget_control , w. Draw , draw_xsize=new_xsize widget_control , w. Draw , draw_ysize=new_ysize (refresh work … ) when table resized event={WIDGET_BASE , ID: 0 L , TOP: 0 L , HANDLER: 0 L , X: 0 L , Y: 0 L } event. x current xsize of WIDGET_BASE event. y current ysize of WIDGET_BASE 显然,event. x和event. y并不能直接用于draw的draw_xsize和draw_ysize。
编程篇 -table_resize事件 方法: s. Geom=widget_info(widget_id , /geometry) 返回一个描述widget_id的相关坐标信息的结构数据, 利用这些数据就可以计算出 新的draw的xsize和ysize s. Geom = { WIDGET_GEOMETRY , XOFFSET: 0. 0 , YOFFSET: 0. 0 , XSIZE: 0. 0 , YSIZE: 0. 0 , SCR_XSIZE: 0. 0 , SCR_YSIZE: 0. 0, , DRAW_XSIZE: 0. 0 , DRAW_YSIZE: 0. 0, , MARGIN: 0. 0 , XPAD: 0. 0 , YPAD: 0. 0 , SPACE: 0. 0 }
编程篇 -timer事件 一个timer事件,就是一个定时器,它按照设定的时间间隔自动产生WIDGET_TIMER事 件,适当地设置timer事件处理程序,就可以让IDL自动地为我们 作了。 timer事件可以绑定在任何合法的widget_id上,只要你能用事件处理程序关联它。 pro timer_example_event, event widget_control, event. id, get_uvalue=uval if (tag_names(event, /structure_name) eq 'WIDGET_TIMER') then begin print, 'timer fired' widget_control, event. top, timer=2 end case uval of 'timer' : widget_control, event. top, timer=2 'exit' : widget_control, event. top, /destroy else: endcase end pro timer_example base = widget_base(/column, uvalue='base') b 1 = widget_button(base, value='fire event', uvalue='timer') b 2 = widget_button(base, value='exit', uvalue='exit') widget_control, base, /realize xmanager, 'timer_example', base, /no_block end
IDL 高级培训 对象图形篇
对象图形篇 -概述 Basic 对象图形是IDL引入面向对象编程概念后出现的。 面向对象编程的基础是对象类的使用。对象类允许程序员将数据和方法封装成为 一个包,称之为对象。一个对象类可以反复使用而每次使用都封装不同的数据。 IDL里对象类的实现主要是用一组预建的对象类构成对象图形系统。对象图形系 统是一个IDL内建的对象类库,可用于创建场景。 对象类也可以用IDL编写以实现程序员自己的要求。程序员可以在IDL环境中用 传统的过程和函数的编写方法加上对象特性编写自己的对象模块。
对象图形篇 -概述 Direct Graphics vs. Object Graphics Direct Graphics: • 创建 2 D图形有优秀表现,如:X-Y plot , contours , mapping等 • 可以在命令行使用,简单、快速 • 图形创建命令通常连同坐标系一起创建 • 图形生成时,针对当前图形设备 • 图形生成并输出后,不可修改或再用。如果需要修改或向其他设备输出,必 须重新输出。 • 后输出的项目总在先输出的项目的“上面” Object Graphics: • 硬件加速的3 D场景显示,灵活,交互性强 • 对象图形系统主要以程序方式使用 • 图形对象是功能性封装的。即独立的对象包含自己的方法,操作自己的数据 • 图形输出没有当前设备的概念,图形对象为层次结构,并使用输出目标概念 • 图形创建后,数据及其属性驻留内存,便于修改,反复使用 • 对象图形驻留内存,因此在退出时要释放内存,避免内存泄漏
对象图形篇 -内容 LIVE_TOOLS 具集 • 一组预建的IDL组件应用程序,使用IDL的对象图形系统,可以构造高质量的可交互的 场景 • 每一个LIVE 具既可以做为单独的应用程序使用,也可以做为组件用于编程 • LIVE 具可以既可以使用鼠标操纵,也可以编程操纵 图形对象系统(IDLxx. Yyyy) • 一组预建的对象类,可用于构造高质量的2 D、3 D场景 • 使用最新的图形硬件加速技术 • 采用灵活的结构,可以多场景输出 • 使用IDL的过程或函数构造图形对象的层次结构 • 图形创建后,场景可以很容易操纵、修改 创建自己的图形对象类 利用IDL的面向对象编程概念和方法,程序员可以创建自己的对象类
对象图形篇 -LIVE_TOOLS共有15个例程,包括创建图形、图形文件输出、打印输出、标注以及控制。
对象图形篇 -LIVE_TOOLS Stand-Alone LIVE Tools LIVE_PLOT , LIVE_CONTOUR , LIVE_SURFACE , LIVE_IMAGE 完整的IDL组件例程,窗口调整、属性设置均可通过鼠标操纵。可以从命令行直接运行。 sincurve=sin(findgen(360)*!dtor) live_plot , sincurve 可以通过调用时设置关键字参数,调整交互界面 live_plot , sincurve , /no_toolbar , /no_status LIVE_OPLOT 向已经创建的LIVE窗口中叠加,只有适合已有坐标系的数据才会加入 sincurve=sin(findgen(360)*!dtor) live_plot , sincurve for i=0. 9 , 0. 1 , -0. 1 do live_oplot , sincurve*I
对象图形篇 -LIVE_TOOLS Multiple LIVE Tools and LIVE_OPLOT 完当同时启动多个LIVE时,LIVE_OPLOT就不知道应该向哪一个窗口叠加。 REFERENCE_OUT=ref 返回窗口信息,结构数据。其中win字段即为窗口标识。 WINDOW_IN=ref. win 指定叠加的窗口 sincurve=sin(findgen(360)*!dtor) live_plot , sincurve ,reference_out=ref for i=0. 9 , 0. 1 , -0. 1 do live_oplot , sincurve*i , window_in=ref. win x=[1. 2, 2. 0, 7. 7, 4. 5, 23. 4] y=3. 0*x+2. 0 new_x=[3. 9, 6. 9, 12. 0, 15. 6] new_y=interpol(x, y, new_x) p. Props={color: 'Light Blue', linestyle: 2, symbol_size: 0. 05, symbol_type: 2} p. Style = live_style('plot', GRAPHIC_PROPERTIES = p. Props) live_plot, y, INDEPENDENT = x, REFERENCE_OUT = refout 2, STYLE = p. Style live_oplot, new_y, INDEPENDENT = new_x, WINDOW_IN = refout 2. win
对象图形篇 -LIVE_TOOLS LIVE_STYLE('contour' | 'image' | 'plot' | 'surface’ , … ) 设置LIVE的窗口风格。可以创建一个包括所有输出窗口的图形属性的结构数据,然 后传给所有准备创建的LIVE。IDL的灵活的结构数据的特点使得每一个LIVE只保留与之 相关的字段值并修改之。 a = findgen(40) a = sin(a/5) / exp(a/50) wave = a # a gp = {bottom: 'Blue', color: 'Brown', shading: 1, style: 2} surfstyle = live_style('surface', GRAPHIC_PROPERTIES = gp) live_surface, wave, STYLE = surfstyle
对象图形篇 -LIVE_TOOLS Multiple Plots in One Window 通过设置图形在窗口中的位置和大小,可以实现在一个窗口中同时显示多个图形。 LOCATION:图形在窗口中的位置,normal坐标 DIMENSION:图形显示的大小,normal坐标 a = findgen(40) a = sin(a/5) / exp(a/50) wave = a # a live_image, wave, REFERENCE_OUT = refout, $ LOCATION = [0. 0, 0. 5], DIMENSIONS = [1. 0, 0. 5] live_contour, wave, WINDOW_IN = refout. win, $ LOCATION = [0. 0, 0. 0], DIMENSIONS = [0. 5, 0. 5] live_surface, wave, WINDOW_IN = refout. win, $ LOCATION = [0. 5, 0. 0], DIMENSIONS = [0. 5, 0. 5]
对象图形篇 -LIVE_TOOLS LIVE Annotations LIVE_TEXT , LIVE_RECT , LIVE_LINE 这些 具可以为一个已创建的LIVE在窗口内的任意位置添加标注。并可以在添加以 后仍然可以通过鼠标操纵修改。normal坐标。 data = alog 10(findgen(100)+1) live_plot, data, REFERENCE_OUT = refout live_text, '对数曲线', WINDOW_IN = refout. win, $ LOCATION = [. 5, . 9], ALIGNMENT = 0. 5, $ FONTNAME = ’隶书', FONTSIZE = 18, COLOR = 'Blue' live_rect, WINDOW_IN = refout. win, COLOR = 'Light Green’, $ LOCATION = [. 2, . 87], DIMENSION = [. 6, . 1] live_line, WINDOW_IN = refout. win, $ LOCATION = [. 2, . 05], DIMENSION = [. 6, 0], $ /ARROW_START, /ARROW_END
对象图形篇 -LIVE_TOOLS LIVE_DESTROY , /ENVIRONMENT 关闭所有LIVE,释放所有与之相关的内存。 LIVE_DESTROY , WINDOW_IN=ref. win , … 关闭ref. win指定的LIVE或其中的图形元素。灵活使用REFERENCE_OUT和 WINDOW_IN,就可以去掉窗口内的指定图形元素。 data = alog 10(findgen(100)+1) live_plot, data, REFERENCE_OUT = refout live_text, ’对数曲线', LOCATION = [. 5, . 9], ALIGNMENT = 0. 5, $ FONTNAME = ‘隶书', FONTSIZE = 18, COLOR = 'Blue', $ WINDOW_IN = refout. win live_rect, LOCATION = [. 2, . 87], DIMENSION = [. 6, . 1], $ COLOR = 'Light Green', WINDOW_IN = refout. win live_line, LOCATION = [. 2, . 05], DIMENSION = [. 6, 0], $ WINDOW_IN = refout. win, /ARROW_START, /ARROW_END ; add a line that will be destroyed live_line, LOCATION = [. 5, . 5], DIMENSIONS = [0. 0, . 25], $ WINDOW_IN = refout. win, REFERENCE_OUT = linerefout wait, 3 live_destroy, linerefout. graphic, WINDOW_IN = refout. win wait, 3 live_destroy, refout. graphic wait, 3 live_destroy, WINDOW_IN = refout. win
对象图形篇 -LIVE_TOOLS Embedded LIVE Tools 除可以做为独立的例程使用之外,LIVE 具可以嵌入到IDL组件程序中,不仅保持 原有的功能,还与IDL的其他组件共同使用, PARENT_BASE LIVE_TOOLS , PARENT_BASE=base_id 在应用程序中使用LIVE,通常为LIVE创建一个BASE将其嵌入。 Event Handling 在widget的用户数据里,通常必须保存LIVE的ref,这样在整个程序运行期间就可以 根据事件的需求对LIVE进行控制。 LIVE_CONTROL 在事件处理程序中,所有需要对LIVE进行控制的请求都通过LIVE_CONTROL实现。 其功能类似widget_control。 特别注意:任何时刻需要更新LIVE的数据时,只能用一个与初始化该LIVE时的数 据变量同名的变量来传递数据。 LIVE_INFO 用于获取指定的LIVE的属性,返回一个结构数据。功能类似widget_info。 LIVE_DESTROY 当widget结束时,必须将LIVE释放。
对象图形篇 -对象图形类(IDLgr. Yyyy) 概述 IDL的对象图形系统是一个内建的对象类库,通过选择适当的内建对象、构造层次结构来 创建图形场景。层次结构描述各种图形元素在 3 D中的层次以及各层之间的关系。 IDL的图形对象类命名方式为IDLgr. Yyyy,其中Yyyy标识类的名称。 IDL的图形对象类如下: Container Objects: IDLgr. Scene, IDLgr. View, IDLgr. Model IDLgr. Viewgroup , IDL_Container Graphical Atom Objects: IDLgr. Plot, IDLgr. Polyline, IDLgr. Ploygon, IDLgr. Contour, IDLgr. Surface, IDLgr. Volume, IDLgr. Image, IDLgr. Axis , IDLgr. Text , IDLgr. Light Destination Objects: IDLgr. Window, IDLgr. Printer, IDLgr. Buffer, IDLgr. Clipboard, IDLgr. VRML Attrigute:(outside the hierarchy, be used when rendering graphic objects) IDLgr. Font, IDLgr. Palette, IDLgr. Symbol Helper: (outside the hierarchy, alter data in useful ways or provide other services) IDLgr. Tessalator, Trackball Composite Objects: IDLgr. Color, IDLgr. Legend
对象图形篇 -对象图形类(IDLgr. Yyyy) The Object Graphics Hierarchy,对象图形的层次结构 Use if multi view Scene Can root hierarchy View Model Contain Graphic Atoms Graphic Atom objects gr. Atom
对象图形篇 -对象图形类(IDLgr. Yyyy) Create Hierarchy 对象图形场景必须以层次结构创建。基本的层次结构创建如下: 1. Creation of an IDLgr. View object 2. Creation of an IDLgr. Model object 3. Creation of a Graphical Atom 4. Add the Model to the View 5. Add Graphical Atom(s) to the Model 6. Creating a Destination Object 7. Drawing the View to the Destination Object 最简单的对象图形例程: o. View=obj_new('IDLgr. View', VIEWPLANE_RECT=[-10, -2, 380, 4]) o. Model=obj_new('IDLgr. Model') o. Plot=obj_new('IDLgr. Surface', sin(findgen(360)*!Dto. R), THICK=3) o. View->Add, o. Model->Add, o. Plot o. Window=obj_new('IDLgr. Window', TITLE='The Simplest OG Plot') o. Window->Draw, o. View
对象图形篇 -对象图形类(IDLgr. Yyyy) 将IDLgr. View或IDLgr. Scenen嵌入IDL的Widget程序 在建立了对象图形层次结构之后,可以将它输出到一个合法的目标类对象,比如一 个Window。Widget_draw就可以成为一个这样的Window。 基本方法 tlb=widget_base() draw=widget_draw(tlb , uname='draw' , GRAPHICS_LEVEL=2 $ , xsize=512 , ysize=512 , retain=2) widget_control , tlb , /realize widget_control , draw , get_value=o. Win->draw , o. View 注意: GRAPHICS_LEVEL=2和retain=2
对象图形篇 -对象图形类(IDLgr. Yyyy) 图形对象操作概述 对象创建:任何一个对象必须从一个对象类中创建 o. OBJ=Obj_new(‘IDLgr. Yyyyy’) 对象属性:每个对象都有唯一的一组属性描述对象的特点。可以在创建对象时指定, 也可以在创建后修改。 o. OBJ=Obj_new(‘IDLgr. Yyyyy’ , color=[255, 0, 0] ) 对象方法:每个对象都有一组自己的内建方法,用于操纵数据和属性。 o. Obj->Get. Property 获取对象的属性 o. Obj->Set. Property 设置对象的属性 o. Obj->add o. Obj->remove 对象注销:对象是驻留内存的,因此当一个图形对象不再使用时,应该注销,从内存 中释放。在应用程序的开发中尤其重要。 obj_destroy , o. OBJ
对象图形篇 -对象图形类(IDLgr. Yyyy) 图形坐标 对象图形系统中的图形坐标是通过设置IDLgr. View的属性实现的。 obj=OBJ_NEW('IDLgr. View’ , UNITS=0|1|2|3 , DIMENSIONS=[width, height] , LOCATION=[x, y] , VIEWPLANE_RECT=[x, y, width, height] , ZCLIP=[near, far] ) UNITS:设置坐标系 0: device(default) , 1: inches , 2: centimeters , 3: normal VIEWPLANE_RECT和ZCLIP:设置坐标系范围 当使用normal坐标系时: • 3个坐标轴的默认范围均为-1~1 • 应对该view下的gr. Atom(s)的数据进行坐标变换 y DIMENSIONS和LOCATION:设置图形的大小和位置 x z
对象图形篇 -对象图形类(IDLgr. Yyyy) 图形变换指对图形的旋转、平移和缩放。 对象图形系统中的图形变换是通过设置IDLgr. Model的变换矩阵实现的。IDLgr. Model一经创 建,便产生一个 4× 4的变换矩阵,图形的变换操作是通过重新设置这个矩阵的值实现的。 设置方法: 1. 通过IDLgr. Model的rotate、translate和scale方法设置。 2. 通过IDLgr. Model的transform属性设置。 恢复初始状态: o. Model-> reset
对象图形篇 -对象图形类(IDLgr. Yyyy) 图形变换-旋转: 1. o. Model-> Rotate , [x, y, z] , Angle 2. o. Model-> Get. Property , transform= t o. Model-> Set. Property , transform= t * new. T Rx = [[1. 0, 0. 0, [0. 0, cosa, -sina, [0. 0, sina, cosa, [0. 0, Ry = [[ cosa, 0. 0, sina, [ 0. 0, 1. 0, 0. 0, [-sina, 0. 0, cosa, [ 0. 0, Rz = [[cosa, -sina, 0. 0, [sina, cosa, 0. 0, [ 0. 0, 1. 0, [ 0. 0, 0. 0], 0. 0], 1. 0]] $ $ $ $ $
对象图形篇 -对象图形类(IDLgr. Yyyy) 图形变换-平移: 1. o. Model-> Translate, dx, dy, dz 2. o. Model-> Get. Property , transform= t o. Model-> Set. Property , transform= t * new. T trans. T = [[1. 0, [0. 0, 1. 0, 0. 0, dx], $ 0. 0, dy], $ 1. 0, dz], $ 0. 0, 1. 0]]
对象图形篇 -对象图形类(IDLgr. Yyyy) 图形变换-比例缩放: 1. o. Model-> Scale , sx , sy , sz 2. o. Model-> Get. Property , transform= t o. Model-> Set. Property , transform= t * new. T scale. T = [[ sx, 0. 0, 0. 0], $ [0. 0, sy, 0. 0], $ [0. 0, sz, 0. 0], $ [0. 0, 1. 0]]
对象图形篇 -对象图形类(IDLgr. Yyyy) gr. Atom中数据的normal坐标转换 当IDLgr. View使用normal坐标时,应该对gr. Atom(s)中的数据进行坐标转换以适应新的坐标系。 o. Atom=obj_new(‘IDLgr. Yyyy’ , data ) Obj[i]->Get. Property, XRANGE=xr, YRANGE=yr, ZRANGE=zr xc = [ -xr[0]/(xr[1]=xr[0]), 1/(xr[1]-xr[0]) ] yc = [ -yr[0]/(yr[1]=yr[0]), 1/(yr[1]-yr[0]) ] yc = [ -zr[0]/(zr[1]=zr[0]), 1/(zr[1]-zr[0]) ] Obj[i]->Set. Property, XCOORD_CONV=xc, YCOORD_CONV=yc, ZCOORD_CONV=zc 事实上,在gr. Atom内部的计算方法为:normalized=so+s 1*data 上述公式的转换结果为为 0~ 1,如果IDLgr. View中的坐标不是 0~ 1,则可以根据需要对xc[0], yc[0],zc[0]进行计算,可以使图形在适当的位置显示。 如:data的值域为 0~ 1,坐标为-1~ 1,则xc[0]=xc[0]-0. 5即可。
对象图形篇 -对象图形类(IDLgr. Yyyy) Trackball Object 真正的交互式图形显示必须能让用户使用鼠标来操纵图形。 obj=OBJ_NEW('Track. Ball’ , Center , Radius , AXIS=0|1|2 ) 其中:center为鼠标作用区域的中心点、radius为鼠标作用区域的半径,均为device坐标。 axis标识旋转轴,0,1,2分别对应x,y,z轴,默认 2。 注意:(1)Track. Ball为Helper类,既无父类也无子类。因此,不能加入到任何一种图形对象 类,通常只做为widget的用户数据传递。 (2)Track. Ball的事件一般只通过widget的事件处理程序处理。 Track. Ball事件处理一般方法: TLB: o. Track=obj_new('Trackball', [200, 200], 200) EH: widget_control , event. top , get_uvalue=p. State b. Have. Xform=(*p. State). o. Track->Update(event, TRANSFORM=Track. Xform) if (b. Have. Xform) then begin (*p. State). o. Model->Get. Property, TRANSFORM=Model. Xform (*p. State). o. Model->Set. Property, TRANSFORM=Model. Xform#Track. Xform (*p. State). o. Window->Draw, (*p. State). o. View endif
对象图形篇 -对象图形类(IDLgr. Yyyy) Light Object 光源是IDL图形对象gr. Atom类之一,它可以加入到对象图形的层次结构中,从而可 以随对象图形的变换而变换(如:旋转、平移和缩放)。 IDL默认为环绕光,这会使 3 D图形看起来象 2 D图形一样。通过设置光源对象的属性, 可以看到真正的3 D图形。 obj=OBJ_NEW(’IDLgr. Light’ , TYPE=0|1|2|3 , LOCATION=[x, y, z], COLOR=[r, g, b]) 其中:TYPE为光源类型。0为环绕光,1为点光源,2为平行光,3为聚光灯。 LOCATION为光源位置;COLOR为光源颜色。 多光源 由于光源可以随对象图形变换,因此为了从各个角度都能清楚地看到图形,就必 须设置多个光源。一个IDLgr. View里最多可以放置 8个光源。 让光源停在特定的位置 单独创建一个包含IDLgr. Light的IDLgr. Model,就可以控制它的动作。
对象图形篇 -对象图形类(IDLgr. Yyyy) Color Palettes Object 颜色的使用总是一件麻烦的事,在对象图形系统中,这个问题得到了较好的解决。 在对象图形系统中,无论以何种方式加载颜色表,IDL总是把颜色表的r,g,b值拷 贝到目标对象的颜色表中中。因此,索引表方式或真彩表方式的差别只是颜色的检索 方式的差别,都是静态颜色模式,不会出现动态颜色模式。 创建颜色模板对象的两种方法: (1) obj=OBJ_NEW('IDLgr. Palette', a. Red, a. Green, a. Blue) (2) obj=OBJ_NEW('IDLgr. Palette') obj->loadct , 33 注意:(1)IDLgr. Palette不是gr. Atom类,因此不能加入到IDLgr. Model里。它只能用于 目标类对象或用于gr. Atom类的PALETTE属性。(如IDLgr. Image) (2)注意目标类对象的color_model。
对象图形篇 -对象图形类(IDLgr. Yyyy) Text and Font Objects 对图形输出而言,文本标注从来都是基本要求之一。 IDL提供高质量、可伸缩的文本用于输出。这些标注可以象图形一起加入层次结构, 从而可以和其他图形一起重写、旋转、平移等。当然,也可以选择‘ONGLASS’,这样 你总可以在屏幕上看见它们。 IDLgr. Text o. Text=obj_new('IDLgr. Text', string , FONT=o. Font , /ONGLASS $ , LOCATION=[-1, 0, 0], COLOR=[0, 255, 0] $ , ALIGNMENT=0. 5 , vertical_alignment=0. 5) 缺省设置:左对齐,与x轴平行,写在原点。 FONT属性设置字体,但该字体必须是IDLgr. Font对象。 IDLgr. Font o. Font = obj_new('IDLgr. Font', '隶书', SIZE=36 ) 可以使用中文True. Type字体
对象图形篇 -对象图形类(IDLgr. Yyyy) Outputting Objects 对象图形系统同样支持多种目标类输出,包括:printer,图形文件等。 1. 输出到打印机 打印机是一个目标对象类,输出的一般方法如下: o. Printer=Obj_New('IDLgr. Printer', /LANDSCAPE, PRINT_QUALITY=3) status=dialog_printersetup(o. Printer) if status eq 0 then return o. Printer->Draw, o. View o. Printer->New. Document ; suppose we have create a view ; ouput and finish print job 2. 输出到图形文件 抓取当前IDLgr. Window的内容,输出到图形文件 ; suppose we have create a window o. Window. Image=o. Window->Read() ; Get the data from the image o. Window. Image->Get. Property, DATA=img write_jpeg, 'og_out. jpg', img, TRUE = 1
对象图形篇 -对象图形类(IDLgr. Yyyy) Images and Texture Mapping 将一幅地形图(image)覆盖在由高程数据形成的曲面(surface)上,是很有实用 价值的。IDLgr. Surface和IDLgr. Polygon都具有将一幅地形图与高程数据曲面适当地组 合的能力。 o. Image=obj_new(‘ILDgr. Image’ , data ) o. Surface=obj_new(‘IDLgr. Surface’ , data , texture_map=o. Image )
对象图形篇 -创建自己的图形对象类 在IDL引入了面向对象设计思想后,程序员使用IDL创建自己的图形对象类成为可能。 创建新的对象类的步骤 1. 为类命名 每当创建一个类对象时, IDL总是用对象类的名标识,因此类名必须唯一。 2. 定义类的属性(data) 一个对象的所有必要的信息必须在类的数据部分适当地定义。 对象类的数据定义使用IDL的命名结构,结构的名就是类名,并且使用 objname__define. pro存储。 3. 定义类的行为(methods) 一个对象类的行为通常称为方法,使用IDL的过程和函数定义。不同点在于命名和 数据传递。 命名:objname: : methodname 数据传递:自动 方法的定义既可以与数据定义使用一个文件;也可以为每一个方法单独使用一个 文件,文件命名必须为objname__method. pro 实例分析:imageobj__define. pro
IDL 高级培训 外部接口篇
接口篇 -概述 IDL提供了多种与外部语言混合编程接口 具 • spawn • IDLDraw. Widget Active. X control (Windows) • Apple. Script (Mac) • Remote Procedure Calls (RPCs) (UNIX) • CALL_EXTERNAL • Callable IDL • Adding System Routines LINKIMAGE and Dynamically Loadable Module (DLM) • ODBC
接口篇 -spawn IDL与外部接口 具中最简便地一种 spawn , command , result=var , errresult=var , /hide , /nowait , /noshell , /log_output , /null_stdin , /stderr (1) Windows下环境下相当与在执行一个DOS命令,但无法返回信息。 (2) 无选项时,弹出一个DOS窗口 (3) nowait,不选,在程序中调用spawn时,直至命令完成才执行spawn的下一句。 (4) hide,不选,在程序中调用spawn时,会弹出一个DOS窗口显示外部命令的执行情况。 选中,则将DOS窗口最小化。(对DOS程序有用) (5) noshell,不选,在程序中调用spawn时,会通过DOS命令行执行。 选中,则不经过命令行,直接运行。(对windows程序有用)
接口篇 -Call_external 以共享库方式通过目标码进行传递,可调用任何语言的代码(如c和Fortran),适合任何 操作平台。 基本格式 result = CALL_EXTERNAL( Image , Entry , … ) image:共享库(Windows平台:DLL,UNIX平台:so) entry:调用名(Windows平台:函数) 缺点:数据在传递时数据大小和类型都必须已知,且不能传递虚拟变量。
接口篇 -Active. X IDL提供了windows平台下标准的Active. X控件,使得我们可以从任意一种支持Active. X嵌 入的语言中使用IDL。只要遵守参数传递标准,IDL的编程与在IDL环境下没有区别。 在不想放弃IDL的前提下,也许是Windows平台下开发应用系统的最好的办法之一。 环境 windowssystem 32idldrawx 2. ocx 需要IDL支持。 以Vb调用IDL为例 • 界面由VB设计,触发事件可由VB或IDL控制。 • 控件初始化 • IDL程序初始化
接口篇 -ODBC 信息技术的发展,终于到了这样一个阶段:Everything is Over Database !,看来,不支 持数据库是不行了。 IDL提供了支持ODBC的接口,Data. Miner,和完整的Intersolv ODBC驱动,支持几乎所 有的主流数据库系统。通过Data. Miner既可以使用标准SQL也可以使用Data. Miner的API 具集对数据库操作而不必知道SQL。 IDL Data. Miner的基本功能 • Connect to a database management system (DBMS) • Query data from a DBMS • Get information about the available database tables in a DBMS • Access a table in a DBMS • Create a table in a DBMS • Delete a table in a DBMS • Perform standard SQL operations in the DBMS • Get information about the columns in a selected table • Add/Change/Delete records in a table 基于ODBC的应用程序架构 • Database Application. call ODBC API to access a data source • Driver Manager. • Drivers. • Data Source. 测试在你的IDL环境下ODBC是否可用:status=DB_EXISTS()
接口篇 -Data. Miner API 创建表并追加数据 ; creat a database object , conect to DB and creat a new table o. DB = obj_new('IDLDBDatabase') o. DB->Connect, Data. Source ="IDLTRAINING" o. DB->Execute. SQL, "create table training( id integer" + $ ", x integer , y integer, data image, name char(50))" ; creat a recordset , append a record o. RS = obj_new('IDLdb. Record. Set', o. DB, table='training' ) o. RS->Add. Record, 1, 400, BYTSCL(DIST(400)), 'first image' ; after working , destroy object obj_destroy , o. RS obj_destroy , o. DB
接口篇 -Data. Miner API 从已有表中读取数据 ; creat a database object , conect to DB and creat a new table o. DB = obj_new('IDLDBDatabase') o. DB->Connect, Data. Source ='IDLTRAINING' ; creat a recordset , append a record o. RS = obj_new('IDLdb. Record. Set', o. DB, table='training') status=o. RS->Move. Cursor(/first) ; retrieve image data and information X = o. RS->Get. Field(1) Y = o. RS->Get. Field(2) image = o. RS->Get. Field(3) name = o. RS->get. Field(4) ; after working , destroy object obj_destroy , o. RS obj_destroy , o. DB ; now we can use these data in IDL WINDOW, COLORS=-5, TITLE=name, XSIZE=x, YSIZE=y image = REFORM(image, 400) TVSCL, image
接口篇 -Data. Miner API 小结: • IDL并不是一个有效的信息系统的界面 具,数据校验功能过弱。这就使得在写入数据库 时预处理过于繁杂,效率不高。但从数据库读取数据非常简单,便于使用。 • 空间数据的存取是IDL通过ODBC的瓶颈,往往如果能结合ORACLE的spatial功能,对于 空间数据的管理不失为一个好办法。 • 如果结合VB开发应用信息系统,应该是一个比较好的选择。
f92c68ee9ba765b401d89089616d40ad.ppt