mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-06 02:30:55 -08:00
Adding Stud Wall & Platonic Solids examples
This commit is contained in:
parent
ef7358e252
commit
72827ff999
5 changed files with 347 additions and 7 deletions
BIN
docs/assets/examples/platonic_solids.png
Normal file
BIN
docs/assets/examples/platonic_solids.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
BIN
docs/assets/examples/stud_wall.png
Normal file
BIN
docs/assets/examples/stud_wall.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
|
|
@ -8,7 +8,7 @@ The build123d Examples
|
||||||
Overview
|
Overview
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
In the GitHub repository you will find an `examples folder <https://github.com/42sol-eu/build123d/tree/examples>`_
|
In the GitHub repository you will find an `examples folder <https://github.com/42sol-eu/build123d/tree/examples>`_.
|
||||||
|
|
||||||
Most of the examples show the builder and algebra modes.
|
Most of the examples show the builder and algebra modes.
|
||||||
|
|
||||||
|
|
@ -39,18 +39,26 @@ Most of the examples show the builder and algebra modes.
|
||||||
:link: examples-build123d_logo
|
:link: examples-build123d_logo
|
||||||
:link-type: ref
|
:link-type: ref
|
||||||
|
|
||||||
|
|
||||||
.. grid-item-card:: Circuit Board With Holes |Builder| |Algebra|
|
.. grid-item-card:: Circuit Board With Holes |Builder| |Algebra|
|
||||||
:img-top: assets/examples/thumbnail_canadian_flag_01.png
|
:img-top: assets/examples/thumbnail_circuit_board_01.png
|
||||||
:link: examples-canadian_flag
|
:link: examples-canadian_flag
|
||||||
:link-type: ref
|
:link-type: ref
|
||||||
|
|
||||||
|
|
||||||
.. grid-item-card:: Canadian Flag Blowing in The Wind |Builder| |Algebra|
|
.. grid-item-card:: Canadian Flag Blowing in The Wind |Builder| |Algebra|
|
||||||
:img-top: assets/examples/thumbnail_circuit_board_01.png
|
:img-top: assets/examples/thumbnail_canadian_flag_01.png
|
||||||
:link: examples-circuit_board
|
:link: examples-circuit_board
|
||||||
:link-type: ref
|
:link-type: ref
|
||||||
|
|
||||||
|
.. grid-item-card:: Stud Wall |Algebra|
|
||||||
|
:img-top: assets/examples/stud_wall.png
|
||||||
|
:link: stud_wall
|
||||||
|
:link-type: ref
|
||||||
|
|
||||||
|
.. grid-item-card:: Platonic Solids |Algebra|
|
||||||
|
:img-top: assets/examples/platonic_solids.png
|
||||||
|
:link: platonic_solids
|
||||||
|
:link-type: ref
|
||||||
|
|
||||||
.. NOTE 01: insert new example thumbnails above this line
|
.. NOTE 01: insert new example thumbnails above this line
|
||||||
|
|
||||||
.. TODO: Copy this block to add the example thumbnails here
|
.. TODO: Copy this block to add the example thumbnails here
|
||||||
|
|
@ -71,7 +79,8 @@ Low Poly Benchy
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
|
|
||||||
The Benchy examples shows hot to import a STL model as a `Solid` object with the class `Mesher` and change it to low poly.
|
The Benchy examples shows how to import a STL model as a `Solid` object with the class `Mesher` and
|
||||||
|
modify it by replacing chimney with a BREP version.
|
||||||
|
|
||||||
.. note
|
.. note
|
||||||
|
|
||||||
|
|
@ -240,6 +249,49 @@ This example demonstrates placing holes around a part.
|
||||||
:start-after: [Code]
|
:start-after: [Code]
|
||||||
:end-before: [End]
|
:end-before: [End]
|
||||||
|
|
||||||
|
.. _stud_wall:
|
||||||
|
|
||||||
|
Stud Wall
|
||||||
|
---------
|
||||||
|
.. image:: assets/examples/stud_wall.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
This example demonstrates creatings custom `Part` objects and putting them into
|
||||||
|
assemblies. The custom object is a `Stud` used in the building industry while
|
||||||
|
the assembly is a `StudWall` created from copies of `Stud` objects for efficiency.
|
||||||
|
Both the `Stud` and `StudWall` objects use `RigidJoints` to define snap points which
|
||||||
|
are used to position all of objects.
|
||||||
|
|
||||||
|
.. dropdown:: |Algebra| Reference Implementation (Algebra Mode)
|
||||||
|
|
||||||
|
.. literalinclude:: ../examples/stud_wall.py
|
||||||
|
:start-after: [Code]
|
||||||
|
:end-before: [End]
|
||||||
|
|
||||||
|
.. _platonic_solids:
|
||||||
|
|
||||||
|
Platonic Solids
|
||||||
|
---------------
|
||||||
|
.. image:: assets/examples/platonic_solids.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
This example creates a custom Part object PlatonicSolid.
|
||||||
|
|
||||||
|
Platonic solids are five three-dimensional shapes that are highly symmetrical,
|
||||||
|
known since antiquity and named after the ancient Greek philosopher Plato.
|
||||||
|
These solids are unique because their faces are congruent regular polygons,
|
||||||
|
with the same number of faces meeting at each vertex. The five Platonic solids
|
||||||
|
are the tetrahedron (4 triangular faces), cube (6 square faces), octahedron
|
||||||
|
(8 triangular faces), dodecahedron (12 pentagonal faces), and icosahedron
|
||||||
|
(20 triangular faces). Each solid represents a unique way in which identical
|
||||||
|
polygons can be arranged in three dimensions to form a convex polyhedron,
|
||||||
|
embodying ideals of symmetry and balance.
|
||||||
|
|
||||||
|
.. dropdown:: |Algebra| Reference Implementation (Algebra Mode)
|
||||||
|
|
||||||
|
.. literalinclude:: ../examples/platonic_solids.py
|
||||||
|
:start-after: [Code]
|
||||||
|
:end-before: [End]
|
||||||
|
|
||||||
.. NOTE 02: insert new example thumbnails above this line
|
.. NOTE 02: insert new example thumbnails above this line
|
||||||
|
|
||||||
|
|
|
||||||
140
examples/platonic_solids.py
Normal file
140
examples/platonic_solids.py
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
"""
|
||||||
|
The Platonic solids as custom Part objects.
|
||||||
|
|
||||||
|
name: platonic_solids.py
|
||||||
|
by: Gumyr
|
||||||
|
date: February 17, 2024
|
||||||
|
|
||||||
|
desc:
|
||||||
|
This example creates a custom Part object PlatonicSolid.
|
||||||
|
|
||||||
|
Platonic solids are five three-dimensional shapes that are highly symmetrical,
|
||||||
|
known since antiquity and named after the ancient Greek philosopher Plato.
|
||||||
|
These solids are unique because their faces are congruent regular polygons,
|
||||||
|
with the same number of faces meeting at each vertex. The five Platonic solids
|
||||||
|
are the tetrahedron (4 triangular faces), cube (6 square faces), octahedron
|
||||||
|
(8 triangular faces), dodecahedron (12 pentagonal faces), and icosahedron
|
||||||
|
(20 triangular faces). Each solid represents a unique way in which identical
|
||||||
|
polygons can be arranged in three dimensions to form a convex polyhedron,
|
||||||
|
embodying ideals of symmetry and balance.
|
||||||
|
|
||||||
|
license:
|
||||||
|
|
||||||
|
Copyright 2024 Gumyr
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# [Code]
|
||||||
|
from build123d import *
|
||||||
|
from math import sqrt
|
||||||
|
from typing import Union, Literal
|
||||||
|
from scipy.spatial import ConvexHull
|
||||||
|
|
||||||
|
from ocp_vscode import show
|
||||||
|
|
||||||
|
PHI = (1 + sqrt(5)) / 2 # The Golden Ratio
|
||||||
|
|
||||||
|
|
||||||
|
class PlatonicSolid(BasePartObject):
|
||||||
|
"""Part Object: Platonic Solid
|
||||||
|
|
||||||
|
Create one of the five convex Platonic solids.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
face_count (Literal[4,6,8,12,20]): number of faces
|
||||||
|
diameter (float): double distance to vertices, i.e. maximum size
|
||||||
|
rotation (RotationLike, optional): angles to rotate about axes. Defaults to (0, 0, 0).
|
||||||
|
align (Union[None, Align, tuple[Align, Align, Align]], optional): align min, center,
|
||||||
|
or max of object. Defaults to None.
|
||||||
|
mode (Mode, optional): combine mode. Defaults to Mode.ADD.
|
||||||
|
"""
|
||||||
|
|
||||||
|
tetrahedron_vertices = [(1, 1, 1), (1, -1, -1), (-1, 1, -1), (-1, -1, 1)]
|
||||||
|
|
||||||
|
cube_vertices = [(i, j, k) for i in [-1, 1] for j in [-1, 1] for k in [-1, 1]]
|
||||||
|
|
||||||
|
octahedron_vertices = (
|
||||||
|
[(i, 0, 0) for i in [-1, 1]]
|
||||||
|
+ [(0, i, 0) for i in [-1, 1]]
|
||||||
|
+ [(0, 0, i) for i in [-1, 1]]
|
||||||
|
)
|
||||||
|
|
||||||
|
dodecahedron_vertices = (
|
||||||
|
[(i, j, k) for i in [-1, 1] for j in [-1, 1] for k in [-1, 1]]
|
||||||
|
+ [(0, i / PHI, j * PHI) for i in [-1, 1] for j in [-1, 1]]
|
||||||
|
+ [(i / PHI, j * PHI, 0) for i in [-1, 1] for j in [-1, 1]]
|
||||||
|
+ [(i * PHI, 0, j / PHI) for i in [-1, 1] for j in [-1, 1]]
|
||||||
|
)
|
||||||
|
|
||||||
|
icosahedron_vertices = (
|
||||||
|
[(0, i, j * PHI) for i in [-1, 1] for j in [-1, 1]]
|
||||||
|
+ [(i, j * PHI, 0) for i in [-1, 1] for j in [-1, 1]]
|
||||||
|
+ [(i * PHI, 0, j) for i in [-1, 1] for j in [-1, 1]]
|
||||||
|
)
|
||||||
|
|
||||||
|
vertices_lookup = {
|
||||||
|
4: tetrahedron_vertices,
|
||||||
|
6: cube_vertices,
|
||||||
|
8: octahedron_vertices,
|
||||||
|
12: dodecahedron_vertices,
|
||||||
|
20: icosahedron_vertices,
|
||||||
|
}
|
||||||
|
_applies_to = [BuildPart._tag]
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
face_count: Literal[4, 6, 8, 12, 20],
|
||||||
|
diameter: float = 1.0,
|
||||||
|
rotation: RotationLike = (0, 0, 0),
|
||||||
|
align: Union[None, Align, tuple[Align, Align, Align]] = None,
|
||||||
|
mode: Mode = Mode.ADD,
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
platonic_vertices = PlatonicSolid.vertices_lookup[face_count]
|
||||||
|
except KeyError:
|
||||||
|
raise ValueError(
|
||||||
|
f"face_count must be one of 4, 6, 8, 12, or 20 not {face_count}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a convex hull from the vertices
|
||||||
|
hull = ConvexHull(platonic_vertices).simplices.tolist()
|
||||||
|
|
||||||
|
# Create faces from the vertex indices
|
||||||
|
platonic_faces = []
|
||||||
|
for face_vertex_indices in hull:
|
||||||
|
corner_vertices = [platonic_vertices[i] for i in face_vertex_indices]
|
||||||
|
platonic_faces.append(
|
||||||
|
Face.make_from_wires(Wire.make_polygon(corner_vertices))
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create the solid from the Faces
|
||||||
|
platonic_solid = Solid.make_solid(Shell.make_shell(platonic_faces)).clean()
|
||||||
|
|
||||||
|
# By definition, all vertices are the same distance from the origin so
|
||||||
|
# scale proportionally to this distance
|
||||||
|
platonic_solid = platonic_solid.scale(
|
||||||
|
(diameter / 2) / Vector(platonic_solid.vertices()[0]).length
|
||||||
|
)
|
||||||
|
|
||||||
|
super().__init__(part=platonic_solid, rotation=rotation, align=align, mode=mode)
|
||||||
|
|
||||||
|
|
||||||
|
solids = [
|
||||||
|
Rot(0, 0, 72 * i) * Pos(1, 0, 0) * PlatonicSolid(faces)
|
||||||
|
for i, faces in enumerate([4, 6, 8, 12, 20])
|
||||||
|
]
|
||||||
|
show(solids)
|
||||||
|
|
||||||
|
# [End]
|
||||||
148
examples/stud_wall.py
Normal file
148
examples/stud_wall.py
Normal file
|
|
@ -0,0 +1,148 @@
|
||||||
|
"""
|
||||||
|
Stud Wall creation using RigidJoints to position components.
|
||||||
|
|
||||||
|
name: stud_wall.py
|
||||||
|
by: Gumyr
|
||||||
|
date: February 17, 2024
|
||||||
|
|
||||||
|
desc:
|
||||||
|
This example builds stud walls from dimensional lumber as an assembly
|
||||||
|
with the parts positioned with RigidJoints.
|
||||||
|
|
||||||
|
license:
|
||||||
|
|
||||||
|
Copyright 2024 Gumyr
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from build123d import *
|
||||||
|
from ocp_vscode import show
|
||||||
|
from typing import Union
|
||||||
|
import copy
|
||||||
|
|
||||||
|
|
||||||
|
# [Code]
|
||||||
|
class Stud(BasePartObject):
|
||||||
|
"""Part Object: Stud
|
||||||
|
|
||||||
|
Create a dimensional framing stud.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
length (float): stud size
|
||||||
|
width (float): stud size
|
||||||
|
thickness (float): stud size
|
||||||
|
rotation (RotationLike, optional): angles to rotate about axes. Defaults to (0, 0, 0).
|
||||||
|
align (Union[Align, tuple[Align, Align, Align]], optional): align min, center,
|
||||||
|
or max of object. Defaults to (Align.CENTER, Align.CENTER, Align.MIN).
|
||||||
|
mode (Mode, optional): combine mode. Defaults to Mode.ADD.
|
||||||
|
"""
|
||||||
|
|
||||||
|
_applies_to = [BuildPart._tag]
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
length: float = 8 * FT,
|
||||||
|
width: float = 3.5 * IN,
|
||||||
|
thickness: float = 1.5 * IN,
|
||||||
|
rotation: RotationLike = (0, 0, 0),
|
||||||
|
align: Union[None, Align, tuple[Align, Align, Align]] = (
|
||||||
|
Align.CENTER,
|
||||||
|
Align.CENTER,
|
||||||
|
Align.MIN,
|
||||||
|
),
|
||||||
|
mode: Mode = Mode.ADD,
|
||||||
|
):
|
||||||
|
self.length = length
|
||||||
|
self.width = width
|
||||||
|
self.thickness = thickness
|
||||||
|
|
||||||
|
# Create the basic shape
|
||||||
|
with BuildPart() as stud:
|
||||||
|
with BuildSketch():
|
||||||
|
RectangleRounded(thickness, width, 0.25 * IN)
|
||||||
|
extrude(amount=length)
|
||||||
|
|
||||||
|
# Create a Part object with appropriate alignment and rotation
|
||||||
|
super().__init__(part=stud.part, rotation=rotation, align=align, mode=mode)
|
||||||
|
|
||||||
|
# Add joints to the ends of the stud
|
||||||
|
RigidJoint("end0", self, Location())
|
||||||
|
RigidJoint("end1", self, Location((0, 0, length), (1, 0, 0), 180))
|
||||||
|
|
||||||
|
|
||||||
|
class StudWall(Compound):
|
||||||
|
"""StudWall
|
||||||
|
|
||||||
|
A simple stud wall assembly with top and sole plates.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
length (float): wall length
|
||||||
|
depth (float, optional): stud width. Defaults to 3.5*IN.
|
||||||
|
height (float, optional): wall height. Defaults to 8*FT.
|
||||||
|
stud_spacing (float, optional): center-to-center. Defaults to 16*IN.
|
||||||
|
stud_thickness (float, optional): Defaults to 1.5*IN.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
length: float,
|
||||||
|
depth: float = 3.5 * IN,
|
||||||
|
height: float = 8 * FT,
|
||||||
|
stud_spacing: float = 16 * IN,
|
||||||
|
stud_thickness: float = 1.5 * IN,
|
||||||
|
):
|
||||||
|
# Create the object that will be used for top and sole plates
|
||||||
|
plate = Stud(
|
||||||
|
length,
|
||||||
|
depth,
|
||||||
|
rotation=(0, -90, 0),
|
||||||
|
align=(Align.MIN, Align.CENTER, Align.MAX),
|
||||||
|
)
|
||||||
|
# Define where studs will go on the plates
|
||||||
|
stud_locations = Pos(stud_thickness / 2, 0, stud_thickness) * GridLocations(
|
||||||
|
stud_spacing, 0, int(length / stud_spacing) + 1, 1, align=Align.MIN
|
||||||
|
)
|
||||||
|
stud_locations.append(Pos(length - stud_thickness / 2, 0, stud_thickness))
|
||||||
|
|
||||||
|
# Create a single stud that will be copied for efficiency
|
||||||
|
stud = Stud(height - 2 * stud_thickness, depth, stud_thickness)
|
||||||
|
|
||||||
|
# For efficiency studs in the walls are copies with their own position
|
||||||
|
studs = []
|
||||||
|
for i, loc in enumerate(stud_locations):
|
||||||
|
stud_joint = RigidJoint(f"stud{i}", plate, loc)
|
||||||
|
stud_copy = copy.copy(stud)
|
||||||
|
stud_joint.connect_to(stud_copy.joints["end0"])
|
||||||
|
studs.append(stud_copy)
|
||||||
|
top_plate = copy.copy(plate)
|
||||||
|
sole_plate = copy.copy(plate)
|
||||||
|
|
||||||
|
# Position the top plate relative to the top of the first stud
|
||||||
|
studs[0].joints["end1"].connect_to(top_plate.joints["stud0"])
|
||||||
|
|
||||||
|
# Build the assembly of parts
|
||||||
|
super().__init__(children=[top_plate, sole_plate] + studs)
|
||||||
|
|
||||||
|
# Add joints to the wall
|
||||||
|
RigidJoint("inside0", self, Location((depth / 2, depth / 2, 0), (0, 0, 1), 90))
|
||||||
|
RigidJoint("end0", self, Location())
|
||||||
|
|
||||||
|
|
||||||
|
x_wall = StudWall(13 * FT)
|
||||||
|
y_wall = StudWall(9 * FT)
|
||||||
|
x_wall.joints["inside0"].connect_to(y_wall.joints["end0"])
|
||||||
|
|
||||||
|
show(x_wall, y_wall, render_joints=False)
|
||||||
|
# [End]
|
||||||
Loading…
Add table
Add a link
Reference in a new issue