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?

参考サイト

上記、サンプルコードを参考に、build123d用のcq-editorを使って、実行できるように調整しました。
PythonSCADコミュニティ、CadQueryコミュニティ、build123dコミュニティ、開発者、記事執筆者に感謝申し上げます。ありがとうございます。

build123dの存在

CadQueryコミュニティから派生した後継的ライブラリで、同じOCCT(Open CASCADE Technology)カーネルであり、よりPython的な書き方(代数モード、コンテキストマネージャ)ができます。CadQueryと並べて一度触って比較する価値があります。
MaterialXを使って表示できるようで、未検証です。

build123d用のcq-editorを使う

cq-editorのfork、build123dのコードが使えます。解凍してダブルクリックです。
GUI editor based on PyQT. This fork has changes from jdegenstein to allow easier use with build123d.

CQ-editor-Windows.zip(384MB)
解凍後のフォルダ容量は、約1.15 GBになります。

**以下、コピペして実行してみてください。**CAD学習、プログラミング学習の参考になればと思います。

40 x 20 x 10 mm の箱, 貫通穴(半径3)

from build123d import *

# 40 x 20 x 10 mm の箱(既定で原点中心)
part = Box(40, 20, 10)

# 中心に直径6mmの貫通穴(半径3, 高さは十分に)
part -= Cylinder(radius=3, height=20)

show_object(part)

スクリーンショット 2026-08-14 173146.png

make_bracket

from dataclasses import dataclass
from build123d import *

@dataclass
class BracketParams:
    L: float = 40.0      # 長さ
    W: float = 20.0      # 幅
    T: float = 4.0       # 厚み
    hole_d: float = 3.4  # 取付穴径(M3ゆるめ)
    margin: float = 6.0  # 穴の端からの距離

def make_bracket(p: BracketParams):
    plate = Box(p.L, p.W, p.T)
    # 長辺方向の両端に取付穴を2つ
    x = p.L/2 - p.margin
    for sx in (-1, 1):
        plate -= Pos(sx * x, 0, 0) * Cylinder(radius=p.hole_d/2, height=p.T*2)
    # 角を丸める(Z方向の縦エッジに2mmフィレット)
    plate = fillet(plate.edges().filter_by(Axis.Z), radius=2)
    return plate

bracket = make_bracket(BracketParams())


show_object(bracket)

スクリーンショット 2026-08-14 173418.png

12. Defining an Edge with a Spline

from build123d import *

pts = [
    (55, 30),
    (50, 35),
    (40, 30),
    (30, 20),
    (20, 25),
    (10, 20),
    (0, 20),
]

with BuildPart() as ex12:
    with BuildSketch() as ex12_sk:
        with BuildLine() as ex12_ln:
            l1 = Spline(pts)
            l2 = Line((55, 30), (60, 0))
            l3 = Line((60, 0), (0, 0))
            l4 = Line((0, 0), (0, 20))
        make_face()
    extrude(amount=10)
    
show_object(ex12)

スクリーンショット 2026-08-14 175115.png

17. Mirroring From Faces

from build123d import *

a, b = 30, 20

with BuildPart() as ex17:
    with BuildSketch() as ex17_sk:
        RegularPolygon(radius=a, side_count=5)
    extrude(amount=b)
    mirror(ex17.part, about=Plane(ex17.faces().group_by(Axis.Y)[0][0]))
    
show_object(ex17)

スクリーンショット 2026-08-14 175327.png

18. Creating Placements on Faces

from build123d import *

length, width, thickness = 80.0, 60.0, 10.0
a, b = 4, 5

with BuildPart() as ex18:
    Box(length, width, thickness)
    chamfer(ex18.edges().group_by(Axis.Z)[-1], length=a)
    fillet(ex18.edges().filter_by(Axis.Z), radius=b)
    with BuildSketch(ex18.faces().sort_by(Axis.Z)[-1]):
        Rectangle(2 * b, 2 * b)
    extrude(amount=-thickness, mode=Mode.SUBTRACT)
    
show_object(ex18)

スクリーンショット 2026-08-14 175617.png

19. Locating a placement on a vertex

from build123d import *

length, thickness = 80.0, 10.0

with BuildPart() as ex19:
    with BuildSketch() as ex19_sk:
        RegularPolygon(radius=length / 2, side_count=7)
    extrude(amount=thickness)
    topf = ex19.faces().sort_by(Axis.Z)[-1]
    vtx = topf.vertices().group_by(Axis.X)[-1][0]
    vtx2Axis = Axis((0, 0, 0), (-1, -0.5, 0))
    vtx2 = topf.vertices().sort_by(vtx2Axis)[-1]
    with BuildSketch(topf) as ex19_sk2:
        with Locations((vtx.X, vtx.Y), (vtx2.X, vtx2.Y)):
            Circle(radius=length / 8)
    extrude(amount=-thickness, mode=Mode.SUBTRACT)
    
show_object(ex19)

スクリーンショット 2026-08-14 180243.png

23. Revolve

from build123d import *

pts = [
    (-25, 35),
    (-25, 0),
    (-20, 0),
    (-20, 5),
    (-15, 10),
    (-15, 35),
]

with BuildPart() as ex23:
    with BuildSketch(Plane.XZ) as ex23_sk:
        with BuildLine() as ex23_ln:
            l1 = Polyline(pts)
            l2 = Line(l1 @ 1, l1 @ 0)
        make_face()
        with Locations((0, 35)):
            Circle(25)
        split(bisect_by=Plane.ZY)
    revolve(axis=Axis.Z)
    
show_object(ex23)

スクリーンショット 2026-08-14 180438.png

24. Loft

from build123d import *

length, width, thickness = 80.0, 60.0, 10.0

with BuildPart() as ex24:
    Box(length, length, thickness)
    with BuildSketch(ex24.faces().group_by(Axis.Z)[0][0]) as ex24_sk:
        Circle(length / 3)
    with BuildSketch(ex24_sk.faces()[0].offset(length / 2)) as ex24_sk2:
        Rectangle(length / 6, width / 6)
    loft()
    
show_object(ex24)

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

25. Offset Sketch

from build123d import *

rad, offs = 50, 10

with BuildPart() as ex25:
    with BuildSketch() as ex25_sk1:
        RegularPolygon(radius=rad, side_count=5)
    with BuildSketch(Plane.XY.offset(15)) as ex25_sk2:
        RegularPolygon(radius=rad, side_count=5)
        offset(amount=offs)
    with BuildSketch(Plane.XY.offset(30)) as ex25_sk3:
        RegularPolygon(radius=rad, side_count=5)
        offset(amount=offs, kind=Kind.INTERSECTION)
    extrude(amount=1)

show_object(ex25)

スクリーンショット 2026-08-14 182016.png

AIからの回答

高校生がbuild123dを習得するとしたら、Builder modeで記述していく練習を優先したほうが良いですか。
Builder modeとAlgebra modeは、どちらもマスターするのでしょうか。混在した記述も大丈夫なのでしょうか。

どちらも「マスターする」必要はありますが、身構えるほどの二重学習ではありません。まずその構造から説明します。

2つのモードの関係

BuilderモードとAlgebraモードは、別々の言語ではなく同じ部品(Box、Cylinder、Plane、セレクタ…)を組み合わせる作法が2通りあるだけです。学習量の9割は共通で、違うのは「合成のさせ方」だけです。

  • Algebraモード: 結果を自分で変数に持ち+ - & で明示的に合成する。隠れた状態がゼロ
  • Builderモード: with BuildPart() という文脈(コンテキスト)が結果を自動で受け取りmode=Mode.SUBTRACT で合成方法を指定する

つまり、前回の「暗黙の状態を避ける」という観点でいうと、実はBuilderモードのほうが暗黙性が高いのです。Box(…)と書くだけで囲んでいるビルダーに自動追加される——これは便利ですが、初学者には「どこにも代入していないのに、なぜ形が増えるのか」という魔法に見えます。Algebraモードの ex2 = Box(…)ex2 -= Cylinder(…) は、変数への代入と演算というPythonの授業でそのまま説明できる形をしています。

混在は大丈夫か

公式に認められた使い方で、実務上も普通に行われます。橋渡しはシンプルで、ビルダーの結果はex2.partex2.sketchで取り出せばAlgebraの世界のオブジェクトになり、逆にAlgebraで作ったオブジェクトはビルダー内でadd(obj)すれば文脈に取り込めます。よくあるのは「複雑な2DスケッチだけBuilderで組み、立体の足し引きはAlgebraで書く」という折衷です。

ただし教材の中では混在を推奨しないことをお勧めします。技術的に安全でも、生徒には「2つのルールがいつ切り替わるのか」という認知負荷になります。単元ごとにどちらかに統一し、両者の接続は上級者向けに1例だけ見せる、が良い塩梅だと思います。

高校生はどちらを優先すべきか

前回の提案と同じ結論になりますが、理由を今回の例に即して言うと——Algebraモードから入るべきだと考えます。

第一に、PythonSCADからの移行コストがほぼゼロです。difference()で引いていた頭のまま-=で引けます。生徒は「新しいCADを覚える」のではなく「同じ考え方が厳密曲面でも通じる」ことを体験します。

第二に、デバッグと読解の教育効果です。Algebraモードは各段階が変数なので、show_object(step1)と途中経過を確かめながら進めます。「動かして、見て、直す」というプログラミング教育の基本ループがそのまま回ります。

では、Builderモードはいつ要るのか。スケッチ駆動の設計と配置の単元からです。BuildSketchで輪郭を描いて押し出す、GridLocationsで穴を並べる——先日のL字フックのような課題はBuilderモードの独壇場で、しかもこの「スケッチ→フィーチャー」という手順はFusion 360やSolidWorksの操作モデルそのものです。つまり、

  1. Algebraモード——CSG的な立体の組み合わせ(PythonSCADの続きとして)
  2. Builderモード——スケッチ・配置・穴あけ(市販CADへの橋渡しとして)

という役割分担で両方に到達する、と設計すれば「どちらもマスター」が自然に達成されます。優先順位というより、**Algebraが入口、Builderが出口(進路接続)**という一本の道です。

導入のつなぎとしては、同じ「箱から円筒を引く」をPythonSCAD版・Algebra版・Builder版の3並びで見せる1枚が効くと思います。生徒は3つの書き方が同じ意味であることを一目で理解し、「書き方は道具、考え方が本体」という先生のメッセージがそのまま伝わります。

PythonSCADでは、.でつなぐメソッドチェーンがありますが、Algebraモードも同じでしょうか。

はい、同じ感覚で使えます。ただし「チェーン」と呼ばれるものには2種類あって、その区別が今回の一連の話の核心なので、整理してお答えします。

2種類のメソッドチェーン

PythonSCADの cube(...).translate(...).rotate(...) は、完成した立体に変換を掛けると、新しい立体が返ってくるという連鎖です。各段階の値はどこで切っても完全な立体で、途中を変数に受ければいつでも確認できます。

build123dのAlgebraモードもこれと同じ性質を持っています。すべての形状はただのPythonオブジェクトなので、変換メソッドが新しい形状を返し、ドットでつなげます。

part = Box(10, 20, 5).rotate(Axis.Z, 45).moved(Location((30, 0, 0)))

これはPythonSCADのチェーンと完全に同型で、途中で切って step1 = Box(10, 20, 5).rotate(Axis.Z, 45) と受けても意味は変わりません。

一方、CadQueryのWorkplaneチェーンは見た目は似ていても別物です。各段階が「立体」ではなく「作業平面スタック+保留中のワイヤ+累積した原点移動」という見えない作業状態を運んでいて、途中で切ると意味が変わることがあります。L字フックでずれた原因はこれでした。つまり——チェーンという書き方自体は問題ではなく、チェーンが運んでいるものが「値」か「状態」かが問題だった、というのが正確な整理です。PythonSCADとbuild123d Algebraは前者、CadQueryは後者です。

Algebraモードにはもう一つの書き方がある

build123dらしい流儀として、変換を掛け算演算子で書く方法もあります。

part = Pos(30, 0, 0) * Rot(Z=45) * Box(10, 20, 5)

数学の変換行列と同じく右から左に適用されます(まず45度回し、それから移動)。メソッドチェーンは左から右に読むので、実は適用順の読み方が逆になります。どちらも正しいAlgebraモードですが、教材では最初どちらかに統一したほうが混乱がありません。

高校生向けには、まずメソッドチェーン(または1行1変数の逐次代入)からをお勧めします。PythonSCADで既に馴染んだ読み方と一致し、「左から順に起きる」ので実行順が直感と合います。Pos * Rot * 形状の演算子スタイルは、数学の授業で行列や写像の合成に触れる頃に「実はこう書くと数学と同じ形になる」と見せると、プログラミングと数学がつながる良い教材になります——書き方が2つあること自体を、合成の順序を考えさせる教材に転用できるわけです。

参考資料

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?