基于ArcEngine 和Teigha.Net 的CAD 路径图输出方法
2023-03-11龚正国陈庆岩秦亚东
张 静,龚正国,梁 伟,陈庆岩,秦亚东,姚 远,王 林
(1.国网南阳供电公司,河南 南阳 473000;2.中国电力工程顾问集团中南电力设计院有限公司,湖北 武汉 430071)
ODA 是一个非盈利的组则,在40 多个国家有1 100多个成员。ODA致力于促进开放的、工业标准的CAD数据和遗留的CAD数据的格式交换。ODA开发用于技术图形应用程序的核心平台TeighaTM,Teigha支持dwg、dgn、stl、pdf之间的数据交换。Teigha支持的多个平台包括Windows、Mac、Unix、Linux 等[1-6]。本文采用Teigha.Net实现dwg文件的写入功能。
1 方法框架
本文基于ArcEngine 和Teigha.Net 的CAD 路径图,输出方法构建在统一的地理参考WGS84 坐标系统下,通过ArcEngine 获取路径信息和底图信息,利用Teigha.Net 写入dwg 文件中,以此实现路径图的输出,其原理如图1所示。
图1 方法原理图
实现CAD路径输出的关键是不同信息系统之间数据转换,需要将ArcGIS系统中的路径、材料信息和底图数据转化成CAD格式的路径图及注记,并添加选择的图框样式。ArcGIS系列软件作为地理信息专业处理和管理系统,在矢量和栅格数据管理方面能力出众,具有丰富的空间信息,CAD更加偏重于矢量数据的管理,针对栅格数据处理能力较弱,针对2 个平台的不同要点,可以将对应的信息转换分解为3 个方面:栅格、矢量和图框分别进行处理。针对栅格数据,利用ArcEngine中栅格数据处理模块并结合.Net平台自带的图像功能,完成栅格数据的转换输出,作为独立数据文件关联到最终成果中[7]。针对矢量数据,利用Teigha.Net 进行矢量信息写入CAD,线状地物直接作为线实体写入,点状要素需要读取对应的dwg 格式的图放入对应位置以符号化形式显示。针对图框,图框作为裁剪栅格的范围比例,在分幅出图的过程中使用图框参数,最终图框需要根据栅格数据的大小进行一定比例的缩放,叠加到CAD 图中[8]。因此,本文设计的基于ArcEngine和Teigha.Net的CAD路径图输出方法流程如图2所示。
图2 方法流程
2 CAD路径图输出方法
基于ArcEngine和Teigha.Net的CAD路径图输出方法包括栅格输出,矢量转换以及图框的叠加。
2.1 栅格数据输出
栅格数据由于来源的不同,例如卫星数据、航摄数据以及其他来源数据,大小和分辨率不一致,在栅格数据的输出中需要根据输出范围的大小进行重采样,降低栅格数据的输出大小。同时,由于添加了在线地图天地图的服务,这种数据采用自定义显示方式,没有继承ArcEngine 自带的IRasterLayer,需要采用特殊的方式进行输出。针对以上情况,本文实现3种栅格数据的输出函数:ArcEngine 自带函数封装、C#自带Bitmap操作封装以及针对在线地图天地图特殊输出处理。
针对ArcEngine 自带栅格数据的输出函数,可以进行栅格数据的输出,优点是可以进行详细的设置,例如栅格数据的重采样,缺点也很明显,功能复杂输出速度慢。封装的函数中,设置输出的图层源、输出范围、存储定义以及输出像素的个数(int x, int y)。输出像素的个数决定了重采样的比例,例如输出栅格范围内的像素个数为10 000×10 000,而输出像素设置为1 000×1 000,那么最终的影像个数为1 000×1 000,这些值会根据10 000×10 000 个像素进行重采样得来的。本文考虑到像素过多最终CAD显示的影响以及输出效率的问题,会将影像进行重采样设置,控制影像的范围[1]。判断的依据是输出栅格范围内的影像的宽度或者高度。
针对C#自带Bitmap的操作函数,也可以用于栅格数据的写入,需要自己获取每一个点像素值,逐像素写入。其优点是写入快效率高,缺点是无法处理大范围影像,影像过大会导致程序内存占用过高。首先申请一个对应影像大小的Bitmap 以及对应的BitmapData,设置对应大小的byte。根据RasterLayer 的数据组织格式,将输出范围划分成128×128大小的块,分别读取对应像素值写入对应byte中。直到所有的信息都写入byte 之后,一次性将所有信息拷贝进BitmapData对象中,最后写入影像文件。需要注意的是,bmpData.Stride 应该等于bmpWidth,但实际上往往不相等,要差几个字节,因为bmpData.Stride 必须是4 的倍数,如果不足,则补上几个字节,让bmpData.Stride是4的倍数,这些多余的字节不会存储任何颜色数据,如果直接令bmpData.Stride=bmpWidth,会导致影像集体右偏移。针对大栅格数据写入导致的内存不足问题,主要是在.NET 中,所有大对象都是分配在另外一个特别的连续内存(LOH)中的,而且,每个大对象在创建时即属于G2,也就是说只有在进行Generation 2的垃圾回收时,才会处理LOH,而且在对LOH 进行垃圾回收时不会压缩内存。更进一步,LOH 上空间的使用方式也很特殊。当分配一个大对象时,运行时会优先尝试在LOH 的尾部进行分配,如果尾部空间不足,就会尝试向操作系统请求更多的内存空间,只有在这一步也失败时,才会重新搜索之前无效对象留下的内存空隙。如果这一步也失败,就会出现内存不足的错误。
在线地图天地图是国家基础地理信息中心建设的网络化地理信息共享与服务门户,向各类用户提供权威、标准、统一的在线地理信息综合服务。本平台可以调用天地图影像服务和地名服务作为底图,进行线路规划。天地图作为独立在线地图的提供方,ArcEngine 中并没有直接的办法进行数据的显示,需要自定义扩展天地图的显示,扩展的核心理念是利用当前地图控件范围的空间位置,根据分辨率计算对应的天地图切片数据图块,通过网络请求获取对应的影像,绘制在地图控件上。由于天地图数据是自定义实现显示,没有实现IRasterLayer 对应接口,不能采用ArcEngine 自带函数或者.Net 自带函数进行栅格数据的输出,.Net 自带函数也利用了IRasterLayer 的像素获取功能。本文利用地图控件的打印输出功能顺利解决这个问题。在天地图栅格数据输出前只显示天地图数据,然后地图控件将输出范围的影像输出为影像文件,之后将其他图层再显示在地图控件上。
3 种栅格输出都有优缺点以及适用的范围,根据栅格数据判断是否是天地图,确定是,则采用天地图输出方法,不是就根据影像的范围再次进行判断,范围过大采用ArcEngine 自带封装函数输出,否则就采用C#自动函数输出。
2.2 矢量输出
矢量输出考虑的关键点是找到ArcGIS平台和CAD平台对矢量图层组织方式的相同点和不同点,找到数据在两者之间转换的对应关系。在ArcGIS中,单一图层里有很多种样式。在CAD中,只能分散到各层,每个层一个样式。这样转出来以后,图层会比ArcGIS中的要多。根据分析,进行矢量数据的输出可以分解为①在CAD 中建立图层样式;②根据数据的样式不同,将数据写入对应的图层。
在建立图层样式之前,需要初始化CAD 对象,这是采用Teigha.Net 封装的CAD 文件管理类,可以操纵CAD 文件,包括创建图层和写入数据等。建立图层样式就是将单一ArcGIS 图层多个样式映射到多个CAD 图层过程,由于本文渲染是根据某一个属性字段来进行的,只需要根据不同的属性字段值建立对应的图层即可,创建的图层还需要根据ArcGIS图层矢量类型设置CAD 图层对应的线宽和颜色等属性。
建立完图层样式,就需要将数据写入图层。遍历图层,获取要素,根据要素的渲染字段找到对应的图层,写入矢量数据。要素分为点线面,在本文应用中暂时只用到了点和线数据,针对点和线数据分别进行处理。针对线数据,将要素转换为点集合,定义CAD 中线对象OdDb2dPolyline,将点集合存入对象中,设置线型。针对点对象,获取点的渲染名称,根据名称获取dwg格式的图块,将图块写入对应的CAD图层中。
标注的摆放位置,由于路径图的走向不固定,无法设定唯一的标注倾斜方向,需要根据路径的方向实时计算结果。同时,针对点要素,如果存在邻接的线,需要根据邻接的线方向作为点要素标注的放置方向。需要特别注意的是,选择的Teigha.Net 平台存在角度达到临界值之后,就是靠近PI∕4.0,会导致计算的偏移靠近直线;如果给角度加上PI∕2,会导致靠近角度和坐标轴的点靠近直线,只能通过判断角度来重新生成角度规避。
2.3 图框叠加
图框的叠加就是将提前选好的dwg 图框插入对应的dwg 中,主要需要考虑比例的缩放,将图框放到对应的位置[9]。
图框边框分为外边框和内边框和数据叠加的范围是内边框范围,示意图如图3 所示。内边框从左下角起始点整个贴合栅格底图,缩放比例按照内边框的范围和影像的范围来计算,具体公式为:
图3 图框示意
式中,scaleX为X方向缩放系数如式(1);scaleY为Y方向缩放系数如式(2);imageWidth 和imageHeight为影像范围的地理坐标宽度和高度;frameWidth 和frameHeight为图框在CAD代表的宽度和高度。生成结果可以在AutoCAD正常打开,编辑等操作也正常。
3 结 论
本文提出基于ArcEngine 和Teigha.Net 的CAD 路径图输出方法,根据ArcGIS 平台的数据利用Teigha.Net 生成CAD 路径图,首先根据栅格数据,导出影像地图,接着转换矢量数据,最后添加图框。结果表明,本文方法能有效解决没有AutoCAD 环境下的CAD 路径图输出的问题,减少了配网软件中对其他组件的依赖。后续需要进一步优化输出细节及生成速度。