landsat99 发表于 2022-4-20 11:18:00

有人Python开发Autocad吗?都是COM,好像很少讨论

有人Python开发吗?都是COM,与vba的接口资料基本一致,好像很少讨论。。这不应该呀。。
开个小贴,抛砖引玉。

yswoyh 发表于 2022-4-21 16:42:00

前些日子做了一个测试,VB,python,vb.net
VB6.0利用ActiveX 操作CAD 画圆 10000个圆 用时 10.05秒
VB.net 利用objectARX技术 操作CAD画圆速度最快 ,画10000圆,用时 0.39 秒
python 利用ActiveX 操作CAD画圆 10000个圆 用时 27.95秒
下面是代码
Private Declare Function GetTickCount Lib "kernel32" () As Long
Dim Acadapp As Object
Dim acaddoc As Object
Dim StartT As Long'获取运算开始时间
Dim SpendT As Long'获取运算结束时间
Private Sub Form_Load()
    StartT = GetTickCount
    Set Acadapp = GetObject(, "autocad.application")
    Set acaddoc = Acadapp.ActiveDocument
    Dim pt(0 To 2) As Double
    Dim a As Object
    Dim i As Long
    pt(0) = 0: pt(1) = 0
    For i = 1 To 10000
      Set a = acaddoc.ModelSpace.AddCircle(pt, 10)      '画圆
      Set a = acaddoc.ModelSpace.AddText(pt(1), pt, 5)    '写文字
      pt(1) = pt(1) + 10
    Next i
    SpendT = GetTickCount - StartT
    acaddoc.Utility.Prompt ("本次操作耗时:" & Format(SpendT / 1000, "0.00") & "秒")
    End
End Sub
#python 利用ActiveX 操作CAD画圆 10000个圆 用时 27.95秒
#代码量最少
#                            加一个添加文字用时56.60秒
from pyautocad import Autocad,APoint
import time
time_start=time.time()
acad=Autocad()
p1=APoint(0,0)
for i in range(0,10000):
    acad.model.AddCircle(p1,10)
    acad.model.AddText(p1.y, p1,5)
    p1.y+=10
time_end=time.time()
acad.prompt(time_end-time_start)
'VB.net 利用objectARX技术 操作CAD画圆速度最快 ,画10000圆,用时 0.39 秒
'引用CAD安装目录下的 acdbmgd.dll,acmgd.dll这两个文件,将本地复制设置为false
'编译生成,用 netload 命令加载程序,执行命令 netCircle
'                                             加一个添加文字用时1.89秒
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.Colors
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.Runtime
Public Class Class1
    Public StartTime As System.DateTime
    Public EndTime As System.DateTime
    Public ts As System.TimeSpan
   Public Sub CreateCircle()
      StartTime = System.DateTime.Now
      Dim pt(0 To 2) As Double
      Dim i As Integer
      pt(0) = 0 : pt(1) = 0 : pt(2) = 0
      For i = 1 To 10000                                     '画10000个圆
            Dim circleId As ObjectId = AddCircle(New Point3d(pt(0), pt(1), pt(2)), 5)
            pt(1) = pt(1) + 10
      Next i
      EndTime = System.DateTime.Now
      ts = EndTime.Subtract(StartTime)
      Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
      ed.WriteMessage("画" & i - 1 & "圆,用时 " & ts.TotalSeconds.ToString & " 秒")
      'MsgBox(ts.TotalSeconds.ToString)
    End Sub
    Public Shared Function AddCircle(ByVal cenPt As Point3d, ByVal radius As Double) As ObjectId
      ' 在内存中创建一个圆对象
      Dim ent As New Circle(cenPt, Vector3d.ZAxis, radius)
      ' 调用AppendEntity函数,将圆加入到模型空间.
      Dim entId As ObjectId = AppendEntity(ent)
      Return entId
    End Function
    ' 将图形对象加入到模型空间的函数.
    Public Shared Function AppendEntity(ByVal ent As Entity) As ObjectId
      ' 得到当前文档图形数据库.
      Dim db As Database = HostApplicationServices.WorkingDatabase
      Dim entId As ObjectId
      Using trans As Transaction = db.TransactionManager.StartTransaction
            ' 以读方式打开块表.
            Dim bt As BlockTable = trans.GetObject(db.BlockTableId, OpenMode.ForRead)
            ' 以写方式打开模型空间块表记录.
            Dim btr As BlockTableRecord = trans.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
            ' 将图形对象的信息添加到块表记录中,并返回ObjectId对象.
            entId = btr.AppendEntity(ent)
            ' 把图形对象添加到事务处理中.
            trans.AddNewlyCreatedDBObject(ent, True)
            ' 提交事务处理.
            trans.Commit()
      End Using
      Return entId
    End Function
    ' 由插入点、文字内容、文字高度和倾斜角度创建单行文字的函数.
    Public Shared Function AddText(ByVal position As Point3d, ByVal textString As String, ByVal height As Double, ByVal oblique As Double) As ObjectId
      Try
            ' 在内存中创建单行文字对象.
            Dim ent As New DBText()
            ' 设置文字插入点.
            ent.Position = position
            '设置文字内容.
            ent.TextString = textString
            '设置文字高度.
            ent.Height = height
            '设置文字倾斜角.
            ent.Oblique = oblique
            ' 调用EntityToModelSpace函数,将单行文字加入到模型空间.
            Dim entId As ObjectId = AppendEntity(ent)
            Return entId
      Catch
            ' 创建失败,则返回一个空的ObjectId.
            Dim nullId As ObjectId = ObjectId.Null
            Return nullId
      End Try
    End Function
End Class

cmcc_gy 发表于 2022-4-20 19:34:00

复制代码
不知道为什么他依然出现了同样的错误:
PyDev console: starting.
Python 3.9.8 (tags/v3.9.8:bb3fdcf, Nov5 2021, 20:48:33) on win32
runfile('C:/pycharm_project/pythonProject666/autocad/pywin32/demo555.py', wdir='C:/pycharm_project/pythonProject666/autocad/pywin32')
test.dwg
Traceback (most recent call last):
File "C:\Python3.9.8\lib\code.py", line 90, in runcode
    exec(code, self.locals)
File "", line 1, in
File "C:\Program Files\JetBrains\PyCharm 2021.3.2\plugins\python\helpers\pydev\_pydev_bundle\pydev_umd.py", line 198, in runfile
    pydev_imports.execfile(filename, global_vars, local_vars)# execute the script
File "C:\Program Files\JetBrains\PyCharm 2021.3.2\plugins\python\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "C:/pycharm_project/pythonProject666/autocad/pywin32/demo555.py", line 36, in
    RetVal = msp.AddExtrudedSolidAlongPath(reval_region2,RetVal_1)
File "", line 2, in AddExtrudedSolidAlongPath
TypeError: The Python instance can not be converted to a COM object

landsat99 发表于 2022-4-20 22:15:00


改了一下,用的AddExtrudedSolid,可以生成。import win32com.client
import pythoncom
ProgramID = "Autocad.Application"# 程序ID
cadapp = win32com.client.Dispatch(ProgramID)# 获取CAD程序
cadapp.Visible = True# 程序可见
doc = cadapp.ActiveDocument# 当前文档
print(doc.Name)# 当前文档的名称
doc.Utility.Prompt("Hello! Autocad from pywin32com.")
msp = doc.ModelSpace# 模型空间
def ConvertArrays2Variant(inputdata, vartype="Variant"):
    if vartype == "ArrayofObjects":# 对象数组
      outputdata = win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_DISPATCH, inputdata)
    if vartype == "Double":# 双精度
      outputdata = win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, inputdata)
    if vartype == "ShortInteger":# 短整型
      outputdata = win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_I2, inputdata)
    if vartype == "LongInteger":# 长整型
      outputdata = win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_I4, inputdata)
    if vartype == "Variant":# 变体
      outputdata = win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_VARIANT, inputdata)
    return outputdata
a = (0, 0, 0)
Center = ConvertArrays2Variant(a, 'Double')
Radius = 10
obj = msp.AddCircle(Center, Radius)
list_obj = []
list_obj.append(obj)
reval_region = msp.AddRegion(ConvertArrays2Variant(list_obj, "ArrayofObjects"))
# PointsArray = ConvertArrays2Variant((0,10,10,10,10,10,10,10,10), 'Double')
# StartTangent = ConvertArrays2Variant((10,10,10), 'Double')
# EndTangent=ConvertArrays2Variant((10,10,10), 'Double')
# RetVal_1 = msp.AddSpline(PointsArray, StartTangent, EndTangent)
# RetVal = msp.AddExtrudedSolidAlongPath(reval_region, RetVal_1)
height = 18
taperAngle = 0.1
RetVal = msp.AddExtrudedSolid(reval_region, height, taperAngle)

如果使用 AddExtrudedSolidAlongPath,在vba下好像有Bug。。因为用Acad官方的AddExtrudedSolidAlongPath 的VBA源码(2020版源码-2020acad)都无法运行!
AddExtrudedSolid 则没有问题。 vba、python都可以运行。

guangdonglbq 发表于 2022-4-20 12:10:00

看这个

landsat99 发表于 2022-4-20 12:42:00


你好呀。上面项目是IronPython的吧,属.net。。。不是标准CPython
IronPython基本不算python,另类小众分支,,它这个仅一层py的语法外衣,可用资源仅限.net, cpy成千上万的包它基本都用不了。。。ironpy微软的实验项目,目前基本废弃了
cpy的价值在u通用型,特指可使用 numpy scipy pandas numba anaconda..这类C实现通用库的标准版本

guangdonglbq 发表于 2022-4-20 13:00:00

那你用pyautocad库吧

landsat99 发表于 2022-4-20 13:10:00


嗯嗯。pyautocvd 的头部连接 各类图素绘制 编辑等等写法确实方便,同是局限性也不小,,,尤其是cad属性类的CRUD..
win32compythoncom主要使用,稳定性还不错

guangdonglbq 发表于 2022-4-20 13:28:00

外部com操作耗时较长,使用要注意。

landsat99 发表于 2022-4-20 14:14:00


com效率确实先天不足。。这是个不大不小的缺陷。一般情况下,运行速度不是瓶颈,工具通用型,编写的便捷性倒是首要因素。
前几天测了次 10万同心圆生成速度。都是几行的简单代码,,
lisp   大约5秒,
vba   10秒,
c++    1.2秒,(没有mfc,所以g++试的,。估计用vc++会更快)
python150秒,
(win10 + acad2020)
过两天试试java调用activex,估计比python快不了多少,都是com,编译的也快不到哪里去。。
vba 倒是出乎意料,com口跑的挺快。vba这个是线程内的吧,不是外部com/activex??咋这么快?
页: [1] 2
查看完整版本: 有人Python开发Autocad吗?都是COM,好像很少讨论