【python自动化办公实例】CAD中用pyautocad简化等高线

一、关于pyautocad

Pyautocad库由俄罗斯工程师Roman Haritonov开发,用于简化使用Python语言书写AutoCAD ActiveX Automation脚本,因官方参考实例较少,相对偏门,很多代码只能靠试验。

但由于这个Pyautocad库[官方链接]写的实在有些简陋,第一次接触pyaotocad的可以参考这几篇文章(带传送门),Hulunbuir写的比较系统:
1、Hulunbuir的Python pyautocad库 使用简介
2、Tong_T的Python3操作AutoCAD:利用pyautocad库能够自动化地进行CAD画图
3、bsider的利用python控制Autocad:pyautocad

二、地形图等高线简化

问题思路

经常遇到地形图中等高线等线形点太密,用到方案中或者模型中很难使用的问题,于是考虑用pyautocad读取密集的PL线的point坐标,在列表中简化一下,比如4个点取一个点,重新生成PL线,以便山体TIN建模不会太大,SU沙盒中顺利生成山体。

需要载入的几个库

需要pyautocad和numpy库,导入格式也是参见了开头说的几篇博文

from pyautocad import Autocad, APoint
import numpy as np 
import pyautocad.types

测试一下CAD连接

测试一下CAD的连接,得正确连上才行,通常出问题的话新建一个CAD页面就没有问题了,这个CAD接口貌似不那么稳定,容易出各种莫名的问题。
官方的测试,会再CAD里命令行写一个"Hello, Autocad from Python\n"

acad = Autocad(create_if_not_exists=True)
acad.prompt("Hello, Autocad from Python\n")
print(acad.doc.Name)

方案一重画PL线

建议将要重新生成的pl线单独一个CAD,pyaotucad是遍历所有的pl线的
重画PL线相对效率更高,画出来的是2DPolyLine,要建模的话得转换类型,虽然是2DPolyLine,给线加高程信息没有问题,炸开得到line是有Z值的

#载入几个库
from pyautocad import Autocad, APoint
import numpy as np   #转化数组的
import pyautocad.types   #算距离的

pl_num=0  #计数
for pl in acad.iter_objects('polyline'):  #获取所有的PL线
    pl_num=pl_num+1
    listx = []
    
    listpl=list(pl.coordinates)           #获取pl线每个点坐标,这个就是一维数组
    if len(listpl)>16:                    #排除太短的线
        for i in range(len(listpl)):   
            #取点,在一维数组中,每一个点有x,y两个坐标,默认z为高度属性不显示,所以每8个点取1个就是%16来判断
            if i%16==0:                      #每8个点取1个点,可以根据需要调整
                listx.append(listpl[i])      #取点坐标
                listx.append(listpl[i+1])
        # 把list变成一个个坐标点再变成array数组,再一维化才能画PL线,直接用读取的一维数组生成就是报错        
        point1 =APoint(listx[0], listx[1])  #第一个点
        p_array = np.array([point1])        #变array数组,开个头
        for i in range(len(listx)):
            if i%2 ==0 and i+1<len(listx) and i>1 :    #>1排除第一个点,i%2 ==0取偶数点,i+1
                point_i = APoint(listx[i], listx[i+1])  #第i个点的坐标
                pi_array = np.array([point_i])          #变成array数组
                p_array = np.vstack((p_array,pi_array)) #通过FOR循环把第i个数组合并进去
        #判断要不要闭合,加第一个点
        if pyautocad.types.distance(point1, point_i)<10:   #判断首尾点之间的距离
            
            p1_array = np.array([point1])                       #转化数组     
            p_array = np.vstack((p_array,p1_array))             #把第一个点也加进去,才闭合
            
        pl_list = p_array.reshape(1,  p_array.shape[0] * p_array.shape[1])[0]  #转换成一维数组
        pl_i = acad.model.AddPolyLine(pl_list)              #画成pl线,画出来的是2DPolyLine,要建模的话得转换类型
        pl_i.Elevation = pl.Elevation                       #虽然是2DPolyLine,给线加高程信息没有问题,炸开得到line是有Z值的
        
        print('完成第{0}根PL线,原有{1}个点,缩减后{2}个点,高度是{3}'.format(pl_num,len(listpl)/2,len(listx)/2,pl.Elevation))  #打印提示进度
    else:
        print('第{0}根PL线太短,忽略,高度是{1}'.format(pl_num,pl.Elevation)) 

结果提示如下:
完成第1根PL线,原有255.0个点,缩减后32.0个点,高度是91.0
完成第2根PL线,原有367.0个点,缩减后46.0个点,高度是90.0
完成第3根PL线,原有508.0个点,缩减后64.0个点,高度是89.0
完成第4根PL线,原有510.0个点,缩减后64.0个点,高度是88.0
完成第5根PL线,原有1630.0个点,缩减后204.0个点,高度是86.9

方案二重画line线

重画line线相对效率较低,代码简单可靠,重画line线后可以根据需要pe成PL线

#载入几个库
from pyautocad import Autocad, APoint
import pyautocad.types  #算距离的

pl_num=0  #计数
for pl in acad.iter_objects('polyline'):  #获取所有的PL线
    pl_num=pl_num+1
    listx = []
    
    listpl=list(pl.coordinates)           #获取pl线每个点坐标
    if len(listpl)>16:                    #排除太短的线
        for i in range(len(listpl)):   
            if i%16==0:                      #每8个点取1个点i%16==0,4取1就是i%8==0,一维列表里每两个值是一个点坐标
                listx.append(listpl[i])      #取点坐标
                listx.append(listpl[i+1])
               
        for i in range(len(listx)):
            if i%2 ==0 and i+3<len(listx) :
                point_a = APoint(listx[i], listx[i+1],pl.Elevation)    #获取第一个点
                point_b = APoint(listx[i+2], listx[i+3],pl.Elevation)  #获取第二个点                            
                acad.model.AddLine(point_a,point_b)                    #画line线
        #判断是否需要闭合,考虑较近的首尾点就可以闭合成环
        point1 = APoint(listx[0], listx[1],pl.Elevation)
        if pyautocad.types.distance(point1, point_b)<20:   #首尾两点的距离
            acad.model.AddLine(point1,point_b)             #补画line
        print('完成第{0}根等高线,原有{1}个点,缩减后{2}个点,高度是{3}'.format(pl_num,len(listpl)/2,len(listx)/2,pl.Elevation))  #打印进度提示
    else:
        print('第{0}根线太短忽略,高度是{1}'.format(pl_num,pl.Elevation))

结果提示如下:
完成第1根等高线,原有609.0个点,缩减后153.0个点,高度是47.9
完成第2根等高线,原有241.0个点,缩减后61.0个点,高度是42.9
完成第3根等高线,原有244.0个点,缩减后61.0个点,高度是43.9
完成第4根等高线,原有283.0个点,缩减后71.0个点,高度是46.9
完成第5根等高线,原有236.0个点,缩减后59.0个点,高度是40.9

你可能感兴趣的:(实用技巧)