build123d/docs/technical_drawing.py
gumyr 30d26904ff
Some checks failed
benchmarks / benchmarks (macos-13, 3.12) (push) Has been cancelled
benchmarks / benchmarks (macos-14, 3.12) (push) Has been cancelled
benchmarks / benchmarks (ubuntu-latest, 3.12) (push) Has been cancelled
benchmarks / benchmarks (windows-latest, 3.12) (push) Has been cancelled
Upload coverage reports to Codecov / run (push) Has been cancelled
pylint / lint (3.10) (push) Has been cancelled
Run type checker / typecheck (3.10) (push) Has been cancelled
Run type checker / typecheck (3.13) (push) Has been cancelled
Wheel building and publishing / Build wheel on ubuntu-latest (push) Has been cancelled
tests / tests (macos-13, 3.10) (push) Has been cancelled
tests / tests (macos-13, 3.13) (push) Has been cancelled
tests / tests (macos-14, 3.10) (push) Has been cancelled
tests / tests (macos-14, 3.13) (push) Has been cancelled
tests / tests (ubuntu-latest, 3.10) (push) Has been cancelled
tests / tests (ubuntu-latest, 3.13) (push) Has been cancelled
tests / tests (windows-latest, 3.10) (push) Has been cancelled
tests / tests (windows-latest, 3.13) (push) Has been cancelled
Wheel building and publishing / upload_pypi (push) Has been cancelled
Adding Technical Drawing Tutorial
2025-05-23 13:47:28 -04:00

188 lines
5.7 KiB
Python

"""
name: technical_drawing.py
by: gumyr
date: May 23, 2025
desc:
Generate a multi-view technical drawing of a part, including isometric and
orthographic projections.
This module demonstrates how to create a standard technical drawing using
`build123d`. It includes:
- Projection of a 3D part to 2D views (plan, front, side, isometric)
- Drawing borders and dimensioning using extension lines
- SVG export of visible and hidden geometry
- Example part: Nema 23 stepper motor from `bd_warehouse.open_builds`
The following standard views are generated:
- Plan View (Top)
- Front Elevation
- Side Elevation (Right Side)
- Isometric Projection
The resulting drawing is exported as an SVG and can be previewed using
the `ocp_vscode` viewer.
license:
Copyright 2025 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 datetime import date
from bd_warehouse.open_builds import StepperMotor
from build123d import *
from ocp_vscode import show
def project_to_2d(
part: Part,
viewport_origin: VectorLike,
viewport_up: VectorLike,
page_origin: VectorLike,
scale_factor: float = 1.0,
) -> tuple[ShapeList[Edge], ShapeList[Edge]]:
"""project_to_2d
Helper function to generate 2d views translated on the 2d page.
Args:
part (Part): 3d object
viewport_origin (VectorLike): location of viewport
viewport_up (VectorLike): direction of the viewport Y axis
page_origin (VectorLike): center of 2d object on page
scale_factor (float, optional): part scalar. Defaults to 1.0.
Returns:
tuple[ShapeList[Edge], ShapeList[Edge]]: visible & hidden edges
"""
scaled_part = part if scale_factor == 1.0 else scale(part, scale_factor)
visible, hidden = scaled_part.project_to_viewport(
viewport_origin, viewport_up, look_at=(0, 0, 0)
)
visible = [Pos(*page_origin) * e for e in visible]
hidden = [Pos(*page_origin) * e for e in hidden]
return ShapeList(visible), ShapeList(hidden)
# The object that appearing in the drawing
stepper: Part = StepperMotor("Nema23")
# Create a standard technical drawing border on A4 paper
border = TechnicalDrawing(
designed_by="build123d",
design_date=date.fromisoformat("2025-05-23"),
page_size=PageSize.A4,
title="Nema 23 Stepper",
sub_title="Units: mm",
drawing_number="BD-1",
sheet_number=1,
drawing_scale=1,
)
page_size = border.bounding_box().size
# Specify the drafting options for extension lines
drafting_options = Draft(font_size=3.5, decimal_precision=1, display_units=False)
# Lists used to store the 2d visible and hidden lines
visible_lines, hidden_lines = [], []
# Isometric Projection - A 3D view where the part is rotated to reveal three
# dimensions equally.
iso_v, iso_h = project_to_2d(
stepper,
(100, 100, 100),
(0, 0, 1),
page_size * 0.3,
0.75,
)
visible_lines.extend(iso_v)
hidden_lines.extend(iso_h)
# Plan View (Top) - The view from directly above the part (looking down along
# the Z-axis).
vis, _ = project_to_2d(
stepper,
(0, 0, 100),
(0, 1, 0),
(page_size.X * -0.3, page_size.Y * 0.25),
)
visible_lines.extend(vis)
# Dimension the top of the stepper
top_bbox = Curve(vis).bounding_box()
perimeter = Pos(*top_bbox.center()) * Rectangle(top_bbox.size.X, top_bbox.size.Y)
d1 = ExtensionLine(
border=perimeter.edges().sort_by(Axis.X)[-1], offset=1 * CM, draft=drafting_options
)
d2 = ExtensionLine(
border=perimeter.edges().sort_by(Axis.Y)[0], offset=1 * CM, draft=drafting_options
)
# Add a label
l1 = Text("Plan View", 6)
l1.position = vis.sort_by(Axis.Y)[-1].center() + (0, 5 * MM)
# Front Elevation - The primary view, typically looking along the Y-axis,
# showing the height.
vis, _ = project_to_2d(
stepper,
(0, -100, 0),
(0, 0, 1),
(page_size.X * -0.3, page_size.Y * -0.125),
)
visible_lines.extend(vis)
d3 = ExtensionLine(
border=vis.sort_by(Axis.Y)[-1], offset=-5 * MM, draft=drafting_options
)
l2 = Text("Front Elevation", 6)
l2.position = vis.group_by(Axis.Y)[0].sort_by(Edge.length)[-1].center() + (0, -5 * MM)
# Side Elevation - Often refers to the Right Side View, looking along the X-axis.
vis, _ = project_to_2d(
stepper,
(100, 0, 0),
(0, 0, 1),
(0, page_size.Y * 0.15),
)
visible_lines.extend(vis)
side_bbox = Curve(vis).bounding_box()
perimeter = Pos(*side_bbox.center()) * Rectangle(side_bbox.size.X, side_bbox.size.Y)
d4 = ExtensionLine(
border=perimeter.edges().sort_by(Axis.X)[-1], offset=1 * CM, draft=drafting_options
)
l3 = Text("Side Elevation", 6)
l3.position = vis.group_by(Axis.Y)[0].sort_by(Edge.length)[-1].center() + (0, -5 * MM)
# Initialize the SVG exporter
exporter = ExportSVG(unit=Unit.MM)
# Define visible and hidden line layers
exporter.add_layer("Visible")
exporter.add_layer("Hidden", line_color=(99, 99, 99), line_type=LineType.ISO_DOT)
# Add the objects to the appropriate layer
exporter.add_shape(visible_lines, layer="Visible")
exporter.add_shape(hidden_lines, layer="Hidden")
exporter.add_shape(border, layer="Visible")
exporter.add_shape([d1, d2, d3, d4], layer="Visible")
exporter.add_shape([l1, l2, l3], layer="Visible")
# Write the file
exporter.write(f"assets/stepper_drawing.svg")
show(border, visible_lines, d1, d2, d3, d4, l1, l2, l3)
# [end]