基于ObjectARX的自定义面域研究
2013-06-26王健洁赵丽娟王晓帆王光昇
王健洁 ,赵丽娟,王晓帆,王光昇
(1.天津市测绘院,天津 300381; 2.天津市国土资源测绘和房屋测量中心,天津 300051)
1 引 言
在国内的测绘行业中,AutoCAD 一直是数据采集加工的主流软件,这主要是因为它方便易用,图形表现灵活多样,尤其是对线划图的表达更是其他制图软件所无法比拟的,所以在数字化测绘的历史进程中,AutoCAD 扮演了相当重要的角色。但在信息化测绘的今天,人们对地图的要求已经不是仅仅局限于图面了,而对信息的承载、获取、共享等方面提出了越来越多的需求。在这种情况下,矛盾就出现了,GIS 数据长于信息的表达,有很多人便提出了摒弃CAD,直接采集GIS 数据的建议,但显然,直接采集GIS 数据的技术手段并不成熟,同时我们也无法一下子就放弃AutoCAD 的巨大优势。发展不应该只有放弃,需要将CAD 与GIS 进行有效地融合,各取所长,寻找更合理的方案使得数据的采集满足信息化的测绘的需求。
天津市测绘院在地形图数据管理中大胆变革,将原来的图幅管理模式改为单元管理,避免了图幅接边问题,保证了数据的完整性,方便了外业修测,但在数据分发时仍需要按图幅裁切提供,在AutoCAD 中,对点、线的裁切分幅是可以用程序来完成的,但对于Hatch 填充面AutoCAD 并没有提供区域裁剪的工具,那么如何实现GIS 数据中的面那样能够任意裁剪呢,本文以自定义面域为例,探讨了如何将GIS 数据的功能有效地融合到AutoCAD 的图形元素中。
2 要素设计
在设计的面域元素时应该考虑到以下几方面问题。
2.1 任意裁剪
通过Clipper 类库实现面域的空间操作。Clipper类库是开源的多边形裁剪库,它可以实现多边形的相交(Intersection)、合并(union)、差异(difference)、异或(xor)、偏移(Offset)等操作,它能够处理复杂的多边形,如自相交、环岛多边形等,如图1所示。
图1 Clipper 类库
2.2 支持圆弧的裁剪
在一般的GIS 数据中是不支持圆弧的,而既然设计在AutoCAD 中表现面域,就需要解决面域中圆弧的裁切问题。
2.3 面域表现
在自定义实体类时,一般是从AutoCAD 基类派生,所以要选择适合表现复杂面的基类,这里选择从AcDbMPolygon 基类派生。
2.4 自定义要素属性
采用自定义实体的优势在于,可以对图形的表现以及与用户交互的接口进行全面的控制,使之符合地形图要素的要求。例如:
(1)定义编码属性
以前通过AutoCAD 对象的thickness 属性来记录编码信息,实际上这种方法是不合理的,因为thickness 在三维空间视图中用于表示目标的厚度。仅仅是由于thickness 允许用户修改,同时受限于以往的技术手段,才勉强这样去做了,当我们用自定义实体技术来定制要素的时候,可以解决这个问题。自定义实体中的属性和方法可以自由地定制,对编码属性而言,用一个字符串类型的成员就可以了,这样一个简单设计可以避免因为使用double 类型值带来的精度损失。
(2)定义要素名称
在自定义实体中,可以在属性面板中显示要素的名称,使得在AutoCAD 中表现的地形图要素更加直观,便于图面判读,如图2所示。
图2 显示要素名称
3 程序实现
3.1 创建自定义对象类
一般创建自定义实体需要建立两个工程,一个是DBX 工程,负责自定义实体的读、写、显示等操作;另一个是ARX 工程,包含了程序的入口点,用户在该工程中建立命令函数创建自定义实体对象实例,然后在AutoCAD 中加载运行。
为了方便起见,一般要在“项目依赖项”中设置ARX 工程依赖于DBX 工程,这样就不用在ARX 工程属性中明确写明所依赖的库文件了。
3.2 显示COM 接口属性
如果想在属性面板中显示自定义的属性,还必须建立一个COM 工程,为每个自定义实体类建立COM Wrapper 对象,然后在自定义实体类中实现subGetClassID 函数,最后在新生成的* _i.c 头文件中复制CLSID 并将其赋值给subGetClassID 函数的参数* pClsid,这样就建立起自定义实体类和COM 包装类的关系,如:
Acad::ErrorStatus CMyPolygon::subGetClassID (CLSID *pClsid)const{
assertReadEnabled ();
* pClsid=CLSID_MyPolygonCom;
return(Acad::eOk);
}
有了COM Wrapper 对象,我们就可以在AutoCAD中通过VisualLISP 创建和编辑自定义对象了。
3.3 注意事项
自定义实体工程不是必须要建立成DBX 类型,也可以建立成ARX 类型,二者的区别在于:DBX 工程是标准的自定义实体工程,可以加载到所有RealDWG 宿主应用程序中,如AutoCAD、VoloView 等;ARX 类型的应用程序只能加载AutoCAD 中,所以当我们的应用程序仅仅是应用在AutoCAD 环境中时,完全可以把自定义实体工程建立成ARX 工程,这样做的原因是,ARX应用程序有很多函数在DBX 工程中不支持,如acedAlert、acedRedraw 等以“aced”开头的函数,改成ARX 工程后,我们可以应用的功能函数更多。
3.4 引用Clipper 图形裁剪库
在互联网上可以很容易下载到Clipper 源程序,将其中的clipper.cpp、clipper.hpp 两个文件添加到自定义面域的工程中,默认情况下Clipper 代码中使用std::max、std::min 函数的地方会与C+ +编译器的全局函数冲突,导致编译错误,需要在工程属性的预处理器定义中添加预定义编译开关NOMINMAX。
假设定义如下的测试函数,用于实现两个CMy-Polygon 对象的裁判剪操作:
Bool DoExecute(CMyPolygon* poly_a,CMyPolygon* poly_b,ClipType clipType,double scale);函数实现思路如下:
定义3 个Polygons 变量:
ClipperLib::Polygons sub;
ClipperLib::Polygons clp;
ClipperLib::Polygons sol;
sub 是目标对象,clp 是剪切器对象,首先,从poly_a、poly_b 中读取闭合环坐标填充到sub 和clp 中,需要注意的是,从poly_a 和poly_b 中读取每个环的坐标时,首尾点是相同的,所以需要去掉最后一个点,这样符合Clipper 类中Polygon 的定义规则,然后,将两个多边形通过AddPolygons 方法填加Clipper 变量中,最后执行剪切操作:
Clipper clpr;
clpr.AddPolygons(sub,ClipperLib::ptSubject;
clpr.AddPolygons(clp,ClipperLib::ptClip);
bool succeeded = clpr.Execute(clipType,sol,ClipperLib::pftEvenOdd,ClipperLib::pftEvenOdd);
运行的结果保存在ClipperLib::Polygons 类型的参数sol 中。
3.5 面域中弧段的裁剪
在Clipper::Polygons 中多边形面中每个闭合路径是通过点表来描述的,所以对CAD 中的弧段需要进行圆弧加密,然后由加密后的点集组成多边形再进行裁剪操作,但是裁剪后的多边形无法复原被分隔后的圆弧信息,如图3所示。
面域1 中的圆弧AB 加密后为绿色线所示,以加密后的点形成的多边形与面域2 进行裁剪,点D 为其中的分割点,由点A 到点D 之间的绿色线是裁剪后的一条边,我们无法从这条边返回对应的圆弧信息,这样就会造成精度的损失,关于这种圆弧裁切的问题我们的解决方法是:
图3 圆弧加密前后的裁剪
首先,通过CAD 中的实体的相交关系找出多边形中的所有弧段,然后计算出每条弧段与另一多边形的各个边的交点,那么这些交点将弧段分隔成子弧段,然后再将子弧段加密,再通过Clipper 进行多边形运算,最后将运行结果中的点按照子弧段进行转换,即加密点转换成圆弧。
对圆弧进行加密可以直接通过ObjectARX 中的getSamplePoints 函数:
参数pointArray 存储从弧起点至终点的所有采集点,包括弧起点和终点。参数approxEps 为弦公差,即偏离一个光滑圆的可接受偏差,它既可用弦角度建立,又可用偏差来建立。弦公差会影响用来在屏幕上画圆圈的弦线的数目,弦公差越小,需要绘制的弦数越多,如图4所示。
图4 弦公差
由于已经存储了子弧段,在裁剪后的加密点返回圆弧的过程中只需要将那些落在子弧段上的点去掉可以了。
4 结 语
本文简要论述了在AutoCAD 中实现自定义面域的基本方法,并将GIS 中对面域的操作引入到自定义实体中。在今后的数据采集中我们可以继续发挥CAD 在线划数据采集上的优势,同时可以有效地借鉴GIS 在信息表达上的长处,将两者融为一体,更好地为信息化测绘服务。
[1]Autodesk.ObjectARX 开发指南[R].1999.
[2]老大中,赵占强.AutoCAD 2000ARX 二次开发实例精粹[M].北京:国防工业出版社,2001.
[3]Charles McAuley.AutoCAD 2000ObjectARX 编 程 指 南[M].北京:机械工业出版社,2000.
[4]张长勋.AutoCAD VisualLISP 程序开发技术[M].北京:国防工业出版社,2005.
[5]余承飞,方勇.AutoCAD 2000 二次开发技术(ObjectARX)[M].北京:人民邮电出版社,1999.
[6]宋延杭,王川,李永宣.ObjectARX 实用指南[M].北京:人民邮电出版社,1999.