文章目錄
- 一、application 版本
- 二、基本操作
- 三、資料轉換
- 四、建立選擇集
- 五、對象常用方法
-
- 六、建立新圖形
一、application 版本
AutoCAD産品名 | 版本号 | ProgID |
AutoCAD 2004 | R16 | AutoCAD.Application.16 |
AutoCAD 2005 | R16.1 | AutoCAD.Application.16.1 |
AutoCAD 2006 | R16.2 | AutoCAD.Application.16.2 |
AutoCAD 2007 | R17 | AutoCAD.Application.17 |
AutoCAD 2008 | R17.1 | AutoCAD.Application.17.1 |
AutoCAD 2009 | R17.2 | AutoCAD.Application.17.2 |
AutoCAD 2010 | R18 | AutoCAD.Application.18 |
AutoCAD 2011 | R18.1 | AutoCAD.Application.18.1 |
AutoCAD 2014 | R19.1 | AutoCAD.Application.19.1 |
AutoCAD 2015 | R20 | AutoCAD.Application.20 |
AutoCAD 2016 | R20.1 | AutoCAD.Application.20.1 |
AutoCAD 2017 | R21 | AutoCAD.Application.21 |
AutoCAD 2018 | R22 | AutoCAD.Application.22 |
AutoCAD 2019 | R23 | AutoCAD.Application.23 |
使用者最後一次使用的CAD | 無 | AutoCAD.Application |
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) # 實作過濾選擇
文法:
模式 | 說明 |
選擇完全在矩形區域内的所有對象,矩形對角由 Point1 和 Point2 定義 |
1 | 選擇在矩形區域内和與矩形區域相交的對象,矩形對角由 Point1 和 Point2 定義 |
3 | 選擇最近的選擇集。如果使用者在圖紙空間和模型空間之間進行切換并試圖使用選擇集,該模式将被忽略 |
4 | 選擇最近生成的可見對象 |
5 | 選擇所有對象 |
- Point1:3維坐标點
- Point2:3維坐标點
- FilterType:過濾類型(DXF組碼)
DXF代碼 | 過濾器類型 |
對象類型(字元串),如“Line”、“Circle”、“Arc”等等 |
2 | 對象類型(字元串),命名對象的表(給定)名稱 |
8 | 圖層名稱(字元串),如“Layer0” |
60 | 對象的可見性(整數),0可見,1不可見 |
62 | 顔色号(整數),0到256的數字索引值,0代表随塊,256代表随層,負值代表圖層關閉 |
67 | 模型/圖紙空間訓示(整數),使用0或忽略為模型空間,1為圖紙空間 |
其他對象選擇方法:
方法 | 說明 |
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')