0
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コードとして新たに再構築したものです。
素敵な知見を共有してくださった作者様に深く感謝いたします。
ありがとうございます。

  • 器生成、便利です。ありがとうございます。

  • PythonSCADでスライドバーの使い方

01. 丸みを帯びた星形トレイ

断面 丸みを帯びた星形

ねじり
0°

形
縁の広がり
0.12

寸法
半径
60mm

縁の高さ
19mm

肉厚
2.6mm

幅
164mm
高さ
19mm

scale=[1.3, 1.3] のように明示的に指定してください。

linear_extrude()scale を数値だけではなく、
scale=[1.12, 1.12] のように X方向・Y方向を明示する形式に修正します。

scale=[outer_scale, outer_scale]

という形にしています。


1. 完成コード(PythonSCAD)

# ==========================================
# 丸みを帯びた星形トレイ
# 作成日: 2026/08/29
# ==========================================

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

# --- パラメータ設定 (単位: mm) ---
width            = 164.0   # トレイ上端の最大幅
rim_height       = 19.0    # 縁の高さ
wall_thickness   = 2.6     # 肉厚
valley_radius    = 60.0    # 星形の谷側半径
rim_flare        = 0.12    # 縁の広がり率 0.12 = 12%広がる
twist_angle      = 0.0     # ねじり角度
star_points      = 5       # 星形の山の数
samples_per_lobe = 24      # 1つの山あたりの分割数
fn_val           = 80      # 円・曲線の滑らかさ
eps              = 0.1     # チラつき防止用微小値

# --- 寸法計算 ---
top_peak_radius = width / 2.0
top_valley_radius = valley_radius

# 縁の広がりを倍率に変換
outer_scale = 1.0 + rim_flare
outer_scale_xy = [outer_scale, outer_scale]

# linear_extrude の scale で上端を広げるため、
# 底面側の半径は上端半径を scale で割っておく
bottom_peak_radius = top_peak_radius / outer_scale
bottom_valley_radius = top_valley_radius / outer_scale

# 内側くり抜き用寸法
inner_bottom_peak_radius = bottom_peak_radius - wall_thickness
inner_bottom_valley_radius = bottom_valley_radius - wall_thickness

inner_top_peak_radius = top_peak_radius - wall_thickness

# 内側の上端も肉厚を保つように広げる
inner_scale = inner_top_peak_radius / inner_bottom_peak_radius
inner_scale_xy = [inner_scale, inner_scale]

floor_thickness = wall_thickness


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

def create_rounded_star_points(peak_r, valley_r, lobes, samples):
    """
    丸みを帯びた星形の2D点群を作る関数。
    cos波で半径をなめらかに変化させる。
    polygon用の点は [x, y] のリスト形式にする。
    """
    pts = []
    total_samples = lobes * samples

    for i in range(total_samples):
        theta = 2.0 * pi * i / total_samples

        wave = 0.5 + 0.5 * cos(lobes * theta)
        r = valley_r + (peak_r - valley_r) * wave

        x = r * cos(theta)
        y = r * sin(theta)

        pts.append([x, y])

    return pts


def create_star_2d(peak_r, valley_r):
    """丸みを帯びた星形の2D断面を作る"""
    pts = create_rounded_star_points(
        peak_r,
        valley_r,
        star_points,
        samples_per_lobe
    )

    return polygon(pts)


def create_outer_body():
    """
    トレイの外形を作る。
    scale は [X方向倍率, Y方向倍率] で明示する。
    """
    outer_2d = create_star_2d(
        bottom_peak_radius,
        bottom_valley_radius
    )

    body = linear_extrude(
        outer_2d,
        height=rim_height,
        twist=twist_angle,
        scale=outer_scale_xy
    )

    return body


def create_cavity_cutter():
    """
    内側をくり抜くカッターを作る。
    底板を wall_thickness 分だけ残す。
    """
    inner_2d = create_star_2d(
        inner_bottom_peak_radius,
        inner_bottom_valley_radius
    )

    cavity = linear_extrude(
        inner_2d,
        height=rim_height - floor_thickness + eps,
        twist=twist_angle,
        scale=inner_scale_xy
    )

    cavity = translate(
        cavity,
        [0, 0, floor_thickness]
    )

    return cavity


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

# 1. 外形とカッターを作成
body = create_outer_body()
cutter = create_cavity_cutter()

# 2. 一括くり抜き
tray = body - cutter

# 3. 色をつける
result = color(tray, "peachpuff")

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

スクリーンショット 2026-08-29 235141.png


変更点はここです。

outer_scale_xy = [outer_scale, outer_scale]

そして linear_extrude() 内で、

scale=outer_scale_xy

としています。

つまり、内部的には今回、

scale=[1.12, 1.12]

として処理されます。

02. 六角形トレイ(縁が広がるタイプ)

linear_extrudescale を数値ではなく、scale=[1.24, 1.24] のように X方向・Y方向を明示したリスト指定に変更します。

1. 完成コード(PythonSCAD)

# ==========================================
# 六角形トレイ(縁が広がるタイプ)
# 作成日: 2026/08/29
# ==========================================

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

# --- パラメータ設定 (単位: mm) ---
base_radius      = 66.0    # 底側の六角形の半径(中心から頂点まで)
flare_ratio      = 0.24    # 縁の広がり率(24%)
tray_height      = 30.0    # トレイ高さ
wall_thickness   = 2.6     # 肉厚
bottom_thickness = 2.6     # 底の厚み

fn_val           = 6       # 六角形
eps              = 0.1     # チラつき防止用微小値

# --- 計算値 ---
top_radius = base_radius * (1.0 + flare_ratio)

inner_base_radius = base_radius - wall_thickness
inner_top_radius  = top_radius - wall_thickness

outer_scale_x = top_radius / base_radius
outer_scale_y = top_radius / base_radius

inner_scale_x = inner_top_radius / inner_base_radius
inner_scale_y = inner_top_radius / inner_base_radius


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

def create_hex_points(radius):
    """原点中心の六角形の頂点リストを作る"""
    points = []

    for i in range(6):
        angle = pi / 6 + i * 2 * pi / 6
        x = radius * cos(angle)
        y = radius * sin(angle)
        points.append([x, y])

    return points


def create_hex_2d(radius):
    """2Dの六角形を作る"""
    pts = create_hex_points(radius)
    return polygon(pts)


def create_outer_body():
    """外側の広がる六角トレイ形状を作る"""
    base_hex = create_hex_2d(base_radius)

    outer = linear_extrude(
        base_hex,
        height=tray_height,
        scale=[outer_scale_x, outer_scale_y]
    )

    return outer


def create_inner_cutter():
    """内側をくり抜くためのカッターを作る"""
    inner_hex = create_hex_2d(inner_base_radius)

    cutter_height = tray_height - bottom_thickness + 2 * eps

    cutter = linear_extrude(
        inner_hex,
        height=cutter_height,
        scale=[inner_scale_x, inner_scale_y]
    )

    # 底板を残すため、カッターを底厚ぶん上に移動
    cutter = translate(cutter, [0, 0, bottom_thickness])

    return cutter


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

body = create_outer_body()
cutter = create_inner_cutter()

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

show(result)

スクリーンショット 2026-08-29 235513.png

03. 丸みを帯びた星形トレイ

1. 完成コード(PythonSCAD)

# ==========================================
# 丸みを帯びた星形トレイ
# 作成日: 2026/08/29
# ==========================================

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

# --- パラメータ設定 (単位: mm) ---
tray_width        = 164.0   # 外接幅(星形の頂点から頂点)
star_valley_r     = 60.0    # 星形の谷側半径
rim_height        = 19.0    # 縁の高さ
wall_thickness    = 2.6     # 肉厚
bottom_thickness  = 2.6     # 底の厚み
rim_flare         = 0.12    # 縁の広がり(0.12 = 上に行くほど12%広がる)
star_count        = 5       # 星の山の数
corner_round_r    = 8.0     # 星形の丸み量
fn_val            = 80      # 円弧のなめらかさ
eps               = 0.1     # チラつき防止用微小値

# --- 派生寸法 ---
top_scale = 1.0 + rim_flare

# scale は [X方向, Y方向] のリストで明示する
outer_scale = [top_scale, top_scale]

# 上面での外側の頂点半径
outer_top_tip_r = tray_width / 2.0

# linear_extrude の scale で上に向かって広げるため、
# 底面側の半径は top_scale で割っておく
outer_bottom_tip_r    = outer_top_tip_r / top_scale
outer_bottom_valley_r = star_valley_r / top_scale

# 内側カッターの広がり率
# 上面でおおよそ肉厚 wall_thickness が残るようにする
inner_scale_value = (outer_top_tip_r - wall_thickness) / (outer_bottom_tip_r - wall_thickness)

# 内側カッターも [X方向, Y方向] のリストで明示する
inner_scale = [inner_scale_value, inner_scale_value]


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

def create_star_points(tip_r, valley_r, count):
    """星形の2D点群を作成する"""
    points = []

    for i in range(count * 2):
        angle = pi / 2.0 + i * pi / count

        if i % 2 == 0:
            r = tip_r
        else:
            r = valley_r

        x = r * cos(angle)
        y = r * sin(angle)
        points.append([x, y])

    return points


def create_rounded_star_2d(tip_r, valley_r, count, round_r):
    """角を丸めた星形2D形状を作成する"""
    pts = create_star_points(tip_r, valley_r, count)
    raw_star = polygon(points=pts)

    # 3段階オフセットで外側・内側の角を丸める
    rounded_star = offset(
        offset(
            offset(raw_star, r=round_r),
            r=-2.0 * round_r
        ),
        r=round_r
    )

    return rounded_star


def create_outer_body():
    """トレイ外形を作成する"""
    outer_2d = create_rounded_star_2d(
        outer_bottom_tip_r,
        outer_bottom_valley_r,
        star_count,
        corner_round_r
    )

    # scale=[1.12, 1.12] のように明示的に指定
    outer_body = linear_extrude(
        outer_2d,
        height=rim_height,
        scale=outer_scale
    )

    return outer_body


def create_cavity_cutter():
    """トレイ内側をくり抜くカッターを作成する"""
    outer_2d = create_rounded_star_2d(
        outer_bottom_tip_r,
        outer_bottom_valley_r,
        star_count,
        corner_round_r
    )

    # 肉厚分だけ内側にオフセットして内側形状を作る
    inner_2d = offset(outer_2d, r=-wall_thickness)

    # 底板を残すため、底厚みより上だけを削る
    cavity_height = rim_height - bottom_thickness + eps

    # 内側カッターも scale=[..., ...] の形式で指定
    cavity = linear_extrude(
        inner_2d,
        height=cavity_height,
        scale=inner_scale
    )

    cavity = translate(cavity, [0, 0, bottom_thickness])

    return cavity


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

# 1. 本体とカッターの生成
body = create_outer_body()
cutter = create_cavity_cutter()

# 2. 一括くり抜き
result = body - cutter

# 3. 色付け
result = color(result, "lightcoral")

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

スクリーンショット 2026-08-29 235924.png


04. 花形トレイ

トレイ

標準

断面

花

形
縁の広がり
0.30

寸法
半径
70mm

縁の高さ
22mm

肉厚
2.4mm

幅
226mm
高さ
22mm

1. 完成コード(PythonSCAD)

# ==========================================
# 花形トレイ
# 作成日: 2026/08/29
# ==========================================

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

# --- パラメータ設定 (単位: mm) ---

# 全体寸法
top_width          = 226.0   # 上端の最大幅
tray_height        = 22.0    # 縁の高さ
wall_thickness     = 2.4     # 肉厚
bottom_thickness   = 2.4     # 底の厚み

# 花形断面
valley_radius_top  = 70.0    # 花形の谷部分の上端半径
petal_count        = 8       # 花びらの数

# 縁の広がり
rim_flare          = 0.30
top_scale_value    = 1.0 + rim_flare
top_scale_xy       = [top_scale_value, top_scale_value]

# 精度・表示
point_count        = petal_count * 32
fn_val             = 80
eps                = 0.1
tray_color         = "lightpink"


# --- 関数定義 ---

def create_flower_profile(max_radius, valley_radius, petals, points):
    """
    上から見た花形の2D輪郭を作る。
    max_radius    : 花びら先端の半径
    valley_radius : 花びらの谷部分の半径
    """
    mean_radius = (max_radius + valley_radius) / 2.0
    wave_radius = (max_radius - valley_radius) / 2.0

    pts = []

    for i in range(points):
        theta = 2.0 * pi * i / points

        # 花びら形状
        r = mean_radius + wave_radius * cos(petals * theta)

        x = r * cos(theta)
        y = r * sin(theta)

        pts.append([x, y])

    return polygon(points=pts)


def create_outer_body():
    """
    外側本体を作る。
    底面を小さく作り、上面へ向かって scale=[1.3, 1.3] で広げる。
    """
    top_max_radius = top_width / 2.0

    bottom_max_radius = top_max_radius / top_scale_value
    bottom_valley_radius = valley_radius_top / top_scale_value

    outer_profile = create_flower_profile(
        bottom_max_radius,
        bottom_valley_radius,
        petal_count,
        point_count
    )

    outer_body = linear_extrude(
        outer_profile,
        height=tray_height,
        scale=top_scale_xy
    )

    return outer_body


def create_inner_cutter():
    """
    トレイ内側をくり抜くためのカッター。
    外側と同じように scale=[1.3, 1.3] で上に広げる。
    """
    top_outer_max_radius = top_width / 2.0

    top_inner_max_radius = top_outer_max_radius - wall_thickness
    top_inner_valley_radius = valley_radius_top - wall_thickness

    bottom_inner_max_radius = top_inner_max_radius / top_scale_value
    bottom_inner_valley_radius = top_inner_valley_radius / top_scale_value

    inner_profile = create_flower_profile(
        bottom_inner_max_radius,
        bottom_inner_valley_radius,
        petal_count,
        point_count
    )

    cavity_height = tray_height - bottom_thickness

    # 上面を確実に突き抜けさせるため eps を追加
    inner_cutter = linear_extrude(
        inner_profile,
        height=cavity_height + eps,
        scale=top_scale_xy
    )

    inner_cutter = translate(
        inner_cutter,
        [0, 0, bottom_thickness]
    )

    return inner_cutter


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

# 1. 外側本体
body = create_outer_body()

# 2. 内側くり抜きカッター
cutter = create_inner_cutter()

# 3. 一括ブーリアンでくり抜き
tray = body - cutter

# 4. 色付け
result = color(tray, tray_color)

# 5. 表示
show(result)

スクリーンショット 2026-08-30 000241.png


修正ポイント

今回の重要な変更点はここです。

scale=top_scale_xy

つまり、

scale=[1.3, 1.3]

として、X方向・Y方向の拡大率を明示しました。

これにより、底面より上面が30%広がるトレイになります。
断面で見ると、側面が垂直ではなく、外側へ少し開いた形になります。


05. 深型・円形トレイ(縁広がりタイプ)

トレイ

深型
断面

円

形
縁の広がり
0.35
scale=[1.35, 1.35] のように明示的に指定してください。

寸法
半径
60mm

縁の高さ
40mm

肉厚
2.6mm

幅
162mm
高さ
40mm

1. 完成コード(PythonSCAD)

# ==========================================
# 深型・円形トレイ(縁広がりタイプ)
# 作成日: 2026/08/29
# ==========================================

from pythonscad import *

# --- パラメータ設定 (単位: mm) ---
bottom_radius      = 60.0     # 底面側の半径
tray_height        = 40.0     # トレイの高さ
wall_thickness     = 2.6      # 肉厚
rim_spread         = 0.35     # 縁の広がり率
outer_scale        = [1.35, 1.35]  # 縁の広がりを明示指定
fn_val             = 120      # 円のなめらかさ
eps                = 0.1      # Zファイティング防止用

# --- 寸法計算 ---
top_radius         = bottom_radius * outer_scale[0]  # 60 * 1.35 = 81mm
top_width          = top_radius * 2                  # 162mm

inner_bottom_radius = bottom_radius - wall_thickness
inner_top_radius    = top_radius - wall_thickness

inner_height = tray_height - wall_thickness + 2 * eps
inner_scale_value = inner_top_radius / inner_bottom_radius
inner_scale = [inner_scale_value, inner_scale_value]

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

def create_outer_body():
    """外側の深型トレイ形状を作る"""
    base_circle = circle(r=bottom_radius, fn=fn_val)

    outer = linear_extrude(
        base_circle,
        height=tray_height,
        scale=outer_scale
    )

    return outer


def create_inner_cutter():
    """内側をくり抜くためのカッターを作る"""
    inner_circle = circle(r=inner_bottom_radius, fn=fn_val)

    cutter = linear_extrude(
        inner_circle,
        height=inner_height,
        scale=inner_scale
    )

    # 底の厚み wall_thickness を残し、上方向に少し突き抜けさせる
    cutter = translate(cutter, [0, 0, wall_thickness])

    return cutter


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

# 1. 外形とカッターを作成
outer_body = create_outer_body()
inner_cutter = create_inner_cutter()

# 2. 一括くり抜き
tray = outer_body - inner_cutter

# 3. 表示
show(tray)

スクリーンショット 2026-08-30 001642.png

2. モデルの内容

  • 底面半径:60mm
  • 上端半径:60 × 1.35 = 81mm
  • 上端の幅:162mm
  • 高さ:40mm
  • 肉厚:2.6mm
  • 縁の広がり:scale=[1.35, 1.35] として明示指定

このコードでは、まず円を高さ方向に押し出しながら広げて、深型の外形を作っています。
そのあと、少し小さい円を同じように押し出した「カッター」で中をくり抜き、底付きの円形トレイにしています。

06. 星形ねじれ

# ==========================================
# 星形ねじり植木鉢
# 作成日: 2026/08/30
# ==========================================

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

# --- パラメータ設定 (単位: mm) ---
pot_height       = 100.0   # 植木鉢の高さ(Z方向)
bottom_diameter  = 45.0    # 下側の外径(星の先端どうし)
taper_scale      = [1.33, 1.33]  # 上方向への広がり倍率(X, Y)

wall_thickness   = 3.0     # 肉厚
bottom_thickness = 3.0     # 底の厚み
drain_hole_r     = 6.0     # 水抜き穴の半径

star_points      = 5       # 星の突起数
star_inner_ratio = 0.75    # 星の谷の深さ比率
twist_angle      = 275.0   # ねじり角度(度)

fn_val           = 80      # 円柱などの分割数
eps              = 0.1     # ブーリアン演算のチラつき防止

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

def create_star_2d(outer_r, inner_ratio, points):
    """
    星形の2D断面を作る。
    outer_r: 星の先端半径
    inner_ratio: 谷部分の半径比率
    points: 星の突起数
    """
    pts = []
    inner_r = outer_r * inner_ratio

    for i in range(points * 2):
        angle = pi / 2 + i * pi / points

        if i % 2 == 0:
            r = outer_r
        else:
            r = inner_r

        x = r * cos(angle)
        y = r * sin(angle)
        pts.append([x, y])

    return polygon(pts)


def create_outer_body():
    """
    外側の植木鉢本体を作る。
    下側45mmから、scale=[1.33, 1.33]で上に広がりながら275度ねじる。
    """
    bottom_outer_r = bottom_diameter / 2.0

    base_star = create_star_2d(
        bottom_outer_r,
        star_inner_ratio,
        star_points
    )

    outer_body = linear_extrude(
        base_star,
        height=pot_height,
        twist=twist_angle,
        scale=taper_scale
    )

    return outer_body


def create_inner_cavity():
    """
    内側の空洞を作るカッター。
    外形と同じく scale=[1.33, 1.33] で広がる。
    底を残すため、bottom_thicknessぶん上に配置する。
    """
    inner_bottom_diameter = bottom_diameter - 2.0 * wall_thickness
    inner_bottom_r = inner_bottom_diameter / 2.0

    inner_star = create_star_2d(
        inner_bottom_r,
        star_inner_ratio,
        star_points
    )

    cavity_height = pot_height - bottom_thickness + eps

    cavity = linear_extrude(
        inner_star,
        height=cavity_height,
        twist=twist_angle,
        scale=taper_scale
    )

    cavity = translate(cavity, [0, 0, bottom_thickness])

    return cavity


def create_drain_hole():
    """
    底面中央の水抜き穴カッター。
    Z方向に少し長めにして、確実に貫通させる。
    """
    hole_h = bottom_thickness + 2.0 * eps

    hole = cylinder(
        h=hole_h,
        r=drain_hole_r,
        center=True,
        fn=fn_val
    )

    hole = translate(hole, [0, 0, bottom_thickness / 2.0])

    return hole


def create_cutters():
    """
    くり抜き用カッターをまとめる。
    空洞と水抜き穴を + で1つのカッターにしてから、一括で引き算する。
    """
    cavity = create_inner_cavity()
    drain  = create_drain_hole()

    cutters = cavity + drain

    return cutters


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

# 1. 外側本体
body = create_outer_body()

# 2. 内側空洞と水抜き穴
cutters = create_cutters()

# 3. 一括くり抜き
result = body - cutters

# 4. 植木鉢らしい色を付ける
result = color(result, "sienna")

# 5. 表示
show(result)

スクリーンショット 2026-08-30 210349.png

08. ねじれ植木鉢、改善版

「ねじれがカクカクで粗くなってしまう」という問題
これは、3D CADが立体を押し出すときの
「スライス(層の数)」が足りていないことが原因です。

💡 なぜカクカクになるの?

linear_extrude は、2Dの図形を底面から上に向かって「地層」や「スライスチーズ」のように何枚も重ねて立体を作ります。
ねじり(twist)を入れる場合、この「重なる枚数(スライス数)」が少ないと、1枚ごとのねじれ角度が大きくなり、階段のようにカクカクした見た目になってしまうのです。

🔧 解決方法

linear_extrude 関数には、Z方向の分割数を指定できる slices という隠しパラメータがあります。
これを追加して、細かくスライスしてあげれば、驚くほど滑らかになりますよ!

コードの冒頭に slices_val = 150 という変数を追加し、2箇所の linear_extrudeslices=slices_val を渡すように修正しました。


1. 完成コード(PythonSCAD)

# ==========================================
# 星形ねじり植木鉢(滑らかさ改善版)
# 作成日: 2026/09/04
# ==========================================

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

# --- パラメータ設定 (単位: mm) ---
pot_height       = 100.0   # 植木鉢の高さ(Z方向)
bottom_diameter  = 45.0    # 下側の外径(星の先端どうし)
taper_scale      = [1.33, 1.33]  # 上方向への広がり倍率(X, Y)

wall_thickness   = 3.0     # 肉厚
bottom_thickness = 3.0     # 底の厚み
drain_hole_r     = 6.0     # 水抜き穴の半径

star_points      = 5       # 星の突起数
star_inner_ratio = 0.75    # 星の谷の深さ比率
twist_angle      = 115.0   # ねじり角度(度)

fn_val           = 80      # 円柱などの分割数
slices_val       = 150     # ねじれの滑らかさ(Z方向のスライス数)
eps              = 0.1     # ブーリアン演算のチラつき防止

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

def create_star_2d(outer_r, inner_ratio, points):
    """
    星形の2D断面を作る。
    outer_r: 星の先端半径
    inner_ratio: 谷部分の半径比率
    points: 星の突起数
    """
    pts = []
    inner_r = outer_r * inner_ratio

    for i in range(points * 2):
        angle = pi / 2 + i * pi / points

        if i % 2 == 0:
            r = outer_r
        else:
            r = inner_r

        x = r * cos(angle)
        y = r * sin(angle)
        pts.append([x, y])

    return polygon(pts)


def create_outer_body():
    """
    外側の植木鉢本体を作る。
    下側45mmから、scale=[1.33, 1.33]で上に広がりながら275度ねじる。
    slices を指定することでねじれを滑らかにする。
    """
    bottom_outer_r = bottom_diameter / 2.0

    base_star = create_star_2d(
        bottom_outer_r,
        star_inner_ratio,
        star_points
    )

    outer_body = linear_extrude(
        base_star,
        height=pot_height,
        twist=twist_angle,
        scale=taper_scale,
        slices=slices_val  # ★ここでスライス数を指定!
    )

    return outer_body


def create_inner_cavity():
    """
    内側の空洞を作るカッター。
    外形と同じく scale=[1.33, 1.33] で広がり、slices で滑らかにねじる。
    底を残すため、bottom_thicknessぶん上に配置する。
    """
    inner_bottom_diameter = bottom_diameter - 2.0 * wall_thickness
    inner_bottom_r = inner_bottom_diameter / 2.0

    inner_star = create_star_2d(
        inner_bottom_r,
        star_inner_ratio,
        star_points
    )

    cavity_height = pot_height - bottom_thickness + eps

    cavity = linear_extrude(
        inner_star,
        height=cavity_height,
        twist=twist_angle,
        scale=taper_scale,
        slices=slices_val  # ★カッター側も同じスライス数を指定!
    )

    cavity = translate(cavity, [0, 0, bottom_thickness])

    return cavity


def create_drain_hole():
    """
    底面中央の水抜き穴カッター。
    Z方向に少し長めにして、確実に貫通させる。
    """
    hole_h = bottom_thickness + 2.0 * eps

    hole = cylinder(
        h=hole_h,
        r=drain_hole_r,
        center=True,
        fn=fn_val
    )

    hole = translate(hole, [0, 0, bottom_thickness / 2.0])

    return hole


def create_cutters():
    """
    くり抜き用カッターをまとめる。
    空洞と水抜き穴を + で1つのカッターにしてから、一括で引き算する。
    """
    cavity = create_inner_cavity()
    drain  = create_drain_hole()

    cutters = cavity + drain

    return cutters


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

# 1. 外側本体
body = create_outer_body()

# 2. 内側空洞と水抜き穴
cutters = create_cutters()

# 3. 一括くり抜き
result = body - cutters

# 4. 植木鉢らしい色を付ける
result = color(result, "sienna")

# 5. 表示
show(result)

スクリーンショット 2026-09-04 160327.png


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

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

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

参考資料

0
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
0
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?