跳到主要内容PythonOCC 基础教程:几何建模与数据交换 | 极客日志Python算法
PythonOCC 基础教程:几何建模与数据交换
PythonOCC 的基础教程,涵盖环境配置、基础形状创建、布尔运算与几何变换、数据交换(STEP/IGES)以及 PyQt5 图形界面开发。内容包含详细的代码示例,展示了如何使用 PythonOCC 进行三维建模、文件读写及简单的 CAD 应用开发。
刀狂8 浏览 | 7.8.1.1 | 3.9 - 3.11 | OCCT 7.8.x | 当前最新稳定版,支持在 Jupyter 中使用 |
| 7.8.1 | 3.9 - 3.11 | OCCT 7.8.x | 于 2024 年 6 月 发布 |
| 7.7.2 | 3.9 - 3.10 | OCCT 7.7.x | 7.7 系列的小幅更新 |
| 7.7.0 | 3.9 | OCCT 7.7.0 | 你最初提到的版本 |
| 7.6.2 | 3.8 - 3.10 | OCCT 7.6.2 | 于 2022 年 8 月 发布,非常稳定的版本 |
| 7.5.1 | 3.7 - 3.9 | OCCT 7.5.1 | 你最初提到的版本 |
| 7.5.0rc1 | 3.7 - 3.9 | OCCT 7.5.0 | 7.5.0 的预发布候选版 |
| 7.4.1 | 3.7 - 3.8 | OCCT 7.4.0 | 7.4 系列的小幅更新 |
| 7.4.0 | 3.7 - 3.8 | OCCT 7.4.0 | 首个基于官方 OCCT 的版本之一 |
| 0.18.2 | 2.7, 3.5 - 3.7 | OCE 0.18 | 旧版,基于社区版 OCE 内核 |
| 0.18.1 | 2.7, 3.4 - 3.6 | OCE 0.18 | |
| 0.18 | 2.7, 3.4 - 3.6 | OCE 0.18 | |
| 0.17.x | 2.7, 3.4 | OCE 0.17 | 更早期的版本系列 |
from OCC.Display.SimpleGui import init_display
from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox
display, start_display, _, _ = init_display()
box = BRepPrimAPI_MakeBox(10,20,30).Shape()
display.DisplayShape(box, update=True)
start_display()
基础形状的创建
| 操作类别 | 核心 API 类 | 代码示例(核心部分) | 关键说明 |
|---|
| 创建点 | gp_Pnt | p = gp_Pnt(x, y, z) | 定义 3D 空间中的位置 |
| 创建线 | BRepBuilderAPI_MakeEdge | edge = BRepBuilderAPI_MakeEdge(p1, p2).Edge() | 两点确定一条线段 |
| 创建立方体 | BRepPrimAPI_MakeBox | box = BRepPrimAPI_MakeBox(dx, dy, dz).Shape() | 指定长宽高 |
| 创建球体 | BRepPrimAPI_MakeSphere | sphere = BRepPrimAPI_MakeSphere(radius).Shape() | 指定半径 |
| 创建圆柱体 | BRepPrimAPI_MakeCylinder | cylinder = BRepPrimAPI_MakeCylinder(radius, height).Shape() | 指定半径和高度 |
""" PythonOCC 基础形状演示 各物体沿 X 轴拉开间距,便于观察 """
from OCC.Display.SimpleGui import init_display
from OCC.Core.gp import gp_Pnt, gp_Ax2, gp_Dir
from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeEdge, BRepBuilderAPI_MakeVertex
from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox, BRepPrimAPI_MakeSphere, BRepPrimAPI_MakeCylinder
display, start_display, _, _ = init_display()
offset_x = 0
p = gp_Pnt(offset_x,0,0)
vertex = BRepBuilderAPI_MakeVertex(p).Vertex()
display.DisplayShape(vertex, color="RED")
offset_x += 35
p1 = gp_Pnt(offset_x,0,0)
p2 = gp_Pnt(offset_x +20,10,0)
edge = BRepBuilderAPI_MakeEdge(p1, p2).Edge()
display.DisplayShape(edge, color="GREEN", transparency=False)
offset_x += 45
box_dx, box_dy, box_dz = 10,20,30
box_corner = gp_Pnt(offset_x - box_dx/2,-box_dy/2,-box_dz/2)
box_axis = gp_Ax2(box_corner, gp_Dir(0,0,1))
box = BRepPrimAPI_MakeBox(box_axis, box_dx, box_dy, box_dz).Shape()
display.DisplayShape(box, color="BLUE", transparency=0.5)
offset_x += 40
sphere_radius = 15
sphere_center = gp_Pnt(offset_x,0,0)
sphere = BRepPrimAPI_MakeSphere(sphere_center, sphere_radius).Shape()
display.DisplayShape(sphere, color="YELLOW", transparency=0.3)
offset_x += 40
cylinder_radius = 10
cylinder_height = 40
cylinder_pos = gp_Pnt(offset_x,0,0)
cylinder_axis = gp_Ax2(cylinder_pos, gp_Dir(0,0,1))
cylinder = BRepPrimAPI_MakeCylinder(cylinder_axis, cylinder_radius, cylinder_height).Shape()
display.DisplayShape(cylinder, color="MAGENTA", transparency=0.4)
display.FitAll()
start_display()
布尔运算与几何变换
1. 布尔运算
布尔运算基于集合论,对两个实体形状进行操作,产生新的形状。PythonOCC 中对应的类位于 OCC.Core.BRepAlgoAPI 命名空间。
| 操作 | 类 | 效果 | 应用场景 |
|---|
| 融合 (Union) | BRepAlgoAPI_Fuse | 合并两个形状,得到它们的并集 | 将多个零件组合成一个整体 |
| 切割 (Cut) | BRepAlgoAPI_Cut | 从第一个形状中减去第二个形状 | 打孔、开槽、切除多余部分 |
| 交集 (Common) | BRepAlgoAPI_Common | 保留两个形状重叠的部分 | 提取交集体积,用于装配干涉检测 |
""" 布尔运算示例:融合、切割、交集 使用一个立方体(蓝色)和一个球体(黄色)演示 结果分别显示在三个区域 """
from OCC.Display.SimpleGui import init_display
from OCC.Core.gp import gp_Pnt, gp_Vec, gp_Trsf
from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox, BRepPrimAPI_MakeSphere
from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Fuse, BRepAlgoAPI_Cut, BRepAlgoAPI_Common
from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_Transform
display, start_display, _, _ = init_display()
box = BRepPrimAPI_MakeBox(10,10,10).Shape()
sphere_center = gp_Pnt(2,0,0)
sphere = BRepPrimAPI_MakeSphere(sphere_center,5).Shape()
fuse = BRepAlgoAPI_Fuse(box, sphere).Shape()
cut = BRepAlgoAPI_Cut(box, sphere).Shape()
common = BRepAlgoAPI_Common(box, sphere).Shape()
offset_x = 20
trsf_fuse = gp_Trsf()
trsf_fuse.SetTranslation(gp_Vec(-offset_x,0,0))
fuse_trans = BRepBuilderAPI_Transform(fuse, trsf_fuse,True).Shape()
display.DisplayShape(fuse_trans, color="GREEN", transparency=0.3)
display.DisplayShape(cut, color="RED", transparency=0.3)
trsf_common = gp_Trsf()
trsf_common.SetTranslation(gp_Vec(offset_x,0,0))
common_trans = BRepBuilderAPI_Transform(common, trsf_common,True).Shape()
display.DisplayShape(common_trans, color="BLUE", transparency=0.3)
display.FitAll()
start_display()
- 左侧(绿色):融合结果(立方体 + 球体并集)
- 中央(红色):切割结果(立方体减去球体,即'挖孔'效果)
- 右侧(蓝色):交集结果(立方体与球体重叠的部分)
2. 几何变换
几何变换是三维建模中的基础操作,允许我们移动、旋转、缩放或镜像一个形状,而不改变其内在几何结构。在 PythonOCC 中,几何变换通过 gp_Trfsf 类定义,并通过 BRepBuilderAPI_Transform 应用到形状上。
""" 几何变换演示(使用 Quantity_Color 精确设置颜色) """
from OCC.Display.SimpleGui import init_display
from OCC.Core.gp import gp_Trsf, gp_Vec, gp_Ax1, gp_Pnt, gp_Dir, gp_Ax2
from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox
from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_Transform
from OCC.Core.Quantity import Quantity_Color, Quantity_TOC_RGB
import math
display, start_display, _, _ = init_display()
def rgb_color(r, g, b):
return Quantity_Color(r, g, b, Quantity_TOC_RGB)
original_box = BRepPrimAPI_MakeBox(10,10,10).Shape()
display.DisplayShape(original_box, color=rgb_color(1.0,1.0,1.0), transparency=0.0)
trsf_trans = gp_Trsf()
trsf_trans.SetTranslation(gp_Vec(15,0,0))
trans_box = BRepBuilderAPI_Transform(original_box, trsf_trans,True).Shape()
display.DisplayShape(trans_box, color=rgb_color(1.0,0.0,0.0), transparency=0.3)
trsf_rot = gp_Trsf()
trsf_rot.SetRotation(gp_Ax1(gp_Pnt(0,0,0), gp_Dir(0,1,0)), math.radians(45))
rot_box = BRepBuilderAPI_Transform(original_box, trsf_rot,True).Shape()
trsf_move = gp_Trsf()
trsf_move.SetTranslation(gp_Vec(-15,0,0))
rot_box_moved = BRepBuilderAPI_Transform(rot_box, trsf_move,True).Shape()
display.DisplayShape(rot_box_moved, color=rgb_color(0.0,1.0,0.0), transparency=0.3)
trsf_scale = gp_Trsf()
trsf_scale.SetScale(gp_Pnt(0,0,0),1.5)
scale_box = BRepBuilderAPI_Transform(original_box, trsf_scale,True).Shape()
trsf_move2 = gp_Trsf()
trsf_move2.SetTranslation(gp_Vec(0,15,0))
scale_box_moved = BRepBuilderAPI_Transform(scale_box, trsf_move2,True).Shape()
display.DisplayShape(scale_box_moved, color=rgb_color(0.0,0.0,1.0), transparency=0.3)
plane_ax2 = gp_Ax2(gp_Pnt(0,0,0), gp_Dir(0,0,1))
trsf_mirror = gp_Trsf()
trsf_mirror.SetMirror(plane_ax2)
mirror_box = BRepBuilderAPI_Transform(original_box, trsf_mirror,True).Shape()
trsf_move3 = gp_Trsf()
trsf_move3.SetTranslation(gp_Vec(0,-15,0))
mirror_box_moved = BRepBuilderAPI_Transform(mirror_box, trsf_move3,True).Shape()
display.DisplayShape(mirror_box_moved, color=rgb_color(1.0,0.0,1.0), transparency=0.3)
trsf_trans2 = gp_Trsf()
trsf_trans2.SetTranslation(gp_Vec(10,10,0))
trsf_rot2 = gp_Trsf()
trsf_rot2.SetRotation(gp_Ax1(gp_Pnt(0,0,0), gp_Dir(0,0,1)), math.radians(45))
combined = trsf_rot2 * trsf_trans2
combined_box = BRepBuilderAPI_Transform(original_box, combined,True).Shape()
display.DisplayShape(combined_box, color=rgb_color(0.0,1.0,1.0), transparency=0.3)
display.FitAll()
start_display()
数据交换与 GUI 开发
在实际的 CAD/CAE 应用中,仅仅建模是不够的,通常需要与外部软件交换模型数据(如 STEP、IGES 格式),并且为用户提供图形界面来交互。PythonOCC 不仅提供了强大的几何内核,还支持与主流 GUI 框架(如 PyQt5、wxPython)无缝集成,让您能够快速开发专业的桌面应用程序。
1. 数据交换:读写 STEP 和 IGES 文件
STEP(ISO 10303)和 IGES(Initial Graphics Exchange Specification)是工业界最常用的三维模型交换格式。PythonOCC 通过 STEPControl_Reader / STEPControl_Writer 和 IGESControl_Reader / IGESControl_Writer 来支持这些格式的读写。
""" 数据交换示例:读取 STEP 文件并显示(直接指定文件路径) """
from OCC.Display.SimpleGui import init_display
from OCC.Core.STEPControl import STEPControl_Reader
from OCC.Core.IFSelect import IFSelect_RetDone
def load_and_display_step(filename):
reader = STEPControl_Reader()
status = reader.ReadFile(filename)
if status != IFSelect_RetDone:
print(f"读取文件失败:{ filename}")
return
reader.TransferRoots()
shape = reader.OneShape()
display, start_display, _, _ = init_display()
display.DisplayShape(shape, color="BLUE", transparency=0.2)
display.FitAll()
start_display()
if __name__ == "__main__":
step_file = r"path/to/your/file.step"
load_and_display_step(step_file)
""" 数据交换示例:读取 IGES 文件并显示(直接指定文件路径) 支持多实体文件,自动将所有形状显示在场景中 """
from OCC.Display.SimpleGui import init_display
from OCC.Core.IGESControl import IGESControl_Reader
def load_and_display_iges(filename):
reader = IGESControl_Reader()
status = reader.ReadFile(filename)
if status <= 0:
print(f"读取文件失败,返回码:{ status}")
return
print(f"成功读取 { status} 个实体")
reader.TransferRoots()
nb_shapes = reader.NbShapes()
print(f"转换得到 { nb_shapes} 个形状")
display, start_display, _, _ = init_display()
if nb_shapes == 1:
shape = reader.OneShape()
display.DisplayShape(shape, color="GREEN", transparency=0.2)
else:
for i in range(nb_shapes):
shape = reader.Shape(i+1)
color = ["BLUE","RED","YELLOW","MAGENTA","CYAN"][i % 5]
display.DisplayShape(shape, color=color, transparency=0.2)
display.FitAll()
start_display()
if __name__ == "__main__":
iges_file = r"path/to/your/file.igs"
load_and_display_iges(iges_file)
import sys
from OCC.Core.STEPControl import STEPControl_Reader
from OCC.Core.IGESControl import IGESControl_Writer
from OCC.Core.IFSelect import IFSelect_RetDone
def step_to_iges(input_step_file, output_iges_file):
""" 将 STEP 文件转换为 IGES 文件 """
step_reader = STEPControl_Reader()
status = step_reader.ReadFile(input_step_file)
if status != IFSelect_RetDone:
print(f"错误:无法读取 STEP 文件 '{ input_step_file}'")
return False
step_reader.TransferRoot()
shape = step_reader.Shape()
iges_writer = IGESControl_Writer()
iges_writer.AddShape(shape)
iges_writer.Write(output_iges_file)
print(f"成功:已将 '{ input_step_file}' 转换为 '{ output_iges_file}'")
return True
if __name__ == "__main__":
step_to_iges("1.step","1.igs")
2. 图形界面开发:将 PythonOCC 嵌入 PyQt5
PythonOCC 提供了与 Qt 框架集成的模块,使得我们可以轻松地将 3D 视图嵌入到 PyQt5 窗口中,并添加各种控件。
PythonOCC 的 OCC.Display.qtDisplay 模块中提供了 QtViewer3d 类,它封装了 OpenGL 渲染上下文和鼠标交互。只需创建一个 QWidget 子类,并将 QtViewer3d 作为其子部件即可。
简易 CAD 查看器(PyQt5 + PythonOCC)
""" 简易 CAD 查看器:支持加载/保存 STEP,显示模型信息 修正:显式加载 Qt 后端 """
import sys
from PyQt5.QtWidgets import(QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QWidget, QPushButton, QFileDialog, QLabel, QStatusBar, QMessageBox)
from PyQt5.QtCore import Qt
from OCC.Display.backend import load_backend
load_backend("pyqt5")
from OCC.Display.qtDisplay import qtViewer3d
from OCC.Core.STEPControl import STEPControl_Reader, STEPControl_Writer
from OCC.Core.IFSelect import IFSelect_RetDone
from OCC.Core.TopExp import TopExp_Explorer
from OCC.Core.TopAbs import TopAbs_FACE, TopAbs_EDGE, TopAbs_VERTEX
class CADViewer(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("简易 CAD 查看器")
self.setGeometry(100,100,1200,800)
central = QWidget()
self.setCentralWidget(central)
layout = QVBoxLayout(central)
self.viewer = qtViewer3d(self)
layout.addWidget(self.viewer)
btn_layout = QHBoxLayout()
load_btn = QPushButton("加载 STEP")
load_btn.clicked.connect(self.load_step)
save_btn = QPushButton("保存 STEP")
save_btn.clicked.connect(self.save_step)
clear_btn = QPushButton("清除")
clear_btn.clicked.connect(self.clear_view)
info_btn = QPushButton("模型信息")
info_btn.clicked.connect(self.show_info)
btn_layout.addWidget(load_btn)
btn_layout.addWidget(save_btn)
btn_layout.addWidget(clear_btn)
btn_layout.addWidget(info_btn)
layout.addLayout(btn_layout)
self.status_bar = QStatusBar()
self.setStatusBar(self.status_bar)
self.status_bar.showMessage("就绪")
self.shape = None
self.current_file = None
def load_step(self):
filename, _ = QFileDialog.getOpenFileName(self,"打开 STEP 文件","","STEP Files (*.step *.stp)")
if not filename:
return
reader = STEPControl_Reader()
status = reader.ReadFile(filename)
if status != IFSelect_RetDone:
self.status_bar.showMessage("读取失败")
return
reader.TransferRoots()
self.shape = reader.OneShape()
self.current_file = filename
self.viewer._display.Context.RemoveAll(True)
self.viewer._display.DisplayShape(self.shape, color="LIGHTBLUE", transparency=0.2)
self.viewer._display.FitAll()
self.status_bar.showMessage(f"已加载:{ filename}")
def save_step(self):
if self.shape is None:
self.status_bar.showMessage("没有可保存的形状")
return
filename, _ = QFileDialog.getSaveFileName(self,"保存 STEP 文件","","STEP Files (*.step)")
if not filename:
return
writer = STEPControl_Writer()
writer.Transfer(self.shape, STEPControl_AsIs)
writer.Write(filename)
self.status_bar.showMessage(f"已保存到:{ filename}")
def clear_view(self):
self.viewer._display.Context.RemoveAll(True)
self.viewer._display.FitAll()
self.shape = None
self.current_file = None
self.status_bar.showMessage("场景已清空")
def show_info(self):
if self.shape is None:
self.status_bar.showMessage("无模型")
return
face_count = 0
edge_count = 0
vertex_count = 0
exp = TopExp_Explorer()
exp.Init(self.shape, TopAbs_FACE)
while exp.More():
face_count += 1
exp.Next()
exp.Init(self.shape, TopAbs_EDGE)
while exp.More():
edge_count += 1
exp.Next()
exp.Init(self.shape, TopAbs_VERTEX)
while exp.More():
vertex_count += 1
exp.Next()
info = f"文件:{ self.current_file}\n面数:{ face_count}\n边数:{ edge_count}\n顶点数:{ vertex_count}"
QMessageBox.information(self,"模型信息", info)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = CADViewer()
window.show()
sys.exit(app.exec_())
参数化建模
import math
from OCC.Core.gp import gp_Pnt, gp_Ax1, gp_Dir, gp_Trsf, gp_Vec
from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeCylinder, BRepPrimAPI_MakeBox
from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_Transform
from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Cut, BRepAlgoAPI_Fuse
from OCC.Display.SimpleGui import init_display
flange_outer_radius = 60.0
flange_inner_radius = 20.0
flange_thickness = 10.0
bolt_circle_radius = 45.0
微信扫一扫,关注极客日志
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- curl 转代码
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
- HTML转Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online