用python做cad二次开发已经快两年的时间了,今天看到群里一个哥们到处问怎么python怎么进行cad二次开发,不禁回想起当初自己找教程找的焦头烂额,却始终不得办法的辛酸。现在网上的教程逐渐多了起来,但是我看很多都没有直接讲一个问题,那就是“我到底怎么去二次开发”或者“我学会了哪些东西我就会二次开发”。今天就简单讲讲,初学者怎么掌握这个技能。
简单说明:python做cad的二次开发,调用的是com接口,cad内置了com接口的相关函数,com接口最典型的开发模式是VBA。python做cad二次开发,就是调用pywin32这个库,并利用pythoncom这个库进行数据类型转换,所以python开发cad完全可以参考VBA的开发教程。这里强烈推荐“明经通道 ActiveX 和 VBA 参考.ch”。
注意:python开发cad要注意两个东西,1、python数据类型需要转换成cad接收的数据类型;2、com接口的API里面的方法需要加上括号,属性不加括号,例如copy方法,
VBA语法为:
RetVal = object.Copy
python语法为:
RetVal = object.Copy()
1、cad对象模型说明
在“明经通道 ActiveX 和 VBA 参考.chm”里面能够看到对象模型中,每个对象的说明,这里不在赘述,我们一般用到的是Documents、MenuBar、MenuGroups,以下是python的代码说明
import win32com.client
wincad = win32com.client.Dispatch("AutoCAD.Application") # 链接cad,这里是调用目前打开的cad
doc = wincad.ActiveDocument # doc表示当前活跃的Document
mp = doc.ModelSpace # mp表示模型空间
从上面的对象模型图中,很容易看到上面三行代码的意思。
2、学会变量类型转换
import pythoncom
#变量类型转换
def vtPnt(x, y, z=0):
"""坐标点转化为浮点数"""
return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (x, y, z))
def vtObj(obj):
"""转化为对象数组"""
return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_DISPATCH, obj)
def vtFloat(list):
"""列表转化为浮点数"""
return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, list)
def vtInt(list):
"""列表转化为整数"""
return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_I2, list)
def vtVariant(list):
"""列表转化为变体"""
return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_VARIANT, list)
上面有五种数据类型的转换,举一个例子说明,假如要在模型空间中画一个点,画点的语法是:
RetVal = object.AddPoint(Point)
其中,Point是“Variant[变体] (三元素双精度数组); 仅用于输入要创建点的坐标”。前面是VBA 参考的解释,python的数据类型一般是列表类型的,因此需要进行数据类型转换
import win32com.client
import pythoncom
def vtFloat(list):
"""列表转化为浮点数"""
return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, list)
wincad = win32com.client.Dispatch("AutoCAD.Application") # 链接cad,这里是调用目前打开的cad
doc = wincad.ActiveDocument # doc表示当前活跃的Document
mp = doc.ModelSpace # mp表示模型空间
Point=vtFloat([1, 1, 1])
Line=vtFloat([1, 1, 1, 2, 2, 2])
RetVal = mp.AddPoint(Point) # 在模型空间里画一个点,坐标为[1, 1, 1]
RetVal = mp.AddLine(Line) # 在模型空间中画一条值线,起点坐标为[1, 1, 1],终点坐标为[2, 2, 2]
上面举了浮点型列表转换的例子,其它转换可以看“明经通道 ActiveX 和 VBA 参考.chm”中需要什么样的类型。
3、在“明经通道 ActiveX 和 VBA 参考.chm”中找需要的API函数
当我们需要实现一个功能时,一定要去查找“明经通道 ActiveX 和 VBA 参考.chm”,这个文档里面内容按照对象、方法、属性进行了分类,比如想画一条多段线时,“多段线”是对象,“画多段线”是方法,这个多段线的线型、颜色等是它的属性。具体:
(1)在对象里找到“LightweightPolyline”,这个就是多段线
(2)“LightweightPolyline”的方法和属性:
(3)调用。
python调用方法时,一定要加括号,不管括号里有没有参数,例如copy方法
RetVal = object.Copy # VBA写法,不需要括号
RetVal = object.Copy() # python写法,需要括号
属性就直接调用
RetVal = object.Closed # 返回一个布尔型数值RetVal
具体每个对象有哪些方法,这就自己去查文档了,另外每个对象、方法、属性在右上角都有一个vba的示例,看下示例也能明白python该怎么写。
下面以一个需求为例,进行演示,需求:将特征线图层里面的所有多段线坐标导出
1、链接cad
import win32com.client
wincad = win32com.client.Dispatch("AutoCAD.Application") # 链接cad,这里是调用目前打开的cad
doc = wincad.ActiveDocument # doc表示当前活跃的Document
mp = doc.ModelSpace # mp表示模型空间
2、准备好转换函数
import pythoncom
#变量类型转换
def vtPnt(x, y, z=0):
"""坐标点转化为浮点数"""
return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (x, y, z))
def vtObj(obj):
"""转化为对象数组"""
return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_DISPATCH, obj)
def vtFloat(list):
"""列表转化为浮点数"""
return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, list)
def vtInt(list):
"""列表转化为整数"""
return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_I2, list)
def vtVariant(list):
"""列表转化为变体"""
return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_VARIANT, list)
3、创建选择集(选择集的作用是自动选中目标)
# 创建选择集,创建ss1的时候,最好先试着删除ss1,不然SelectionSets里已经有ss1时,会报错
try:
doc.SelectionSets.Item("ss1").Delete()
except:
print("Delete selection failed")
# 选择到图框
ss1 = doc.SelectionSets.Add("ss1")
point1 = ref_fun.vtFloat([-10000000000, -10000000000, 0])
point2 = ref_fun.vtFloat([10000000000, 10000000000, 0])
model = 5
ftype = ref_fun.vtInt([8, ])
fdata = ref_fun.vtVariant(["特征线", ])
ss1.Select(model, point1, point2, ftype, fdata) # 选中特征线图层里的所有图元
4、利用ObjectName属性进行筛选,当然也可以在选择集创建的时候就筛选,但是python在选择集那里的操作有点问题,最好利用ObjectName属性筛选
data1=[]
for i in range(len(ss1)):
if ss1[i].ObjectName=="LightweightPolyline": # 只保存特征线图层里,对象名称为LightweightPolyline的线坐标
mid = ss1[i].Coordinates
mid_data = []
for j in range(len(mid)):
if j % 2 == 0:
mid_coordinate = [mid[j], mid[j + 1]]
mid_data.append(mid_coordinate)
data1.append(mid_data)
print(data1)
以上就是自学py的cad二开简单教程,说白了,就是照着VBA的形式,用python语言调用com口的API函数。所以“明经通道 ActiveX 和 VBA 参考.chm”和一本VBA的CAD二次开发书籍,就能够完成基本上所有cad二次开发功能。
特别感谢以下文章作者、工作室、论坛,文章中,很多代码都是摘抄至链接1、链接2,本人学习的过程也深受下面链接启发,最后向以下作者、工作室、论坛表示衷心的感谢!
scdn作者Hulunbuir的Python 二次开发 AutoCAD 简介系列教程
微信335工作室系列python二次开发教程
明经通道论坛