ArcGIS Engine开发中复杂符号的实现
2016-07-19魏志明
魏志明,李 家
(辽宁师范大学 城市与环境学院,辽宁 大连 116029)
ArcGIS Engine开发中复杂符号的实现
魏志明,李 家
(辽宁师范大学 城市与环境学院,辽宁 大连 116029)
摘要:提出了地图符号概念:以ArcGIS Engine作为二次开发平台,利用ArcGIS Engine组件库所提供的接口,采用C#开发语言,实现在ArcGIS Engine中对条件符号、多层符号(如铁路符号等)、唯一值符号的制定。分析了实现过程中所涉及的接口及接口中的相关属性与方法。程序运行结果表明:基于ArcGIS Engine二次开发平台,可以实现复杂符号的定制。
关键词:地图符号;ArcGIS Engine开发;条件符号;多层符号;唯一值符号
1前言
地图符号是地图的图解语言,是表示地图内容的基本手段[1]。空间中的地物依据其几何外观,可以抽象划分为点状、线状、面状3种类型。因此按空间分布情况,可相应地将地图符号分为点状符号、线状符号和面状符号[2]。既专业又形象的地图符号可以更加生动的表达地图的内容与含义[3,4]。虽然人工可以对图层符号进行设置,但在动态生成图层的情况下,需要根据具体需求通过开发语言编程实现符号的定制,可以大大地提高工作效率。例如大量的环境监测数据平时存储在Oracle数据库中,根据实际需要,要对监测数据进行动态生产如ArcGIS图层格式的文件,此时则要根据图例规范自动定制图层符号,而不能通过人工去逐层更改。故无论是在地图制图系统中,还是在地图信息系统中,地图符号的制作与研究都是具有重要意义[5]。
2地图符号概括
地图符号从广义上讲是表示各种事物现象的线划图形、色彩、数学语言和记注的总和,也称为地图符号系统。而狭义的地图符号是在图上表示制图对象空间分布、数量、质量等特征的标志和信息载体,包括线划符号、色彩图形和注记。
客观世界的事物错综复杂,人们根据需要对它们进行归纳(分类、分级)和抽象,用比较简单的符号形象地表现它们,不仅解决了描绘真实世界的困难,而且能反映出事物的本质和规律。因此,地图符号的形成实质上是一种科学抽象的过程,是对制图对象的首次综合[7]。
3ArcGIS中符号概述
3.1符号分类
空间上的任何地物以其几何外观来划分,可以抽象划分为点状、线状、面状3种类型[2]。在ArcGIS中包含点状符号、线状符号、面状符号以及注记符号。其中注记作为一种特殊的符号,说明这些点、线、面的某些属性,可以类似于点状符号来处理[8]。
ArcMap中的将点状符号分为6种。分别为3D标记符号、3D简单标记符号、3D字符标记符号、地图标记符号、简单标记符号、箭头标记符号和图片标记符号。
3.2标注与注记
3.2.1标注
地图上用来识别地图要素的文本称为标注(Label),其可以帮助地图读者更好地理解地图含义。标注在ArcMap中表示图层的属性,可动态创建,可用于说明地图上要素的名称、性质和数量等具体特征。它弥补地图符号的不足,丰富地图的内容,并且在某种程度上还可以起到符号的作用,使地图具有可读性、可译性以及成为一种信息传输工具。
3.2.2注记
在地图上起说明作用的各种文字、数字,统称注记。注记常和符号相配合,说明地图上所表示的地物的名称、位置、范围、高低、等级、主次等。注记以更加复杂的方法和属性来对要素的图层进行标记,同时作为地理要素被储存。每个注记都可以被独立操作,可以选择是否和其他要素相关,注记也可以由其他数据转换而来。注记可分为名称注记、说明注记、数字注记。为了鲜明、正确、便于读解的目的,注记的字体、规格和用途必须有统一规定。
3.3TrueType字体
TrueType是由Apple公司和Microsoft公司联合提出的一种新型数学字形描述技术。它用数学函数描述字体轮廓外形,含有字形构造、颜色填充、数字描述函数、流程条件控制、栅格处理控制、附加提示控制等指令。TrueType采用几何学中二次B样条曲线及直线来描述字体的外形轮廓,其特点是其既可以作打印字体,又可以用作屏幕显示;由于它是由指令对字形进行描述,因此它与分辨率无关,输出时总是按照打印机的分辨率输出。无论放大或缩小,字符总是光滑的,不会有锯齿出现。ArcGIS字体符号都是TrueType字体(.TTF),其最大的特点就是它是由一种数学模式来进行定义的基于轮廓技术的字体,这使得它们比基于矢量的字体更容易处理,保证了屏幕与打印输出的一致性。
4复杂符号的实现
所谓复杂符号是相对于简单符号而言的。复杂符号是由多个TrueType字体符号通过叠加、位移、组合等设置而形成的,而简单符号仅由单一TrueType字体符号形成。如图1所示,对水深点的深度属性进行了标注。标注点图1A将水深点的深度属性通过程序代码而表达成更加符合现实海图中水深点符号的形式,并将标注作为要素符号显示在地图上,而标注点图1B仅通过ArcMap软件动态创建水深点的深度标注,与现实生活中海图水深点的习惯表达方式不相符;由此也可以看出,复杂符号在表达地图含义等方面,相对于简单符号更具有优势,故而复杂符号的设计对地图完整含义的表达具有重要的价值。
图1 水深标注分布
4.1条件符号
4.1.1概念
条件符号就是根据图层中某一属性要求确定的符号。将图层的某几个属性通过脚本语言进行判断,返回一个字符串作为符号显示在地图位置上用以解释该要素属性的具体意义。同一图层中各要素因其属性值的不同表现为不同的符号。
4.1.2实现代码
条件符号的实现代码如下。
(1) 获取当前图层。利用IGeoFeatureLayer接口去定义一个图层变量,指向axMapControl控件的一个图层。
(2)获取标注集。在函数中定义IAnnotateLayerPropertiesCollection(注释层属性集合)接口变量 coll,将coll变量指向当前获取图层的注记属性,即用AnnotationProperties来获取当前图层的标注集(标注集与某个要素图层相关联,用于描述要素图层是如何被标记的)。若coll不为空,则用Clear方法将coll置空,再重新设置要素标注集。若coll为空,则将coll定义为AnnotateLayerPropertiesCollectionClass集合对象并指向当前图层的标注集。
(3)设置标注布局。定义IPointPlacementPriorties接口place变量来完成对标注位置布局的设置。用变量place 控制要素标注的位置。利用接口中的AboveCenter、AboveLeft、AboveRight、BelowCenter、BelowRight、CenterLeft、CenterRight7个属性设置标注的具体位置。
(4)设置标注位置与样式。IBasicOverposterLayerProperties接口定义的basic变量可以用于对标注文本的位置以及标注文本的样式进行具体设定,将basic指向BasicOverposterLayerPropertiesClass。esriBasicOverposterFeatureType是一个提供标签功能的枚举类型,其中包括esriOverposterPoint、esriOverposterPolyline、esriOverposterPolygon三个常量。设置basic的要素类型为esriBasicOverposterFeatureType的esriOverposterpoint常量值;将basic变量的标签放置位置的优先选择属性指向控制标签布局的place变量。
(5)要素属性字段的获取与设置。获取符号某个字段的属性值与样式的设置需要添加JavaScirpt语句。IAnnotationExpressionEngine接口提供的方法可以访问基于标签属性生成的JavaScirpt脚本信息。故而应首先定义一个AnnotationJScriptEngineClass类型的变量jsEngine,并且指向AnnotationJScriptEngine对象。再新建一个图层标注引擎对象label,用来对图层标注属性进行相关的设置。ILabelEngineLayerProperties接口提供了相关属性的设置,定义ILabelEngineLayerProperties接口变量label指向LabelEngineLayerPropertiesClass()对象,将label是否是简单表达式属性设置为否,利用label的Expression属性,运用JavaScript语言来设置标注表达式。在代码中加入的JavaScirpt脚本代码是根据要素的具体属性进行的符号设置,创建名为FindLabel的函数,获取要素deep的属性值,若属性值中含小数点,则定义一个变量n保存小数点的位置,返回属性值中小数点前面的字符串;如果不包含小数点则返回传来的属性值。并将Label的ExpressionParser属性指向脚本解析器的对象jsEngine。BasicOverposterLayerProperties属性用于指向确定标注位置的变量basic。
(6)字体设置。利用命名空间stodle的IFontDisp接口定义变量font,用于设置字体信息。变量font的name属性设置字体为宋体。label的Symbol.Size属性用于设置字体大小、Font属性设置字体类型为宋体。通过ISimpleTextSymbol接口的YOffset属性设置文字符号的y轴偏移量。通过coll变量的Add属性增加这个文字符号到标注集中。
(7)属性字段小数点后字符的设置。按照上述的顺序重新定义一个LabelEngineLayerPropertiesClass类的变量label,根据要素属性重新设置label变量的IsExpressionSimple、Expression、ExpressionParser、BasicOverposterLayerProperties属性,重新指向字体类型、文字大小、横纵轴偏移位置。在Expression属性中的JavaScript脚本代码中获取deep字段小数点后面的数值。最后通过coll变量的Add属性增加另一个文字符号到标注集中。
(8)显示标注。将IGeoFeatureLayer接口的DisplayAnnotation属性值设置为true,显示该图层的标注。
(9)渲染图层。定义ISimpleRenderer接口变量simpleRender指向geoFeatureLayer图层的Renderer属性,用于对该图层进行渲染。利用循环语句分别访问符号的每一层,并对颜色进行设置。IColor接口提供访问颜色的成员。定义一个IColor接口的变量pColor,将变量mSymbol每层的Color属性指向变量pColor,使该符号的颜色为无色IColor接口的NullColor属性赋予true,设置每层颜色为无色。否则定义ISimpleMarkerSymbol接口变量markerSymbol指向simpleRender变量的Symbol属性,用来确定该渲染器中的Symbol属性。ISimpleMarkerSymbol接口的Outline属性赋予false,使该符号无轮框线。代码如下:
ISimpleRenderer simpleRenderer = geoLayer.Renderer as ISimpleRenderer;
if (simpleRenderer.Symbol is IMultiLayerMarkerSymbol)
{
IMultiLayerMarkerSymbol mSimbol = simpleRenderer.Symbol as IMultiLayerMarkerSymbol;
IColor pColor1 = new RgbColor();
for (int i = 0; i < mSimbol.LayerCount; i++)
{
mSimbol.get_Layer(i).Color = pColor1;
pColor1.NullColor = true;
mSimbol.get_Layer(i).Color = pColor1;
}
}
else
{
ISimpleMarkerSymbol markerSymbol = simpleRenderer.Symbol as ISimpleMarkerSymbol;
IColor pColor = new RgbColor();
pColor.NullColor = true;
markerSymbol.Color = pColor;
markerSymbol.Outline = false;
}
(10) 刷新图层。利用AxMapControl控件的Refresh方法对图层进行刷新。
4.2多层符号
4.2.1多层符号
多层符号即具有简单性又具有复杂性。多层符号的简单性体现在于对叠加的层数没有限制,可根据地理要素属性的具体要求自由组合;复杂性则是在进行编码之前需要了解各种符号类型,以便更准确的选择符号。
4.2.2多层点状实现代码
多层点状符号的实现可以分为如下步骤。
(1) 获取当前图层。获取当前图层最简便的方法是直接利用IGeoFeatureLayer接口定义一个图层变量。
(2) 获取颜色值。IRgbColor接口提供访问控制RGB颜色值的成员。定义IRgbColor接口变量rgbColor获取自定义函数getRGB的返回值。
(3) 符号样式设置。FontDisp接口用来定义新的字型。利用命名空间stdole的IFontDisp接口定义变量font,将变量font的Name属性指向ESRI系统自带符号样式ESRI Business。Bold属性用来表示符号的边框是否加粗,返回bool值。
(4) 符号属性设置。ICharacterMarkerSymbol接口提供访问控制字符的标记符号的成员,该接口的Font、Size、Color以及CharacterIndex属性分别用来描述标记符号的字体类型、大小、颜色以及在某一字体中的字符索引。定义一个ICharacterMarkerSymbol接口的变量symbol,将该变量的Font属性指向int型变量font,Size属性赋值为50,Color属性指向IRgbColor接口的rgbColor变量,CharacterIndex属性赋值为33,相当于在该字体中指定第33个符号。
(5) 添加符号层。IMultiLayerMarkerSymbol接口提供存取控制多层标记符号的成员,该接口的AddLayer方法用来添加标记符号。定义IMultiLayerMarkerSymbol接口变量multiLayermrkSymbol,调用该接口的AddLayer方法,传入symbol参数,在符号层中添加第一层符号。
创建第二层符号时,就是重复上述的编码过程,重新定义IRgbColor接口变量rgbColor1。利用IFontDisp接口新建变量font1,将该变量的Name属性指向字体类型为华文彩云,Bold属性为true。定义ICharacterMarkerSymbol接口变量symbol_1,将该变量的Font属性指向int型变量font,Size属性赋值为60,Color属性指向IRgbColor接口的rgbColor变量,CharacterIndex属性赋值为42。最后利用IMultiLayerMarkerSymbol接口的AddLayer方法传入symbol_1参数,在符号层中添加第二层符号。
(6) 渲染多层符号。定义ISimpleRenderer接口变量render,将变量render的Symbol属性指向IMultiLayerMarkerSymbol接口变量multiLayermrkSymbol,来绘制双层符号。将geoFeatureLayer图层的Renderer渲染器属性指向render变量。
(7) 刷新图层。利用AxMapControl控件的Represh方法对图层进行刷新。
4.2.3多层线状符号的实现
多层线状符号以铁路符号为例,分别设置黑白两个线状符号,通过在新图成上将线状符号叠合而成。
(1)设置底层简单线状符号。利用 ILineSymbol接口定义一个新的线状要素集并利用接口中的Color获取颜色,利用 ILineSymbol接口中的Width定义底层黑色线状符号的宽度。
(2)设置上层线状符号。利用ICartographicLineSymbol接口定义一个新的线状要素集并利用接口中的Color获取颜色,利用 ILineSymbol接口中的Width定义上层白色线状符号的宽度。
(3)设置上层白色线状符号间隔。定义ITemplate接口变量,并利用ITemplate接口中的Interval设置白色线状符号的间隔为10。使用ITemplate接口中AddPatternElement绘制线状符号与留白的比率为1:1。设置偏移量为0。
(4)叠合图层。IMultiLayerMarkerSymbol接口提供存取控制多层标记符号的成员,该接口的AddLayer方法用来添加标记符号。定义IMultiLayerMarkerSymbol接口变量multiLayermrkSymbol,调用该接口的AddLayer方法,传入symbol参数,在符号层中添加底层符号。重复上述方法在添加上层符号。
(5) 渲染图层。定义ISimpleRenderer接口变量rende。将geoFeatureLayer图层的Renderer渲染器属性指向render变量,渲染图层。
4.3唯一值符号
唯一值符号是根据要素的一个或几个不同属性字段的值,给每个要素一个单独的颜色符号,从而区分每一个要素。这其中的颜色选择是根据具体的需要,在进行编码之前进行相应的筛选,对于属性字段的选择同样是在实现编码之前进行筛选。唯一值符号可以清晰地表示出每一个要素的区别,但它也具有局限性,唯一值符号的实现对属性字段的值有相应要求,即各个要素的属性值必须不同的,否则符号一致。
实现唯一值符号可以分为如下6个步骤。
4.3.1 构建颜色带
唯一值符号的实现不仅需要构建获取颜色函数,也要构建创建颜色带的函数:private IColorRamp CreateAlgorithmicColorRamp(int count),其中函数中的参数count为颜色梯度个数。函数中的代码可以分为如下几个主要部分。
(1)创建颜色梯度成员。IAlgorithmicColorRamp接口提供访问控制颜色梯度算法的成员,故定义IAlgorithmicColorRamp接口变量algColorRamp。IRgbColor接口提供访问控制RGB颜色值的成员,定义IRgbColor接口fromColor变量为开始颜色,toColor变量为结束颜色。
(2)设置起始与结束颜色。通过变量fromColor和toColor的Red、Green和Blue属性设置开始颜色和结束颜色。
(3)颜色梯度设置。IAlgorithmicColorRamp接口的FromColor属性用来获取颜色梯度中的第一个颜色,ToColor属性用来获取颜色梯带的最后一个颜色。IAlgorithmicColorRamp接口的Algorithm属性用来设置颜色梯度类型,esriColorRampAlgorithm枚举用来指定颜色梯度,其中一种枚举常量是esriCIELabAlgorithm,它的属性值为1。将algColorRamp变量的FormColor属性指向toColor 变量,ToColor属性指向fromColor变量,Algorithm属性指向esriColorRampAlgorithm . esriCIELabAlgorithm恒量,Size属性赋值为count。
(4)要素属性字段的获取与设置。定义一个bool值变量bture,赋值true。IAlgorithmicColorRamp接口的CreateRamp方法根据确定的梯度长度属性值生成颜色梯度。给algColorRamp变量的CreateRamp方法一个bool值参数,最后返回一个颜色梯度。
4.3.2获取当前图层
用IGeoFeatureLayer接口定义一个图层变量。
4.3.3设置渲染对象
IUniqueValueRenderer接口提供访问唯一值属性符号的渲染器的对象,定义IUniqueValueRenderer接口的变量uniqueValueRenderer,将该接口表示确定唯一值的字段个数的属性(FieldCount)设置为1,用于设置具体的属性字段名称方法(set_Field方法)的第二个参数设置为name。
4.3.4符号填充
SimpleFillSymbol是简单填充符号的接口,esriSimpleFillStyle类是用来描述符号样式。定义 SimpleFillSymbol接口变量 SimpleFillSymbol,将该变量的 Style 属性赋为esriSimpleFillStyle枚举的esriSFSSolid常量。
4.3.5获取游标遍历要素
IFeatureCursor接口可以遍历选定的要素。定义IFeatureCursor接口变量featureCursor指向geoFeatureLayer,调用IFeatureClass接口的Search方法,获取游标。如果游标featureCursor不为空,则定义IEnumColors接口变量enumColors接收CreateAlgorithmicColorRamp函数返回的Color属性值,同时给CreateAlgorithmicColorRamp函数传入40作为颜色的梯度的个数。定义一个int型变量fieldIndex通过geoFeatureLayer变量调用FeatureClass类的Fields属性的FindField方法,获取属性字段name的索引。IFeatureCursor接口的NextFeature方法用来返回游标中的下一个要素。通过while循环,获取每个要素的name字段的值,同时利用IEnumColors接口的Next方法获取颜色梯度值,赋给一个SimpleFillSymbol对象。通过IUniqueValueRenderer接口的AddValue方法传入字段值、字段名称和需要填充的符号,就可增加一个唯一值符号层。
4.3.6实现渲染并刷新图层
将geoFeatureLayer图层变量的Renderer属性设置为uniqueValueRenderer变量改变该图层的渲染效果,利用AxMapControl控件中的Refresh方法对图层进行刷新。
5结语
对ArcGIS中的符号以及标注与注记等相关内容做了大致的说明,并着重对以ArcGIS Engine作为开发平台,采用C#开发语言实现条件符号、多层符号和唯一值符号的制定做了具体分析。通过对复杂符号的实现,探究摸索了ArcGIS Engine中与复杂符号定制相关的接口的用途以及使用方法。从而得出这样的结论:基于ArcGIS Engine二次开发平台,不仅可以实现复杂符号的制作,而且还可以根据需要,把要实现的各种功能组件搭建起来,从而实现地理信息系统的灵活应用和功能扩展。
参考文献:
[1]胡庆武.基于MapObject的地图符号库设计[J].测绘学报,2001(10).
[2]姜琦,周晓光.基于ARCGIS土地利用现状图符号化的探讨[J].地理信息世界,2012(2).
[3]刘洪光. 基于ArcGIS的地质灾害地图符号库设计与实现[J]. 国土资源遥感,2011(1).
[4]刘志军.基于ArcGIS的空间数据符号化研究[J].海洋测绘,2010(1).
[5]赵成福.基于ArcGIS+Engine的符号化研究与实现[J].地理空间信息,2009(4).
[6]何忠焕.GIS符号库中复杂线状符号设计技术的研究[J].武汉大学学报,2004(2).
[7]陶陶,闾国年.GIS地图符号共享研究进展与展望[J].中国气象图像学报,2008(8).
[8]杨杰,廖胜利.基于AE二次开发的地图符号的实现[J].四川测绘,2007(2).
[9]邱洪刚,张青莲,陆绍强.ArcGIS Engine开发从入门到精通[M].北京:人民邮电出版社,2010.
[10]赵江洪,殷赣华.通用地图符号库的算法设计及其实现[J].测绘通报,2002(4).
[11]张俊岭,夏武,熊卫东.基于ArcGIS+Engine的地图符号制作工具的设计实现[J].测绘信息与工程.2006(5).
[12]谭浩强.C语言程序设计[M].3版.北京:清华大学出版社,2009.
[13]李崇贵,陈峥.ArcGIS Engine组件式开发及应用[M].北京:科学出版社,2012.
The Realization of Complex Symbols in Development ofArcGIS Engine
Wei Zhiming,Li Jia
(CollegeofUrbanandEnvironmentalSciences,LiaoningNormalUniversity,Liaoning116029)
Abstract:At the beginning, the overview of map symbol was briefly presented. Based on the second development platform of ArcGIS Engine, the customization of conditional-symbol, specific symbol such as railway sign of ArcGIS Engine and unique value render function are developed in C# by using module class, interface, methods and types from ArcObjects component library. What’s more, it emphatically describes all of the interfaces and their attributes and methods that are involved in the implement procedure. The results showed complex symbols can be designed with the second development platform of ArcGIS Engine, having a certain reference value to customize complicated signs and develop GIS.
Key words:map symbol;ArcGIS Engine;conditions symbol; multilayer symbol; unique value symbol
收稿日期:2016-04-14
作者简介:魏志明(1991—),男,辽宁师范大学城市与环境学院硕士研究生。
中图分类号:P208
文献标识码:A
文章编号:1674-9944(2016)10-0225-05