import pythoncom
import win32com.client
import time
# 常量
SW_DOC_PART = 1
SW_DOC_ASSEMBLY = 2
def connect_to_solidworks():
"""连接到 SolidWorks 应用"""
pythoncom.CoInitialize()
try:
swApp = win32com.client.Dispatch("SldWorks.Application")
swApp.Visible = True
return swApp
except Exception as e:
print(f"无法连接到 SolidWorks: {e}")
pythoncom.CoUninitialize()
return None
def get_active_assembly(swApp):
"""获取当前活动的装配体文档"""
model = swApp.ActiveDoc
if model is None or model.GetType != SW_DOC_ASSEMBLY:
print("请在 SolidWorks 中打开一个装配体文件")
return None, None
return model, model # model 即为 AssemblyDoc
def get_all_leaf_components(assembly):
"""
递归提取装配体中所有叶子节点零件 (Component2 对象)
子装配体会被展开,最终列表只包含最底层零件组件。
"""
leaves = []
def recurse(comp_list):
if not comp_list:
return
for comp in comp_list:
if comp is None:
continue
try:
children = comp.GetChildren() # 修正为方法调用
if not children:
leaves.append(comp)
else:
recurse(children)
except Exception as e:
print(f"无法获取 {comp.Name2} 的子组件: {e}")
leaves.append(comp) # 假设无子组件,视为叶子节点
try:
top_comps = assembly.GetComponents(True) # True = 包含子装配
recurse(top_comps)
except Exception as e:
print(f"获取顶级组件失败: {e}")
return leaves
def check_collision(assembly):
"""
使用 CheckInterference2 检查是否存在干涉
返回 True=有干涉, False=无干涉
"""
try:
ext = assembly.Extension
result = ext.CheckInterference2(False, True, False)
if result is None:
print("干涉检查返回 None,可能 API 调用失败")
return False
return result.Count > 0
except Exception as e:
print(f"干涉检查出错: {e}")
return False
def try_move_component(comp, assembly, direction, step=0.01, max_move=0.1):
"""
尝试沿给定方向移动零件,每次移动 step 米,最多移动 max_move 米。
direction: (dx,dy,dz) 单位向量
返回 True=成功无碰撞, False=碰撞或出错并恢复
"""
if comp is None or comp.IsFixed: # 修正:移除括号
print(f"{comp.Name2 if comp else 'None'} 被固定或无效")
return False
# 抑制相关配合关系
suppressed_mates = []
try:
mates = assembly.GetMates()
for mate in mates:
if mate.Component1 == comp or mate.Component2 == comp:
mate.Suppressed = True
suppressed_mates.append(mate)
except Exception as e:
print(f"无法获取或抑制 {comp.Name2} 的配合关系: {e}")
try:
original = comp.Transform2
mat = list(original.ArrayData)
if len(mat) != 16:
print(f"变换矩阵长度错误: {len(mat)}")
return False
print(f"初始变换矩阵 for {comp.Name2}: {mat}")
moved = 0.0
while moved < max_move:
mat[12] += direction[0] * step
mat[13] += direction[1] * step
mat[14] += direction[2] * step
math_data = win32com.client.Dispatch("SldWorks.MathUtility")
transform = math_data.CreateTransform(mat)
comp.Transform2 = transform # 使用 Transform2 替代 SetTransform
assembly.EditRebuild3()
time.sleep(0.05)
if check_collision(assembly):
comp.Transform2 = original
assembly.EditRebuild3()
for mate in suppressed_mates:
mate.Suppressed = False
return False
moved += step
for mate in suppressed_mates:
mate.Suppressed = False
return True
except Exception as e:
print(f"移动 {comp.Name2} 出错: {e}")
comp.Transform2 = original
assembly.EditRebuild3()
for mate in suppressed_mates:
mate.Suppressed = False
return False
def attempt_disassembly(comp, assembly):
"""对单个零件按 6 向尝试拆卸,返回 True=任一方向成功"""
directions = [
(1, 0, 0), (-1, 0, 0),
(0, 1, 0), (0, -1, 0),
(0, 0, 1), (0, 0, -1),
]
for dir_vec in directions:
print(f" 尝试方向 {dir_vec}")
if try_move_component(comp, assembly, dir_vec):
print(f" ✅ 零件 {comp.Name2} 沿 {dir_vec} 拆卸成功")
return True
print(f" ❌ 零件 {comp.Name2} 在所有方向均发生碰撞")
return False
def main():
swApp = connect_to_solidworks()
if swApp is None:
return
model, assembly = get_active_assembly(swApp)
if assembly is None:
return
comps = get_all_leaf_components(assembly)
print(f"检测到 {len(comps)} 个叶子零件,开始拆卸尝试...\n")
for comp in comps:
print(f"开始处理零件: {comp.Name2}")
if attempt_disassembly(comp, assembly):
pass
else:
print(f" ⚠️ 无法拆卸零件 {comp.Name2}")
print("-" * 40)
print("所有零件拆卸尝试完成。")
pythoncom.CoUninitialize()
if __name__ == "__main__":
main()运行结果:D:\Anaconda\install\envs\myenv\python.exe D:/Anaconda/install/envs/myenv/7yue/1.py
无法获取 圆形导轨上-2 的子组件: 'tuple' object is not callable
无法获取 下-3 的子组件: 'tuple' object is not callable
无法获取 圆形导轨盖-2 的子组件: 'tuple' object is not callable
检测到 3 个叶子零件,开始拆卸尝试...
开始处理零件: 圆形导轨上-2
尝试方向 (1, 0, 0)
无法获取或抑制 圆形导轨上-2 的配合关系: <unknown>.GetMates
初始变换矩阵 for 圆形导轨上-2: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, -0.29158931171836594, 0.09585032812809255, -0.1541236130884311, 1.0, 0.0, 0.0, 0.0]
移动 圆形导轨上-2 出错: (-2147221005, '无效的类字符串', None, None)
Traceback (most recent call last):
File "D:\Anaconda\install\envs\myenv\lib\site-packages\win32com\client\dynamic.py", line 81, in _GetGoodDispatch
IDispatch = pythoncom.connect(IDispatch)
pywintypes.com_error: (-2147221005, '无效的类字符串', None, None)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "D:\Anaconda\install\envs\myenv\7yue\1.py", line 110, in try_move_component
math_data = win32com.client.Dispatch("SldWorks.MathUtility")
File "D:\Anaconda\install\envs\myenv\lib\site-packages\win32com\client\__init__.py", line 116, in Dispatch
dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch, userName, clsctx)
File "D:\Anaconda\install\envs\myenv\lib\site-packages\win32com\client\dynamic.py", line 101, in _GetGoodDispatchAndUserName
return (_GetGoodDispatch(IDispatch, clsctx), userName)
File "D:\Anaconda\install\envs\myenv\lib\site-packages\win32com\client\dynamic.py", line 83, in _GetGoodDispatch
IDispatch = pythoncom.CoCreateInstance(
pywintypes.com_error: (-2147221005, '无效的类字符串', None, None)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "D:\Anaconda\install\envs\myenv\7yue\1.py", line 175, in <module>
main()
File "D:\Anaconda\install\envs\myenv\7yue\1.py", line 165, in main
if attempt_disassembly(comp, assembly):
File "D:\Anaconda\install\envs\myenv\7yue\1.py", line 145, in attempt_disassembly
if try_move_component(comp, assembly, dir_vec):
File "D:\Anaconda\install\envs\myenv\7yue\1.py", line 131, in try_move_component
assembly.EditRebuild3()
TypeError: 'bool' object is not callable
进程已结束,退出代码1