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

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

参考サイト

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

  • build123dのExamples

  • CadQueryのExamples

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

01. 寸法100×60×30mmの直方体(ボックス)

完成コード(PythonSCAD)

# ==========================================
# 直方体ボックス(100×60×30mm)
# 作成日: 2026/08/14
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
size_x = 100.0   # 幅(X方向)
size_y = 60.0    # 奥行き(Y方向)
size_z = 30.0    # 高さ(Z方向)

# --- メイン処理 ---
# 原点中心に配置(X/Y/Zすべて中心基準)
result = cube([size_x, size_y, size_z], center=True)

show(result)

スクリーンショット 2026-08-15 173744.png

02. 直径80mm、高さ50mmの円柱

完成コード(PythonSCAD)

# ==========================================
# 円柱(直径80mm・高さ50mm)
# 作成日: 2026/08/14
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
dia    = 80.0   # 直径
height = 50.0   # 高さ(Z方向)
fn_val = 80     # 分割数(円の滑らかさ)

def r_from_dia(d):
    """直径→半径 変換"""
    return d / 2.0

# --- メイン処理 ---
result = cylinder(h=height, r=r_from_dia(dia), center=True, fn=fn_val)

show(result)

スクリーンショット 2026-08-15 173925.png

03. 直径60mmの球

完成コード(PythonSCAD)

# ==========================================
# 直径60mmの球
# 作成日: 2026/08/14
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
sphere_d = 60.0     # 直径
sphere_r = sphere_d / 2.0
fn_val   = 80       # 滑らかさ(分割数)

# --- メイン処理 ---
result = sphere(r=sphere_r, fn=fn_val)

show(result)

スクリーンショット 2026-08-15 174052.png

04. 底面直径100mm、上面直径0mm(先端)、高さ80mmの円すい

完成コード(PythonSCAD)

# ==========================================
# 円錐(底面φ100、先端、H=80)
# 作成日: 2026/08/14
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
base_d   = 100.0   # 底面直径
top_d    = 0.0     # 上面直径(先端なので0)
height   = 80.0    # 高さ(Z方向)
fn_val   = 120     # 円の滑らかさ(分割数)

# --- ヘルパー ---
def r_from_dia(d):
    return d / 2.0

# --- メイン処理 ---
cone = cylinder(
    h=height,
    r1=r_from_dia(base_d),
    r2=r_from_dia(top_d),
    center=False,   # 底面をZ=0に置いて、上に伸ばす
    fn=fn_val
)

show(cone)

スクリーンショット 2026-08-15 174349.png

05. 寸法120×80×40mmのボックス。全エッジにR5フィレット

完成コード(PythonSCAD)

# ==========================================
# R5フィレット付きボックス(外形 120×80×40)
# 作成日: 2026/08/14
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
width   = 120.0   # X方向
depth   = 80.0    # Y方向
height  = 40.0    # Z方向
fillet_r = 5.0    # 全エッジのR
fn_val  = 80      # 球の分割数(見た目の滑らかさ)

# --- 関数(モジュール)定義 ---
def filleted_box(w, d, h, r, fn):
    """
    外形 w×d×h の直方体に、全エッジR=rのフィレットを付けた形状
    minkowski(小さくした直方体, 球) で作る
    """
    core = cube([w - 2*r, d - 2*r, h - 2*r], center=True)
    ball = sphere(r=r, fn=fn)
    return minkowski(core, ball)

# --- メイン処理 ---
result = filleted_box(width, depth, height, fillet_r, fn_val)

show(result)

※この方法(minkowski)は「全エッジに均一なR」を付けるのに強い一方、計算が重くなりやすいので、動作が重いときは fn_val を少し下げて調整してください。

スクリーンショット 2026-08-15 174618.png

06. 寸法100×60×30mmのボックス。全エッジにC3チャンファー

# ==========================================
# 100×60×30mm ボックス(全エッジ C3 チャンファー)
# 作成日: 2026/08/14
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
width   = 100.0  # X方向
depth   = 60.0   # Y方向
height  = 30.0   # Z方向
c       = 3.0    # C面取りサイズ(C3)
eps     = 0.1    # 念のための微小値

# --- 関数定義 ---

def octahedron(a):
    """原点中心の正八面体(頂点が±X, ±Y, ±Z にある)"""
    pts = [
        [ a, 0, 0],  # 0
        [0,  a, 0],  # 1
        [-a, 0, 0],  # 2
        [0, -a, 0],  # 3
        [0, 0,  a],  # 4 (top)
        [0, 0, -a],  # 5 (bottom)
    ]
    faces = [
        [4, 0, 1],
        [4, 1, 2],
        [4, 2, 3],
        [4, 3, 0],
        [5, 1, 0],
        [5, 2, 1],
        [5, 3, 2],
        [5, 0, 3],
    ]
    return polyhedron(points=pts, faces=faces)

def chamfered_box(w, d, h, chamfer):
    """
    全エッジC面取りの直方体
    仕組み:
      小さくした直方体 + 正八面体 を minkowski して、角をC面にする
    """
    if w <= 2 * chamfer or d <= 2 * chamfer or h <= 2 * chamfer:
        raise ValueError("C面取りが大きすぎます。各寸法は 2*C より大きくしてください。")

    core = cube([w - 2 * chamfer, d - 2 * chamfer, h - 2 * chamfer], center=True)
    tool = octahedron(chamfer)
    return minkowski(core, tool)

# --- メイン処理 ---
result = chamfered_box(width, depth, height, c)

show(result)

スクリーンショット 2026-08-15 175305.png

07. 底面100×100mm、高さ50mmのブロック。側面の縦エッジ(Z方向の4本)は R8。上面の外周エッジも R8。底面の外周エッジは 丸めない。

完成コード(PythonSCAD)

# ==========================================
# 片側(底面だけ)シャープなR付きブロック
# 作成日: 2026/08/14
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
size_x  = 100.0   # 底面サイズX
size_y  = 100.0   # 底面サイズY
height  = 50.0    # 高さZ
r_edge  = 8.0     # 指定R(縦エッジ&上面外周エッジ)
fn_val  = 96      # 円・球の分割数
eps     = 0.05    # ちらつき防止&わずかに重ねる用

# --- 関数定義 ---

def rounded_square_2d(w, d, r, fn):
    """
    XY平面の角丸四角形(縦エッジRの元になる輪郭)
    ※ square は fn を持てないので minkowski + circle で角丸を作る
    """
    core = square([w - 2 * r, d - 2 * r], center=True)
    return minkowski(core, circle(r=r, fn=fn))

def full_rounded_block_all_edges(w, d, h, r, fn):
    """
    いったん「全部の外周エッジがR」のブロックを作る(Minkowski)
    → 後で底面側だけ“埋め戻して”シャープにする
    """
    core = cube([w - 2 * r, d - 2 * r, h - 2 * r], center=True)
    return minkowski(core, sphere(r=r, fn=fn))

def bottom_sharp_filler(w, d, r, fn, eps):
    """
    底面外周エッジを丸めないための“埋め戻し材”
    高さ r だけ、縦壁をストンと立てて底エッジをシャープに戻す。
    """
    prof = rounded_square_2d(w, d, r, fn)
    # 底~高さ(r)までを埋める(ほんの少し上まで eps で重ねる)
    return linear_extrude(prof, height=r + eps, center=False)

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

# 1) 全エッジRのブロック(中心基準)を作って、底がZ=0になるように持ち上げ
rounded_all = full_rounded_block_all_edges(size_x, size_y, height, r_edge, fn_val)
rounded_all = translate(rounded_all, [0, 0, height / 2])

# 2) 底面だけシャープに戻す“埋め戻し”
filler = bottom_sharp_filler(size_x, size_y, r_edge, fn_val, eps)

# 3) 足す形状は + で結合(底面外周エッジだけ丸めない仕様にする)
result = rounded_all + filler

show(result)

形状の解釈(重要)

  • 「縦エッジR8」=平面(XY)で角がR8になっている(四隅が丸い)
  • 「底面の外周エッジは丸めない」=底面(Z=0)と側面の境界をZ方向にR付けしない(底の立ち上がりはシャープ)
    という意味で作っています。

スクリーンショット 2026-08-15 175659.png

08. 直径70mm、高さ60mmの円柱。上下両端の円形エッジにR4フィレット

完成コード(PythonSCAD)

# ==========================================
# 円柱(上下エッジR4フィレット)
# 作成日: 2026/08/14
# ==========================================

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

# --- パラメータ設定 (単位: mm) ---
dia       = 70.0   # 円柱 直径
height    = 60.0   # 円柱 高さ
fillet_r  = 4.0    # 上下端の円形エッジ フィレット半径
fn_val    = 120    # 回転体の分割数(円周方向)
arc_seg   = 24     # フィレット(1/4円)の分割数
eps       = 0.1    # 予備(今回は未使用)

radius = dia / 2.0

# --- 関数(モジュール)定義 ---
def arc_points(cx, cy, r, deg0, deg1, n):
    """2Dの円弧点列を生成(polygon用:点は [x, y] のリスト)"""
    pts = []
    for i in range(n + 1):
        t = i / n
        deg = deg0 + (deg1 - deg0) * t
        a = deg * pi / 180.0
        pts.append([cx + r * cos(a), cy + r * sin(a)])
    return pts

def create_profile_2d(R, H, r, seg):
    """
    回転体用2D断面(XY平面)を作る。
    rotate_extrudeによりZ軸回転 → 3D化される(y が高さ方向になる)。
    """
    if r <= 0:
        return polygon([[0, 0], [R, 0], [R, H], [0, H]])

    if r * 2 > H or r > R:
        raise ValueError("fillet_r が大きすぎます(高さや半径に対して不適切)")

    # 下側フィレット(外側コーナー: [R,0] を丸める)
    # 中心: [R-r, r]、角度: -90° -> 0°
    bottom_arc = arc_points(R - r, r, r, -90.0, 0.0, seg)

    # 上側フィレット(外側コーナー: [R,H] を丸める)
    # 中心: [R-r, H-r]、角度: 0° -> 90°
    top_arc = arc_points(R - r, H - r, r, 0.0, 90.0, seg)

    pts = []
    pts += [[0.0, 0.0]]          # 軸上の底
    pts += [[R - r, 0.0]]        # 底面の外周(フィレット開始点)
    pts += bottom_arc[1:]        # [R, r] へ
    pts += [[R, H - r]]          # 側面を上へ
    pts += top_arc[1:]           # [R-r, H] へ
    pts += [[0.0, H]]            # 軸上の上面

    return polygon(pts)

# --- メイン処理 ---
profile_2d = create_profile_2d(radius, height, fillet_r, arc_seg)
result = rotate_extrude(profile_2d, fn=fn_val)

show(result)

補足(設計の考え方)

  • minkowski で丸めると「端面が完全な平面」にならず、カプセル形状に近づきやすいので、今回は 断面を作って rotate_extrude で「上下の面はフラットのまま、外周エッジだけR」を確実に作っています。
    スクリーンショット 2026-08-15 180102.png

09. 外径80mm・内径60mm・長さ150mmのパイプ

完成コード(PythonSCAD)

# ==========================================
# パイプ(外径80・内径60・長さ150)
# 作成日: 2026/08/14
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
outer_d = 80.0
inner_d = 60.0
length_z = 150.0

fn_val = 80      # 円の滑らかさ
eps    = 0.1     # チラつき防止(カッター用マージン)

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

def r_from_dia(d):
    """直径から半径へ変換"""
    return d / 2.0

def create_body(od, h, fn):
    """本体(足す形状):外径の円柱"""
    return cylinder(h=h, r=r_from_dia(od), center=True, fn=fn)

def create_cutter(id_, h, fn, eps_val):
    """カッター(引く形状):内径の円柱(貫通&マージン付き)"""
    return cylinder(h=h + 2 * eps_val, r=r_from_dia(id_), center=True, fn=fn)

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

body = create_body(outer_d, length_z, fn_val)
cutter = create_cutter(inner_d, length_z, fn_val, eps)

result = body - cutter

show(result)

スクリーンショット 2026-08-15 180400.png

10. 寸法100×100×30mmのボックス。中央に直径40mmの貫通穴

完成コード(PythonSCAD)

# ==========================================
# 100x100x30 Box with Ø40 Through Hole
# 作成日: 2026/08/14
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
box_x   = 100.0   # X方向サイズ
box_y   = 100.0   # Y方向サイズ
box_z   = 30.0    # Z方向サイズ(高さ)
hole_d  = 40.0    # 穴の直径
fn_val  = 80      # 円柱の分割数(滑らかさ)
eps     = 0.1     # チラつき防止用微小値

# --- 関数(モジュール)定義 ---
def create_body(x, y, z):
    """本体(足す形状)"""
    return cube([x, y, z], center=True)

def create_cutter(z, hole_d, fn):
    """カッター(引く形状):Z方向の貫通穴"""
    hole_r = hole_d / 2.0
    return cylinder(h=z + 2 * eps, r=hole_r, center=True, fn=fn)

# --- メイン処理 ---
body = create_body(box_x, box_y, box_z)
cutter = create_cutter(box_z, hole_d, fn_val)

result = body - cutter

show(result)

スクリーンショット 2026-08-15 180949.png

11. 寸法120×80×25mmのプレート。四隅に直径10mmの取付穴(穴中心は端から15mm)

完成コード(PythonSCAD)

# ==========================================
# 取付穴つきプレート(120×80×25)
# 作成日: 2026/08/14
# ==========================================

from pythonscad import *

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

hole_d    = 10.0
hole_r    = hole_d / 2.0
edge_off  = 15.0    # 穴中心の端からの距離

fn_val    = 60
eps       = 0.1     # チラつき防止(カッターを少し長くする)

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

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

def create_cutter(w, l, h, r, off, fn):
    """四隅の貫通穴カッター(引く形状)を1つにまとめる"""
    x = (w / 2.0) - off
    y = (l / 2.0) - off

    hole = cylinder(h=h + 2.0 * eps, r=r, center=True, fn=fn)

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

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

body   = create_body(plate_w, plate_l, plate_h)
cutter = create_cutter(plate_w, plate_l, plate_h, hole_r, edge_off, fn_val)

result = body - cutter

show(result)

補足:プレートは center=True なので中心が原点 [0,0,0]、穴の中心座標は ±(幅/2-15), ±(奥行/2-15) に自動的に配置されています。

スクリーンショット 2026-08-15 181336.png

12. 直径100mm・高さ40mmの円柱。中央に直径50mm・深さ30mmの凹み(非貫通穴)

完成コード(PythonSCAD)

# ==========================================
# 円柱 + 中央の凹み(非貫通穴)
# 作成日: 2026/08/14
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
base_d   = 100.0   # 外径
base_h   = 40.0    # 高さ

pocket_d = 50.0    # 凹み径
pocket_h = 30.0    # 凹み深さ(上面から下へ)

fn_val   = 100     # 円の滑らかさ
eps      = 0.1     # チラつき防止用微小値

# --- 関数(モジュール)定義 ---
def create_body(d, h, fn):
    """本体(足す形状):Z=0を底面にして上へ伸びる円柱"""
    return cylinder(h=h, r=d / 2, center=False, fn=fn)

def create_cutter_pocket(d, depth, base_height, fn):
    """カッター(引く形状):上面から深さdepthだけ掘る非貫通の凹み"""
    # Z=base_height が上面。そこから depth だけ下へ掘る。
    # cutter は少しだけ上に突き出す(+eps)ようにして、面一致による描画バグを防ぐ
    pocket = cylinder(h=depth + 2 * eps, r=d / 2, center=False, fn=fn)
    return translate(pocket, [0, 0, base_height - depth - eps])

# --- メイン処理 ---
body = create_body(base_d, base_h, fn_val)
cutter = create_cutter_pocket(pocket_d, pocket_h, base_h, fn_val)

result = body - cutter

show(result)

スクリーンショット 2026-08-15 181615.png

13. 寸法150×100×20mmのベースプレート。中央列に直径8mm の穴を5個、20mm等間隔で配置

完成コード(PythonSCAD)

# ==========================================
# ベースプレート(中央列 8mm穴×5)
# 作成日: 2026/08/14
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
plate_w   = 150.0   # 幅(X方向)
plate_l   = 100.0   # 奥行き(Y方向)
plate_h   = 20.0    # 高さ(Z方向)

hole_d    = 8.0     # 穴径
hole_r    = hole_d / 2.0

hole_pitch = 20.0   # 穴の等間隔
hole_n     = 5      # 穴の個数(中央列)

fn_val   = 60       # 円の分割数
eps      = 0.1      # チラつき防止用微小値

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

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

def create_cutter(h, r, pitch, n, fn):
    """中央列の貫通穴カッター(引く形状)を + で一体化して返す"""
    # 5個なら -2, -1, 0, 1, 2 のように中央対称に並べる
    start_i = -(n // 2)

    cutter = None
    for i in range(n):
        x = (start_i + i) * pitch
        y = 0.0
        z = 0.0

        hole = cylinder(h=h + 2 * eps, r=r, center=True, fn=fn)
        hole = translate(hole, [x, y, z])

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

    return cutter

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

body = create_body(plate_w, plate_l, plate_h)
cutter = create_cutter(plate_h, hole_r, hole_pitch, hole_n, fn_val)

result = body - cutter

show(result)

スクリーンショット 2026-08-15 182157.png

14. 寸法100×100×50mmのボックスの上面中央に、直径40mm・高さ30mmの円柱ボス

完成コード(PythonSCAD)

# ==========================================
# 100x100x50 Box + Top Center Boss
# 作成日: 2026/08/14
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
box_w   = 100.0   # 幅(X方向)
box_l   = 100.0   # 奥行き(Y方向)
box_h   = 50.0    # 高さ(Z方向)

boss_d  = 40.0    # ボス直径
boss_h  = 30.0    # ボス高さ

fn_val  = 80      # 円柱の滑らかさ
eps     = 0.1     # 予備(今回は未使用だが、穴あけ等で活躍)

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

def create_box(w, l, h):
    """底面Z=0の箱(ブロック)"""
    body = cube([w, l, h], center=True)
    return translate(body, [0, 0, h / 2])

def create_boss(d, h, base_z, fn):
    """上面に載る円柱ボス(底面が base_z から開始)"""
    r = d / 2
    boss = cylinder(h=h, r=r, center=False, fn=fn)
    return translate(boss, [0, 0, base_z])

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

box_body = create_box(box_w, box_l, box_h)
boss     = create_boss(boss_d, boss_h, base_z=box_h, fn=fn_val)

result = box_body + boss

show(result)

スクリーンショット 2026-08-15 182416.png

15. 直径120mm・高さ10mmの円盤の上面に、直径80mm・高さ40mmの円柱を同軸に配置した形状

完成コード(PythonSCAD)

# ==========================================
# 同軸2段円柱(円盤+円柱)
# 作成日: 2026/08/14
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
disc_d   = 120.0   # 円盤 直径
disc_h   = 10.0    # 円盤 高さ
boss_d   = 80.0    # 上の円柱 直径
boss_h   = 40.0    # 上の円柱 高さ
fn_val   = 120     # 円の分割数(滑らかさ)

# --- メイン処理 ---
# 円盤(底面Z=0から上に積み上げ)
disc = cylinder(h=disc_h, r=disc_d / 2, center=False, fn=fn_val)

# 上の円柱(円盤の上面に同軸で配置)
boss = translate(
    cylinder(h=boss_h, r=boss_d / 2, center=False, fn=fn_val),
    [0, 0, disc_h]
)

result = disc + boss

show(result)

スクリーンショット 2026-08-15 182651.png

16. 外径120mm・内径80mm・厚さ15mmのフランジリング。外周部に直径10mmの穴を6個、均等配置

完成コード(PythonSCAD)

# ==========================================
# フランジリング(外周6穴)
# 作成日: 2026/08/14
# ==========================================

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

# --- パラメータ設定 (単位: mm) ---
outer_d        = 120.0   # 外径
inner_d        = 80.0    # 内径
thickness      = 15.0    # 厚さ(Z方向)

hole_d         = 10.0    # 外周穴の直径
hole_count     = 6       # 穴数(等配)
edge_margin    = 5.0     # 外周から穴中心までの余裕(外周部の目安)

fn_val         = 80      # 円の滑らかさ
eps            = 0.1     # チラつき防止用微小値

# --- ヘルパー ---
def r_from_dia(d):
    return d / 2.0

# --- 関数(モジュール)定義 ---
def create_body(od, h, fn):
    """本体(足す形状): 外径の円柱"""
    return cylinder(h=h, r=r_from_dia(od), center=True, fn=fn)

def create_cutter(od, id_, h, hole_d, hole_n, margin, fn):
    """カッター(引く形状): 内径くり抜き + 外周ボルト穴(等配)"""
    r_outer = r_from_dia(od)
    r_inner = r_from_dia(id_)
    r_hole  = r_from_dia(hole_d)

    # 内径くり抜き(貫通。Zファイティング防止で高さに余裕)
    inner_cut = cylinder(h=h + 2 * eps, r=r_inner, center=True, fn=fn)

    # 外周穴の中心半径(外周から margin 分だけ内側、さらに穴半径分内側)
    bolt_circle_r = r_outer - margin - r_hole

    holes = None
    for i in range(hole_n):
        ang = 2 * pi * i / hole_n
        x = bolt_circle_r * cos(ang)
        y = bolt_circle_r * sin(ang)

        one_hole = translate(
            cylinder(h=h + 2 * eps, r=r_hole, center=True, fn=fn),
            [x, y, 0]
        )
        holes = one_hole if holes is None else (holes + one_hole)

    return inner_cut + holes

# --- メイン処理 ---
body   = create_body(outer_d, thickness, fn_val)
cutter = create_cutter(outer_d, inner_d, thickness, hole_d, hole_count, edge_margin, fn_val)

result = body - cutter

show(result)

必要なら「穴をどれくらい外周寄りにするか」を edge_margin(外周からの余裕)で調整できます。例えば外周ギリギリに寄せたいなら edge_margin = 2.0 などにします。

スクリーンショット 2026-08-15 184116.png

17. 対辺距離30mm・高さ25mmの正六角柱

完成コード(PythonSCAD)

# ==========================================
# 正六角柱(対辺距離 30mm・高さ 25mm)
# 作成日: 2026/08/14
# ==========================================

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

# --- パラメータ設定 (単位: mm) ---
across_flats = 30.0   # 対辺距離(向かい合う辺どうしの距離)
height       = 25.0   # 高さ(Z方向)
eps          = 0.1    # 予備(今回は未使用)

# --- 関数(モジュール)定義 ---
def regular_hexagon_2d(af):
    """
    正六角形(2D)をXY平面上に、原点中心で作る。
    af = 対辺距離(across flats)
    """
    n = 6
    apothem = af / 2.0                      # 内接円半径(中心→辺の距離)
    R = apothem / cos(pi / n)              # 外接円半径(中心→頂点の距離)

    pts = []
    for i in range(n):
        theta = 2 * pi * i / n
        pts.append([R * cos(theta), R * sin(theta)])  # (x, y)はタプル禁止なのでリストで

    return polygon(pts)

def hex_prism(af, h):
    """正六角柱(Z=0を底面基準)"""
    hex2d = regular_hexagon_2d(af)
    return linear_extrude(hex2d, height=h)

# --- メイン処理 ---
result = hex_prism(across_flats, height)

show(result)

補足(寸法の意味): 「対辺距離30mm」は“向かい合う平らな面どうしの距離”なので、六角ナットの「二面幅」と同じ定義です。高さ25mmはZ方向にそのまま押し出しています(底面がZ=0)。

スクリーンショット 2026-08-15 184656.png

18. 外接円直径60mm・高さ20mmの正六角柱。全エッジにC2チャンファー

完成コード(PythonSCAD)

# ==========================================
# 正六角柱(外接円φ60・高さ20)全エッジC2チャンファー
# 作成日: 2026/08/14
# ==========================================

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

# --- パラメータ設定 (単位: mm) ---
circum_d = 60.0   # 外接円直径(頂点が乗る円)
height   = 20.0   # 高さ(Z方向)
c        = 2.0    # チャンファー寸法 C2
eps      = 0.05   # チラつき防止&hull用の薄板厚み

# --- 幾何ヘルパー(2Dベクトル) ---
def v_sub(a, b):
    return [a[0] - b[0], a[1] - b[1]]

def v_add(a, b):
    return [a[0] + b[0], a[1] + b[1]]

def v_mul(a, s):
    return [a[0] * s, a[1] * s]

def v_len(a):
    return sqrt(a[0] * a[0] + a[1] * a[1])

def v_unit(a):
    L = v_len(a)
    return [a[0] / L, a[1] / L]

# --- 関数(モジュール)定義 ---
def regular_hex_vertices(R):
    """原点中心・外接円半径Rの正六角形の頂点(CCW順)"""
    verts = []
    for i in range(6):
        th = i * (pi / 3.0)
        verts.append([R * cos(th), R * sin(th)])
    return verts

def chamfered_hex_profile_2d(R, chamfer):
    """
    垂直エッジ(縦の稜線)をC寸法で落とした断面(=頂点を面取りした12角形)を作る。
    ※この2D断面を押し出すと「縦エッジのC2」が入る。
    """
    v = regular_hex_vertices(R)

    # out[i] : 頂点iから次の頂点(i+1)方向へ chamfer だけ進んだ点
    # inn[i] : 頂点iから前の頂点(i-1)方向へ chamfer だけ進んだ点
    out = []
    inn = []
    for i in range(6):
        v_i = v[i]
        v_next = v[(i + 1) % 6]
        v_prev = v[(i - 1) % 6]

        dir_next = v_unit(v_sub(v_next, v_i))
        dir_prev = v_unit(v_sub(v_prev, v_i))

        out.append(v_add(v_i, v_mul(dir_next, chamfer)))
        inn.append(v_add(v_i, v_mul(dir_prev, chamfer)))

    # 辺ごとに「out[i] -> inn[i+1]」でつながるので、その順に12点を並べる
    pts = []
    for i in range(6):
        pts.append(out[i])
        pts.append(inn[(i + 1) % 6])

    return polygon(points=pts)

def plate_at_z(shape2d, z):
    """hull用:2D形状を薄く押し出して、指定Z位置へ置いた“薄板”にする"""
    slab = linear_extrude(shape2d, height=eps)   # Z: 0..eps
    return translate(slab, [0, 0, z])

def create_chamfered_hex_prism(circum_dia, h, chamfer):
    """
    全エッジCチャンファーを、3つのボリューム(下C部+中間+上C部)の足し算で作る。
    - 縦エッジC:断面を12角形(頂点面取り)にして押し出し
    - 上下面の外周エッジC:hullで「フル断面」⇔「内側オフセット断面」を45°で接続
    """
    R = circum_dia / 2.0

    # 縦エッジC(断面の頂点面取り)を入れた“フル断面”
    prof_full = chamfered_hex_profile_2d(R, chamfer)

    # 上下面のC用に、断面を内側へ平行オフセット(側面方向に2mm引っ込める)
    # これで、上面/下面のC2が「45°(2mm×2mm)」になりやすい形を作れる
    prof_in = offset(prof_full, r=-chamfer)

    # 中間のストレート部(Z=chamfer .. h-chamfer)
    mid_h = h - 2.0 * chamfer
    mid = linear_extrude(prof_full, height=mid_h)
    mid = translate(mid, [0, 0, chamfer])

    # 下のチャンファー部(Z=0..chamfer)
    bottom = hull(
        plate_at_z(prof_in, 0.0),
        plate_at_z(prof_full, chamfer)
    )

    # 上のチャンファー部(Z=h-chamfer..h)
    # plateの厚みeps分だけ上に飛び出さないよう、上側は(h-eps)に置く
    top = hull(
        plate_at_z(prof_full, h - chamfer),
        plate_at_z(prof_in, h - eps)
    )

    return bottom + mid + top

# --- メイン処理 ---
result = create_chamfered_hex_prism(circum_d, height, c)

show(result)

補足(設計の考え方)

  • 「縦の稜線(側面どうしの交線)」のC2は、2D断面で頂点を面取りした12角形を作って押し出すことで入れています
  • 「上面・下面の外周エッジ」のC2は、上側/下側で断面を内側へ2mmオフセットした形を用意し、hull() で45°の斜面になるようにつないでいます
    スクリーンショット 2026-08-15 184946.png

19. 外径20mm・内径10mm・高さ15mmのスペーサー(円筒カラー)

完成コード(PythonSCAD)

# ==========================================
# 円筒スペーサー(円筒カラー)
# 作成日: 2026/08/15
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
outer_d = 20.0   # 外径
inner_d = 10.0   # 内径
height  = 15.0   # 高さ
fn_val  = 80     # 円の滑らかさ
eps     = 0.1    # チラつき防止(貫通カッターの余裕)

def r_from_dia(d):
    """直径→半径"""
    return d / 2.0

def create_body(od, h, fn):
    """足す形状(外側円筒)"""
    return cylinder(h=h, r=r_from_dia(od), center=True, fn=fn)

def create_cutter(id_, h, fn, eps_):
    """引く形状(内側の貫通穴)"""
    return cylinder(h=h + 2 * eps_, r=r_from_dia(id_), center=True, fn=fn)

# --- メイン処理 ---
body = create_body(outer_d, height, fn_val)
cutter = create_cutter(inner_d, height, fn_val, eps)

result = body - cutter

show(result)

※「高さ方向(Z)も center=True」にしてあるので、原点[0,0,0]に対して上下対称の位置にできます(組み立て基準が作りやすいです)。

スクリーンショット 2026-08-15 185216.png

20. 外径30mm・内径16mm・高さ10mmのカラー。両端にR1フィレット

1. 完成コード(PythonSCAD)

# ==========================================
# カラー(外径30 / 内径16 / 高さ10, 両端R1)
# 作成日: 2026/08/15
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
outer_d   = 30.0   # 外径
inner_d   = 16.0   # 内径
height    = 10.0   # 高さ
fillet_r  = 1.0    # フィレット半径 R
fn_val    = 96     # 円・球の分割数
eps       = 0.05   # チラつき防止用微小値

# --- 寸法の派生 ---
outer_r = outer_d / 2.0
inner_r = inner_d / 2.0

# minkowski でRを付けた後に最終寸法が狙い値になるよう、芯材を縮める
core_outer_r = outer_r - fillet_r
core_inner_r = inner_r + fillet_r
core_h       = height  - 2.0 * fillet_r

# --- 関数(モジュール)定義 ---
def create_collar_core(r_out, r_in, h, fn):
    """R付け前の芯材(リング)"""
    outer = cylinder(h=h, r=r_out, center=True, fn=fn)
    inner = cylinder(h=h + 2.0 * eps, r=r_in, center=True, fn=fn)  # 余裕を持って貫通
    return outer - inner

# --- メイン処理 ---
core = create_collar_core(core_outer_r, core_inner_r, core_h, fn_val)

# 両端(上下)+内外周エッジにR1が入る
result = minkowski(core, sphere(r=fillet_r, fn=fn_val))

show(result)

※この作り方(minkowski)は「両端の角だけ」ではなく、内径側の上下エッジにもRが入ります。もし「外径側の上下エッジだけR1にしたい」など、Rを入れる場所を限定したい場合は別方式を検証してみてください。

スクリーンショット 2026-08-15 185524.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?