目次
- はじめに
- pythonOCCとはなんぞや?
- 実行環境
- 入力
- 事前設定
- 動かしたコード
- 結果
- 今後の予定
- 最後に
- 参考情報
はじめに
LIGTHzアドベントカレンダー 2022の18日目の記事です。
サイズの大きなstepファイル(3DCADデータファイル)の幾何情報や寸法情報を
市販ツールを使う事なく簡易的に調べたくなる場面があり、オープンソース
を使って手早く幾何情報や寸法情報を識別する方法がないかを調べています。
python OpenCasCade Technology(通称pythonOCC)を用い
stepファイル(3DCADデータファイル)から面の形を検出したので
手順を残します。(初心者向け)
PythonOCCとはなんぞや?
・C++実装のOSSであるOpenCascade Technology(OCCT)にpythonのラッパーがかぶさったOSSを指し、
3次元CADやCAM、その他のための開発プラットフォームとして提供されています。(wikipedia参照)
・OCCTを使う事により、stp/B-repデータから3D形状の寸法や幾何情報などを読み出したり、
3D形状設計を行う事などができます。
・20年以上、非ソフトウェア分野を含む幅広な技術ドメインで利用されてきた事もあり、
ややサグラダファミリア化しているとの声もある様です。(参照記事)
・使い方などの詳細はリンク先をご参照願います。
OCCTのコミュニティサイト
開発者による利用方法の説明動画(youtube)
何に使うのか?
・3D形状設計を簡易的に行いたい時
・step/B-repファイルなどの3DCADデータから寸法情報や表面の形状情報などを自動的に取り出したい時
実行環境
OS: Ubuntu 20.04 LTS
python: 3.8.13
conda: 4.14.0
numpy: 1.22.4
IPython : 8.5.0
jupyter_core : 4.11.1
pythonOCC: 7.6.1 (GNU GPLv3ライセンス)
ソースコード(pythonocc_core)
ソースコード(pythonocc_util)
ソースコード(pythonocc_demos)
入力
以下オープンソースで提供されている3DCADデータを用いました。
stpデータ
(MITライセンス)
事前設定
以下の環境設定を行います。
% conda create -n test python=3.8.13
% conda activate test
% conda install -c conda-forge pythonocc-core=7.5.1
% conda install -c numpy
% git clone https://github.com/tpaviot/pythonocc-core.git
% git clone https://github.com/tpaviot/pythonocc-demos.git
% git clone https://github.com/tpaviot/pythonocc-utils.git
以下を実行し、実行OKメッセージが出たら環境構築完了です。
% cd ./pythonocc-core/test/
% python run_test.py
:
:
test_midpoint (core_extend_shapefactory_unittest.TestExtendShapeFactory) ... ok
test_scale_shape (core_extend_shapefactory_unittest.TestExtendShapeFactory) ... ok
----------------------------------------------------------------------
Ran 117 tests in 5.931s
OK
動かしたコード
以下のコードは、pythonocc-demos/core_geometry_face_recognition_from_stepfile.py
を基に若干の修正を加えたものとなります。
まず、形状面を識別するためのライブラリ群をimportします。
BRepAdaptor_Surfaceが形状面の種別判定用classとなります。
import os
import os.path
import sys
from OCC.Core.STEPControl import STEPControl_Reader
from OCC.Core.IFSelect import IFSelect_RetDone, IFSelect_ItemsByEntity
from OCC.Core.GeomAbs import GeomAbs_Plane, GeomAbs_Cylinder
from OCC.Core.TopoDS import topods_Face
from OCC.Core.BRepAdaptor import BRepAdaptor_Surface
from OCC.Display.SimpleGui import init_display
from OCC.Extend.TopologyUtils import TopologyExplorer
#pythonOCC library
from OCC.Core.Geom import Geom_ElementarySurface
from OCC.Core.Geom import Geom_CylindricalSurface
from OCC.Core.BRep import BRep_Tool_Surface
次に、stp(step)ファイルをロードするための関数を定義します。
def read_step_file(filename):
""" read the STEP file and returns a compound
"""
step_reader = STEPControl_Reader()
status = step_reader.ReadFile(filename)
if status == IFSelect_RetDone: # check status
failsonly = False
step_reader.PrintCheckLoad(failsonly, IFSelect_ItemsByEntity)
step_reader.PrintCheckTransfer(failsonly, IFSelect_ItemsByEntity)
step_reader.TransferRoot(1)
a_shape = step_reader.Shape(1)
else:
print("Error: can't read file.")
sys.exit(0)
return a_shape
次に、stepファイルから形状面の名称などを識別する関数を定義します。
BRepAdaptor_Surfaceでa_face(3DCADデータ実体)の形状面を識別して結果毎に表示処理を変えています。
def recognize_face(a_face):
""" Takes a TopoDS shape and tries to identify its nature
whether it is a plane a cylinder a torus etc.
if a plane, returns the normal
if a cylinder, returns the radius
"""
surf = BRepAdaptor_Surface(a_face, True)
surf_type = surf.GetType()
if surf_type == GeomAbs_Plane:
print("--> plane")
# look for the properties of the plane
# first get the related gp_Pln
gp_pln = surf.Plane()
location = gp_pln.Location() # a point of the plane
normal = gp_pln.Axis().Direction() # the plane normal
# then export location and normal to the console output
print("--> Location (global coordinates)", location.X(), location.Y(), location.Z())
print("--> Normal (global coordinates)", normal.X(), normal.Y(), normal.Z())
elif surf_type == GeomAbs_Cylinder:
print("--> cylinder")
# look for the properties of the cylinder
# first get the related gp_Cyl
gp_cyl = surf.Cylinder()
location = gp_cyl.Location() # a point of the axis
axis = gp_cyl.Axis().Direction() # the cylinder axis
# then export location and normal to the console output
print("--> Location (global coordinates)", location.X(), location.Y(), location.Z())
print("--> Axis (global coordinates)", axis.X(), axis.Y(), axis.Z())
else:
# TODO there are plenty other type that can be checked
# see documentation for the BRepAdaptor class
# https://www.opencascade.com/doc/occt-6.9.1/refman/html/class_b_rep_adaptor___surface.html
print("not implemented")
> # TODO there are plenty other type that can be checked
> # see documentation for the BRepAdaptor class
> # https://www.opencascade.com/doc/occt-6.9.1/refman/html/class_b_rep_adaptor___surface.html
C++最新版のOCC(7.6.3)にpythonoccのバージョンアップが追い付いていない(6.9.1)様で上記のコメントがあります。
全機能を本格的に使いこなすにはC++版も確認する必要があるかもしれないですね。
最後に、実際のstepファイル(./sample.stp(各自で動かす時は事前に用意してください))
をrecognize_faceで読み込み、形状面の名称などを識別します。
path: str = './sample.stp'
shp = read_step_file(path)
t = TopologyExplorer(shp)
# loop over faces only
for f in t.faces():
# call the recognition function
recognize_face(f)
結果
Output exceeds the size limit. Open the full output data in a text editor
--> cylinder
--> Location (global coordinates) 13.5 20.5 5.2
--> Axis (global coordinates) 0.0 0.0 2.0
--> plane
--> Location (global coordinates) 60.5 12.5 3.2
--> Normal (global coordinates) 0.0 -1.0 0.0
:
形状面毎の形の識別結果(cylinder、planeなど)や座標位置(Location)などを検出する事が出来ました。
今後の予定
- 寸法や形状面同士の接続関係を識別するコードの実装方法を調査し、適宜掲載予定です
- pythonocc-demos以下などのソースコードの読み解き結果を適宜掲載予定です
- OCCT利用方法の調査結果を適宜掲載予定です
最後に
弊社では、自動車・機械産業のお客様に向けたソリューション開発エンジニアを絶賛採用中(2022/12時点)です
https://www.wantedly.com/projects/1181162
参考情報
- pythonOCC Q&A
https://github.com/tpaviot/pythonocc-core/issues - pythonOCC利用例
https://qiita.com/MachineCAT/items/c3e417a44d40890c608c