mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-05 18:20:46 -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
|
||||
--------------------------------
|
||||
|
||||
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.
|
||||
|
||||
|
|
@ -39,18 +39,26 @@ Most of the examples show the builder and algebra modes.
|
|||
:link: examples-build123d_logo
|
||||
:link-type: ref
|
||||
|
||||
|
||||
.. 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-type: ref
|
||||
|
||||
|
||||
.. 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-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
|
||||
|
||||
.. TODO: Copy this block to add the example thumbnails here
|
||||
|
|
@ -71,7 +79,8 @@ Low Poly Benchy
|
|||
: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
|
||||
|
||||
|
|
@ -240,6 +249,49 @@ This example demonstrates placing holes around a part.
|
|||
:start-after: [Code]
|
||||
: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
|
||||
|
||||
|
|
|
|||
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