熊忠招,陶彣君
(1.湖北省国土测绘院,湖北 武汉 430010)
基于AutoCAD二次开发的CASS地物直角化算法改进
熊忠招1,陶彣君1
(1.湖北省国土测绘院,湖北 武汉 430010)
针对因数字化误差或策略误差造成地物角点不是直角而需进行修正的问题,提出了一种基于AutoCAD的,既能保证地物角点正确直角化,又能保证纠正后顶点偏离原始顶点的坐标值尽可能小的高效算法。实践表明,该算法能够高效完成地物直角化的工作,简单易行,可满足实际生产需要。
AutoCAD;直角化;二次开发;CASS
随着计算机技术的飞速发展,GNSS﹑无人机等一 大批新兴技术越来越多地融入到测绘数据采集中,在利用计算机进行地形图绘制或对已有纸质地形图进行扫描矢量化时[1-6],常会出现某些地物所有或某些顶点需要直角化的情况。传统做法是采用手工方法对需要直角化的顶点进行纠正,或将地形图导入其他具有直角纠正功能的商业软件中进行纠正,不仅效率低下,且有可能得不到想要的直角纠正结果。图1为使用CASS软件自带的直角纠正功能对地物进行直角纠正的结果(虚线为纠正前的图形,实线为纠正后的图形)。对比纠正前后图形可知,图形发生了翻转,与原图形偏差巨大,完全不满足直角纠正的要求。
图1 CASS软件直角纠正功能纠正后效果图
鉴于此,本文结合已有商业软件和算法的优势,对这些算法进行优化,提出了一种以每条边中点为旋转基点,结合顶点内角判定方法进行直角纠正的高效地物直角化算法,以满足对地形图地物直角化的需求。
1.1 线段不同位置构建直角效果对比
图2中ABCD为一个四边形,其中∠B和∠C不是直角,需对这两个角进行直角化。该图形中可以AB边为基准,将BC边纠正为与AB边垂直。
图2 线段不同位置构建直角效果对比图
通过BC边上的任意一点作AB边的垂线,即可得到∠B纠正后的新位置。虽然可有任意多种作直角的方式,但存在3种特殊情况:
1)以顶点B为基准,过顶点B作AB边的垂线,即BC″边,此时顶点B相对于纠正前的偏离距离为0,顶点C相对于纠正前的偏离距离为CC″。
2)通过BC边的中点M作AB边的垂线,相交于B′点,此时顶点B相对于纠正前的偏离距离为BB′,顶点C相对于纠正前的偏离距离为CC ′。
3)以顶点C作为基准,过顶点C作AB边的垂线,此时顶点B相对于纠正前的偏离距离为CC″,顶点C相对于纠正前的偏离距离为0。
综合上述3种情况可以看出,第二种方法最为合理,能使多边形中各顶点的偏离距离基本保持一致,不会存在偏离过大或过小的情况,本文采用该方法。
1.2 以最接近90°顶点进行直角构建
图3为图4中的顶点C的局部图,∠C是与90°最为接近的角,故对该图形进行直角化应该从顶点C开始。建立初始边的具体步骤为:①计算BC边和CD边的中点,以各自边的中点作为该条边后续的旋转基点。②将各顶点处的内角值与90°进行比较:若该顶点处的内角值大于90°,则将该顶点相邻两条边各自往多边形的外部旋转差值的一半(否则会导致该顶点新位置偏离原始位置过大,旋转后得到的新位置是所有方法中偏离原始位置最小的);若小于90°,则向多边形内部旋转差值的一半。如图3所示,顶点C未处理前的内角为89°,小于90°,故将顶点C相邻两条边各自往多边形内部旋转一半,得到新的交点C ′,此时该顶点变为90°,顶点C的位置更改为新位置C ′,即完成了对顶点C的直角化,也为后续各顶点的直角化建立了基准。
图3 以最接近90°顶点进行直角构建示意图
图4 四边形ABCD的各顶点内角值
1.3 算法实现步骤
在考虑影响重构闭合多边形各条边方向和各顶点位置等诸多因素的基础上,本文设计算法实现的具体步骤为:
1)判断多边形是否闭合。如图4所示,ABCD是一个具有4个顶点的多边形,要将该地物的各内角直角化,需要对闭合多边形进行判断。首先必须判断该多边形是否闭合,若该多边形为闭合多边形则继续执行后续步骤,否则不处理。
2)判定多边形的顶点个数。在绘图软件中,利用多段线进行地物绘制时,当顶点≥2个,即可让该多段线闭合,而此时所绘制的地物是不能用于进行直角纠正的,故需将顶点<4个的多边形排除,不作处理。
3)判断整个多边形中是否有某一条边平行于UCS的X轴或Y轴。具体方法为:①利用AutoCAD提供的方法获取整体多段线的顶点坐标;②依次计算相邻两个点是否存在X坐标或Y坐标相等的情况,若存在,则表示该多边形存在某一条边平行于UCS的X轴或Y 轴,记录该条边并结束判断,否则继续判定其他顶点。
4)若步骤3)中判定出存在某一条边平行于UCS的X轴或Y轴,则以该条边为基准,以顺指针或逆时针方向,依次从各条边的中点作上一条计算结果边的垂线,从而得到各顶点新的坐标位置,待循环完成一 周则可将整个多边形进行直角化。
5)若步骤3)中判定为不存在某一条边平行于UCS的X轴或Y轴,则需要计算各顶点处该多边形的内角值(图4),并将所有内角值与90°进行比较,找出差值最小的一个顶点。
6)在与90°最接近的顶点处构建一个直角,以便将该顶点直角化,待找出第一个顶点位置后,按照步骤4)循环处理每一条边,即对整个多边形进行直角化。
1.4 程序流程图
结合实际程序设计,对地物进行直角化的程序如图5所示。
图5 直角纠正的流程图
2.1 算法实现
本算法利用ObjectARX .NET编写程序,并在AutoCAD下测试通过[7-12]。其具体的核心实现代码为:
‘开始事务处理,也就是往CAD中加入东西
using (Transaction trans = tm.StartTransaction())
{
BlockTable bt = (BlockTable)tm.GetObject(db.BlockTableId, OpenMode.ForRead, false);
BlockTableRecord btr = (BlockTableRecord)tm.GetObject(b t[BlockTableRecord.ModelSpace], OpenMode.ForWrite, false);
‘遍历建立选择实体的ObjectID集合
foreach (ObjectId obj in objs)
{
Entity ent = trans.GetObject(obj, OpenMode.ForWrite) as Entity;
if (!(ent is Polyline))
continue;
Polyline pl = ent as Polyline;
if (pl.Closed == false)
continue; ‘必须是闭合多边形才进行处理
Point3dCollection pts = new Point3dCollection();
pl.GetStretchPoints(pts);
for (int i = 0; i < pts.Count - 2; i++)
{
Point3d ptqian = pts[i];
Point3d pt = pts[i + 1];
Point3d pthou = pts[i + 2];
Point3d midqian = new Point3d((pt.X + ptqian.X) / 2, (pt.Y + ptqian.Y) / 2, (pt.Z + ptqian.Z) / 2);
Point3d midhou = new Point3d((pt.X + pthou.X) / 2, (pt.Y + pthou.Y) / 2, (pt.Z + pthou.Z) / 2);
Point3d pt1 = new Point3d(midqian.X, midhou.Y, pt.Z);
Point3d pt2 = new Point3d(midhou.X, midqian.Y, pt.Z);
double d1 = pt1.Convert2d(new Plane()).GetDistanceTo(pt. Convert2d(new Plane()));
double d2 = pt2.Convert2d(new Plane()).GetDistanceTo(pt. Convert2d(new Plane()));
Point3d newpt = d1 > d2 ? new Point3d(pt2.ToArray()) : new Point3d(pt1.ToArray());
‘使用新的点代替原始点
pl.RemoveVertexAt(i + 1);
pl.AddVertexAt(i + 1, newpt.Convert2d(new Plane()), pl.GetBulgeAt(i + 1), pl.GetStartWidthAt(i + 1), pl.GetEndWidthAt(i + 1));
}
‘倒数第1个点
Point3d ptqian1 = pts[pts.Count - 2];
Point3d pt01 = pts[pts.Count - 1];
Point3d pthou1 = pts[0];
Point3d midqian1 = new Point3d((pt01.X + ptqian1.X) / 2, (pt01.Y + ptqian1.Y) / 2, (pt01.Z + ptqian1.Z) / 2);
Point3d midhou1 = new Point3d((pt01.X + pthou1.X) / 2, (pt01.Y + pthou1.Y) / 2, (pt01.Z + pthou1.Z) / 2);
Point3d pt11 = new Point3d(midqian1.X, midhou1.Y, pt01.Z);
Point3d pt12 = new Point3d(midhou1.X, midqian1.Y, pt01.Z);
double d11 = pt11.Convert2d(new Plane()). GetDistanceTo(pt01.Convert2d(new Plane()));
double d12 = pt12.Convert2d(new Plane()). GetDistanceTo(pt01.Convert2d(new Plane()));
Point3d newpt1 = d11 > d12 ? new Point3d(pt12.ToArray()) : new Point3d(pt11.ToArray());
‘使用新的点代替原始点
pl.RemoveVertexAt(pts.Count - 1);
pl.AddVertexAt(pts.Count - 1, newpt1.Convert2d(new Plane()), pl.GetBulgeAt(pts.Count - 2), pl.GetStartWidthAt(pts. Count - 2), pl.GetEndWidthAt(pts.Count - 2));
‘第一个点
Point3d ptqian2 = pts[pts.Count - 1];
Point3d pt02 = pts[0];
Point3d pthou2 = pts[1];
Point3d midqian2 = new Point3d((pt02.X + ptqian2.X) / 2, (pt02.Y + ptqian2.Y) / 2, (pt02.Z + ptqian2.Z) / 2);
Point3d midhou2 = new Point3d((pt02.X + pthou2.X) / 2, (pt02.Y + pthou2.Y) / 2, (pt02.Z + pthou2.Z) / 2);
Point3d pt21 = new Point3d(midqian2.X, midhou2.Y, pt02. Z);
Point3d pt22 = new Point3d(midhou2.X, midqian2.Y, pt02. Z);
double d21 = pt21.Convert2d(new Plane()). GetDistanceTo(pt02.Convert2d(new Plane()));
double d22 = pt22.Convert2d(new Plane()). GetDistanceTo(pt02.Convert2d(new Plane()));
Point3d newpt2 = d21 > d22 ? new Point3d(pt22.ToArray()) : new Point3d(pt21.ToArray());
‘使用新的点代替原始点
pl.RemoveVertexAt(0);
pl.AddVertexAt(0, newpt2.Convert2d(new Plane()), pl.GetBulgeAt(0), pl.GetStartWidthAt(0), pl.GetEndWidthAt(0));
}
trans.Commit();
}
在AutoCAD中输入地物直角化命令后便会出现如图6所示的程序界面,在该界面中可设置多段线顶点偏离直角的最大允许角度,也可设置是否只处理多段线所有内角偏离值均在限差之内的多边形。如果设置只处理所有内角偏离值均在限差之内的多边形,则若某个多边形的某个内角与90°的差值大于程序界面所设值,则程序会跳过该多边形,不作任何处理;如果未作该项设置,则程序会对所有多边形进行处理,且会对偏离值在程序设置的最大允许角度以内的多边形顶点进行直角化,其余顶点保持不变。这些参数设置完成后,在AutoCAD命令行中还可选择单个直角纠正或整体纠正,以及对全图或单个多边形进行处理等。
图6 程序运行界面
2.2 应用效果展示
目前,国内生产单位普遍使用的数字化绘图成图软件均采用AutoCAD作为平台,所需要的地形图数据格式也是AutoCAD的dwg格式。如果采用导入其他商业软件中进行直角纠正后再导入AutoCAD中的方法,不仅繁琐,还会造成某些属性的丢失,给客户造成不必要的麻烦。南方CASS是基于AutoCAD开发的一款数字成图软件,也带有直角纠正功能,但其直角纠正功能存在诸多问题,某些多边形直角纠正后出现了严重错误,且其只能处理多段线所有内角偏离值均在限差之内的多边形,不能完全满足用户的需要。图7为利用本文算法编写的程序模块对地物进行直角化处理后的效果图(图中实线为原始多边形,虚线为直角化后的多边形),可以看出,所有多边形均已直角化,且每个顶点直角化后与原始位置偏离较小,保证了各顶点直角化后的位置精度。
图7 地物直角化效果图
利用该方法进行地物的直角化纠正已应用于实际生产中。实践证明,该方法不仅能够保证地物各顶点的精度,而且能够满足对于地物直角化的需求,非常高效。在笔记本电脑上做测试,对一幅包含有3 313个闭合多边形的地形图作直角纠正,利用该算法能够在0.3 s内完成直角化,这些多边形中顶点最少为4个,顶点最多为200个。程序运行时间随多边形顶点个数的变化而变化,且程序运行时间均在能够接受的范围之内。
本文对地物直角化的算法进行了详细介绍,并对如何选择起始基准边和起始基准顶点做了详细分析和阐述。在此基础上,本文对该算法进行了具体实现,并通过实际应用证明了该算法能够满足实际生产需要,对地物的直角化效率高,直角化后对地物的顶点坐标保持更小的偏移,大大提高了生产效率。但该算法仍存在一些不足,如对于边长悬殊过大﹑某些特殊角度等情况仍可能会产生一定程度的问题,期望在对算法进行改进和优化时,着重解决上述问题。
[1] 钟业勋.数理地图学:地图学及其数学原理[M].北京:测绘出版社,2007:29-68
[2] 祝国瑞.地图学[M].武汉:武汉大学出版社,2004:36-95
[3] 何孝莹,包红岩,韩颜顺.大比例尺扫描地形图中房屋的识别[J].测绘与空间地理信息,2005,28(4):61-63
[4] 刘彦花,向南平.地图扫描矢量化问题分析[J].四川测绘,2001,24(3):120-121,124
[5] 易辉伟,江资斌,周翠竹,等.地形图矢量化的后处理[J].中国有色金属学报,2002,12(4):808-811
[6] 龚子桢,花向红,徐秀川,等.在CAD平台下实现房屋属性自动修改的方法[J].测绘通报,2011(9):80-82,94
[7] 蔡希林.AutoCAD2006中文版实用教程[M].北京:清华大学出版社,2006
[8] 李冠亿.深居浅出AutoCAD二次开发基础[M].北京:中国建筑工业出版社,2012
[9] 曾洪飞,张帆,卢择临.AutoCAD VBA & VB.NET开发基础与实例教程[M].北京:中国电力出版社,2009
[10] 张帆,郑立楷,王华杰,等.AutoCAD VBA 开发精彩实例教程[M].北京:清华大学出版社,2004
[11] John Sharp. Visual C#2010从入门到精通[M].周靖,译.北京:清华大学出版社,2010
[12] 刘彬.基于.NET的AutoCAD二次开发实例[J].现代矿业,2009(12):120-122
P283
B
1672-4623(2017)09-0041-04
10.3969/j.issn.1672-4623.2017.09.014
2017-03-07。
熊忠招,高级工程师,主要从事基础测绘生产技术和管理工作。