1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PythonSCADコミュニティ・開発者に感謝申し上げます。ありがとうございます。

以下は、開発者からアドバイスを受けて修正した custom_minicar.py のコードです。PythonSCADならではの「より短く、より直感的に書ける」便利な書き方がたくさん取り入れられています。

高校生の皆さんにも分かりやすいように、変更された4つの重要なポイント(移動、回転、結合、複数配置)について順番に解説していきます。

custom_minicar.py
from pythonscad import *

#--- パラメータ設定 (単位: mm) ---
##座標系の約束:
#X軸=前後(進行方向) / Y軸=左右(車幅方向) / Z軸=上下
#ボディ(下の直方体)
body_x = 60 # 長さ(X方向)
body_y = 20 # 幅(Y方向)
body_z = 10 # 高さ(Z方向)

#キャビン(上の直方体)
cabin_x = 30 # 長さ(X方向)
cabin_y = 20 # 幅(Y方向)
cabin_z = 10 # 高さ(Z方向)
cabin_offset_x = -10 # 「少し後ろ寄り」(Xマイナス方向にずらす)

#タイヤ(円柱)
wheel_r = 8 # 半径
wheel_thick = 3 # 厚さ(円柱の長さ)
wheel_pos_x = 20 # 前後位置(±)
wheel_pos_y = 15 # 左右位置(±)
wheel_pos_z = -body_z / 2 # 取り付け高さ(今回はボディ中心より下側に配置するイメージ)

#車軸(円柱)
axle_r = 2
axle_len = 30 # 車軸の長さ(Y方向に貫通させる)
axle_pos_z = wheel_pos_z # タイヤ中心と同じ高さにする

#表示品質など
fn_val = 80 # 円柱の滑らかさ
eps = 0.1 # 面のチラつき防止用(今回は予備として)

#--- 関数(モジュール)定義 ---
def make_body():
    # 土台ボディ(直方体):center=True で原点中心に作る
    return cube([body_x, body_y, body_z], center=True)

def make_cabin():
    # キャビン(直方体)を上に載せる
    cabin = cube([cabin_x, cabin_y, cabin_z], center=True)
    # ボディ上面に接する高さへ移動(Z方向)
    z_up = body_z / 2 + cabin_z / 2
    # 少し後ろ寄りに移動(X方向マイナス)
    return  cabin +  [cabin_offset_x, 0, z_up]
    
def make_wheel():
    # wheel は回転軸が「Y軸」になるように作る(円柱はデフォルトZ方向に伸びるため回転させる)
    cyl = cylinder(h=wheel_thick, r=wheel_r, center=True, fn=fn_val)
    wheel = cyl.rotx(90) # Z軸方向の円柱 → Y軸方向の円柱
    return wheel

def make_axle():
    # 車軸も Y軸方向へ(円柱を倒す)
    cyl = cylinder(h=axle_len, r=axle_r, center=True, fn=fn_val)
    axle = cyl.rotx(90) # Z軸方向 → Y軸方向
    return axle
    

#--- メイン処理 ---
#1) ボディ(下)
car = make_body()

#2) キャビン(上)
car = car | make_cabin()

show(car)

#3) タイヤ4つ(前後左右)
wheel_proto = make_wheel()

wheel_positions = [
[+wheel_pos_x, +wheel_pos_y, wheel_pos_z],
[+wheel_pos_x, -wheel_pos_y, wheel_pos_z],
[-wheel_pos_x, +wheel_pos_y, wheel_pos_z],
[-wheel_pos_x, -wheel_pos_y, wheel_pos_z],
]
#wheels = wheel_proto + wheel_positions
#or
wheels = wheel_proto ^ [[wheel_pos_x, -wheel_pos_x], [wheel_pos_y,-wheel_pos_y], wheel_pos_z]

show(wheels)

#4) 車軸2本(前後)
axle_proto = make_axle()

show( axle_proto ^ [[wheel_pos_x,-wheel_pos_x],0,axle_pos_z] )

スクリーンショット 2026-07-30 105139.png


1. 移動の書き方:translate から + リストへ

  • 元のコードtranslate(cabin, [cabin_offset_x, 0, z_up]) と関数を使っていました。

  • 新しいコードcabin + [cabin_offset_x, 0, z_up] と書いています。

【解説】
PythonSCADでは、3Dオブジェクト(形)に対して [X, Y, Z] のような「座標のリスト」を +(足し算)すると、それが自動的に「移動」として扱われます。関数名をわざわざ書かなくても、「元の形 + ずらす量」という感覚で、より直感的でスッキリとしたプログラムになります。

2. 回転の書き方:rotate から .rotx()

  • 元のコードrotate(cyl, [90, 0, 0]) のように、X, Y, Zのすべての角度をリストで指定していました。

  • 新しいコードcyl.rotx(90) となっています。

【解説】
これはPythonの「オブジェクト指向」という仕組みを活用した書き方です。「円柱(cyl)に対して、X軸を中心に90度回転(rotx)して!」と直接命令しています。X軸を回したいのか、Y軸を回したいのかが一目で分かるようになり、入力ミスも減らすことができます。

3. 図形の結合(和集合):+ から |

  • 元のコードcar = car + make_cabin() のように + 記号で図形同士を合体していました。

  • 新しいコードcar | make_cabin() となっています。

【解説】
プログラミング(数学の集合演算)において、|(パイプ記号と呼ばれる縦線)は「和集合(どちらも含む)」を表す記号としてよく使われます。1番で解説したように + を「移動」として使うようになったため、図形同士の「結合」には | を使うことで、コードの中で「移動」と「結合」の意味をはっきりと区別できるようになっています。

4. 複数配置の魔法の演算子:for 文から ^

  • 元のコード:4つのタイヤの座標リストを作り、for 文の繰り返し処理を使って1つずつ移動・合体させるという、少し長い処理を書いていました。

  • 新しいコードwheel_proto ^ [[wheel_pos_x, -wheel_pos_x], [wheel_pos_y,-wheel_pos_y], wheel_pos_z] と、なんと1行で書いています。

【解説】
この ^ 記号は、PythonSCADにおける「指定した組み合わせすべてにコピーを配置する」という非常に強力な機能です。
上記のコードでは、X座標のリスト(前後)とY座標のリスト(左右)を渡しています。するとプログラムが自動的に「前の右、前の左、後ろの右、後ろの左」という全パターンの組み合わせを計算し、一気に4箇所にタイヤを配置してくれます。同様に車軸も axle_proto ^ [[wheel_pos_x,-wheel_pos_x],0,axle_pos_z] と書くことで、前後の2箇所へ一瞬で配置しています。


PythonSCADにおいて,、^ 演算子は「XOR(排他的論理和)」ではない

別の記事での説明と内容が食い違ってしまい訂正します。申し訳ございません。

PythonSCADにおいて ^ 演算子は「XOR(排他的論理和)」ではありません。「配列コピー(スタンプ一括配置)」の機能です。

以前書いた説明は、残念ながら「通常のPythonの文法」と「PythonSCAD特有の機能」が混ざってしまった誤った情報です。
通常のPythonプログラミング(数学やデータ処理)では、^ 記号は確かに「XOR(排他的論理和)」を意味します。
しかし、PythonSCADの開発者は、3Dモデリングで頻繁に行う「複数パーツの規則的な配置」を極限まで短く書けるようにするため、この ^ 記号を「座標リストへの一括スタンプ演算子」として特別に改造(オーバーロード)しています。

そのため、PythonSCAD上で part1 ^ part2 のように図形同士を ^ で計算しようとすると、プログラムが「右側は座標のリストじゃないぞ?」と困ってしまい、エラーになります。

^ 演算子(一括スタンプ機能)の正しいまとめ

^ 演算子は、「左側の形」を「右側の座標の組み合わせ」すべてに一気にコピーして配置する機能です。

【基本の書き方】

配置した図形 = 元のパーツ ^ [X座標のリスト, Y座標のリスト, Z座標のリスト]

【覚えておくべき3つのルール】

  1. 全パターンの組み合わせを作る:
    Xに [10, -10]、Yに [20, -20] を渡すと、「(10, 20), (10, -20), (-10, 20), (-10, -20)」の 2×2=4箇所 に自動でスタンプされます。
  2. 固定したい軸には単一の数字(スカラー値)を渡す:
    「Z軸は高さ0のまま変えたくない」という場合は、リスト [0] ではなく、単に 0 と書くことができます。
    例:パーツ ^ [xのリスト, yのリスト, 0]
  3. リストは直接書いても、変数で渡してもOK:
    あらかじめ x_list = [0, 10, 20] と変数を作っておき、パーツ ^ [x_list, y_list, 0] と書くのが、プログラムが読みやすくなるコツです。

【おまけ】 もし本当に「XOR(重なっていない部分)」を作りたい時は?

3D CADの世界では、XORにあたる専用の記号は用意されていないことがほとんどです。しかし、私たちが学んできた +(結合)-(削る) を組み合わせれば、論理的なパズルとして自分で作り出すことができます!

「AとBの重なっていない部分だけを残す」には、以下のように考えます。

  1. A から B を削るA - B:Aだけにある部分)
  2. B から A を削るB - A:Bだけにある部分)
  3. その2つを合体させる+ 演算子)
# XOR(排他的論理和)の形状を自作する式
xor_shape = (partA - partB) + (partB - partA)

「XOR(重なっていない部分)」

スクリーンショット 2026-08-17 210409.png
renderボタンで、2D図形(厚みなし)は赤い線がでます。

from pythonscad import *

partA=circle(r=3,fn=28).show()
partB=(circle(r=3,fn=28)+[4,0,0]).show()

xor_shape = (partA - partB) + (partB - partA)

(xor_shape +[0,-7,0]).show()

球体で、上記のことをやっても、見た目は変わりません。空洞になっているかどうかは、ちょっとだけ移動してみてのぞいてみてください。


^ 演算子を使った規則的な配置例

この ^ 演算子は、PythonSCADの中でもトップクラスに便利で強力な機能です。cube(直方体)を綺麗に並べて、レゴブロックの土台やビル群のような「グリッド配置(格子状の配置)」を作るのにも大活躍します。

今回は、3×3の合計9個の cube を等間隔に配置するサンプルコードを作成しました。さっそく見てみましょう!

1. 完成コード(PythonSCAD)

# ==========================================
# [3×3のブロックアート(cubeの規則配置)]
# 作成日: 2026/07/30
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
# 座標系の約束: X軸=前後(長さ) / Y軸=左右(幅) / Z軸=上下(高さ)
cube_size = 10     # キューブ1辺の長さ
spacing   = 20     # 配置の間隔(中心から中心までの距離)
base_z    = 5      # 土台の高さ
fn_val    = 60     # 円・球の滑らかさ(今回は未使用ですが標準として定義)
eps       = 0.1    # 面のチラつき防止用の微小値

# 配置したい座標のリスト(前後・左右)
x_positions = [-spacing, 0, spacing]
y_positions = [-spacing, 0, spacing]

# --- 関数(モジュール)定義 ---

# 1. 基準となる柱(キューブ)
def make_pillar():
    # center=True を指定し、原点[0,0,0]を中心に作ります
    return cube([cube_size, cube_size, cube_size], center=True)

# 2. 全体を支える土台
def make_base():
    # 3つのキューブがすっぽり収まるように全体の幅と奥行きを計算
    w = spacing * 2 + cube_size + 10
    return cube([w, w, base_z], center=True)

# --- メイン処理 ---

# 土台の生成
base = make_base()

# 基準となる柱を1つ生成
pillar = make_pillar()

# 土台の上面に乗るようにZ方向の移動量を計算
# (土台の厚みの半分) + (キューブの高さの半分)
z_up = base_z / 2 + cube_size / 2

# ^ 演算子を使って一気に配置!
# X軸(3パターン) × Y軸(3パターン) = 9個のキューブが生成されます
pillars = pillar ^ [x_positions, y_positions, z_up]

# 土台と9つの柱を結合( + 演算子 )
result = base + pillars

# 3Dプレビュー表示
show(result)


🌟 解説ポイント

1. ^ 演算子は「組み合わせの魔法」

通常のプログラミング(Pythonなど)で縦横に物を並べようとすると、for 文という繰り返し処理を2重(マトリョーシカのような状態)にして書く必要があります。
しかし、PythonSCADの ^ 演算子を使えば、「X座標のリスト」と「Y座標のリスト」を渡すだけで、すべての組み合わせを自動で計算してくれます。
コードの中の pillar ^ [x_positions, y_positions, z_up] の1行だけで、一瞬にして9つのブロックが規則正しく並びます。

2. リストの使い方

今回、X軸(前後)とY軸(左右)の配置場所として [-spacing, 0, spacing](つまり [-20, 0, 20])という「リスト」をあらかじめ変数として定義しました。
これを [-40, -20, 0, 20, 40] のように要素を増やすだけで、5×5=25個のブロック配列へと一瞬で拡張できます。これがパラメトリック設計(数値を変更するだけで全体が変わる設計)の強みです。

3. Z方向(高さ)の計算

今回はブロックを土台の上にピッタリ乗せたかったため、z_up という変数で高さを計算しました。
すべての部品を center=True(原点中心)で作っているため、「土台の厚みの半分」と「ブロックの高さの半分」を足し算すれば、絶対にめり込んだり浮いたりしない正確な位置に移動できます。これはものづくりの図面を考える上でも非常に大切な考え方です。

ぜひ、パラメータの spacingcube_size の数値を変更して、プレビュー画面でどう変化するか実験してみましょう。

スクリーンショット 2026-07-30 110520.png

参考資料

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?