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?

はじめに

Pythonプログラミングで始める3D CADの形状作成の練習帳です。PythonSCADにコピペして、確認していきましょう。たくさん試してください。
きっと、世界は広いと感じられます。ありがとうございます。

PythonSCAD

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

01. 直径80mm、高さ50mmの円柱、上面にC3面取り

1. 完成コード(PythonSCAD)

# ==========================================
# 円柱(上面C3面取り)
# 作成日: 2026/08/16
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
dia        = 80.0     # 直径
radius     = dia / 2  # 半径
height     = 50.0     # 全高
chamfer_c  = 3.0      # C面取り量(45度想定)
fn_val     = 80       # 円の分割数

# --- 本体生成(足す形状だけで作る:下の円柱 + 上のテーパー部) ---
h_lower = height - chamfer_c

lower = cylinder(h=h_lower, r=radius, center=False, fn=fn_val)

# 上面のC面取りは、上側を「半径が少し小さい円柱(円すい台)」として作る
upper = cylinder(h=chamfer_c, r1=radius, r2=radius - chamfer_c, center=False, fn=fn_val)
upper = translate(upper, [0, 0, h_lower])

result = lower + upper

show(result)

※ここでは「上面外周のC3(45°)」を、上側3mmぶんを円すい台にして再現しています(削るのではなく、形状を分割して“最初からその形”にするので安定です)。

スクリーンショット 2026-08-22 112332.png

02. 次に、半径20で、くりぬいてください。

2. 完成コード(PythonSCAD)

# ==========================================
# 円柱(上面C3面取り)+ 中心に貫通穴(r=20)
# 作成日: 2026/08/16
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
outer_dia   = 80.0
outer_r     = outer_dia / 2
height      = 50.0

chamfer_c   = 3.0          # 上面のC面取り(45度想定)
hole_r      = 20.0         # くり抜き半径

fn_val      = 80
eps         = 0.1          # チラつき防止

# --- 関数定義 ---

def create_body(outer_r, height, chamfer_c, fn):
    """本体(足す形状): 下側円柱 + 上側円すい台(C面取り相当)"""
    h_lower = height - chamfer_c

    lower = cylinder(h=h_lower, r=outer_r, center=False, fn=fn)

    upper = cylinder(h=chamfer_c, r1=outer_r, r2=outer_r - chamfer_c, center=False, fn=fn)
    upper = translate(upper, [0, 0, h_lower])

    return lower + upper

def create_cutter(hole_r, height, fn, eps):
    """カッター(引く形状): 中心の貫通穴(上下に少しはみ出させる)"""
    hole = cylinder(h=height + 2 * eps, r=hole_r, center=False, fn=fn)
    hole = translate(hole, [0, 0, -eps])
    return hole

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

body = create_body(outer_r, height, chamfer_c, fn_val)
cutter = create_cutter(hole_r, height, fn_val, eps)

result = body - cutter

show(result)

スクリーンショット 2026-08-22 112545.png

貫通穴の円柱を height + 2*eps にして上下に少しはみ出させているのは、面がぴったり一致して起きるチラつき(Zファイティング)を防ぐためです。

03. 次に、上面の穴にC2面取りをかけてください。

3. 完成コード(PythonSCAD)

# ==========================================
# 円柱(上面C3面取り)+ 中心貫通穴(r=20)+ 上面穴口にC2面取り
# 作成日: 2026/08/16
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
outer_dia     = 80.0
outer_r       = outer_dia / 2
height        = 50.0

outer_chamfer = 3.0     # 上面外周のC面取り(45度想定)
hole_r        = 20.0    # 貫通穴 半径
hole_chamfer  = 2.0     # 上面の穴口 C2(45度想定)

fn_val        = 80
eps           = 0.1     # チラつき防止

# --- 関数定義 ---

def create_body(outer_r, height, outer_chamfer, fn):
    """本体(足す形状): 下側円柱 + 上側円すい台(C面取り相当)"""
    h_lower = height - outer_chamfer

    lower = cylinder(h=h_lower, r=outer_r, center=False, fn=fn)

    upper = cylinder(
        h=outer_chamfer,
        r1=outer_r,
        r2=outer_r - outer_chamfer,
        center=False,
        fn=fn
    )
    upper = translate(upper, [0, 0, h_lower])

    return lower + upper

def create_cutter(hole_r, height, hole_chamfer, fn, eps):
    """カッター(引く形状): 貫通穴 + 上面穴口C面取り を1つにまとめる"""
    # 貫通穴(上下に少しはみ出し)
    hole = cylinder(h=height + 2 * eps, r=hole_r, center=False, fn=fn)
    hole = translate(hole, [0, 0, -eps])

    # 上面の穴口C2(45°):上に向かって半径が +2mm 広がる円すい台で削る
    chamfer_h = hole_chamfer + 2 * eps
    chamfer = cylinder(
        h=chamfer_h,
        r1=hole_r,                 # 下(内側)は元の穴半径
        r2=hole_r + hole_chamfer,  # 上(入口側)が広がる
        center=False,
        fn=fn
    )
    chamfer = translate(chamfer, [0, 0, height - hole_chamfer - eps])

    return hole + chamfer

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

body = create_body(outer_r, height, outer_chamfer, fn_val)
cutter = create_cutter(hole_r, height, hole_chamfer, fn_val, eps)

result = body - cutter

show(result)

スクリーンショット 2026-08-22 112651.png

上面の穴口C2は「45°の面取り」なので、Z方向に2mm下がる間に、半径が2mm広がる(r が hole_r → hole_r+2)円すい台を“カッター”として追加して一括で引いています。

04. 次に、下面の外周エッジにC3面取り

4. 完成コード(PythonSCAD)

# ==========================================
# 円柱(上面C3 + 下面外周C3)+ 中心貫通穴(r=20)+ 上面穴口C2
# 作成日: 2026/08/16
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
outer_dia      = 80.0
outer_r        = outer_dia / 2
height         = 50.0

top_chamfer    = 3.0     # 上面外周 C3(45度想定)
bottom_chamfer = 3.0     # 下面外周 C3(45度想定)

hole_r         = 20.0    # 貫通穴 半径
hole_chamfer   = 2.0     # 上面の穴口 C2(45度想定)

fn_val         = 80
eps            = 0.1     # チラつき防止

# --- 関数定義 ---

def create_body(outer_r, height, top_c, bottom_c, fn):
    """本体(足す形状): 下面C + 胴体 + 上面C を積み上げで生成"""
    mid_h = height - top_c - bottom_c
    if mid_h < 0:
        raise ValueError("面取り量が大きすぎます。height >= top_chamfer + bottom_chamfer にしてください。")

    # 下面外周C面取り:下で半径が小さく、上で元の半径になる円すい台
    bottom = cylinder(
        h=bottom_c,
        r1=outer_r - bottom_c,
        r2=outer_r,
        center=False,
        fn=fn
    )

    # 胴体(まっすぐな円柱)
    mid = cylinder(h=mid_h, r=outer_r, center=False, fn=fn)
    mid = translate(mid, [0, 0, bottom_c])

    # 上面外周C面取り:下で元の半径、上で半径が小さくなる円すい台
    top = cylinder(
        h=top_c,
        r1=outer_r,
        r2=outer_r - top_c,
        center=False,
        fn=fn
    )
    top = translate(top, [0, 0, bottom_c + mid_h])

    return bottom + mid + top

def create_cutter(hole_r, height, hole_chamfer, fn, eps):
    """カッター(引く形状): 貫通穴 + 上面穴口C面取り を1つにまとめる"""
    # 貫通穴(上下に少しはみ出し)
    hole = cylinder(h=height + 2 * eps, r=hole_r, center=False, fn=fn)
    hole = translate(hole, [0, 0, -eps])

    # 上面の穴口C2(45°):上に向かって半径が +2mm 広がる円すい台で削る
    chamfer_h = hole_chamfer + 2 * eps
    chamfer = cylinder(
        h=chamfer_h,
        r1=hole_r,
        r2=hole_r + hole_chamfer,
        center=False,
        fn=fn
    )
    chamfer = translate(chamfer, [0, 0, height - hole_chamfer - eps])

    return hole + chamfer

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

body = create_body(outer_r, height, top_chamfer, bottom_chamfer, fn_val)
cutter = create_cutter(hole_r, height, hole_chamfer, fn_val, eps)

result = body - cutter

show(result)

スクリーンショット 2026-08-22 112926.png

下面外周のC3は「底面(Z=0)の外周半径が outer_r-3 になり、上に3mm行くまでに outer_r に戻る」円すい台を足し形状として作ってあります。

05. 次に、底面の穴にC2面取りをかけてください。

5. 完成コード(PythonSCAD)

# ==========================================
# 円柱(上面C3 + 下面外周C3)
# + 中心貫通穴(r=20)
# + 上面穴口C2 + 下面穴口C2
# 作成日: 2026/08/16
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
outer_dia      = 80.0
outer_r        = outer_dia / 2
height         = 50.0

top_chamfer    = 3.0     # 上面外周 C3(45度想定)
bottom_chamfer = 3.0     # 下面外周 C3(45度想定)

hole_r         = 20.0    # 貫通穴 半径
hole_chamfer   = 2.0     # 穴口のC2(上面・下面ともに)

fn_val         = 80
eps            = 0.1     # チラつき防止

# --- 関数定義 ---

def create_body(outer_r, height, top_c, bottom_c, fn):
    """本体(足す形状): 下面C + 胴体 + 上面C を積み上げで生成"""
    mid_h = height - top_c - bottom_c
    if mid_h < 0:
        raise ValueError("面取り量が大きすぎます。height >= top_chamfer + bottom_chamfer にしてください。")

    # 下面外周C:下で半径が小さく、上で元の半径になる円すい台
    bottom = cylinder(h=bottom_c, r1=outer_r - bottom_c, r2=outer_r, center=False, fn=fn)

    # 胴体
    mid = cylinder(h=mid_h, r=outer_r, center=False, fn=fn)
    mid = translate(mid, [0, 0, bottom_c])

    # 上面外周C:下で元の半径、上で半径が小さくなる円すい台
    top = cylinder(h=top_c, r1=outer_r, r2=outer_r - top_c, center=False, fn=fn)
    top = translate(top, [0, 0, bottom_c + mid_h])

    return bottom + mid + top

def create_cutter(hole_r, height, hole_c, fn, eps):
    """カッター(引く形状): 貫通穴 + 上下面の穴口C面取り を1つにまとめる"""
    # 貫通穴(上下に少しはみ出し)
    hole = cylinder(h=height + 2 * eps, r=hole_r, center=False, fn=fn)
    hole = translate(hole, [0, 0, -eps])

    # 上面の穴口C2(45°)
    # 上面(Z=height)側で入口が広がる:半径 hole_r → hole_r+hole_c
    top_ch = cylinder(
        h=hole_c + 2 * eps,
        r1=hole_r,
        r2=hole_r + hole_c,
        center=False,
        fn=fn
    )
    top_ch = translate(top_ch, [0, 0, height - hole_c - eps])

    # 下面の穴口C2(45°)
    # 下面(Z=0)側で入口が広がる:Z=0で hole_r+hole_c、Z=hole_c で hole_r
    bottom_ch = cylinder(
        h=hole_c + 2 * eps,
        r1=hole_r + hole_c,  # 底面入口側(大きい)
        r2=hole_r,           # 内側へ入ると元の穴径へ
        center=False,
        fn=fn
    )
    bottom_ch = translate(bottom_ch, [0, 0, -eps])

    return hole + top_ch + bottom_ch

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

body = create_body(outer_r, height, top_chamfer, bottom_chamfer, fn_val)
cutter = create_cutter(hole_r, height, hole_chamfer, fn_val, eps)

result = body - cutter

show(result)

下面の穴口C2は、底面(Z=0)で穴半径が hole_r + 2 に広がり、上に2mm入ると hole_r に戻る円すい台カッターを追加して、一括で引き算しています。

image.png

06. 円柱より少し大きめのcubeで、中心からカットし、+y方向を残してください。

6. 完成コード(PythonSCAD)

# ==========================================
# 円柱(面取り・穴付き)を中心(Y=0)でカットして +Y 側だけ残す
# 作成日: 2026/08/16
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
outer_dia      = 80.0
outer_r        = outer_dia / 2
height         = 50.0

top_chamfer    = 3.0     # 上面外周 C3(45度想定)
bottom_chamfer = 3.0     # 下面外周 C3(45度想定)

hole_r         = 20.0    # 貫通穴 半径
hole_chamfer   = 2.0     # 穴口のC2(上面・下面ともに)

fn_val         = 80
eps            = 0.1     # チラつき防止

# カット用cubeの「少し大きめ」マージン
cut_margin     = 2.0

# --- 関数定義 ---

def create_body(outer_r, height, top_c, bottom_c, fn):
    """本体(足す形状): 下面C + 胴体 + 上面C を積み上げで生成(Z=0が底)"""
    mid_h = height - top_c - bottom_c
    if mid_h < 0:
        raise ValueError("面取り量が大きすぎます。height >= top_chamfer + bottom_chamfer にしてください。")

    bottom = cylinder(h=bottom_c, r1=outer_r - bottom_c, r2=outer_r, center=False, fn=fn)

    mid = cylinder(h=mid_h, r=outer_r, center=False, fn=fn)
    mid = translate(mid, [0, 0, bottom_c])

    top = cylinder(h=top_c, r1=outer_r, r2=outer_r - top_c, center=False, fn=fn)
    top = translate(top, [0, 0, bottom_c + mid_h])

    return bottom + mid + top

def create_cutter(hole_r, height, hole_c, fn, eps):
    """カッター(引く形状): 貫通穴 + 上下面の穴口C面取り を1つにまとめる"""
    hole = cylinder(h=height + 2 * eps, r=hole_r, center=False, fn=fn)
    hole = translate(hole, [0, 0, -eps])

    top_ch = cylinder(h=hole_c + 2 * eps, r1=hole_r, r2=hole_r + hole_c, center=False, fn=fn)
    top_ch = translate(top_ch, [0, 0, height - hole_c - eps])

    bottom_ch = cylinder(h=hole_c + 2 * eps, r1=hole_r + hole_c, r2=hole_r, center=False, fn=fn)
    bottom_ch = translate(bottom_ch, [0, 0, -eps])

    return hole + top_ch + bottom_ch

def create_keep_cube(outer_r, height, margin, eps):
    """
    +Y側だけ残すための「半空間」cube(円柱より少し大きめ)
    y=0 の面がカット面になる(中心からカット)
    """
    cut_x = 2 * outer_r + 2 * margin
    cut_y = outer_r + margin           # y: 0 〜 +側だけ覆えばOK
    cut_z = height + 2 * eps

    keep = cube([cut_x, cut_y, cut_z], center=False)
    keep = translate(keep, [-cut_x / 2, 0, -eps])  # y=0を中心切断面に合わせる
    return keep

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

body = create_body(outer_r, height, top_chamfer, bottom_chamfer, fn_val)
cutter = create_cutter(hole_r, height, hole_chamfer, fn_val, eps)
full_model = body - cutter

keep_cube = create_keep_cube(outer_r, height, cut_margin, eps)

# +Y側だけ残す(積集合)
result = intersection(full_model, keep_cube)

show(result)

スクリーンショット 2026-08-22 113517.png

  • 「中心からカット」は 平面 y=0 での切断です。
  • その平面より +Y 側だけを覆う cube を用意して、intersection() で「残す側」だけを取り出しています

スクリーンショット 2026-08-22 113441.png

07. intersectionの可視化

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

body = create_body(outer_r, height, top_chamfer, bottom_chamfer, fn_val)
cutter = create_cutter(hole_r, height, hole_chamfer, fn_val, eps)
full_model = body - cutter

keep_cube = create_keep_cube(outer_r, height, cut_margin, eps).color([0.8,0.2,0.2,0.3])

# +Y側だけ残す(積集合)
result = intersection(full_model, keep_cube).color([0.2,0.2,0.8,0.3])

show(result,keep_cube)

スクリーンショット 2026-08-22 114800.png

08. プロンプトからの作成 その1

以下のルールに沿って、外径40mm、内径25mm、長さ80mmのパイプを作成してください。
両端(上面と底面)にC2の面取りを施しますが、3D CADのセオリーに従い、
外側と内側で作り方を厳密に分けてください。

外側の面取り(上面・底面):カッターで削るのではなく、パイプ本体を作る際に
「円柱と円錐台(テーパー)」を足し算(+)して組み立ててください。

内側・穴の面取り(上面・底面):ストレートな貫通穴と、両端の面取り用円錐台を
足し算(+)して「1つのカッターパーツ」を作り、最後に本体から引き算(-)してください。

完成コード(PythonSCAD)

# ==========================================
# Chamfered Pipe (OD40 / ID25 / L80, C2 both ends)
# 作成日: 2026/08/16
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
outer_d   = 40.0
inner_d   = 25.0
length_z  = 80.0
chamfer_c = 2.0       # C2(45°面取りを想定:軸方向2mm、半径方向2mm)
fn_val    = 100
eps       = 0.1       # チラつき防止&確実に貫通させる微小値

r_out = outer_d / 2.0
r_in  = inner_d / 2.0

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

def create_body_pipe(rod, lz, c, fn):
    """
    本体(足す形状):
    外側の面取りは「削る」のではなく、円柱+円錐台(テーパー)を足し算で組み立てる。
    """
    # 中央のストレート外形(面取り分だけ短く)
    mid_h = lz - 2.0 * c
    mid = cylinder(h=mid_h, r=rod, center=True, fn=fn)

    # 45°外面取り:端面に向かって半径が (rod -> rod-c) へ細くなる円錐台
    top_ch = cylinder(h=c, r1=rod,     r2=rod - c, center=True, fn=fn)
    bot_ch = cylinder(h=c, r1=rod - c, r2=rod,     center=True, fn=fn)

    top_ch = translate(top_ch, [0, 0, (lz / 2.0) - (c / 2.0)])
    bot_ch = translate(bot_ch, [0, 0, -(lz / 2.0) + (c / 2.0)])

    return mid + top_ch + bot_ch


def create_inner_cutter(rid, lz, c, fn, eps_val):
    """
    カッター(引く形状):
    内側(穴)の面取りは「ストレート穴」+「両端の面取り円錐台」を足し算で1つにまとめ、
    最後に本体から一括で引き算する。
    """
    # ストレート貫通穴(確実に貫通させるため少し長め)
    hole = cylinder(h=lz + 2.0 * eps_val, r=rid, center=True, fn=fn)

    # 内面取り:端面に向かって穴半径が (rid -> rid+c) と広がる円錐台
    ch_h = c + eps_val
    top_ch = cylinder(h=ch_h, r1=rid,     r2=rid + c, center=True, fn=fn)
    bot_ch = cylinder(h=ch_h, r1=rid + c, r2=rid,     center=True, fn=fn)

    top_ch = translate(top_ch, [0, 0, (lz / 2.0) - (ch_h / 2.0)])
    bot_ch = translate(bot_ch, [0, 0, -(lz / 2.0) + (ch_h / 2.0)])

    return hole + top_ch + bot_ch


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

body = create_body_pipe(r_out, length_z, chamfer_c, fn_val)
cutter = create_inner_cutter(r_in, length_z, chamfer_c, fn_val, eps)

result = body - cutter
result = color(result, "skyblue")

show(result)

スクリーンショット 2026-08-22 144507.png

ねらい(CADのセオリーに沿った作り分け)

  • 外側C2:外形を「削って作る」と、外形寸法が削り量に依存してズレやすいので、最初から“完成外形”を足し算で組み立てています(円柱+円錐台×2)
  • 内側C2:穴は加工の考え方に近く、穴形状(ストレート+面取り)をカッターとして1つにまとめ、最後に 本体 - カッター で一括加工しています

09. プロンプトからの作成 その2 回転体

外径40mm、内径25mm、長さ80mmのパイプを作成してください。
両端面について、外側エッジと内側エッジの両方に C2の面取りを施してください。

【作成の条件】
立体の足し算・引き算は使わず、「断面プロファイル方式」を採用してください。
面取りが完了した状態のパイプの右半分(Z軸より右側)の2D断面図を polygon で作成し、
それを rotate_extrude で回転させて3D化するコードにしてください。

完成コード(PythonSCAD)

# ==========================================
# 面取り付きパイプ(断面プロファイル方式 / rotate_extrude)
# 作成日: 2026/08/16
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
outer_d   = 40.0
inner_d   = 25.0
length_z  = 80.0
chamfer_c = 2.0      # C2(45°想定)
fn_val    = 120      # 回転分割(滑らかさ)

# --- 派生寸法 ---
ro = outer_d / 2.0
ri = inner_d / 2.0
z0 = -length_z / 2.0
z1 =  length_z / 2.0
c  = chamfer_c

# 安全チェック(寸法的に面取りが成立する条件)
# 外側: ro - c > 0
# 内側: ri + c < ro - c (肉厚が面取りで消えない)
if ro - c <= 0 or (ri + c) >= (ro - c):
    raise ValueError("寸法が不適切です。C2面取りが成立するように外径・内径・C値を見直してください。")

# --- 2D断面(右半分: x>=0)を polygon で作成 ---
# rotate_extrude は Z軸回転。2Dの [x, y] の y が、3D化後の Z(長さ方向)になります。
# ここでは y を「Z位置」として扱い、パイプ軸を Z 方向にします。
profile_pts = [
    # 外側(下端の面取り → 外周 → 上端の面取り)
    [ro - c, z0],       # 下端面(外側面取りの終点)
    [ro,     z0 + c],   # 下端面取りの斜辺終点(外周へ)
    [ro,     z1 - c],   # 外周(直線)
    [ro - c, z1],       # 上端面(外側面取りの終点)

    # 上端面(外側→内側へ移動)
    [ri + c, z1],       # 上端面(内側面取りの終点)

    # 内側(上端の面取り → 内周 → 下端の面取り)
    [ri,     z1 - c],   # 上端内側面取りの斜辺終点(内周へ)
    [ri,     z0 + c],   # 内周(直線)
    [ri + c, z0],       # 下端面(内側面取りの終点)
    # ここから開始点 [ro - c, z0] に戻って閉じられます(明示的に同一点を繰り返さない)
]

profile_2d = polygon(profile_pts)

# --- 回転して3D化(断面プロファイル方式:足し算・引き算なし) ---
result = rotate_extrude(profile_2d, fn=fn_val)

show(result)

スクリーンショット 2026-08-22 145026.png

補足(設計の意味):

  • C2面取りは通常「45°で2mm×2mm削る」ので、断面では端面から 2mm、半径方向にも 2mm ずらした点同士を直線で結んでいます。
  • 断面の x は半径(r)y は長さ方向の位置(= 3D化後のZ) として扱っています

10. プロンプトからの作成 その3

以下のルールに沿って、外径80mm、内径40mm、長さ50mmのパイプを作成してください。
両端(上面と底面)にC3の面取りを施しますが、3D CADのセオリーに従い、外側と内側で作り方を厳密に分けてください。

外側の面取り(上面・底面):カッターで削るのではなく、パイプ本体を作る際に「円柱と円錐台(テーパー)」を足し算(+)して組み立ててください。

内側・穴の面取り(上面・底面):ストレートな貫通穴と、両端の面取り用円錐台を足し算(+)して「1つのカッターパーツ」を作り、最後に本体から引き算(-)してください。

完成コード(PythonSCAD)

# ==========================================
# C3面取り付きパイプ(外側は足し算構築/内側はカッターで一括差し引き)
# 作成日: 2026/08/22
# ==========================================

from pythonscad import *

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

chamfer_c = 3.0      # C3(45°想定なので、Z方向にも半径方向にも3mm)
fn_val    = 80
eps       = 0.1      # チラつき防止&確実なくり抜き用

r_out = outer_d / 2.0
r_in  = inner_d / 2.0

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

def create_body_pipe_outer(r_out, L, c, fn):
    """
    外形(足す形状):
    外側の面取りは「削る」のではなく、
    中央円柱 + 上下の円錐台(テーパー)を + で組み立てる。
    Z=0 を底面にして積み上げ(center=False)。
    """
    mid_h = L - 2.0 * c

    mid = translate(
        cylinder(h=mid_h, r=r_out, center=False, fn=fn),
        [0, 0, c]
    )

    bottom_ch = cylinder(h=c, r1=r_out - c, r2=r_out, center=False, fn=fn)
    top_ch = translate(
        cylinder(h=c, r1=r_out, r2=r_out - c, center=False, fn=fn),
        [0, 0, L - c]
    )

    return mid + bottom_ch + top_ch


def create_inner_cutter(r_in, L, c, fn, eps):
    """
    内側(穴)の面取りはカッターで作る:
    1) ストレート貫通穴(円柱)
    2) 上下端の面取り用の円錐台(内径が端面で広がる)
    これらを + で「1つのカッターパーツ」にまとめ、最後に一括で - する。
    """
    # 貫通穴(上下にeps分はみ出させて確実に貫通)
    straight = translate(
        cylinder(h=L + 2.0 * eps, r=r_in, center=False, fn=fn),
        [0, 0, -eps]
    )

    # 内側面取り(端面で穴が広がる形状)
    # bottom: z=0 で r_in+c → z=c で r_in
    bottom_ch = cylinder(h=c + eps, r1=r_in + c, r2=r_in, center=False, fn=fn)

    # top: z=L-c で r_in → z=L で r_in+c(上にもepsだけ延長)
    top_ch = translate(
        cylinder(h=c + eps, r1=r_in, r2=r_in + c, center=False, fn=fn),
        [0, 0, L - c]
    )

    return straight + bottom_ch + top_ch


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

body = create_body_pipe_outer(r_out, length_z, chamfer_c, fn_val)
cutter = create_inner_cutter(r_in, length_z, chamfer_c, fn_val, eps)

result = body - cutter

show(result)

スクリーンショット 2026-08-22 150108.png

ねらい(作り方を外側/内側で分ける理由)

  • 外側C面:見た目の輪郭(外形)そのものなので、最初から足し算で完成形を構築すると設計意図が明確で、寸法管理もしやすいです
  • 内側C面:穴加工は現実の加工でも「穴あけ→面取り」の順で行うため、貫通穴+面取り形状を1つのカッターにまとめて一括で引くのがブーリアン的にも安全で管理しやすいです

11. プロンプトからの作成 その4

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

完成コード(PythonSCAD)

# ==========================================
# シャープ底面 + 上面R付きブロック(部分フィレット)
# 作成日: 2026/08/22
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
width   = 100.0   # X方向
depth   = 100.0   # Y方向
height  = 50.0    # Z方向
r_fillet = 8.0    # R
fn_val  = 80      # 円・球の分割数
eps     = 0.05    # かすかな重なり(面一致回避)

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

def rounded_square_2d(w, d, r, fn):
    """
    XY断面の角R(垂直エッジR用)
    minkowski(□, ○) で「外形寸法を保ったまま」角丸四角形を作る。
    """
    core = square([w - 2 * r, d - 2 * r], center=True)
    return minkowski(core, circle(r=r, fn=fn))

def create_block_sharp_bottom_top_r(w, d, h, r, fn):
    """
    要求仕様:
    - 側面の縦エッジ(4本): R8 → XY断面を角丸にして押し出す
    - 上面外周エッジ: R8 → 全エッジRのブロックを使って上側だけ確保
    - 底面外周エッジ: 丸めない → 下側は「押し出しブロック」を足して復元
    """
    # (A) 上面Rを作るために「全エッジR」ブロック(外形100x100x50になるように縮めてからminkowski)
    all_round_center = minkowski(
        cube([w - 2 * r, d - 2 * r, h - 2 * r], center=True),
        sphere(r=r, fn=fn)
    )
    all_round_base = translate(all_round_center, [0, 0, h / 2])  # 底面をZ=0へ

    # (B) 底面をシャープに戻すための「縦エッジRだけ」の押し出しブロック(底面Z=0)
    prof = rounded_square_2d(w, d, r, fn)
    sharp_bottom = linear_extrude(prof, height=h - r + eps, center=False)

    # (C) 足し算で合成(底はシャープ、上だけRが残る)
    return all_round_base + sharp_bottom

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

show(result)

スクリーンショット 2026-08-23 190451.png

補足(設計の考え方)

  • minkowski(立方体, 球) は「上も下も全部R」になってしまうので、そのままだと底面外周も丸まります
  • そこで、底面側だけ「角丸断面の押し出し形状」を 足し算(+)で追加して、下のR部分を埋め戻し、底面外周エッジをシャープにしています

📄 ライセンスと「オープンソース」の文化について

本記事のソースコードは、すべて MIT ライセンス で公開しています。

  • 高校生のみなさんへ 🚀
    プログラミングの世界には、「自分が作った便利な仕組みをみんなに共有し、お互いに助け合って技術を発展させる(オープンソース)」という素晴らしい文化があります。このコードも、作者の名前(クレジット)さえ残してもらえれば、改造して学校の課題に使ったり、自分のアプリに組み込んだりして自由に無料で使ってOKです!
    ぜひこのコードをベースに、自分だけの新しいプログラムを作って挑戦してみてください。
  • 免責事項 ⚠️
    本記事およびコードは個人の研究・検証に基づくものであり、所属する組織の公式見解ではありません。自由に使っていただけますが、利用に伴ういかなる損害についても執筆者は責任を負いかねますので、すべて「自己責任(無保証)」の範囲内で楽しく学んでくださいね。

参考資料

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?