python:ActiveX

一、application 版本

AutoCAD产品名版本号ProgID
AutoCAD 2004R16AutoCAD.Application.16
AutoCAD 2005R16.1AutoCAD.Application.16.1
AutoCAD 2006R16.2AutoCAD.Application.16.2
AutoCAD 2007R17AutoCAD.Application.17
AutoCAD 2008R17.1AutoCAD.Application.17.1
AutoCAD 2009R17.2AutoCAD.Application.17.2
AutoCAD 2010R18AutoCAD.Application.18
AutoCAD 2011R18.1AutoCAD.Application.18.1
AutoCAD 2014R19.1AutoCAD.Application.19.1
AutoCAD 2015R20AutoCAD.Application.20
AutoCAD 2016R20.1AutoCAD.Application.20.1
AutoCAD 2017R21AutoCAD.Application.21
AutoCAD 2018R22AutoCAD.Application.22
AutoCAD 2019R23AutoCAD.Application.23
用户最后一次使用的CADAutoCAD.Application
['16','16.1','16.2','17','17.1','17.2','18','18.1','19.1','20','20.1','21','22','23']

CAD类

import pythoncom
import win32com.client as win32

# todo:cad基本操作类
class Cad():
    def __init__(self):
        self.version = self.version()
        self.cad = win32.Dispatch('AutoCAD.Application.%s' % self.version)  # 20.1
        self.color = self.cad.GetInterfaceObject('AutoCAD.AcCmColor.%s' % self.version)
        self.doc = self.cad.ActiveDocument
        self.docs = self.cad.Documents
        self.msp = self.doc.ModelSpace
        self.utl = self.doc.Utility
    def vtpnt(self, x, y, z=0):
        """坐标点转化为浮点数"""
        return win32.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (x, y, z))
    def vtobj(self, obj):
        """转化为对象数组"""
        return win32.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_DISPATCH, obj)
    def vtfloat(self, lst):
        """列表转化为浮点数"""
        return win32.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, lst)
    def vtInt(self, list):
        """列表转化为整数"""
        return win32.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_I2, list)
    def vtVariant(self, list):
        """列表转化为变体"""
        return win32.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_VARIANT, list)

    # todo:全部范围选择
    def select_all(self, name, filterType, filterData):
        # cad = win32.Dispatch("AutoCAD.Application")
        # doc = cad.ActiveDocument
        try:
            ssget1 = self.doc.SelectionSets.Add("%s" % name)  # 若无选择集,尝试新增"SS1"选择集
        except BaseException:
            ssget1 = self.doc.SelectionSets("%s" % name)  # 如果"SS1"选择集已存在,就以它作为我们的选择集
            ssget1.Clear()  # 清空"SS1"选择集的内容

        # filterType = [2, 8]  # 定义过滤类型
        # filterData = ["FWSX", "FWSX"]  # 设置过滤参数
        filterType = self.vtInt(filterType)  # 数据类型转换
        filterData = self.vtVariant(filterData)  # 数据类型转换

        ssget1.Select(5, 0, 0, filterType, filterData)  # 实现过滤选择

        return ssget1
    # todo:部分范围选择
    def select_little(self, name, filterType, filterData, coordinates):
        """选择模式1,选择矩形框相交的对象"""
        try:
            ssget1 = self.doc.SelectionSets.Add("%s" % name)
        except BaseException:
            ssget1 = self.doc.SelectionSets("%s" % name)
            ssget1.Clear()
        # filterType = [2, 8]  # 定义过滤类型
        # filterData = ["FWSX", "FWSX"]  # 设置过滤参数
        filterType = self.vtInt(filterType)  # 数据类型转化
        filterData = self.vtVariant(filterData)  # 数据类型转化

        ssget1.Select(1, self.vtpnt(coordinates[0] - 30, coordinates[1] + 30),
                      self.vtpnt(coordinates[0] + 30, coordinates[1] - 30), filterType, filterData)  # 实现过滤

        return ssget1
    # todo:利用多边形选择
    def select_poly(self, name, mode, lst, filterType, filterData):
        try:
            ssget1 = self.doc.SelectionSets.Add("%s" % name)  # 若无选择集,尝试新增"SS1"选择集
        except BaseException:
            ssget1 = self.doc.SelectionSets("%s" % name)  # 如果"SS1"选择集已存在,就以它作为我们的选择集
            ssget1.Clear()  # 清空"SS1"选择集的内容

        # filterType = [2, 8]  # 定义过滤类型
        # filterData = ["FWSX", "FWSX"]  # 设置过滤参数
        filterType = self.vtInt(filterType)  # 数据类型转换
        filterData = self.vtVariant(filterData)  # 数据类型转换

        ssget1.SelectByPolygon(mode, self.vtfloat(lst), filterType, filterData)  # 实现过滤选择

        return ssget1

    # todo:获取对象交集坐标
    def get_union_points(self, objlist):
        try:
            # # 判断多边形是否相交
            # rel = objlist[0].IntersectWith(objlist[1], 0)
            # if len(rel) == 0:
            #     return None
            # 多边形形成面域
            self.msp.AddRegion(self.vtobj(objlist))
            # 查找生成的面域
            region_union = self.select_all('ss2', [8, 0], ['0', 'region'])
            # 将所有面域并成一个面域
            while len(region_union)>1:
                # 面域进行并集
                region_union[0].Boolean(0, region_union[1])
                # 查找生成的面域
                region_union = self.select_all('ss2', [8, 0], ['0', 'region'])
            # 炸开合并后的这一整个面域(如果只有一个面域则返回多条直线,如果有多个面域,则返回每个独立的面域)
            line = region_union[0].Explode()
            region_union[0].Delete() # 删除已炸开面域
            # 判断炸开面域后是否还存在面域
            region_union = self.select_all('ss2', [8, 0], ['0', 'region'])
            points_lst = []
            if len(region_union) > 0: # 被炸的是多个面域,返回的是每个独立面域
                for i in region_union: # 遍历每个面域,转换为坐标列表
                    lines = i.Explode()
                    i.Delete()  # 删除已炸开面域
                    points_lst.append(self.union2points(lines))
            else: # 被炸的是一个面域,返回的是直线段
                points_lst.append(self.union2points(line))

            return points_lst
        except Exception as e:
            print('get_union_points出错:' + str(e))
    # todo:炸开后的直线合并成多边形,返回坐标
    def union2points(self, lines):
        """
        :param lines: 多个直线段对象
        :return: 多边形坐标列表[x,y,x1,y1...xn,yn]
        """
        # 获取炸开后的直线坐标并删除直线
        point_list = []
        for i in lines:
            point_list.append([i.StartPoint, i.EndPoint])
            i.Delete()

        # 处理坐标
        lst = [point_list[0]]
        point_list.pop(0)
        for _ in range(len(lines) - 1):
            for i in point_list:
                if lst[-1][-1] == i[0]:
                    lst.append(i)
                    point_list.remove(i)
                    break
                elif lst[-1][-1] == i[1]:
                    lst.append([i[1], i[0]])
                    point_list.remove(i)
                    break

        result_lst = []
        for i in lst:
            result_lst.extend([i[0][0], i[0][1]])
        # result_lst.append(result_lst[0])
        # 删除多余节点
        result_lst = self.delete_point(result_lst)
        # 坐标序列改为逆时针
        result_lst = self.coordinate_sorting(result_lst, -1)

        return result_lst

    # todo:坐标序列转换
    def coordinate_sorting(self, lst, flag):
        # z小于0说明原坐标列表为顺时针,z大于0说明原坐标列表为逆时针,flag正为顺,flag负为逆
        # lst = [431699.3549,3473066.7616,431715.2278,3473083.8972,431732.0926,3473073.7823,431716.9179,3473057.0712]

        # 坐标转为元组
        point_lst = []
        for i in range(0, len(lst), 2):
            point_lst.append((lst[i], lst[i + 1]))

        point_lst.append(point_lst[0])
        point_lst.insert(0, point_lst[-2])

        # print(point_lst)
        # 查找最右上角的坐标
        max_point = (0, 0)
        for i in range(1, len(point_lst) - 1):
            if point_lst[i][0] > max_point[0]:
                max_point = point_lst[i]
            elif point_lst[i][0] == max_point[0]:
                if point_lst[i][1] >= max_point[1]:
                    max_point = point_lst[i]

        # print(max_point)
        # 记录max坐标的索引
        index_num = point_lst[1:-1].index(max_point) + 1
        # 返回需要的三个点
        p1 = point_lst[index_num - 1]
        p2 = point_lst[index_num]
        p3 = point_lst[index_num + 1]
        # print(p1, p2, p3)
        x1 = p2[0] - p1[0]
        y1 = p2[1] - p1[1]
        x2 = p3[0] - p2[0]
        y2 = p3[1] - p2[1]
        z = x1 * y2 - x2 * y1  # z<0,顺时针
        if z < 0 and flag < 0:
            # print('逆时针')
            point_lst.reverse()
        elif z > 0 and flag > 0:
            point_lst.reverse()
        new_lst = []
        for i in range(1, len(point_lst) - 1):
            new_lst.extend(point_lst[i][:])
        # print(new_lst)

        return new_lst
    # todo:计算两点方位角
    def degree(self, x, y, x1, y1):
        try:
            dx = x1 - x  # 最长线段的x坐标差
            dy = y1 - y  # 最长线段的y坐标差
            dy = dy + m.pow(10, -10)
            degree = m.pi * (1 - np.sign(dy) / 2) - m.atan(dx / dy)  # 计算最长线段的方位角

            return degree
        except Exception as e:
            print('degree出错:' + str(e))
    # todo:删除多余节点
    def delete_point(self, lst):
        try:
            # 添加起点坐标
            lst.extend(lst[:2])
            # 列表转为元组
            new_lst = []
            for i in range(0, len(lst), 2):
                new_lst.append((lst[i], lst[i + 1]))
            # 开头插入元素
            new_lst.insert(0, new_lst[-2])
            delete = []
            # 查找多余节点
            for i in range(1, len(new_lst) - 1):
                d1 = round(self.degree(new_lst[i - 1][0], new_lst[i - 1][1], new_lst[i][0], new_lst[i][1]), 4)
                d2 = round(self.degree(new_lst[i][0], new_lst[i][1], new_lst[i + 1][0], new_lst[i + 1][1]), 4)

                if d1 == d2:
                    delete.append((new_lst[i]))

            # 元组列表删除头尾
            del new_lst[0]
            del new_lst[-1]

            # 删除多余节点
            for i in delete:
                while i in new_lst:
                    new_lst.remove(i)
            # # 末尾添加起点坐标
            # new_lst.append(new_lst[0])
            lst = []
            # 还原坐标格式
            for i in new_lst:
                lst.extend([i[0], i[1]])

            return lst
        except Exception as e:
            print('delete_point出错:' + str(e))
    # todo:cad版本查询
    def version(self):
        applist = ['16','16.1','16.2','17','17.1','17.2','18','18.1','19.1','20','20.1','21','22','23']
        for i in applist:
            try:
                win32.Dispatch('AutoCAD.Application.%s' % i)  # 20.1
                return i
            except Exception:
                pass
        return None


if __name__ == '__main__':
    cad = Cad()
    cad.cad.ZoomExtents()
    
    ssget1 = cad.select_all('ss1', [2, 8], ["FWSX", "FWSX"])

    insertionPoint = (434817.9258476031, 3476325.6359382486, 0.0)
    ssget2 = cad.select_little('ss2', [0, 0], ['lwpolyline', 'lwpolyline'], insertionPoint)

    new_lst = [434813.7128951931, 3476307.5265556867, 0,
               434826.12550053425, 3476313.3009239333, 0,
               434827.8843840688, 3476309.5200207722, 0,
               434815.4717787276, 3476303.7456525257, 0]
    ssget3 = cad.select_poly('ss3', 6, new_lst, [8, 0], ['面积插入', 'TEXT'])

二、基本操作

import pythoncom
import win32com.client as win32

cad = win32.Dispatch("AutoCAD.Application")
doc = cad.ActiveDocument
msp = doc.ModelSpace
color = cad.GetInterfaceObject("AutoCAD.AcCmColor.17")

三、数据转换

def vtpnt(x, y, z=0):
    """坐标点转化为浮点数"""
    return win32.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (x, y, z))

def vtobj(obj):
    """转化为对象数组"""
    return win32.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_DISPATCH, obj)

def vtfloat(lst):
    """列表转化为浮点数"""
    return win32.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, lst)

def vtInt(list):
    """列表转化为整数"""
    return win32.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_I2, list)

def vtVariant(list):
    """列表转化为变体"""
    return win32.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_VARIANT, list)

四、创建选择集

try:
    ssget1 = doc.SelectionSets.Add("SS1")  # 若无选择集,尝试新增"SS1"选择集
except BaseException:
    ssget1 = doc.SelectionSets("SS1")  # 如果"SS1"选择集已存在,就以它作为我们的选择集
    ssget1.Clear()  # 清空"SS1"选择集的内容

filterType = [2, 8]  # 定义过滤类型
filterData = ["FWSX", "FWSX"]  # 设置过滤参数
filterType = vtInt(filterType)  # 数据类型转换
filterData = vtVariant(filterData)  # 数据类型转换

ssget1.Select(5, 0, 0, filterType, filterData)  # 实现过滤选择

语法:

object.Select(Mode, Point1, Point2, FilterType, FilterData)
  • object:选择集
  • Mode:选择模式
模式说明
0选择完全在矩形区域内的所有对象,矩形对角由 Point1 和 Point2 定义
1选择在矩形区域内和与矩形区域相交的对象,矩形对角由 Point1 和 Point2 定义
3选择最近的选择集。如果用户在图纸空间和模型空间之间进行切换并试图使用选择集,该模式将被忽略
4选择最近生成的可见对象
5选择所有对象
  • Point1:3维坐标点
  • Point2:3维坐标点
  • FilterType:过滤类型(DXF组码)
DXF代码过滤器类型
0对象类型(字符串),如“Line”、“Circle”、“Arc”等等
2对象类型(字符串),命名对象的表(给定)名称
8图层名称(字符串),如“Layer0”
60对象的可见性(整数),0可见,1不可见
62颜色号(整数),0到256的数字索引值,0代表随块,256代表随层,负值代表图层关闭
67模型/图纸空间指示(整数),使用0或忽略为模型空间,1为图纸空间
  • FilterData:过滤参数

其他对象选择方法:

方法说明
Addltem添加一个或多个对象到指定的选择集。
Select选择对象并将其放入活动的选择集中。用户可选择所有对象、矩形窗选区域或矩形框选区域的对象、多边形窗选区域或多边形框选区域的对象、栅选的对象、最近创建的对象、最近选择集的对象。
SelectAtPoint选择通过给定点的对象并将其放入活动的选择集中。
SelectByPolygon通过栅选的对象并将其放入活动的选择集中。
SelectOnScreen提示用户从屏幕中拾取对象并将其添加到活动的选择中。

五、对象常用方法

1、对象相交

rel = obj1.IntersectWith(obj2, 0)
print(rel)

(1218.1517971803642, 625.2198412500425, 0.0, 1144.7959481512107, 361.0629323395639, 0.0)

2、对象上色

# 获取颜色接口
color = cad.GetInterfaceObject('AutoCAD.AcCmColor.17')
# 设置颜色
color.ColorIndex = 1
color.SetRGB(0, 255, 255)
# 给对象上色
obj.TrueColor = color

在这里插入图片描述

3、图层对象

# 添加图层
layer1 = doc.Layers.Add("户主名称")
# 设置当前图层
doc.ActiveLayer = layer1
# 指定图层的状态
layer1.LayerOn = False

# 遍历所有图层
for i in doc.Layers:
    if i.Name == '0':
        layer2 = i
    if i.Name == '面积插入':
        layer3 = i
# 设置当前图层
doc.ActiveLayer = layer2
# 删除图层
layer3.Delete()

六、创建新图形

cad = Cad()

new_doc = cad.docs.Add(r'C:\Users\liu\Desktop\1.dwg')

startPoint = cad.vtpnt(0, 0)
endPoint = cad.vtpnt(10, 10)

lineobj = new_doc.ModelSpace.AddLine(startPoint, endPoint)

new_doc.SaveAs(r'C:\Users\liu\Desktop\1.dwg')
new_doc.Close('TRUE')
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值