Blog Links






一、前言


  用户要对已有的一些对象进行删除、复制、移动等编辑操作,都需要选中被操作的对象。选择对象或对操作对象进行筛选的过程,称为构造选择集。选择对象可以只选择一个对象,也可以同时选择多个对象。AutoCAD 中常用构造选择集有直接拾取、窗口、窗交、栏选等多种方式。[1]

  本文简要介绍在 CAD 二次开发过程中几种常用选择对象即构造选择集的方法。



二、连接CAD的方式


  为了保证代码的顺利运行,本文采用 win32com 库连接 CAD,具体代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
=============================
Author:DalNur
Email: liyang@alu.hit.edu.cn
=============================
'''

import win32com.client
import pythoncom

acad = win32com.client.Dispatch("AutoCAD.Application.19")  
       # AutoCAD.Application.19为 ProgID
doc = acad.ActiveDocument
doc.Utility.Prompt("Hello AutoCAD\n")
mp = doc.ModelSpace
print(doc.Name)

2.1. ProgID


  根据 CAD 版本的不同, ProgID 可能发生变化,部分版本 CAD 的 ProgID 如下:


AutoCAD 版本ProgID
2010AutoCAD.Application.18
2014AutoCAD.Application.19

  常见版本 CAD 的 ProgID 详见博文: autocad application 版本

  其余版本 CAD 的 ProgID 在官方二次开发帮助文档中查看,具体查找位置如下图所示。


在这里插入图片描述


  官方二次开发帮助文档的获取方式详见博文:Python pyautocad库 使用简介 前沿部分。



三、数据转换


  说明:本人非计算机专业出身,文中某些表述可能不严谨甚至错误,还请各位见谅。


  Python 中的数据类型较少,且对数据本身的要求也较为宽松,如一个列表中的各个元素可以分别属于不同的数据类型,这虽然有利于降低程序的编写难度,但也对 CAD 的二次开发产生了一些不必要的麻烦。


  在 CAD 二次开发过程中,很多函数/方法的参数要求输入的数据类型为 Variant (array of objects) ,但在 Python 中似乎又没有哪一种数据类型与之直接相对应,若采用 list 代替 Variant,那么程序无法顺利执行,报错为 “ 对象数组无效 ”。因此,需要某种转换方式,将Python中定义的变量转换为能够被CAD识别的数据类型 Variant


  VARIANT 结构体主要是使用在 COM(组件对象模型)中用于传递参数使用,它的存在主要是为了保持一个在 COM 参数传递方法的统一性,它几乎包含了所有普通常用类型的数据类型的传递,如整型,浮点型,布尔型等,以及相应类型的指针类型,如整型指针。[3]


  部分类型与变量对应关系如下表:


Member nameDescription
VT_EMPTYIndicates that a value was not specified.
VT_R8Indicates a double value.
VT_DISPATCHIndicates an IDispatch pointer.

  另外,NumPy arrays can be passed as VARIANT arrays arguments. The array is converted to a SAFEARRAY according to its type. [4] ( 此为 comptypes 库帮助文档原文,本人对计算机了解有限,为了不曲解原文,此处不做翻译),部分对应关系如下:


NumPy typeVARIANT type
int32, int, intc, int_VT_I4
uint32, uint, uintcVT_UI4
float64, float_VT_R8

  comtypes 是一个轻量级的 python com 包,其中文网站详见:https://www.cnpython.com/pypi/comtypes;官方文档详见:comtypes 1.1.3 documentation

  NumPy 是用 Python 进行科学计算的基础软件包,其官方的中文文档详见网站: Numpy 中文网



  本文用到的数据转化函数代码如下:

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)

  其他数据类型的转化方式可查询 PyWin32 的官方帮助文档,它的获取方式如下:首先确保你已经成功安装了 pywin32 模块,然后在搜索神器 Everything 的搜索栏中输入 PyWin32.chm,便可得到其所在的路径,打开文件 PyWin32.chm,在搜索栏中输入 pythoncom.VT_ARRAY , 便可查看各种数据类型的转化。


在这里插入图片描述

PyWin32帮助文档的获取

在这里插入图片描述

VARIANT的查询


四、创建测试图元

[pnt1, pnt2, pnt3, pnt4, pnt5, pnt6] = [vtpnt(-40, -40), vtpnt(500, 500), vtpnt(300, 200),
                                        vtpnt(600, 200), vtpnt(700, 200), vtpnt(100, 0)]

LineObj = mp.AddLine(pnt1, pnt2)
CircleObj = mp.AddCircle(pnt3, 100)
ArcObj = mp.AddArc(pnt4, 50, 0, 1.57)
EllObj = mp.AddEllipse(pnt5, pnt6, 0.5)


五、创建选择集


  创建名称为 SS1 的选择集。

try:
    doc.SelectionSets.Item("SS1").Delete()
except:
    print("Delete selection failed")
    
slt = doc.SelectionSets.Add("SS1")


六、常规选择


6.1. 屏幕拾取

slt.SelectOnScreen()
print("请在屏幕拾取图元,以Enter键结束")
obj = slt[0]
print(obj.ObjectID)
print(slt)

6.2. 选择过定点图元

pnt = APoint(0, 0)
slt.SelectAtPoint(pnt)
obj = slt[0]
print(obj.StartPoint) # 当不止一个图元过点pnt时,slt中的元素也不止一个。

6.3. 多边形框选

  多边形由给定各点依次连直线形成,最终实现该多边形区域内的全选。

pnts = [-50, -50, 0, -50, 550, 0, 550, 550, 0, 550, -50, 0, -50, -50, 0]
pnts=vtFloat(pnts)

slt.SelectByPolygon(6, pnts) # acSelectionSetWindowPolygon = 6

obj = slt[0]
print(obj.ObjectID)
obj = slt[1]
print(obj.ObjectID)

6.4. 全选

slt.Select(5) # acSelectionSetAll = 5
obj = slt[0]
print(obj.layer)


七、快速选择


7.1. 语法


  • object.Select(Mode, Point1, Point2, FilterType, FilterData)

   - object:SelectionSet. The object this method applies to 。

   - Mode:选择模式,AcSelect enum,具体含义下表。

   - Point1:3维坐标点。

   - Point2:3维坐标点。

   - FilterType:A DXF group code specifying the type of filter to use 。

   - FilterData:The value to filter on 。


ModeenumDescription
acSelectionSetWindow0Selects all objects completely inside a rectangular area whose corners are defined by Point1 and Point2.
acSelectionSetCrossing1Selects objects within and crossing a rectangular area whose corners are defined by Point1 and Point2.
acSelectionSetPrevious3Selects the most recent selection set. This mode is ignored if you switch between paper space and model space and attempt to use the selection set.
acSelectionSetLast4Selects the most recently created visible objects.
acSelectionSetAll5Selects all objects.

7.2. DXF组码


  详见:CADVBA中的选择集过滤及DXF组码表

     CAD中的选择集过滤----有条件选择AutoCAD实体 (二)


  此外,在二次开发帮助文档 ActiveX Developer’s Guide 中,搜索 DXF ,便可得到官方的权威解释,操作如下:


在这里插入图片描述

7.3. 实例


  选择 0 图层上所有半径大于 5 的圆并删除,代码如下:

filterType = [0, -4, 40, 8]  # 定义过滤类型
filterData = ["Circle", ">=", 5, "0"]  # 设置过滤参数

filterType = vtInt(filterType)  # 数据类型转化
filterData = vtVariant(filterData)  # 数据类型转化

slt.Select(5, 0, 0, filterType, filterData)  # 实现过滤

obj = slt[0]
print(obj.Diameter)

slt.Erase()  # 删除符合条件的所有圆


八、GetEntity


在这里插入图片描述


  以下代码实现将用户选择的图元的颜色更改为红色。


print("请在屏幕中鼠标左键点选图元,未选中则报错!")  # try...except处理报错
rtnObj = doc.Utility.GetEntity()  # 返回对象

print(rtnObj)

print("所选图元的ID:", rtnObj[0].ObjectID)
print("鼠标单击处的坐标:", rtnObj[1])

sltObject = doc.ObjectIdToObject(rtnObj[0].ObjectID) # 图元ID转化为对应的图元

clr = doc.Application.GetInterfaceObject("AutoCAD.AcCmColor.19")
clr.SetRGB(255, 0, 0)  # 创建红色
sltObject.TrueColor = clr  # 指定颜色

doc.Application.Update()


九、致谢


  选择集功能的顺利实现离不开 ke1078 同学的大力支持,特此感谢!



十、尾声


  以上,便是关于 AutoCAD 选择集 的一些基本代码,因篇幅有限,某些非关键功能未做详细介绍,如有疑问,欢迎邮件来询。

  鉴于,相关示例代码相对较少,特写本文,一方面是为自己的阶段性学习做一个总结,另一方面更是为有需要的人提供多一点参考。

  如果您已实现一些本文未提及的功能,还请在评论区呈现,以便为后续学习者提供更多的帮助。

  胸藏文墨怀若谷,腹有诗书气自华,希望各位都能在知识的 pāo 子里快乐徜徉。

  因本人野生学习 Python,水平确实有限,文中难免有所疏漏,还请各位大神不吝批评指正。

  最后,祝各位攻城狮们,珍爱生命,保护发际线!

  本文部分内容,源于网络!

  欢迎大家点赞、评论及转载,转载请注明出处!

  为我打call,不如为我打款!

  打赏可备注邮箱,本人将赠送本系列博客的全部 Python 源代码。



在这里插入图片描述




十、参考文献


[1]. AutoCAD中构造选择集的方法. 机械制图课堂.

[2]. 基于Python AutoCAD ActiveX 二次开发,pyautocad应用技术. 为中华崛起而.

[3]. VARIANT的使用方法. xinzhiyounizhiyouni.

[4]. comtypes 1.1.3 documentation




Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐