From 91034a6745a3091a90640340ef0ec0e59b84ab0c Mon Sep 17 00:00:00 2001 From: gumyr Date: Sat, 5 Apr 2025 11:15:45 -0400 Subject: [PATCH] Adding toy truck code --- examples/toy_truck.py | 185 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 examples/toy_truck.py diff --git a/examples/toy_truck.py b/examples/toy_truck.py new file mode 100644 index 0000000..840e3f1 --- /dev/null +++ b/examples/toy_truck.py @@ -0,0 +1,185 @@ +""" + +name: toy_truck.py +by: Gumyr +date: April 4th 2025 + +desc: + + This example demonstrates how to design a toy truck using BuildPart and + BuildSketch in Builder mode. The model includes a detailed body, cab, grill, + and bumper, showcasing techniques like sketch reuse, symmetry, tapered + extrusions, selective filleting, and the use of joints for part assembly. + Ideal for learning complex part construction and hierarchical modeling in + build123d. + +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] +import pathlib +from build123d import * +from ocp_vscode import ImageFace, show, show_object + +# Create an ocp_vscode image object to use as a design reference +project_root = pathlib.Path(__file__).resolve().parents[1] +reference_image_path = ( + project_root / "docs" / "assets" / "examples" / "toy_truck_picture.jpg" +) +image = ImageFace( + str(reference_image_path), + scale=0.012, + location=Location((0, 0, -1), (0, 0, 90)), +) +show_object(image) + + +# Toy Truck Blue +truck_color = Color(0x4683CE) + +# Create the main truck body — from bumper to bed, excluding the cab +with BuildPart() as body: + # The body has two axes of symmetry, so we start with a centered sketch. + # The default workplane is Plane.XY. + with BuildSketch() as body_skt: + Rectangle(20, 35) + # Fillet all the corners of the sketch. + # Alternatively, you could use RectangleRounded. + fillet(body_skt.vertices(), 1) + + # Extrude the body shape upward + extrude(amount=10, taper=4) + # Reuse the sketch by accessing it explicitly + extrude(body_skt.sketch, amount=8, taper=2) + + # Create symmetric fenders on Plane.YZ + with BuildSketch(Plane.YZ) as fender: + # The trapezoid has asymmetric angles (80°, 88°) + Trapezoid(18, 6, 80, 88, align=Align.MIN) + # Fillet top edge vertices (Y-direction highest group) + fillet(fender.vertices().group_by(Axis.Y)[-1], 1.5) + + # Extrude the fender in both directions + extrude(amount=10.5, both=True) + + # Create wheel wells with a shifted sketch on Plane.YZ + with BuildSketch(Plane.YZ.shift_origin((0, 3.5, 0))) as wheel_well: + Trapezoid(12, 4, 70, 85, align=Align.MIN) + fillet(wheel_well.vertices().group_by(Axis.Y)[-1], 2) + + # Subtract the wheel well geometry + extrude(amount=10.5, both=True, mode=Mode.SUBTRACT) + + # Fillet the top edges of the body + fillet(body.edges().group_by(Axis.Z)[-1], 1) + + # Isolate a set of body edges and preview before filleting + body_edges = body.edges().group_by(Axis.Z)[-6] + fillet(body_edges, 0.1) + + # Combine edge groups from both sides of the fender and fillet them + fender_edges = body.edges().group_by(Axis.X)[0] + body.edges().group_by(Axis.X)[-1] + fender_edges = fender_edges.group_by(Axis.Z)[1:] + fillet(fender_edges, 0.4) + + # Create a sketch on the front of the truck for the grill + with BuildSketch( + Plane.XZ.offset(-body.vertices().sort_by(Axis.Y)[-1].Y - 0.5) + ) as grill: + Rectangle(16, 8.5, align=(Align.CENTER, Align.MIN)) + fillet(grill.vertices().group_by(Axis.Y)[-1], 1) + + # Add headlights (subtractive circles) + with Locations((0, 6.5)): + with GridLocations(12, 0, 2, 1): + Circle(1, mode=Mode.SUBTRACT) + + # Add air vents (subtractive slots) + with Locations((0, 3)): + with GridLocations(0, 0.8, 1, 4): + SlotOverall(10, 0.5, mode=Mode.SUBTRACT) + + # Extrude the grill forward + extrude(amount=2) + + # Fillet only the outer grill edges (exclude headlight/vent cuts) + grill_perimeter = body.faces().sort_by(Axis.Y)[-1].outer_wire() + fillet(grill_perimeter.edges(), 0.2) + + # Create the bumper as a separate part inside the body + with BuildPart() as bumper: + # Find the midpoint of a front edge and shift slightly to position the bumper + front_cnt = body.edges().group_by(Axis.Z)[0].sort_by(Axis.Y)[-1] @ 0.5 - (0, 3) + + with BuildSketch() as bumper_plan: + # Use BuildLine to draw an elliptical arc and offset + with BuildLine(): + EllipticalCenterArc(front_cnt, 20, 4, start_angle=60, end_angle=120) + offset(amount=1) + make_face() + + # Extrude the bumper symmetrically + extrude(amount=1, both=True) + fillet(bumper.edges(), 0.25) + + # Define a joint on top of the body to connect the cab later + RigidJoint("body_top", joint_location=Location((0, -7.5, 10))) + body.part.color = truck_color + +# Create the cab as an independent part to mount on the body +with BuildPart() as cab: + with BuildSketch() as cab_plan: + RectangleRounded(16, 16, 1) + # Split the sketch to work on one symmetric half + split(bisect_by=Plane.YZ) + + # Extrude the cab forward and upward at an angle + extrude(amount=7, dir=(0, 0.15, 1)) + fillet(cab.edges().group_by(Axis.Z)[-1].group_by(Axis.X)[1:], 1) + + # Rear window + with BuildSketch(Plane.XZ.shift_origin((0, 0, 3))) as rear_window: + RectangleRounded(8, 4, 0.75) + extrude(amount=10, mode=Mode.SUBTRACT) + + # Front window + with BuildSketch(Plane.XZ) as front_window: + RectangleRounded(15.2, 11, 0.75) + extrude(amount=-10, mode=Mode.SUBTRACT) + + # Side windows + with BuildSketch(Plane.YZ) as side_window: + with Locations((3.5, 0)): + with GridLocations(10, 0, 2, 1): + Trapezoid(9, 5.5, 80, 100, align=(Align.CENTER, Align.MIN)) + fillet(side_window.vertices().group_by(Axis.Y)[-1], 0.5) + extrude(amount=12, both=True, mode=Mode.SUBTRACT) + + # Mirror to complete the cab + mirror(about=Plane.YZ) + + # Define joint on cab base + RigidJoint("cab_base", joint_location=Location((0, 0, 0))) + cab.part.color = truck_color + +# Attach the cab to the truck body using joints +body.joints["body_top"].connect_to(cab.joints["cab_base"]) + +# Show the result +show(image, body.part, cab.part) +# [End]