1
1

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

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

参考サイト

OpenSCADコミュニティ、CadQueryコミュニティ、build123dコミュニティ、開発者、記事執筆者に感謝申し上げます。ありがとうございます。

  • build123dyのExamples

  • CadQueryのExamples

  • 高校生のためのPythonSCAD練習帳

21. 外形寸法200×200×10mmのプレート。直径15mmの穴を4×4のグリッド(40mm間隔)に配置

完成コード(PythonSCAD)

# ==========================================
# 200x200x10 Plate with 4x4 Hole Grid
# 作成日: 2026/08/15
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
plate_w   = 200.0   # X方向
plate_l   = 200.0   # Y方向
plate_h   = 10.0    # Z方向

hole_d    = 15.0
hole_r    = hole_d / 2.0

grid_n    = 4       # 4x4
pitch     = 40.0    # 穴間隔

fn_val    = 80
eps       = 0.1     # チラつき防止(カッターのはみ出し)

# --- 関数定義 ---

def create_plate(w, l, h):
    """プレート本体(足す形状)"""
    return cube([w, l, h], center=True)

def create_hole_cutter(hole_r, plate_h, n, pitch, fn):
    """4x4の貫通穴カッター(引く形状)を1つにまとめて返す"""
    # 4点を中心対称に並べる座標: [-60, -20, 20, 60] (pitch=40, n=4)
    offset0 = -((n - 1) / 2.0) * pitch
    coords = [offset0 + i * pitch for i in range(n)]

    cutter = None
    for x in coords:
        for y in coords:
            hole = cylinder(h=plate_h + 2 * eps, r=hole_r, center=True, fn=fn)
            hole = translate(hole, [x, y, 0.0])

            cutter = hole if cutter is None else (cutter + hole)

    return cutter

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

body = create_plate(plate_w, plate_l, plate_h)
cutter = create_hole_cutter(hole_r, plate_h, grid_n, pitch, fn_val)

result = body - cutter

show(result)

スクリーンショット 2026-08-16 073840.png

22. 外形寸法150×60×10mmのプレート。直径8mmの穴を3×2(X方向50mm間隔・Y方向30mm間隔)で配置

完成コード(PythonSCAD)

# ==========================================
# 150×60×10mm プレート(3×2 穴あき)
# 作成日: 2026/08/15
# ==========================================

from pythonscad import *
from math import pi  # 今回は未使用だが、拡張しやすいので残してOK

# --- パラメータ設定 (単位: mm) ---
plate_x   = 150.0   # プレート寸法 X
plate_y   = 60.0    # プレート寸法 Y
plate_z   = 10.0    # 厚み Z

hole_d    = 8.0     # 穴の直径
hole_r    = hole_d / 2.0

nx        = 3       # X方向の穴数
ny        = 2       # Y方向の穴数
pitch_x   = 50.0    # X方向ピッチ
pitch_y   = 30.0    # Y方向ピッチ

fn_val    = 60
eps       = 0.1     # チラつき防止&確実に貫通させる余裕

# --- 関数(モジュール)定義 ---
def create_plate(w, d, h):
    """プレート本体(足す形状)"""
    return cube([w, d, h], center=True)

def create_hole_cutter(h, r, nx, ny, px, py, fn):
    """穴カッター(引く形状):3×2の円柱を + で一括結合"""
    cutter = None

    # 中心基準で座標を作る(3列なら -px, 0, +px / 2列なら -py/2, +py/2)
    x0 = -(nx - 1) * px / 2.0
    y0 = -(ny - 1) * py / 2.0

    for ix in range(nx):
        for iy in range(ny):
            x = x0 + ix * px
            y = y0 + iy * py
            hole = cylinder(h=h + 2 * eps, r=r, center=True, fn=fn)
            hole = translate(hole, [x, y, 0])

            cutter = hole if cutter is None else (cutter + hole)

    return cutter

# --- メイン処理 ---
plate  = create_plate(plate_x, plate_y, plate_z)
cutter = create_hole_cutter(plate_z, hole_r, nx, ny, pitch_x, pitch_y, fn_val)

result = plate - cutter

show(result)

補足(位置の確認)

  • X位置: -50, 0, +50 mm(50mm間隔で3列、中心揃え)
  • Y位置: -15, +15 mm(30mm間隔で2列、中心揃え)

スクリーンショット 2026-08-16 081632.png

23. 底面80×80mm、上面40×40mm、高さ60mmのピラミッド台形

完成コード(PythonSCAD)

# ==========================================
# 角錐台(ピラミッド台形)
# 作成日: 2026/08/15
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
base_w = 80.0   # 底面の幅(X方向)
base_l = 80.0   # 底面の奥行(Y方向)
top_w  = 40.0   # 上面の幅(X方向)
top_l  = 40.0   # 上面の奥行(Y方向)
height = 60.0   # 高さ(Z方向)

# --- メイン処理 ---
# square は常にXY平面、center=Trueで原点中心に配置
base_2d = square([base_w, base_l], center=True)

# linear_extrude はZ=0を底面基準(center=False)で積み上げ
# scale は [X倍率, Y倍率]
scale_xy = [top_w / base_w, top_l / base_l]
result = linear_extrude(base_2d, height=height, scale=scale_xy, center=False)

show(result)

ポイント:

  • scale=[top/base, top/base] を使うと、底面→上面へ線形に縮小される「角錐台」が作れます
  • XYは原点中心、Zは底面が z=0 からスタートする配置です

スクリーンショット 2026-08-16 082829.png

24. 外径60mm・内径56mm・高さ20mmの円筒キャップ(上面閉じ・底面開口)

完成コード(PythonSCAD)

# ==========================================
# 円筒キャップ(上面閉じ・底面開口)
# 作成日: 2026/08/15
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
outer_d = 60.0   # 外径
inner_d = 56.0   # 内径(中空部の直径)
cap_h   = 20.0   # 高さ
fn_val  = 80     # 円の滑らかさ
eps     = 0.1    # チラつき防止用微小値

# 半径に変換
outer_r = outer_d / 2.0
inner_r = inner_d / 2.0

# 肉厚(半径方向)
wall_th = (outer_d - inner_d) / 2.0

# 上面の板厚(指定が無いので「肉厚と同じ」にする)
top_th = wall_th

# --- 関数定義 ---

def create_body(outer_radius, height, fn):
    """外形(足す形状): 底面Z=0、上面Z=height"""
    return cylinder(h=height, r=outer_radius, center=False, fn=fn)

def create_cutter(inner_radius, height, top_thickness, fn, eps):
    """
    中空を作るカッター(引く形状)
    底面は開口したいので下にepsだけはみ出させる。
    上面は top_thickness を残す(削りすぎ防止で eps 分だけ余裕を残す)。
    """
    hollow_h = height - top_thickness - eps
    if hollow_h < 0:
        hollow_h = 0

    hollow = cylinder(h=hollow_h, r=inner_radius, center=False, fn=fn)
    hollow = translate(hollow, [0, 0, -eps])  # 底面側を少しはみ出して確実に開口
    return hollow

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

body = create_body(outer_r, cap_h, fn_val)
cutter = create_cutter(inner_r, cap_h, top_th, fn_val, eps)

result = body - cutter

show(result)

スクリーンショット 2026-08-16 083409.png

25. 外径80mm・高さ30mmの円筒容器(底面あり・上面開口・肉厚4mm)

完成コード(PythonSCAD)

# ==========================================
# 円筒容器(底あり・上面開口)
# 作成日: 2026/08/15
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
outer_d = 80.0      # 外径
height  = 30.0      # 全高(Z方向)
thick   = 4.0       # 肉厚(側面+底)
fn_val  = 120       # 円の滑らかさ
eps     = 0.1       # チラつき防止用微小値

outer_r = outer_d / 2.0
inner_r = outer_r - thick
inner_h = height - thick  # 底厚=thick として、内側空間の高さ

def create_body(outer_r, height, fn):
    """足す形状:外側の円筒(底面Z=0基準)"""
    return cylinder(h=height, r=outer_r, center=False, fn=fn)

def create_cutter(inner_r, inner_h, thick, fn):
    """引く形状:内側の空洞(上面を確実に開口させるためにepsを追加)"""
    cavity = cylinder(h=inner_h + 2 * eps, r=inner_r, center=False, fn=fn)
    # 底を残すため、空洞は底厚(thick)の上から開始
    cavity = translate(cavity, [0, 0, thick + eps])
    return cavity

# --- メイン処理 ---
body   = create_body(outer_r, height, fn_val)
cutter = create_cutter(inner_r, inner_h, thick, fn_val)

result = body - cutter

show(result)

必要なら「底だけ厚みを変えたい(例:底6mm、側面4mm)」など仕様変更してみましょう。

スクリーンショット 2026-08-16 083634.png

26. 直径25mm・長さ200mmの段付きシャフト。中央80mmは直径35mm

完成コード(PythonSCAD)

# ==========================================
# 段付きシャフト(中央太径)
# 作成日: 2026/08/15
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
shaft_d       = 25.0     # 両端側の直径
shaft_len     = 200.0    # 全長(Z方向)
middle_d      = 35.0     # 中央の直径
middle_len    = 80.0     # 中央太径部の長さ
fn_val        = 80       # 円柱の滑らかさ
eps           = 0.1      # 念のため(今回は未使用)

# --- 関数(モジュール)定義 ---
def r_from_dia(d):
    """直径→半径"""
    return d / 2.0

def create_shaft(d_small, len_total, d_mid, len_mid, fn):
    """
    段付きシャフト(足す形状のみ)
    ・全体: 直径 d_small, 長さ len_total
    ・中央: 直径 d_mid,   長さ len_mid(中心に配置)
    """
    base = cylinder(h=len_total, r=r_from_dia(d_small), center=True, fn=fn)
    mid  = cylinder(h=len_mid,   r=r_from_dia(d_mid),   center=True, fn=fn)
    return base + mid

# --- メイン処理 ---
result = create_shaft(shaft_d, shaft_len, middle_d, middle_len, fn_val)

show(result)

補足(設計の考え方): 「全長200mmの細い軸」に「中央80mmだけ太い円柱を足す」ことで段付き形状を作っています。全て center=True なので、原点 [0,0,0] がシャフトの真ん中になります。

スクリーンショット 2026-08-16 084955.png

27. M10ナット相当: 対辺距離17mm・高さ8mmの正六角柱。中央に直径10.5mmの貫通穴

完成コード(PythonSCAD)

# ==========================================
# M10ナット相当(六角柱 + 貫通穴)
# 作成日: 2026/08/15
# ==========================================

from pythonscad import *
from math import pi, sin, cos

# --- パラメータ設定 (単位: mm) ---
across_flats = 17.0     # 対辺距離(二面幅)
height_z     = 8.0      # 高さ(Z方向)
hole_d       = 10.5     # 貫通穴 直径
fn_val       = 80       # 円の分割数
eps          = 0.1      # チラつき防止用微小値

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

def hex_points_from_across_flats(af):
    """
    正六角形の頂点座標を作る(XY平面、原点中心)
    対辺距離 af から外接円半径 R を求める:
      af = R * sqrt(3)  =>  R = af / sqrt(3)
    ※ sqrt(3) は (3 ** 0.5) で計算
    """
    R = af / (3 ** 0.5)
    pts = []
    for i in range(6):
        ang = i * (pi / 3.0)  # 0, 60, 120, ...
        pts.append([R * cos(ang), R * sin(ang)])
    return pts

def create_body(af, h):
    """六角柱(足す形状)"""
    hex2d = polygon(hex_points_from_across_flats(af))
    return linear_extrude(hex2d, height=h)  # Z=0 を底面(center=False相当)

def create_cutter(hole_dia, h):
    """貫通穴カッター(引く形状)"""
    hole = cylinder(h=h + 2 * eps, r=hole_dia / 2.0, center=False, fn=fn_val)
    hole = translate(hole, [0, 0, -eps])  # 下にもepsだけはみ出させて確実に貫通
    return hole

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

body = create_body(across_flats, height_z)
cutter = create_cutter(hole_d, height_z)

result = body - cutter

show(result)

スクリーンショット 2026-08-16 090515.png

28. 外径30mm・内径10.5mm・厚さ3mmの丸座金(ワッシャー)

完成コード(PythonSCAD)

# ==========================================
# 丸座金(ワッシャー)
# 作成日: 2026/08/15
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
outer_d = 30.0     # 外径
inner_d = 10.5     # 内径(穴径)
thick   = 3.0      # 厚さ(Z方向)
fn_val  = 80       # 円の分割数(滑らかさ)
eps     = 0.1      # チラつき防止用微小値

# --- ヘルパー ---
def r_from_dia(d):
    """直径 -> 半径"""
    return d / 2.0

# --- メイン処理 ---
outer = cylinder(h=thick, r=r_from_dia(outer_d), center=True, fn=fn_val)
hole  = cylinder(h=thick + 2 * eps, r=r_from_dia(inner_d), center=True, fn=fn_val)

result = outer - hole

show(result)

スクリーンショット 2026-08-16 090728.png

29. 直径150mm・高さ15mmの円盤。中心から半径50mmの位置に直径8mmの穴を8個、均等配置

完成コード(PythonSCAD)

# ==========================================
# 8穴円盤(等配)
# 作成日: 2026/08/15
# ==========================================

from pythonscad import *
from math import pi, sin, cos

# --- パラメータ設定 (単位: mm) ---
disk_d        = 150.0   # 円盤の直径
disk_h        = 15.0    # 円盤の高さ(厚み)
hole_d        = 8.0     # 穴の直径
hole_count    = 8       # 穴の個数
hole_pitch_r  = 50.0    # 中心から穴中心までの半径
fn_val        = 80      # 円の滑らかさ
eps           = 0.1     # チラつき防止用微小値

# --- 関数(モジュール)定義 ---
def create_body(d, h, fn):
    """本体(足す形状)"""
    return cylinder(h=h, r=d/2, center=True, fn=fn)

def create_cutter(hole_d, disk_h, hole_count, pitch_r, fn, eps):
    """カッター(引く形状): 8個の穴を + でまとめる"""
    hole_h = disk_h + 2 * eps
    one_hole = cylinder(h=hole_h, r=hole_d/2, center=True, fn=fn)

    cutters = None
    for i in range(hole_count):
        ang = 2 * pi * i / hole_count
        x = pitch_r * cos(ang)
        y = pitch_r * sin(ang)
        h_i = translate(one_hole, [x, y, 0.0])

        cutters = h_i if cutters is None else (cutters + h_i)

    return cutters

# --- メイン処理 ---
body = create_body(disk_d, disk_h, fn_val)
cutter = create_cutter(hole_d, disk_h, hole_count, hole_pitch_r, fn_val, eps)

result = body - cutter

show(result)

(確認ポイント)穴は「中心から半径50mm」の円周上に、45°ずつ(360°/8)均等配置されています。必要なら「穴の開始角度(回し始め)」も検討してみてください。

image.png

30. ヒートシンク:60×60×5mmのベースプレートの上に、厚さ2mm、高さ20mm、長さ60mmの放熱フィンを4mm間隔で15枚並べた形状。ベースの四隅には直径3mmの取り付け穴

完成コード(PythonSCAD)

# ==========================================
# ヒートシンク(60x60ベース + 15枚フィン + 取付穴)
# 作成日: 2026/08/15
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
base_w   = 60.0   # ベース幅(X)
base_l   = 60.0   # ベース奥行(Y)
base_t   = 5.0    # ベース厚み(Z)

fin_n    = 15     # フィン枚数
fin_t    = 2.0    # フィン厚み(X方向)
fin_h    = 20.0   # フィン高さ(Z方向)
fin_len  = 60.0   # フィン長さ(Y方向)
fin_pitch = 4.0   # フィンのピッチ(中心-中心の間隔) ※「4mm間隔」をピッチと解釈

hole_d   = 3.0
hole_r   = hole_d / 2.0

fn_val   = 80
eps      = 0.1

# --- 関数(モジュール)定義 ---
def create_body():
    """足す形状:ベース + フィン群"""
    # ベース(XYは原点中心、底面Z=0になるようにZだけ持ち上げ)
    base = translate(
        cube([base_w, base_l, base_t], center=True),
        [0, 0, base_t / 2.0]
    )

    # フィン(ベース上に積み上げ)
    fins = None
    x0 = -((fin_n - 1) * fin_pitch) / 2.0  # フィン列の中心合わせ

    for i in range(fin_n):
        x = x0 + i * fin_pitch
        fin = translate(
            cube([fin_t, fin_len, fin_h], center=True),
            [x, 0, base_t + fin_h / 2.0]
        )
        fins = fin if fins is None else (fins + fin)

    return base + fins


def create_cutter():
    """引く形状:ベース四隅の取付穴(貫通)"""
    # 穴はベース厚みを確実に貫通させ、Zファイティング防止でepsを上下に足す
    hole = cylinder(h=base_t + 2 * eps, r=hole_r, center=True, fn=fn_val)

    x = base_w / 2.0 - hole_r
    y = base_l / 2.0 - hole_r
    z = base_t / 2.0  # ベース中心高さ

    holes = (
        translate(hole, [ x,  y, z]) +
        translate(hole, [ x, -y, z]) +
        translate(hole, [-x,  y, z]) +
        translate(hole, [-x, -y, z])
    )
    return holes


# --- メイン処理 ---
body = create_body()
cutter = create_cutter()

result = body - cutter

show(result)

補足(設計の読み替え)

  • 「4mm間隔」は、フィンの中心同士の間隔(ピッチ)= 4mmとして配置しています(厚み2mmなので、すき間は2mm)。この解釈だと 15枚が60mm幅に収まります
  • もし「すき間が4mm(ピッチ6mm)」の意味だと、15枚は60mmに入らないので、枚数や寸法の再指定が必要です

スクリーンショット 2026-08-16 091738.png

31. 電子基板ケース:外寸100×70×30mmのボックスを、肉厚2mmでシェル化(上部が開口)。底面の内側四隅に、高さ10mm、外径6mm、内径3mmのボス(円柱のスタンドオフ)を配置。側面の1つに15×8mmの長方形のUSBポート用切り欠き。

完成コード(PythonSCAD)

# ==========================================
# 電子基板ケース(上部開口・ボス付き)
# 作成日: 2026/08/15
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
outer_w   = 100.0   # 外寸X
outer_l   = 70.0    # 外寸Y
outer_h   = 30.0    # 外寸Z
t_wall    = 2.0     # 肉厚(側壁&底)

# ボス(スタンドオフ)
boss_h    = 10.0
boss_od   = 6.0     # 外径
boss_id   = 3.0     # 内径
boss_clear = 1.0    # 壁からの逃げ(組付け余裕)

# USB切り欠き(側面)
usb_w     = 15.0    # 幅(X方向)
usb_h     = 8.0     # 高さ(Z方向)
usb_zc    = 12.0    # 切り欠き中心Z(底からの高さ)
usb_side  = "pos_y" # "pos_y" 側面に配置(+Y側)

fn_val    = 80
eps       = 0.15    # チラつき防止&貫通マージン


# --- 関数定義 ---

def create_outer_block(w, l, h):
    """外形ブロック(底面Z=0、XYは原点中心)"""
    blk = cube([w, l, h], center=True)
    return translate(blk, [0, 0, h / 2])


def create_inner_cavity(w, l, h, t):
    """
    内側空間カッター(上部開口)
    底は t_wall を残し、上は少しepsだけ突き抜けて確実に開口させる
    """
    inner_w = w - 2 * t
    inner_l = l - 2 * t
    inner_h = h - t + eps  # 上にepsだけはみ出して開口を確実に

    cav = cube([inner_w, inner_l, inner_h], center=True)
    zc = t + inner_h / 2
    return translate(cav, [0, 0, zc])


def create_usb_cutout(w, l, t, usb_w, usb_h, usb_zc, side):
    """USBポート用の長方形切り欠き(側壁を貫通するカッター)"""
    cut_th = t + 2 * eps  # 壁厚より少し厚くして確実に貫通
    cut = cube([usb_w, cut_th, usb_h], center=True)

    if side == "pos_y":
        yc = (l / 2) - (t / 2)
        return translate(cut, [0, yc, usb_zc])
    elif side == "neg_y":
        yc = -(l / 2) + (t / 2)
        return translate(cut, [0, yc, usb_zc])
    else:
        # 必要なら pos_x / neg_x も追加してOK
        return translate(cut, [0, (l / 2) - (t / 2), usb_zc])


def create_boss(od, idd, h, fn):
    """ボス1本(筒形:外径od、内径idd)"""
    r_out = od / 2
    r_in  = idd / 2

    outer = cylinder(h=h, r=r_out, center=False, fn=fn)
    inner = cylinder(h=h + 2 * eps, r=r_in, center=False, fn=fn)
    inner = translate(inner, [0, 0, -eps])  # 上下にepsはみ出し

    return outer - inner


def create_bosses(outer_w, outer_l, t, boss_h, boss_od, boss_id, boss_clear, fn):
    """内側底面四隅にボスを配置(底の内側=Z=t から立ち上げ)"""
    r_out = boss_od / 2
    x = (outer_w / 2) - t - (r_out + boss_clear)
    y = (outer_l / 2) - t - (r_out + boss_clear)

    one = create_boss(boss_od, boss_id, boss_h, fn)

    b1 = translate(one, [ x,  y, t])
    b2 = translate(one, [ x, -y, t])
    b3 = translate(one, [-x,  y, t])
    b4 = translate(one, [-x, -y, t])

    return b1 + b2 + b3 + b4


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

outer_block = create_outer_block(outer_w, outer_l, outer_h)

# カッター(引く形状)は + でまとめる
cavity_cutter = create_inner_cavity(outer_w, outer_l, outer_h, t_wall)
usb_cutter    = create_usb_cutout(outer_w, outer_l, t_wall, usb_w, usb_h, usb_zc, usb_side)
cutter = cavity_cutter + usb_cutter

# まず外形から中空化&切り欠き
shell = outer_block - cutter

# ボスは「残したい形状」なので、くり抜き後に足し算で追加
bosses = create_bosses(outer_w, outer_l, t_wall, boss_h, boss_od, boss_id, boss_clear, fn_val)

result = shell + bosses

show(result)

USB切り欠きの位置(底から何mmか、左右どちら寄りか)、フタ(上蓋)も作るかどうかで、実用性が一気に上がります。

スクリーンショット 2026-08-16 092039.png

参考資料

1
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?