刘超 汤人杰 尹竹莹
(中车株洲电力机车有限公司 湖南株洲 412001)
轨道交通车辆牵引计算需要使用线路的坡度和坡长数据。传统的提取方式为人工读取CAD文件,将数据逐一录入到Excel 中。在CAD 文件中,与整条线路相比,坡度坡长数据的字体不大;相邻数据间隔较大。若放大图纸,一次读取的数据较少,将大幅增加录入时间;若不放大图纸,某些数字容易读错,将直接影响牵引计算的精度。
基于VBA的CAD二次开发功能,可以使用程序批量处理大量文档数据,已经用于软件及插件开发[1-2]、图纸绘制及修改[3-8]、数据提取[9-11]等。
为自动提取坡度坡长数据,本文编写了VBA 程序。读取设计坡度和设计标高所在图层的数据,将其导出到Excel,排序后确定上行线、下行线和环线数据,通过设计标高得到坡度值的正负号。实际应用结果验证了程序的有效性和可行性。
通过InputBox( )得到手动输入的设计坡度、设计标高图层名称。
一张图纸中可能同时存在上行线、下行线、环线,不同线路设计坡度、设计标高所在图层的名称可能不同,故需要判定是否包含多个图层,若存在多个图层,分离出每个图层名称和图层总数。
对于设计标高图层的数据,若图层名称和设计标高图层名称相同、类型为文本,则将字符串、坐标保存到数组中,通过计数器变量实时更新总数。
设计坡度图层中除了坡度和坡长以外,还存在旋转了90°的数据,如图1 所示,故除了图层名称和类型需满足要求外,还需限定旋转角度为0。
图1 图纸示例
设计坡度图层中,每一段路程的起点和终点有一条竖线,如图1 所示,读取竖线的坐标,用于匹配坡度坡长数据、更新起点站和终点站的坡长。
本文使用的是中望CAD,文本、线条类型分别为ZcadText和ZcadLine。不同类型的对象的属性不完全相同,故在获取数据时,满足类型相同后才判断其他条件。
一般图纸中起点站左边、终点站右边均存在少量线路数据,故需要获取起点站、终点站的坐标,用于标记有用数据。
每条线路最左侧会有注释,如图1 中的“设计坡度”和“设计标高”。获取“设计坡度”和“设计标高”的坐标,用于分离每条线路的数据。
图纸中文字可能存在空格,如“设 计 标 高”,故对于文本类型的对象,需要对每个字符进行匹配,同时满足时将坐标存储于数组中。
若图纸只有一条线路,默认为上行线;若包含环线且终点站在环线上,默认环线位于上行线或下行线的右侧。
CAD VBA 读取数据的原则是根据数据放置的先后顺序,则读取的数据不一定按照横坐标从小到大的顺序排列,本文借助Excel 对其进行排序。通过CAD VBA 新建Excel 文件,新增3 个空白工作簿,分别保存坡度坡长、标高、竖线的数据。
写入数据时,先将保存在数组中的变量赋值给Variant变量,再赋值给Excel,将无用的数据清除。
将竖线的横坐标按照升序进行排序,调整竖线的起点和终点,始终满足起点的纵坐标小于终点的纵坐标。
图2 为每条线路的标注,一般设计标高和设计坡度不在两端,则两条线路之间的距离大于竖线的长度。此外,同一条线路的竖线的长度不一定相同,可能存在细微偏差,如图3所示。
图2 图纸标注示例
图3 上行线和下行线划分
记横坐标最小的竖线V0的起点坐标和终点坐标分别为(xst,yst)和(xed,yed),长度为l0。以V0为基准,将y≥yed+l0的竖线标记为上行线,此时上行线标志位flag_sxx=1;y≤yst-l0的竖线标记为下行线,下行线标志位flag_xxx=1;yed-l0≤y≤yst+l0的竖线标记为中线,如图3所示。
(1)若flag_sxx=1 且flag_xxx=1,则同时存在上行线、下行线和环线,此时不更新标记。
(2)若flag_sxx=1且flag_xxx=0,则存在一条线路在上方,默认纵坐标大的线路为上行线,将中线改为下行线。
(3)除上述情况外,将中线改为上行线。
更新标记后,进行以下处理。
(1)按照标记升序的原则进行排序。
(2)对于相邻、横坐标之差小于1 的竖线,删除其中一条。
(3)确定上行线和下行线的分界点和分界线,见图4。
图4 上行线和下行线分界线
分界线纵坐标表达式为ysx=(ysxx0+yxxx0)/2,ysxx0、yxxx0分别为上行线第一条竖线起点纵坐标和下行线第一条竖线终点纵坐标。若图纸中只有一条线路,则ysx=0。
通过分界点确定下行线数据个数,可能存在个别上行线竖线偏离其他竖线,被判定为下行线的情况,故假定下行线数据个数大于3个时才计算分界线。
若存在环线,环线数据位于上行线或下行线数据中,则存在一个“设计坡度”的横坐标xzy满足(xzy-xxx0)(xzy-xxxk)<0,其中xxx0、xxxk分别为上行线或下行线的起点和终点的横坐标,设定该横坐标xzy为环线的分界线。
将上行线和下行线中横坐标大于xzy的竖线标记为环线。
通过ysx将标高数据标记为上行线和下行线,然后按照标记升序进行排序,确定上行线和下行线的分界点;通过xzy标记标高环线数据。
相邻标高数据,若满足标高值、横坐标和纵坐标之差的绝对值小于1,则删除其中一个标高数据。图5是环线分界线图。
图5 环线分界线
可能存在位于两条竖线之间的标高值,如图6 所示。一条竖线对应一个标高数据,对于第k个标高数据,从第k-n条竖线开始判断,若标高的横坐标和竖线的横坐标之差的绝对值大于10,清除该行的标高数据。n为第k个标高数据之前被清空数据的标高的总数,每清空一个标高数据时通过n=n+1更新n值。所有的标高数据均核对后,将清空形成的空白行删除。
图6 冗余的标高数据
和标高数据的处理方式相同,通过ysx和xzy标记上行线、下行线和环线。排序后确定上行线和下行线的分界点。
将坡度坡长数据放到左侧最近的标高数据所在行,以图6为例,将坡度值-2、坡长值430及坐标放到标高11.64所在行。
由于同一组坡度坡长未合并到同一行,对于第n个坡度坡长,从第Roundup(n/2)个标高数据开始遍历,当坡度或坡长的横坐标介于第m个和m+1个标高的横坐标之间时,将第n个坡度坡长放在第m个标高数据所在行,满足先坡度后坡长;然后通过标高值确定坡度的正负号,若第m个标高值大于第m+1个标高值,则坡度符号为正,否则为负。
只考虑两种站点标注方式,第一种如图7所示,每个站点标注了相邻站点的名称。
图7 站点标注
第二种只标注每个站点的名称。站点个数为奇数时,以中间站为真实站点;为偶数个时,对于起点站,以横坐标较小的为真实站点;对于终点站,以横坐标较大的为真实站点。
如图8所示,以起点站为例,起点站到右侧竖线的距离表达式为d=p(xn+1-xqdz)/(xn+1-xn),p为坡度值,xqdz、xn、xn+1分别为起点站、第n条竖线、第n+1条竖线的横坐标。
图8 起点站路段
对于起点站,直接更新第n个标高所在行的坡长值;对于终点站,在第n个和第n+1 个标高之间插入空白行,此时空白行为第n+1个数据,将第n行赋给第n+1行,更新第n个和第n+1个坡长值。
若存在环线,默认终点站左侧的数据属于上行线,右侧数据属于下行线。按照上行线/下行线、环线进行排序,排序后下行线数据顺序为先环线再主线,按照横坐标从大到小的顺序对主线进行排序。保存提取的数据默认保存在D盘根目录。
以某项目为例,无环线,上行线和下行线分别单独放在一张图纸中。程序运行后,弹出4个对话框,分别要求手动输入坡度图层、标高图层、起点站名称、终点站名称,如图9所示。
图9 输入对话框
4个对话框均输入后,程序自动运行,输出的部分结果如图10 所示,原始图纸如图11 所示。坡度值、坡长值满足要求,坡度的正负号符合要求。
图10 提取的部分数据
图11 原始图纸
该图纸中存在个别坡度坡长数据的图层为0,如图12所示,程序读取的结果如图13所示。
图12 坡度坡长异常数据
图13 坡度坡长异常数据提取结果
该路段不在两端,坡度坡长数据为空,标高不为空,设计人员可以通过标高值快速找到异常数据的位置。
以包含环线的项目的图纸进行测试,部分结果如图14 所示。上行线最后一条竖线没有对应的坡度坡长值,和实际相符。
图14 环线提取结果
由上述结果可知,程序提取结果满足要求。
为了自动从CAD 图纸中提取线路的坡度坡长数据,编写了VBA 程序,只需人工输入起点站和终点站名称、坡度坡长和标高所在图层,操作简单。测试结果表明:由程序提取的坡度坡长的准确性满足要求;与传统方法相比,大幅减少了数据录入的时间。