diff --git a/docs/tutorial_lego.rst b/docs/tutorial_lego.rst index 168b3d0..0ac2ab4 100644 --- a/docs/tutorial_lego.rst +++ b/docs/tutorial_lego.rst @@ -21,7 +21,7 @@ The dimensions of the Lego block follow. A key parameter is ``pip_count``, the l of the Lego blocks in pips. This parameter must be at least 2. .. literalinclude:: ../examples/lego.py - :lines: 29, 32-45 + :lines: 30,31, 34-47 ******************** Step 2: Part Builder @@ -31,7 +31,7 @@ The Lego block will be created by the ``BuildPart`` builder as it's a discrete t dimensional part; therefore, we'll instantiate a ``BuildPart`` with the name ``lego``. .. literalinclude:: ../examples/lego.py - :lines: 47 + :lines: 49 ********************** Step 3: Sketch Builder @@ -43,7 +43,7 @@ object. As this sketch will be part of the lego part, we'll create a sketch bui in the context of the part builder as follows: .. literalinclude:: ../examples/lego.py - :lines: 47-49 + :lines: 49-51 :emphasize-lines: 3 @@ -59,7 +59,7 @@ of the Lego block. The following step is going to refer to this rectangle, so it be assigned the identifier ``perimeter``. .. literalinclude:: ../examples/lego.py - :lines: 47-51 + :lines: 49-53 :emphasize-lines: 5 Once the ``Rectangle`` object is created the sketch appears as follows: @@ -76,7 +76,7 @@ hollowed out. This will be done with the ``Offset`` operation which is going to create a new object from ``perimeter``. .. literalinclude:: ../examples/lego.py - :lines: 47-51,55-61 + :lines: 49-53,58-64 :emphasize-lines: 7-12 The first parameter to ``Offset`` is the reference object. The ``amount`` is a @@ -104,7 +104,7 @@ objects are in the scope of a location context (``GridLocations`` in this case) that defined multiple points, multiple rectangles are created. .. literalinclude:: ../examples/lego.py - :lines: 47-51,55-61,65-69 + :lines: 49-53,58-64,69-73 :emphasize-lines: 13-17 Here we can see that the first ``GridLocations`` creates two positions which causes @@ -125,8 +125,8 @@ To convert the internal grid to ridges, the center needs to be removed. This wil with another ``Rectangle``. .. literalinclude:: ../examples/lego.py - :lines: 47-51,55-61,65-69,74-78 - :emphasize-lines: 17-22 + :lines: 49-53,58-64,69-73,78-83 + :emphasize-lines: 18-23 The ``Rectangle`` is subtracted from the sketch to leave the ridges as follows: @@ -142,8 +142,8 @@ Lego blocks use a set of internal hollow cylinders that the pips push against to hold two blocks together. These will be created with ``Circle``. .. literalinclude:: ../examples/lego.py - :lines: 47-51,55-61,65-69,74-76,82-87 - :emphasize-lines: 21-26 + :lines: 49-53,58-64,69-73,78-83,88-93 + :emphasize-lines: 24-29 Here another ``GridLocations`` is used to position the centers of the circles. Note that since both ``Circle`` objects are in the scope of the location context, both @@ -162,8 +162,8 @@ Now that the sketch is complete it needs to be extruded into the three dimension wall object. .. literalinclude:: ../examples/lego.py - :lines: 47-51,55-61,65-69,74-76,82-87,91-92 - :emphasize-lines: 27-28 + :lines: 49-53,58-64,69-73,78-83,88-93,98-99 + :emphasize-lines: 30-31 Note how the ``Extrude`` operation is no longer in the ``BuildSketch`` scope and has returned back into the ``BuildPart`` scope. This causes ``BuildSketch`` to exit and transfer the @@ -183,8 +183,8 @@ Now that the walls are complete, the top of the block needs to be added. Althoug could be done with another sketch, we'll add a box to the top of the walls. .. literalinclude:: ../examples/lego.py - :lines: 47-51,55-61,65-69,74-76,82-87,91-92,100-108 - :emphasize-lines: 29-37 + :lines: 49-53,58-64,69-73,78-83,88-93,98-99,110-118 + :emphasize-lines: 32-40 To position the top, we'll describe the top center of the lego walls with a ``Locations`` context. To determine the height we'll extract that from the @@ -211,8 +211,8 @@ The final step is to add the pips to the top of the Lego block. To do this we'll a new workplane on top of the block where we can position the pips. .. literalinclude:: ../examples/lego.py - :lines: 47-51,55-61,65-69,74-76,82-87,91-92,100-108,116-124 - :emphasize-lines: 38-46 + :lines: 49-53,58-64,69-73,78-83,88-93,98-99,110-118,129-137 + :emphasize-lines: 41-49 In this case, the workplane is created from the top Face of the Lego block by using the ``faces`` method and then sorted vertically and taking the top one ``sort_by(Axis.Z)[-1]``. diff --git a/examples/build123d_customizable_logo_algebra.py b/examples/build123d_customizable_logo_algebra.py index 4492e48..29bd81c 100644 --- a/examples/build123d_customizable_logo_algebra.py +++ b/examples/build123d_customizable_logo_algebra.py @@ -41,7 +41,7 @@ l2 = Line( (logo_width, -font_height * 0.1), (logo_width, -ext_line_length - font_height * 0.1), ) -extension_lines = l1 + l2 +extension_lines = Curve() + (l1 + l2) extension_lines += Pos(*(l1 @ 0.5)) * arrow_left extension_lines += (Pos(*(l2 @ 0.5)) * Rot(Z=180)) * arrow_left extension_lines += Line(l1 @ 0.5, l1 @ 0.5 + Vector(dim_line_length, 0)) diff --git a/examples/build123d_logo_algebra.py b/examples/build123d_logo_algebra.py index 7c6d65b..f5d732a 100644 --- a/examples/build123d_logo_algebra.py +++ b/examples/build123d_logo_algebra.py @@ -37,7 +37,7 @@ l2 = Line( (logo_width, -font_height * 0.1), (logo_width, -ext_line_length - font_height * 0.1), ) -extension_lines = l1 + l2 +extension_lines = Curve() + (l1 + l2) extension_lines += Pos(*(l1 @ 0.5)) * arrow_left extension_lines += (Pos(*(l2 @ 0.5)) * Rot(Z=180)) * arrow_left extension_lines += Line(l1 @ 0.5, l1 @ 0.5 + Vector(dim_line_length, 0)) diff --git a/examples/custom_sketch_objects_algebra.py b/examples/custom_sketch_objects_algebra.py index c67a3f8..a61c4c6 100644 --- a/examples/custom_sketch_objects_algebra.py +++ b/examples/custom_sketch_objects_algebra.py @@ -33,7 +33,7 @@ class Spade(Sketch): b1 = Bezier(b0 @ 1, (242, -72), (114, -168), (11, -105)) b2 = Bezier(b1 @ 1, (31, -174), (42, -179), (53, -198)) l0 = Line(b2 @ 1, (0, -198)) - spade = l0 + b0 + b1 + b2 + spade = b0 + b1 + b2 + l0 spade += mirror(spade, Plane.YZ) spade = make_face(spade) spade = scale(spade, height / spade.bounding_box().size.Y) diff --git a/examples/lego.py b/examples/lego.py index cbd7cad..88cb1a4 100644 --- a/examples/lego.py +++ b/examples/lego.py @@ -26,9 +26,11 @@ license: See the License for the specific language governing permissions and limitations under the License. """ -from build123d import * -from ocp_vscode import * +from build123d import * +from ocp_vscode import show_object + +GEN_DOCS = False pip_count = 6 lego_unit_size = 8 @@ -49,9 +51,10 @@ with BuildPart() as lego: with BuildSketch() as plan: # Start with a Rectangle the size of the block perimeter = Rectangle(width=block_length, height=block_width) - exporter = ExportSVG(scale=6) - exporter.add_shape(plan.sketch) - exporter.write("assets/lego_step4.svg") + if GEN_DOCS: + exporter = ExportSVG(scale=6) + exporter.add_shape(plan.sketch) + exporter.write("assets/lego_step4.svg") # Subtract an offset to create the block walls offset( perimeter, @@ -59,44 +62,51 @@ with BuildPart() as lego: kind=Kind.INTERSECTION, mode=Mode.SUBTRACT, ) - exporter = ExportSVG(scale=6) - exporter.add_shape(plan.sketch) - exporter.write("assets/lego_step5.svg") + if GEN_DOCS: + exporter = ExportSVG(scale=6) + exporter.add_shape(plan.sketch) + exporter.write("assets/lego_step5.svg") # Add a grid of lengthwise and widthwise bars with GridLocations(x_spacing=0, y_spacing=lego_unit_size, x_count=1, y_count=2): Rectangle(width=block_length, height=ridge_width) with GridLocations(lego_unit_size, 0, pip_count, 1): Rectangle(width=ridge_width, height=block_width) - exporter = ExportSVG(scale=6) - exporter.add_shape(plan.sketch) - exporter.write("assets/lego_step6.svg") + if GEN_DOCS: + exporter = ExportSVG(scale=6) + exporter.add_shape(plan.sketch) + exporter.write("assets/lego_step6.svg") # Substract a rectangle leaving ribs on the block walls Rectangle( block_length - 2 * (wall_thickness + ridge_depth), block_width - 2 * (wall_thickness + ridge_depth), mode=Mode.SUBTRACT, ) - exporter = ExportSVG(scale=6) - exporter.add_shape(plan.sketch) - exporter.write("assets/lego_step7.svg") + if GEN_DOCS: + exporter = ExportSVG(scale=6) + exporter.add_shape(plan.sketch) + exporter.write("assets/lego_step7.svg") # Add a row of hollow circles to the center with GridLocations( x_spacing=lego_unit_size, y_spacing=0, x_count=pip_count - 1, y_count=1 ): Circle(radius=support_outer_diameter / 2) Circle(radius=support_inner_diameter / 2, mode=Mode.SUBTRACT) - exporter = ExportSVG(scale=6) - exporter.add_shape(plan.sketch) - exporter.write("assets/lego_step8.svg") + if GEN_DOCS: + exporter = ExportSVG(scale=6) + exporter.add_shape(plan.sketch) + exporter.write("assets/lego_step8.svg") # Extrude this base sketch to the height of the walls extrude(amount=base_height - wall_thickness) - visible, hidden = lego.part.project_to_viewport((-5, -30, 50)) - exporter = ExportSVG(scale=6) - exporter.add_layer("Visible") - exporter.add_layer("Hidden", line_color=(99, 99, 99), line_type=LineType.ISO_DOT) - exporter.add_shape(visible, layer="Visible") - exporter.add_shape(hidden, layer="Hidden") - exporter.write("assets/lego_step9.svg") + if GEN_DOCS: + visible, hidden = lego.part.project_to_viewport((-5, -30, 50)) + exporter = ExportSVG(scale=6) + exporter.add_layer("Visible") + exporter.add_layer( + "Hidden", line_color=(99, 99, 99), line_type=LineType.ISO_DOT + ) + exporter.add_shape(visible, layer="Visible") + exporter.add_shape(hidden, layer="Hidden") + exporter.write("assets/lego_step9.svg") # Create a box on the top of the walls with Locations((0, 0, lego.vertices().sort_by(Axis.Z)[-1].Z)): # Create the top of the block @@ -106,13 +116,16 @@ with BuildPart() as lego: height=wall_thickness, align=(Align.CENTER, Align.CENTER, Align.MIN), ) - visible, hidden = lego.part.project_to_viewport((-5, -30, 50)) - exporter = ExportSVG(scale=6) - exporter.add_layer("Visible") - exporter.add_layer("Hidden", line_color=(99, 99, 99), line_type=LineType.ISO_DOT) - exporter.add_shape(visible, layer="Visible") - exporter.add_shape(hidden, layer="Hidden") - exporter.write("assets/lego_step10.svg") + if GEN_DOCS: + visible, hidden = lego.part.project_to_viewport((-5, -30, 50)) + exporter = ExportSVG(scale=6) + exporter.add_layer("Visible") + exporter.add_layer( + "Hidden", line_color=(99, 99, 99), line_type=LineType.ISO_DOT + ) + exporter.add_shape(visible, layer="Visible") + exporter.add_shape(hidden, layer="Hidden") + exporter.write("assets/lego_step10.svg") # Create a workplane on the top of the block with BuildPart(lego.faces().sort_by(Axis.Z)[-1]): # Create a grid of pips @@ -122,14 +135,17 @@ with BuildPart() as lego: height=pip_height, align=(Align.CENTER, Align.CENTER, Align.MIN), ) - visible, hidden = lego.part.project_to_viewport((-100, -100, 50)) - exporter = ExportSVG(scale=6) - exporter.add_layer("Visible") - exporter.add_layer("Hidden", line_color=(99, 99, 99), line_type=LineType.ISO_DOT) - exporter.add_shape(visible, layer="Visible") - exporter.add_shape(hidden, layer="Hidden") - exporter.write("assets/lego.svg") + if GEN_DOCS: + visible, hidden = lego.part.project_to_viewport((-100, -100, 50)) + exporter = ExportSVG(scale=6) + exporter.add_layer("Visible") + exporter.add_layer( + "Hidden", line_color=(99, 99, 99), line_type=LineType.ISO_DOT + ) + exporter.add_shape(visible, layer="Visible") + exporter.add_shape(hidden, layer="Hidden") + exporter.write("assets/lego.svg") assert abs(lego.part.volume - 3212.187337781355) < 1e-3 -show_object(lego.part.wrapped, name="lego") +show_object(lego.part, name="lego") diff --git a/examples/platonic_solids.py b/examples/platonic_solids.py index c862690..0d527f4 100644 --- a/examples/platonic_solids.py +++ b/examples/platonic_solids.py @@ -118,7 +118,7 @@ class PlatonicSolid(BasePartObject): platonic_faces.append(Face(Wire.make_polygon(corner_vertices))) # Create the solid from the Faces - platonic_solid = Solid.make_solid(Shell.make_shell(platonic_faces)).clean() + platonic_solid = Solid(Shell(platonic_faces)).clean() # By definition, all vertices are the same distance from the origin so # scale proportionally to this distance diff --git a/examples/projection.py b/examples/projection.py index dedc0ca..b5c3b7b 100644 --- a/examples/projection.py +++ b/examples/projection.py @@ -37,7 +37,7 @@ projection_direction = Vector(0, 1, 0) square = Face.make_rect(20, 20, Plane.ZX.offset(-80)) square_projected = square.project_to_shape(sphere, projection_direction) -square_solids = Compound([f.thicken(2) for f in square_projected]) +square_solids = Compound([Solid.thicken(f, 2) for f in square_projected]) projection_beams = [ Solid.make_loft( [ @@ -75,7 +75,7 @@ text = Compound.make_text( font_size=15, align=(Align.MIN, Align.CENTER), ) -projected_text = sphere.project_faces(text, path=arch_path) +projected_text = Sketch(sphere.project_faces(text, path=arch_path)) # Example 1 show_object(sphere, name="sphere_solid", options={"alpha": 0.8}) diff --git a/examples/projection_algebra.py b/examples/projection_algebra.py index 14ed71d..3e0ece2 100644 --- a/examples/projection_algebra.py +++ b/examples/projection_algebra.py @@ -9,7 +9,7 @@ projection_direction = Vector(0, 1, 0) square = Plane.ZX.offset(-80) * Rectangle(20, 20) square_projected = square.faces()[0].project_to_shape(sphere, projection_direction) -square_solids = Part() + [f.thicken(2) for f in square_projected] +square_solids = Part() + [Solid.thicken(f, 2) for f in square_projected] face = square.faces()[0] projection_beams = loft([face, Pos(0, 160, 0) * face]) @@ -39,7 +39,7 @@ text = Text( font_size=15, align=(Align.MIN, Align.CENTER), ) -projected_text = sphere.project_faces(text.faces(), path=arch_path) +projected_text = Sketch(sphere.project_faces(text.faces(), path=arch_path)) # Example 1 show_object(sphere, name="sphere_solid", options={"alpha": 0.8}) diff --git a/examples/roller_coaster_algebra.py b/examples/roller_coaster_algebra.py index db2fa6b..67c21a3 100644 --- a/examples/roller_coaster_algebra.py +++ b/examples/roller_coaster_algebra.py @@ -1,4 +1,5 @@ from build123d import * +from ocp_vscode import show_object powerup = Spline( (0, 0, 0), @@ -10,11 +11,10 @@ powerup = Spline( corner = RadiusArc(powerup @ 1, (100, 60, 0), -30) screw = Helix(75, 150, 15, center=(75, 40, 15), direction=(-1, 0, 0)) -roller_coaster = powerup + corner + screw +roller_coaster = Curve() + (powerup + corner + screw) roller_coaster += Spline(corner @ 1, screw @ 0, tangents=(corner % 1, screw % 0)) roller_coaster += Spline( screw @ 1, (-100, 30, 10), powerup @ 0, tangents=(screw % 1, powerup % 0) ) -if "show_object" in locals(): - show_object(roller_coaster) +show_object(roller_coaster) diff --git a/src/build123d/operations_generic.py b/src/build123d/operations_generic.py index 80b0f00..c2b2e50 100644 --- a/src/build123d/operations_generic.py +++ b/src/build123d/operations_generic.py @@ -821,7 +821,7 @@ def project( elif isinstance(context, BuildLine): projected_shapes.extend(projection) else: # BuildPart - projected_shapes.append(projection[0]) + projected_shapes.extend(projection.faces()) projected_points: ShapeList[Vector] = ShapeList() for pnt in point_list: