乐筑天下

搜索
欢迎各位开发者和用户入驻本平台 尊重版权,从我做起,拒绝盗版,拒绝倒卖 签到、发布资源、邀请好友注册,可以获得银币 请注意保管好自己的密码,避免账户资金被盗
查看: 269|回复: 12

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

[复制链接]

2

主题

39

帖子

9

银币

初来乍到

Rank: 1

铜币
47
发表于 2022-4-20 11:18:00 | 显示全部楼层 |阅读模式
有人Python开发吗?都是COM,与vba的接口资料基本一致,好像很少讨论。。这不应该呀。。
开个小贴,抛砖引玉。
回复

使用道具 举报

29

主题

50

帖子

9

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
166
发表于 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
回复

使用道具 举报

1

主题

5

帖子

1

银币

初来乍到

Rank: 1

铜币
9
发表于 2022-4-20 19:34:00 | 显示全部楼层
复制代码
不知道为什么他依然出现了同样的错误:
PyDev console: starting.
Python 3.9.8 (tags/v3.9.8:bb3fdcf, Nov  5 2021, 20:48:33) [MSC v.1929 64 bit (AMD64)] 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 "[i]", 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
回复

使用道具 举报

2

主题

39

帖子

9

银币

初来乍到

Rank: 1

铜币
47
发表于 2022-4-20 22:15:00 | 显示全部楼层

改了一下,用的AddExtrudedSolid,可以生成。
  1. import win32com.client
  2. import pythoncom
  3. ProgramID = "Autocad.Application"  # 程序ID
  4. cadapp = win32com.client.Dispatch(ProgramID)  # 获取CAD程序
  5. cadapp.Visible = True  # 程序可见
  6. doc = cadapp.ActiveDocument  # 当前文档
  7. print(doc.Name)  # 当前文档的名称
  8. doc.Utility.Prompt("Hello! Autocad from pywin32com.")
  9. msp = doc.ModelSpace  # 模型空间
  10. def ConvertArrays2Variant(inputdata, vartype="Variant"):
  11.     if vartype == "ArrayofObjects":  # 对象数组
  12.         outputdata = win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_DISPATCH, inputdata)
  13.     if vartype == "Double":  # 双精度
  14.         outputdata = win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, inputdata)
  15.     if vartype == "ShortInteger":  # 短整型
  16.         outputdata = win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_I2, inputdata)
  17.     if vartype == "LongInteger":  # 长整型
  18.         outputdata = win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_I4, inputdata)
  19.     if vartype == "Variant":  # 变体
  20.         outputdata = win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_VARIANT, inputdata)
  21.     return outputdata
  22. a = (0, 0, 0)
  23. Center = ConvertArrays2Variant(a, 'Double')
  24. Radius = 10
  25. obj = msp.AddCircle(Center, Radius)
  26. list_obj = []
  27. list_obj.append(obj)
  28. reval_region = msp.AddRegion(ConvertArrays2Variant(list_obj, "ArrayofObjects"))
  29. # PointsArray = ConvertArrays2Variant((0,10,10,10,10,10,10,10,10), 'Double')
  30. # StartTangent = ConvertArrays2Variant((10,10,10), 'Double')
  31. # EndTangent  =ConvertArrays2Variant((10,10,10), 'Double')
  32. # RetVal_1 = msp.AddSpline(PointsArray, StartTangent, EndTangent)
  33. # RetVal = msp.AddExtrudedSolidAlongPath(reval_region[0], RetVal_1)
  34. height = 18
  35. taperAngle = 0.1
  36. RetVal = msp.AddExtrudedSolid(reval_region[0], height, taperAngle)

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

使用道具 举报

16

主题

48

帖子

42

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
112
发表于 2022-4-20 12:10:00 | 显示全部楼层
看这个
回复

使用道具 举报

2

主题

39

帖子

9

银币

初来乍到

Rank: 1

铜币
47
发表于 2022-4-20 12:42:00 | 显示全部楼层

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

使用道具 举报

16

主题

48

帖子

42

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
112
发表于 2022-4-20 13:00:00 | 显示全部楼层
那你用pyautocad库吧
回复

使用道具 举报

2

主题

39

帖子

9

银币

初来乍到

Rank: 1

铜币
47
发表于 2022-4-20 13:10:00 | 显示全部楼层

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

使用道具 举报

16

主题

48

帖子

42

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
112
发表于 2022-4-20 13:28:00 | 显示全部楼层
外部com操作耗时较长,使用要注意。
回复

使用道具 举报

2

主题

39

帖子

9

银币

初来乍到

Rank: 1

铜币
47
发表于 2022-4-20 14:14:00 | 显示全部楼层

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

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  • 微信公众平台

  • 扫描访问手机版

  • 点击图片下载手机App

QQ|关于我们|小黑屋|乐筑天下 繁体中文

GMT+8, 2024-11-22 01:24 , Processed in 0.369636 second(s), 72 queries .

© 2020-2024 乐筑天下

联系客服 关注微信 帮助中心 下载APP 返回顶部 返回列表