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里命令行写一个"Hello, Autocad from Python\n"
acad = Autocad(create_if_not_exists=True)
acad.prompt("Hello, Autocad from Python\n")
print(acad.doc.Name)
建议将要重新生成的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线后可以根据需要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