1. コマンドラインからのpng出力
GUI版PythonSCADで、ターミナルから、PNG画像の出力ができました。
.\pythonscad.exe --enable python-engine --trust-python -o preview.png --autocenter --viewall --imgsize 800,600 sample.py
.\pythonscad.exe --enable python-engine --trust-python -o render.png --render --autocenter --viewall --imgsize 1920,1080 --colorscheme "DeepOcean" sample.py
スクリプト内の、export(obj,"preview.png")は、モデル出力であり、0KBになります。
コマンドでrender()がありますが、
obj.render().show()
レンダリングモードで、GUIで表示するようです。
別のコマンド命令で、pythonscad-python.exeがあります。png出力はできないようです。
> .\pythonscad-python.exe -h
PS C:\Users\yourname\Documents\PythonSCAD-1.1.2> usage: C:\Users\yuchi\Documents\PythonSCAD-1.1.2\pythonscad-python.exe [option] ... [-c cmd | -m mod | file | -] [arg] ...
Options (and corresponding environment variables):
-b : issue warnings about converting bytes/bytearray to str and comparing
bytes/bytearray with str or bytes with int. (-bb: issue errors)
-B : don't write .pyc files on import; also PYTHONDONTWRITEBYTECODE=x
-c cmd : program passed in as string (terminates option list)
-d : turn on parser debugging output (for experts only, only works on
debug builds); also PYTHONDEBUG=x
-E : ignore PYTHON* environment variables (such as PYTHONPATH)
-h : print this help message and exit (also -? or --help)
-i : inspect interactively after running script; forces a prompt even
if stdin does not appear to be a terminal; also PYTHONINSPECT=x
-I : isolate Python from the user's environment (implies -E, -P and -s)
-m mod : run library module as a script (terminates option list)
-O : remove assert and __debug__-dependent statements; add .opt-1 before
.pyc extension; also PYTHONOPTIMIZE=x
-OO : do -O changes and also discard docstrings; add .opt-2 before
.pyc extension
-P : don't prepend a potentially unsafe path to sys.path; also
PYTHONSAFEPATH
-q : don't print version and copyright messages on interactive startup
-s : don't add user site directory to sys.path; also PYTHONNOUSERSITE=x
-S : don't imply 'import site' on initialization
-u : force the stdout and stderr streams to be unbuffered;
this option has no effect on stdin; also PYTHONUNBUFFERED=x
-v : verbose (trace import statements); also PYTHONVERBOSE=x
can be supplied multiple times to increase verbosity
-V : print the Python version number and exit (also --version)
when given twice, print more information about the build
-W arg : warning control; arg is action:message:category:module:lineno
also PYTHONWARNINGS=arg
-x : skip first line of source, allowing use of non-Unix forms of #!cmd
-X opt : set implementation-specific option
--check-hash-based-pycs always|default|never:
control how Python invalidates hash-based .pyc files
--help-env: print help about Python environment variables and exit
--help-xoptions: print help about implementation-specific -X options and exit
--help-all: print complete help information and exit
Arguments:
file : program read from script file
- : program read from stdin (default; interactive mode if a tty)
arg ...: arguments passed to program in sys.argv[1:]
python3.11にimport pythonscadを入れました。
headlessでの、png出力は、できないでしょうか。
探し方として、help
>>> help(pythonscad.render)
Help on built-in function render in module _openscad:
render(...)
Render Object.
openscadのモジュールに準拠しているのでしょうか。
headlessで、
コマンドラインのPNG出力処理でもモデル評価のトリガーになるような方法があればよいです。
現状は、pythonscadコマンドだけでしょうか。
2. AIからの回答
1. モジュールはOpenSCAD準拠
help() の表示に module _openscad と出ている通り、import pythonscad(実体は _openscad)はOpenSCADの内部APIをPythonに露出したものです。したがって pythonscad.render() はOpenSCADの render() と同じ意味、つまり**CGAL/Manifoldによるジオメトリの完全評価(F6相当)**であって、画像レンダリングではありません。obj.render().show() でGUI表示になるのはそのためです(評価済みメッシュをビューポートに送っているだけ)。
2. なぜ export(obj, "preview.png") が0KBになるか
PNG出力は幾何演算ではなく、**OpenGLのオフスクリーン描画(OffscreenView/フレームバッファ)**を必要とします。この描画系はGUI/CLI一体の pythonscad.exe 本体にしかリンクされていません。pythonscad-python.exe や python3.11 に入れたモジュールは幾何カーネルのみを持つため、GLコンテキストが存在せず、拡張子でPNGにルーティングされても中身を描けずに空ファイルになる、という構図です。つまり現状、素のPythonインタプリタからのヘッドレスPNGは不可で、pythonscad.exe のCLIが唯一の経路という理解で合っています。
3. ただし、その pythonscad.exe -o xxx.png こそが実質ヘッドレスです
-o 付き起動はウィンドウを開かないコマンドラインモードで動きます。そして重要な点として:
-
--renderを付けたPNG出力はモデルの完全評価をトリガーします(プレビューPNGはOpenCSG描画、--render付きはF6相当の評価後に描画) - コマンドラインモードでもスクリプト内の
export(obj, "out.stl")などのモデル出力は普通に実行されます
つまり「PNG出力処理がモデル評価のトリガーにもなる方法」は、いまお使いのコマンドがすでにそれです。1回の起動でSTLとPNGを両方得たい場合は、スクリプト内に export(obj, "model.stl") を書いたまま -o render.png --render で起動すれば、評価1回で両方出ます。また、OpenSCAD 2021.01以降は -o の複数指定(-o model.stl -o render.png)にも対応しているので、PythonSCADでも pythonscad.exe -h で確認のうえ試す価値があります。
4. どうしてもPythonプロセス内で完結させたい場合の代替
obj.mesh(triangulate=True) で頂点・三角形を取り出せるので、mental ray用 .mi 書き出しでやられたのと同じ要領で、matplotlibの Poly3DCollection や trimesh/vedo に渡して自前でPNGを描く手はあります。GLに依存しないmatplotlib描画なら、教室のポータブル環境(追加インストール最小)とも相性が良いはずです。ビュー品質はPythonSCAD本体のプレビューには及びませんが、「サムネイル自動生成」「教材の一括画像化」用途なら十分実用になります。
まとめると、公式のヘッドレスPNGは pythonscad.exe CLIのみ・これは仕様(描画系が本体にしかない)、そして --render -o png はそれ自体が評価トリガーなので、STL出力と組み合わせればバッチ処理は一本化できます。
3. Windowsパソコン教室での作業
$env:PATH += ";C:\Users\yourname\Documents\PythonSCAD-1.1.2" のようにセッション内で通せば、作業フォルダから pythonscad.exe -o ... を直接叩けます。この方式はそのPowerShellセッション限りなので、教室のポータブル環境向けにはむしろ好都合ですね(レジストリや恒久設定を汚さない)。起動用の .ps1 や .bat にPATH追加とバッチレンダリングをまとめておけば、Documentsフォルダ配布のスタイルにもそのまま乗ると思います。
ありがとうございます。
4. logとサンプル
.\pythonscad.exe --enable python-engine --trust-python -o preview.png --autocenter --viewall --imgsize 800,600 sample.py
PS C:\Users\yourname\Documents\PythonSCAD-1.1.2> Python Code globally trusted
Compiling design (CSG Products normalization)...
Normalized CSG tree has 4 elements
Geometries in cache: 5
Geometry cache size in bytes: 190112
CGAL Polyhedrons in cache: 1
CGAL cache size in bytes: 480000
Total rendering time: 0:00:00.204
.\pythonscad.exe --enable python-engine --trust-python -o render.png --render --autocenter --viewall --imgsize 1920,1080 --colorscheme "DeepOcean" sample.py
PS C:\Users\yourname\Documents\PythonSCAD-1.1.2> Python Code globally trusted
Geometries in cache: 7
Geometry cache size in bytes: 210784
CGAL Polyhedrons in cache: 4
CGAL cache size in bytes: 1155500
Total rendering time: 0:00:00.289
Top level object is a 3D object (manifold):
Status: NoError
Genus: 1
Vertices: 2160
Facets: 4320
Measurements:
Surface: 11169.51
Volume: 63921.04
PythonSCADコード
from pythonscad import *
width = 60 # 幅(X方向)
length = 55 # 奥行き(Y方向)
height = 20 # 高さ(Z方向)
radius = 2 # 外側角丸の半径 (R2)
hole_radius = 5 # 中央穴の半径
chamfer = 1 # 穴のフチの面取りサイズ (C1)
fn_val = 60 # 円・球の滑らかさ
eps = 0.1 # 面のチラつき防止用の微小値
# --- 関数(モジュール)定義 ---
# 1. 土台形状(角丸長方形ブロック)
def rounded_box(w, l, h, r, fn):
# 内側の直方体を球の半径ぶん小さくして角丸めを適用
inner_cube = cube([w - 2 * r, l - 2 * r, h - 2 * r], center=True)
rounding_sphere = sphere(r=r, fn=fn)
return minkowski(inner_cube, rounding_sphere)
# 2. 貫通穴 + 上下面の面取りカッター
def chamfered_hole_cutter(r, chamfer_size, h, fn):
# 貫通穴(貫通させるため上下にマージンを設ける)
main_hole = cylinder(h=h + 2 * eps, r=r, center=True, fn=fn)
# 上面の面取り(r1:穴径 -> r2:面取り径 上に広がる)
top_cyl = cylinder(h=chamfer_size + eps, r1=r, r2=r + chamfer_size, center=False, fn=fn)
top_chamfer = translate(top_cyl, [0, 0, h / 2 - chamfer_size])
# 底面の面取り(r1:面取り径 -> r2:穴径 下に広がる)
bottom_cyl = cylinder(h=chamfer_size + eps, r1=r + chamfer_size, r2=r, center=False, fn=fn)
bottom_chamfer = translate(bottom_cyl, [0, 0, -h / 2 - eps])
# カッターパーツを + 演算子で1つに統合して返す
return main_hole + top_chamfer + bottom_chamfer
# --- メイン処理 ---
# 土台の生成
base = rounded_box(width, length, height, radius, fn_val)
# カッターの生成
cutter = chamfered_hole_cutter(hole_radius, chamfer, height, fn_val)
# 引き算(- 演算子)で穴と面取りを一気に削り落とす
result = base - cutter
# 3Dプレビュー表示
# ※ GUI実行時は表示されますが、コマンドラインのPNG出力処理でもモデル評価のトリガーになります
show(result)
参考資料

