-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFunction_autoassembly.py
More file actions
203 lines (141 loc) · 8.47 KB
/
Copy pathFunction_autoassembly.py
File metadata and controls
203 lines (141 loc) · 8.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# use CQ-Editor to tune the code, moving parts to proper locations or adding constraints to make assembly
# then copy the code here
def autoassem_coldplate(CP_path, lets_path, chips_path, output=None):
import cadquery as cq
from cadquery import importers
import os
# ==========================================
# 1.Import parts
# ==========================================
coldplate = importers.importStep(CP_path)
inoutlet = importers.importStep(lets_path)
chips = importers.importStep(chips_path)
# ==========================================
# 2. define location of parts
# --- (Coldplate location) ---
loc_base = cq.Location(cq.Vector(0, 0, 0))
# --- (inoutlet location) ---
loc_blue = cq.Location(cq.Vector(0, -15/2, 4.175/2), cq.Vector(1, 0, 0), 90)
lets_location = [(0, -15/2, 4.175/2),
(0, 15/2+200, 4.175/2)
]
# --- (chips location) ---
loc_chip_1 = cq.Location(cq.Vector(7.5/2, 7.5/2, -0.125/2), cq.Vector(1,0,0), 90)
chip_location = [
(7.5/2, 7.5/2, -0.125/2),
(7.5/2, -7.5/2, -0.125/2),
(-7.5/2, 7.5/2, -0.125/2),
(-7.5/2, -7.5/2, -0.125/2)
]
# ==========================================
# 3. 组装 (Assembly)
# ==========================================
assem = cq.Assembly()
# add parts into assembly
# syntex ----- assem.add(part variable, name="assign name for this part", color=cq.Color("red"))
# add Coldplate core
assem.add(coldplate, name="Coldplate", loc=loc_base, color=cq.Color("red"))
# add two header lets to the end of coldplate
for i, pos in enumerate(lets_location):
lets_loc = cq.Location(cq.Vector(*pos), cq.Vector(1, 0, 0), 90)
lets_name = f"let_{i}"
assem.add(inoutlet, name=lets_name, loc=lets_loc, color=cq.Color("blue"))
# assem.add(inoutlet, name="inlet", loc=loc_blue, color=cq.Color("blue"))
# add 4 chips onto the bottion of the coldplate
for i,pos in enumerate (chip_location):
chips_loc = cq.Location(cq.Vector(*pos), cq.Vector(1,0,0), 90)
chips_name = f"chip_{i}"
assem.add(chips, name=chips_name, loc=chips_loc, color=cq.Color("green"))
# assem.add(chips, name="chip_1", loc=loc_chips, color=cq.Color("green"))
if output is None:
# obtain current user main path获取当前用户的“用户主目录” (如 C:\Users\Username)
user_home = os.path.expanduser("~")
# obtain desktop path 拼接出桌面路径
desktop_path = os.path.join(user_home, "Desktop")
# define a file name 定义一个默认文件名
save_path = os.path.join(desktop_path, "undefined_path_export.step")
else:
save_path = output
assem.save(save_path)
return save_path
# 1.定平面 (Find Plane):找到盒子顶面,作为侦测的基准。
# 2.找圆心 (Find XY):在顶面上扫描所有轮廓线,取最短的那条(孔口),计算其圆心坐标 (x, y)。
# 3.找孔底 (Find Z):扫描盒子所有朝上的平面,按高度排名。第 2 高的面即为孔底,获取其高度 z。
# 4.合体 (Assemble):将插销的基准点直接搬运到计算出的 (x, y, z) 坐标。
def Auto_box_OneHole_OnePin(box_path, pin_path, output=None):
import cadquery as cq
from cadquery import importers
import os
# ==========================================
# 1. Import files
# ==========================================
box = importers.importStep(box_path)
pin = importers.importStep(pin_path)
# ==========================================
# 2. The Parametric Logic locating the hole 全自动定位逻辑
# ==========================================
try:
print("scanning geometry features...")
# --- Step 1: locate center of hole 找 XY 中心 ---
top_face = box.faces(">Z")
wires = top_face.wires().vals()
# Looking for the shortest perimeter 找最短的轮廓(孔口)
hole_wire = sorted(wires, key=lambda w: w.Length())[0]
center_xy = hole_wire.Center()
# --- Step 2: fine the z for bottom of hole 找 Z 高度 (孔底) ---
# fine all surface which face to the top(normal to (0,0,1)), from top to bottom 找到所有法线向上(0,0,1)的平面,按高度从高到低排序
# [0] is the top face of box, [1]is bottom of hoel [0]是盒子顶面, [1]通常就是盲孔的底面
all_planes = box.faces("%Plane").vals()
upward_planes = [f for f in all_planes if f.normalAt(None).z > 0.9]
upward_planes.sort(key=lambda f: f.Center().z, reverse=True)
if len(upward_planes) > 1:
# second height face is bottom of hole 找到了第二高的面,认为是孔底
target_z = upward_planes[1].Center().z
print(f"✅ detect bottom of hole: Z={target_z:.2f}")
else:
# 没找到(可能是通孔),就用盒子最底面
target_z = box.faces("<Z").val().Center().z
print(f"⚠️ not bottom surface found, all through hole: Z={target_z:.2f}")
# 组合最终目标坐标
target_loc = cq.Vector(center_xy.x, center_xy.y, target_z)
print(f"✅ locate the mating coordination: {target_loc}")
except Exception as e:
print(f"⚠️ failed to dected the hole: {e}")
target_loc = cq.Vector(0,0,0)
# ==========================================
# 3. 组装 (Assembly)
# ==========================================
assem = cq.Assembly()
loc_base = cq.Location(cq.Vector(0, 0, 0))
# translate pin to the coordination just found 【关键】把插销直接放到计算好的 (x, y, z_bottom)
loc_pin = cq.Location(target_loc)
assem.add(box, name="box", loc=loc_base, color=cq.Color("red"))
assem.add(pin, name="pin", loc=loc_pin, color=cq.Color("blue"))
# 判断用户是否输入了路径
if output is None:
# obtain current user main path获取当前用户的“用户主目录” (如 C:\Users\Username)
user_home = os.path.expanduser("~")
# obtain desktop path 拼接出桌面路径
desktop_path = os.path.join(user_home, "Desktop")
# define a file name 定义一个默认文件名
save_path = os.path.join(desktop_path, "undefined_path_export.step")
else:
save_path = output
assem.save(save_path)
return save_path
if __name__ =="__main__":
CP_path = r"C:\Users\lichengd\OneDrive - Oregon State University\1. PhD\Chiller\automation\Chiller_auto_Python\CAD_files\Export_Coldplate_spreadsheet.step"
lets_path = r"C:\Users\lichengd\OneDrive - Oregon State University\1. PhD\Chiller\automation\Chiller_auto_Python\CAD_files\InOutlet_MaxWidth_step.SLDPRT.STEP"
chips_path = r"C:\Users\lichengd\OneDrive - Oregon State University\1. PhD\Chiller\automation\Chiller_auto_Python\CAD_files\chip1_step.STEP"
save_path = r"C:\Users\lichengd\OneDrive - Oregon State University\1. PhD\Chiller\automation\Chiller_auto_Python\CAD_files\Export_autoAssem_coldplate.step"
result = autoassem_coldplate(CP_path, lets_path, chips_path, output=save_path)
print(f"Assembly exported to:\n{result}")
# CP_path = r"C:\Users\lichengd\OneDrive - Oregon State University\1. PhD\Chiller\automation\Chiller_auto_Python\CAD_files\Export_Coldplate_spreadsheet.step"
# lets_path = r"C:\Users\lichengd\OneDrive - Oregon State University\1. PhD\Chiller\automation\Chiller_auto_Python\CAD_files\InOutlet_MaxWidth_step.SLDPRT.STEP"
# chips_path = r"C:\Users\lichengd\OneDrive - Oregon State University\1. PhD\Chiller\automation\Chiller_auto_Python\CAD_files\chip1_step.STEP"
# save_path = r"C:\Users\lichengd\OneDrive - Oregon State University\1. PhD\Chiller\automation\Chiller_auto_Python\CAD_files\Export_autoAssem_coldplate.step"
box_path = r"C:\Users\lichengd\OneDrive - Oregon State University\1. PhD\Chiller\automation\Chiller_auto_Python\CAD_files\Export_Box_hole_Spreadsheet.step"
pin_path = r"C:\Users\lichengd\OneDrive - Oregon State University\1. PhD\Chiller\automation\Chiller_auto_Python\CAD_files\Export_pin_Spreadsheet.step"
save_path = r"C:\Users\lichengd\OneDrive - Oregon State University\1. PhD\Chiller\automation\Chiller_auto_Python\CAD_files\Export_autoAssem_BoxPin.step"
result = Auto_box_OneHole_OnePin(box_path,pin_path, output=save_path)
print(f"Assembly exported to:\n{result}")