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コミュニティ・開発者に感謝申し上げます。ありがとうございます。

1. 「wrap(ラップ)」とは何か?

PythonSCADの開発者の方からコメントアドバイスをいただきました。ありがとうございます。
「wrap」とは、3D CADの世界で「2Dの図形や文字を、円柱や球の曲面に沿ってぐるりと巻き付ける(投影する)機能」のことです。(ペットボトルのラベルを貼るようなイメージです)。
しかし、曲面にピッタリと図形を変形させる計算は数学的に非常に複雑でエラーが起きやすいため、まだPythonSCADでは、不安定(non-stable)のようです。

from pythonscad import *
S = sphere(20,fn=10)
Fa = S.faces()
F = Fa[0] # or Python min function with lambda of F.matrix
F1 =Fa[1]
S += cylinder(2,2).multmatrix(F.matrix)
S += cylinder(2,2).multmatrix(F1.matrix)
show(S)
print(len(Fa))
print(F.matrix)
print(F1.matrix)

Running Python 3.14.6 in venv ''.
42
[[-0.8090169943749475, -0.5877852522924732, 0.0, 0.0], [0.5877852522924732, -0.8090169943749475, 0.0, 0.0], [0.0, 0.0, 1.0, 19.02113032590307], [0.0, 0.0, 0.0, 1.0]]
[[-0.6545084971874738, 0.4881447467463533, 0.5773502691896256, 10.590169943749475], [-0.4755282581475769, -0.8594660780797404, 0.1875924740850798, 4.755282581475768], [0.587785252292473, -0.15176549955167154, 0.7946544722917663, 15.388417685876266], [0.0, 0.0, 0.0, 1.0]]

スクリーンショット 2026-08-11 203634.png

2. F.matrix(4x4変換行列)の正体と凄さ

print で出力した [[...], [...], [...], [...]] という数字の羅列。これが高校数学(数学C)や3Dグラフィックスの心臓部である「4x4 変換行列(トランスフォーム・マトリックス)」です。

通常、球体の表面に円柱を垂直に立てようとすると、

  1. サイン・コサインを使って表面のX, Y, Z座標を計算する(位置の移動)
  2. 面の傾きに合わせて、X軸回転、Y軸回転、Z軸回転の角度を計算する(向きの回転)
    という非常に面倒な計算が必要です。

しかし、F.matrix には「その面がどこにあるか(座標)」と「その面がどっちを向いているか(法線ベクトルの角度)」という2つの情報がすべて計算済みの状態でパックされています。
だから .multmatrix(F.matrix) を使うだけで、面倒な計算を一切せずに、指定した面にパーツが
「ピタッと垂直にテレポート」します。
「Relative object Design(相対的なオブジェクト配置)は簡単だよ」と開発者の方からアドバイスをもらいました。これは便利な機能ですね。ありがとうございます。


この魔法の faces()matrix を使って、球体の「すべての面」に一気に円柱を配置して、ウニのようなトゲトゲの球体(あるいはゴルフボールのような窪みのある球体)を作るサンプルを用意しました!

完成コード(PythonSCAD)

# ==========================================
# [相対座標デザイン(面マトリックスの活用)]
# 作成日: 2026/08/13
# ==========================================

from pythonscad import *
from math import pi, sin, cos  # 数学関数(ルールに則りインポート)

# --- パラメータ設定 (単位: mm) ---
base_r  = 20      # ベースとなる球の半径
fn_val  = 15      # 球の滑らかさ(面を増やすと配置されるトゲも増えます)

spike_r = 2       # トゲ(または穴)の半径
spike_h = 5       # トゲの長さ(穴の深さ)

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

# 1. ターゲットの「すべての面」にパーツを配置して合体させる関数
def create_surface_objects(target_obj, r, h, fn):
    # ターゲットオブジェクトからすべての「面(faces)」のリストを取得
    faces = target_obj.faces()
    
    # 結合用の空オブジェクトを変数として用意
    surface_parts = None
    
    # for文で、すべての面に対して1つずつパーツを配置していく
    for f in faces:
        # 面に垂直に立つ円柱を作成
        # ※ center=False にすることで、Z=0(底面)がピッタリ表面にくっつきます
        cyl = cylinder(h=h, r=r, center=False, fn=fn)
        
        # 4x4変換行列を適用し、面にピタッと配置(移動+回転を一発で処理)
        placed_cyl = cyl.multmatrix(f.matrix)
        
        # + 演算子でどんどん合体させていく
        if surface_parts is None:
            surface_parts = placed_cyl
        else:
            surface_parts = surface_parts + placed_cyl
            
    return surface_parts

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

# 1. 基準となる球体を作成
base_sphere = sphere(r=base_r, fn=fn_val)

# 2. すべての面に配置されるパーツ群を生成
spikes = create_surface_objects(base_sphere, spike_r, spike_h, fn_val)

# ==============================================================
# 3. モード切り替え(コメントアウトで操作)
# ==============================================================

# 【モードA】トゲトゲの球体(足し算でウニのような形にする)
result = base_sphere + spikes

# 【モードB】ゴルフボール(引き算で表面に穴をあける)
# 開発者の「壁に穴をあける」アプローチ!
# result = base_sphere - spikes

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

スクリーンショット 2026-08-13 121533.png


🌟 解説ポイント

  • 絶対座標から相対座標へ:
    今までの設計は「原点から見て X=10, Y=20 に置く」という「絶対座標」でした。しかし今回の方法は「親となる球体の『この面』を基準にして置く」という「相対的なデザイン(Relative Design)」です。これにより、元の球体がどんな形になっても、自動的に表面の正しい位置にパーツが張り付くようになります。
  • リストとfor文の強力なコンボ:
    len(Fa) は42でした。つまり faces() で取得したリストを for 文で回せば、42個の面すべてに正確にパーツを配置できます。

この「面の法線(垂直な向き)を取得してモノを置く」というテクニックは、3Dゲームのプログラミング(キャラクターが地形の斜面に沿って立つ処理など)でも全く同じ計算が使われています。工業デザインだけでなく、プログラミングの応用力が一気に広がる素晴らしい学びになります。ありがとうございます。

まだ、開発中なので、これからが楽しみですね。ありがとうございます。

3. 別サンプル例

スクリーンショット 2026-08-11 205619.png

# ==========================================
# [42面体の各面に円柱を配置]
# 作成日: 2026/08/11
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
sphere_r = 20      # ベースとなる球の半径
fn_val   = 10      # 球の滑らかさ(この値で多面体の面の数が決まります)
cyl_h    = 2       # 追加する円柱の高さ
cyl_r    = 2       # 追加する円柱の半径

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

# 全ての面に円柱を取り付ける関数
def add_cylinders_to_faces(base_shape, c_h, c_r):
    # base_shape.faces() で、図形が持つすべての面情報のリストを取得
    face_list = base_shape.faces()
    
    # 結合していくための土台を用意(最初はベースの図形そのまま)
    result_shape = base_shape
    
    # 取得したすべての面に対して、1つずつ処理を繰り返す(for文)
    for face in face_list:
        # 1. 円柱を作成する(キーワード引数 h, r を明記すると安全です)
        # center=False にすることで、円柱の底面が基準になり、面から外に向かって生えます
        peg = cylinder(h=c_h, r=c_r, center=False)
        
        # 2. 面の向きと位置のデータ(face.matrix)を使って円柱を移動・回転させる
        placed_peg = peg.multmatrix(face.matrix)
        
        # 3. + 演算子で土台に結合する
        result_shape = result_shape + placed_peg
        
    return result_shape

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

# 1. ベースとなる42面体(球の解像度を下げたもの)を作成
base_sphere = sphere(r=sphere_r, fn=fn_val)

# 2. 関数を呼び出して、すべての面に円柱を取り付ける
final_object = add_cylinders_to_faces(base_sphere, cyl_h, cyl_r)

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

# (おまけ)面の数を確認したい場合はコンソールにプリントできます
print(f"この図形の面の数は {len(base_sphere.faces())} 個です。")

4. 別サンプル例 translateを使う

「40×40×2の板に、4×4の円柱(cylinder)を配置したい」
cyl_h = 2 # 追加する円柱の高さ
cyl_r = 2 # 追加する円柱の半径

「10×10×2の板の中心にcylinderを配置してから、10,10,2の板を4 x 4合成する方法」 、あるいは 「40×40の板を一つ作り、そこに数学的な計算(for文)を使って16個の円柱を均等に並べる方法」 のどちらか。

プログラミング的には、後者の 「for文を使って座標を計算し、円柱を並べる(配列する)方法」 が最も一般的で、応用が利く書き方です。
今回は、高校生向けに「2重のfor文(X方向とY方向の繰り返し)」を使って、大きな板の上に等間隔で円柱を配置するコードを作ります。

スクリーンショット 2026-08-12 125455.png

1. 完成コード(PythonSCAD)

# ==========================================
# [4x4の円柱が並んだ板]
# 作成日: 2026/08/11
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
plate_w = 40       # 板の幅 (X方向)
plate_l = 40       # 板の奥行き (Y方向)
plate_h = 2        # 板の厚み (Z方向)

cyl_h   = 2        # 円柱の高さ
cyl_r   = 2        # 円柱の半径
fn_val  = 30       # 円柱の滑らかさ

rows    = 4        # Y方向の円柱の数
cols    = 4        # X方向の円柱の数

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

# 複数の円柱を格子状(グリッド状)に並べて結合する関数
def create_cylinder_grid(w, l, r, h, c_rows, c_cols, fn):
    # 結合していくための「空の土台」を用意(最初は何もなし)
    # PythonSCADでは、空の形状を作る明確な関数がないため、最初は None にしておきます。
    grid_shape = None
    
    # 円柱の配置間隔(ピッチ)を計算します
    # 40mmを4等分するので、10mm間隔になります
    pitch_x = w / c_cols
    pitch_y = l / c_rows
    
    # 基準となる位置(左下の最初の円柱の中心座標)を計算します
    # -20 + (10 / 2) = -15 の位置がスタート地点になります
    start_x = -w / 2 + pitch_x / 2
    start_y = -l / 2 + pitch_y / 2
    
    # 2重のfor文を使って、X方向とY方向に円柱を配置していきます
    for i in range(c_cols):      # X方向 (列) のループ
        for j in range(c_rows):  # Y方向 (行) のループ
            
            # 1つの円柱を作成
            # center=False で底面を基準(Z=0)にします
            peg = cylinder(h=h, r=r, center=False, fn=fn)
            
            # i と j に応じて、配置する X, Y 座標を計算
            pos_x = start_x + (i * pitch_x)
            pos_y = start_y + (j * pitch_y)
            
            # 円柱を計算した座標に移動
            # Z方向は板の上面(板の厚みの半分)の高さに乗せます
            moved_peg = translate(peg, [pos_x, pos_y, plate_h / 2])
            
            # 作成した円柱を全体に追加(結合)していく
            if grid_shape is None:
                grid_shape = moved_peg # 最初だけ
            else:
                grid_shape = grid_shape + moved_peg # 2個目以降は結合(+ 演算子)
                
    return grid_shape

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

# 1. 土台となる板を作成(center=True なので Z=0 を中心に配置されます)
base_plate = cube([plate_w, plate_l, plate_h], center=True)

# 2. 関数を使って、4x4 の円柱群を作成
cylinders = create_cylinder_grid(plate_w, plate_l, cyl_r, cyl_h, rows, cols, fn_val)

# 3. 板と円柱群を結合(+ 演算子)
final_object = base_plate + cylinders

# 4. 3Dプレビュー表示
show(final_object)


① 板には分割情報がない

前回の42面体のような「ポリゴンの面データ(Faces)」から座標を取る方法は、複雑な曲面に対しては非常に有効です。しかし、cube のような単純な直方体は「上下前後左右の6面」という情報しか持っていないため、指定した分割数で座標を取ってくることができません。

② 「2重ループ(ネスト)」を使った配置計算

プログラミングで格子状(マス目状)に物を並べるときによく使うのが 「2重のfor文(ループのネスト)」 です。

  • 外側のループ(for i in range(c_cols):)がX方向
  • 内側のループ(for j in range(c_rows):)がY方向
    を担当し、4 × 4 = 16回 の処理を自動で行います。
    ij0, 1, 2, 3 と増えていくので、それに pitch_x (10mm) を掛けることで、「0mm, 10mm, 20mm, 30mm...」と規則正しい間隔の座標(pos_x, pos_y)を計算できます。これはCADでの設計において非常に重要な考え方です。

1
0
3

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?