From 4a32cedcd2fbae2583a439f34a372e739eb7344a Mon Sep 17 00:00:00 2001 From: gumyr Date: Sun, 19 Oct 2025 15:31:47 -0400 Subject: [PATCH] Updating surface modeling docs --- docs/_static/spitfire_wing.glb | Bin 0 -> 12476 bytes docs/assets/surface_modeling/heart_token.png | Bin 0 -> 27335 bytes .../assets/surface_modeling/spitfire_wing.png | Bin 0 -> 45374 bytes .../spitfire_wing_profiles_guides.svg | 11 ++ .../token_half_surface.png | Bin .../token_heart_perimeter.png | Bin .../token_heart_solid.png | Bin .../{ => surface_modeling}/token_sides.png | Bin docs/heart_token.py | 68 +++++++ docs/spitfire_wing_gordon.py | 77 ++++++++ docs/tutorial_surface_heart_token.rst | 125 ++++++++++++ docs/tutorial_surface_modeling.rst | 181 ++++-------------- examples/tea_cup.py | 12 +- 13 files changed, 327 insertions(+), 147 deletions(-) create mode 100644 docs/_static/spitfire_wing.glb create mode 100644 docs/assets/surface_modeling/heart_token.png create mode 100644 docs/assets/surface_modeling/spitfire_wing.png create mode 100644 docs/assets/surface_modeling/spitfire_wing_profiles_guides.svg rename docs/assets/{ => surface_modeling}/token_half_surface.png (100%) rename docs/assets/{ => surface_modeling}/token_heart_perimeter.png (100%) rename docs/assets/{ => surface_modeling}/token_heart_solid.png (100%) rename docs/assets/{ => surface_modeling}/token_sides.png (100%) create mode 100644 docs/heart_token.py create mode 100644 docs/spitfire_wing_gordon.py create mode 100644 docs/tutorial_surface_heart_token.rst diff --git a/docs/_static/spitfire_wing.glb b/docs/_static/spitfire_wing.glb new file mode 100644 index 0000000000000000000000000000000000000000..93c275b4dc50962012f1e3c0d0ee3c816d71d491 GIT binary patch literal 12476 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 literal 0 HcmV?d00001 diff --git a/docs/assets/surface_modeling/heart_token.png b/docs/assets/surface_modeling/heart_token.png new file mode 100644 index 0000000000000000000000000000000000000000..24cfeb78261372c3e2815720f21a880bed5104f7 GIT binary patch literal 27335 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 literal 0 HcmV?d00001 diff --git a/docs/assets/surface_modeling/spitfire_wing.png b/docs/assets/surface_modeling/spitfire_wing.png new file mode 100644 index 0000000000000000000000000000000000000000..10924261ecb9f5d3e79aa22a3a12bbdd1e3d2d15 GIT binary patch literal 45374 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

yn_?pft7a-#=MUUG1+Ba6xMKqmYypLQnIT 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 X=)L;wtlTID1_lOCS3j3^P6 + + + + + + + + + + \ No newline at end of file diff --git a/docs/assets/token_half_surface.png b/docs/assets/surface_modeling/token_half_surface.png similarity index 100% rename from docs/assets/token_half_surface.png rename to docs/assets/surface_modeling/token_half_surface.png diff --git a/docs/assets/token_heart_perimeter.png b/docs/assets/surface_modeling/token_heart_perimeter.png similarity index 100% rename from docs/assets/token_heart_perimeter.png rename to docs/assets/surface_modeling/token_heart_perimeter.png diff --git a/docs/assets/token_heart_solid.png b/docs/assets/surface_modeling/token_heart_solid.png similarity index 100% rename from docs/assets/token_heart_solid.png rename to docs/assets/surface_modeling/token_heart_solid.png diff --git a/docs/assets/token_sides.png b/docs/assets/surface_modeling/token_sides.png similarity index 100% rename from docs/assets/token_sides.png rename to docs/assets/surface_modeling/token_sides.png diff --git a/docs/heart_token.py b/docs/heart_token.py new file mode 100644 index 0000000..da11e68 --- /dev/null +++ b/docs/heart_token.py @@ -0,0 +1,68 @@ +# [Code] +from build123d import * +from ocp_vscode import show + +# Create the edges of one half the heart surface +l1 = JernArc((0, 0), (1, 1.4), 40, -17) +l2 = JernArc(l1 @ 1, l1 % 1, 4.5, 175) +l3 = IntersectingLine(l2 @ 1, l2 % 1, other=Edge.make_line((0, 0), (0, 20))) +l4 = ThreePointArc(l3 @ 1, (0, 0, 1.5) + (l3 @ 1 + l1 @ 0) / 2, l1 @ 0) +heart_half = Wire([l1, l2, l3, l4]) +# [SurfaceEdges] + +# Create a point elevated off the center +surface_pnt = l2.arc_center + (0, 0, 1.5) +# [SurfacePoint] + +# Create the surface from the edges and point +top_right_surface = Pos(Z=0.5) * -Face.make_surface(heart_half, [surface_pnt]) +# [Surface] + +# Use the mirror method to create the other top and bottom surfaces +top_left_surface = top_right_surface.mirror(Plane.YZ) +bottom_right_surface = top_right_surface.mirror(Plane.XY) +bottom_left_surface = -top_left_surface.mirror(Plane.XY) +# [Surfaces] + +# Create the left and right sides +left_wire = Wire([l3, l2, l1]) +left_side = Pos(Z=-0.5) * Shell.extrude(left_wire, (0, 0, 1)) +right_side = left_side.mirror(Plane.YZ) +# [Sides] + +# Put all of the faces together into a Shell/Solid +heart = Solid( + Shell( + [ + top_right_surface, + top_left_surface, + bottom_right_surface, + bottom_left_surface, + left_side, + right_side, + ] + ) +) +# [Solid] + +# Build a frame around the heart +with BuildPart() as heart_token: + with BuildSketch() as outline: + with BuildLine(): + add(l1) + add(l2) + add(l3) + Line(l3 @ 1, l1 @ 0) + make_face() + mirror(about=Plane.YZ) + center = outline.sketch + offset(amount=2, kind=Kind.INTERSECTION) + add(center, mode=Mode.SUBTRACT) + extrude(amount=2, both=True) + add(heart) + +heart_token.part.color = "Red" + +show(heart_token) +# [End] +# export_gltf(heart_token.part, "heart_token.glb", binary=True) diff --git a/docs/spitfire_wing_gordon.py b/docs/spitfire_wing_gordon.py new file mode 100644 index 0000000..8b41a0c --- /dev/null +++ b/docs/spitfire_wing_gordon.py @@ -0,0 +1,77 @@ +""" +Supermarine Spitfire Wing +""" + +# [Code] + +from build123d import * +from ocp_vscode import show + +wing_span = 36 * FT + 10 * IN +wing_leading = 2.5 * FT +wing_trailing = wing_span / 4 - wing_leading +wing_leading_fraction = wing_leading / (wing_leading + wing_trailing) +wing_tip_section = wing_span / 2 - 1 * IN # distance from root to last section + +# Create leading and trailing edges +leading_edge = EllipticalCenterArc( + (0, 0), wing_span / 2, wing_leading, start_angle=270, end_angle=360 +) +trailing_edge = EllipticalCenterArc( + (0, 0), wing_span / 2, wing_trailing, start_angle=0, end_angle=90 +) + +# [AirfoilSizes] +# Calculate the airfoil sizes from the leading/trailing edges +airfoil_sizes = [] +for i in [0, 1]: + tip_axis = Axis(i * (wing_tip_section, 0, 0), (0, 1, 0)) + leading_pnt = leading_edge.intersect(tip_axis)[0] + trailing_pnt = trailing_edge.intersect(tip_axis)[0] + airfoil_sizes.append(trailing_pnt.Y - leading_pnt.Y) + +# [Airfoils] +# Create the root and tip airfoils - note that they are different NACA profiles +airfoil_root = Plane.YZ * scale( + Airfoil("2213").translate((-wing_leading_fraction, 0, 0)), airfoil_sizes[0] +) +airfoil_tip = ( + Plane.YZ + * Pos(Z=wing_tip_section) + * scale(Airfoil("2205").translate((-wing_leading_fraction, 0, 0)), airfoil_sizes[1]) +) + +# [Profiles] +# Create the Gordon surface profiles and guides +profiles = airfoil_root.edges() + airfoil_tip.edges() +profiles.append(leading_edge @ 1) # wing tip +guides = [leading_edge, trailing_edge] +# Create the wing surface as a Gordon Surface +wing_surface = -Face.make_gordon_surface(profiles, guides) +# Create the root of the wing +wing_root = -Face(Wire(wing_surface.edges().filter_by(Edge.is_closed))) + +# [Solid] +# Create the wing Solid +wing = Solid(Shell([wing_surface, wing_root])) +wing.color = 0x99A3B9 # Azure Blue + +show(wing) +# [End] +# Documentation artifact generation +# wing_control_edges = Curve( +# [airfoil_root, airfoil_tip, Vertex(leading_edge @ 1), leading_edge, trailing_edge] +# ) +# visible, _ = wing_control_edges.project_to_viewport((50 * FT, -50 * FT, 50 * FT)) +# max_dimension = max(*Compound(children=visible).bounding_box().size) +# svg = ExportSVG(scale=100 / max_dimension) +# svg.add_shape(visible) +# svg.write("assets/surface_modeling/spitfire_wing_profiles_guides.svg") + +# export_gltf( +# wing, +# "assets/surface_modeling/spitfire_wing.glb", +# binary=True, +# linear_deflection=0.1, +# angular_deflection=1, +# ) diff --git a/docs/tutorial_surface_heart_token.rst b/docs/tutorial_surface_heart_token.rst new file mode 100644 index 0000000..2c45f62 --- /dev/null +++ b/docs/tutorial_surface_heart_token.rst @@ -0,0 +1,125 @@ +################################## +Tutorial: Heart Token (Basics) +################################## + +This hands‑on tutorial introduces the fundamentals of surface modeling by building +a heart‑shaped token from a small set of non‑planar faces. We’ll create +non‑planar surfaces, mirror them, add side faces, and assemble a closed shell +into a solid. + +As described in the `topology_` section, a BREP model consists of vertices, edges, faces, +and other elements that define the boundary of an object. When creating objects with +non-planar faces, it is often more convenient to explicitly create the boundary faces of +the object. To illustrate this process, we will create the following game token: + +.. raw:: html + + + + +Useful :class:`~topology.Face` creation methods include +:meth:`~topology.Face.make_surface`, :meth:`~topology.Face.make_bezier_surface`, +and :meth:`~topology.Face.make_surface_from_array_of_points`. See the +:doc:`surface_modeling` overview for the full list. + +In this case, we'll use the ``make_surface`` method, providing it with the edges that define +the perimeter of the surface and a central point on that surface. + +To create the perimeter, we'll define the perimeter edges. Since the heart is +symmetric, we'll only create half of its surface here: + +.. literalinclude:: heart_token.py + :start-after: [Code] + :end-before: [SurfaceEdges] + +Note that ``l4`` is not in the same plane as the other lines; it defines the center line +of the heart and archs up off ``Plane.XY``. + +.. image:: ./assets/surface_modeling/token_heart_perimeter.png + :align: center + :alt: token perimeter + +In preparation for creating the surface, we'll define a point on the surface: + +.. literalinclude:: heart_token.py + :start-after: [SurfaceEdges] + :end-before: [SurfacePoint] + +We will then use this point to create a non-planar ``Face``: + +.. literalinclude:: heart_token.py + :start-after: [SurfacePoint] + :end-before: [Surface] + +.. image:: ./assets/surface_modeling/token_half_surface.png + :align: center + :alt: token perimeter + +Note that the surface was raised up by 0.5 using an Algebra expression with Pos. Also, +note that the ``-`` in front of ``Face`` simply flips the face normal so that the colored +side is up, which isn't necessary but helps with viewing. + +Now that one half of the top of the heart has been created, the remainder of the top +and bottom can be created by mirroring: + +.. literalinclude:: heart_token.py + :start-after: [Surface] + :end-before: [Surfaces] + +The sides of the heart are going to be created by extruding the outside of the perimeter +as follows: + +.. literalinclude:: heart_token.py + :start-after: [Surfaces] + :end-before: [Sides] + +.. image:: ./assets/surface_modeling/token_sides.png + :align: center + :alt: token sides + +With the top, bottom, and sides, the complete boundary of the object is defined. We can +now put them together, first into a :class:`~topology.Shell` and then into a +:class:`~topology.Solid`: + +.. literalinclude:: heart_token.py + :start-after: [Sides] + :end-before: [Solid] + +.. image:: ./assets/surface_modeling/token_heart_solid.png + :align: center + :alt: token heart solid + +.. note:: + When creating a Solid from a Shell, the Shell must be "water-tight," meaning it + should have no holes. For objects with complex Edges, it's best practice to reuse + Edges in adjoining Faces whenever possible to avoid slight mismatches that can + create openings. + +Finally, we'll create the frame around the heart as a simple extrusion of a planar +shape defined by the perimeter of the heart and merge all of the components together: + +.. literalinclude:: heart_token.py + :start-after: [Solid] + :end-before: [End] + +Note that an additional planar line is used to close ``l1`` and ``l3`` so a ``Face`` +can be created. The :func:`~operations_generic.offset` function defines the outside of +the frame as a constant distance from the heart itself. + +Summary +------- + +In this tutorial, we've explored surface modeling techniques to create a non-planar +heart-shaped object using build123d. By utilizing methods from the :class:`~topology.Face` +class, such as :meth:`~topology.Face.make_surface`, we constructed the perimeter and +central point of the surface. We then assembled the complete boundary of the object +by creating the top, bottom, and sides, and combined them into a :class:`~topology.Shell` +and eventually a :class:`~topology.Solid`. Finally, we added a frame around the heart +using the :func:`~operations_generic.offset` function to maintain a constant distance +from the heart. + +Next steps +---------- + +Continue to :doc:`tutorial_heart_token` for an advanced example using +:meth:`~topology.Face.make_gordon_surface` to create a Supermarine Spitfire wing. diff --git a/docs/tutorial_surface_modeling.rst b/docs/tutorial_surface_modeling.rst index 08ed253..4d8fca0 100644 --- a/docs/tutorial_surface_modeling.rst +++ b/docs/tutorial_surface_modeling.rst @@ -1,156 +1,55 @@ -################ +################# Surface Modeling -################ +################# -Surface modeling is employed to create objects with non-planar surfaces that can't be -generated using functions like :func:`~operations_part.extrude`, -:func:`~operations_generic.sweep`, or :func:`~operations_part.revolve`. Since there are no -specific builders designed to assist with the creation of non-planar surfaces or objects, -the following should be considered a more advanced technique. -As described in the `topology_` section, a BREP model consists of vertices, edges, faces, -and other elements that define the boundary of an object. When creating objects with -non-planar faces, it is often more convenient to explicitly create the boundary faces of -the object. To illustrate this process, we will create the following game token: +Surface modeling refers to the direct creation and manipulation of the skin of a 3D +object—its bounding faces—rather than starting from volumetric primitives or solid +operations. -.. raw:: html +Instead of defining a shape by extruding or revolving a 2D profile to fill a volume, +surface modeling focuses on building the individual curved or planar faces that together +define the outer boundary of a part. This approach allows for precise control of complex +freeform geometry such as aerodynamic surfaces, boat hulls, or organic transitions that +cannot easily be expressed with simple parametric solids. - - +In build123d, as in other CAD kernels based on BREP (Boundary Representation) modeling, +all solids are ultimately defined by their boundaries: a hierarchy of faces, edges, and +vertices. Each face represents a finite patch of a geometric surface (plane, cylinder, +Bézier patch, etc.) bounded by one or more edge loops or wires. When adjacent faces share +edges consistently and close into a continuous boundary, they form a manifold +:class:`~topology.Shell`—the watertight surface of a volume. If this shell is properly +oriented and encloses a finite region of space, the model becomes a solid. -There are several methods of the :class:`~topology.Face` class that can be used to create -non-planar surfaces: +Surface modeling therefore operates at the most fundamental level of BREP construction. +Rather than relying on higher-level modeling operations to implicitly generate faces, +it allows you to construct and connect those faces explicitly. This provides a path to +build geometry that blends analytical and freeform shapes seamlessly, with full control +over continuity, tangency, and curvature across boundaries. -* :meth:`~topology.Face.make_bezier_surface`, -* :meth:`~topology.Face.make_surface`, and -* :meth:`~topology.Face.make_surface_from_array_of_points`. +This section provides: +- A concise overview of surface‑building tools in build123d +- Hands‑on tutorials, from fundamentals to advanced techniques like Gordon surfaces -In this case, we'll use the ``make_surface`` method, providing it with the edges that define -the perimeter of the surface and a central point on that surface. +.. rubric:: Available surface methods -To create the perimeter, we'll use a ``BuildLine`` instance as follows. Since the heart is -symmetric, we'll only create half of its surface here: +Methods on :class:`~topology.Face` for creating non‑planar surfaces: -.. code-block:: python - - with BuildLine() as heart_half: - l1 = JernArc((0, 0), (1, 1.4), 40, -17) - l2 = JernArc(l1 @ 1, l1 % 1, 4.5, 175) - l3 = IntersectingLine(l2 @ 1, l2 % 1, other=Edge.make_line((0, 0), (0, 20))) - l4 = ThreePointArc(l3 @ 1, Vector(0, 0, 1.5) + (l3 @ 1 + l1 @ 0) / 2, l1 @ 0) - -Note that ``l4`` is not in the same plane as the other lines; it defines the center line -of the heart and archs up off ``Plane.XY``. - -.. image:: ./assets/token_heart_perimeter.png - :align: center - :alt: token perimeter - -In preparation for creating the surface, we'll define a point on the surface: - -.. code-block:: python - - surface_pnt = l2.edge().arc_center + Vector(0, 0, 1.5) - -We will then use this point to create a non-planar ``Face``: - -.. code-block:: python - - top_right_surface = -Face.make_surface(heart_half.wire(), [surface_pnt]).locate( - Pos(Z=0.5) - ) - -.. image:: ./assets/token_half_surface.png - :align: center - :alt: token perimeter - -Note that the surface was raised up by 0.5 using the locate method. Also, note that -the ``-`` in front of ``Face`` simply flips the face normal so that the colored side -is up, which isn't necessary but helps with viewing. - -Now that one half of the top of the heart has been created, the remainder of the top -and bottom can be created by mirroring: - -.. code-block:: python - - top_left_surface = top_right_surface.mirror(Plane.YZ) - bottom_right_surface = top_right_surface.mirror(Plane.XY) - bottom_left_surface = -top_left_surface.mirror(Plane.XY) - -The sides of the heart are going to be created by extruding the outside of the perimeter -as follows: - -.. code-block:: python - - left_wire = Wire([l3.edge(), l2.edge(), l1.edge()]) - left_side = Face.extrude(left_wire, (0, 0, 1)).locate(Pos(Z=-0.5)) - right_side = left_side.mirror(Plane.YZ) - -.. image:: ./assets/token_sides.png - :align: center - :alt: token sides - -With the top, bottom, and sides, the complete boundary of the object is defined. We can -now put them together, first into a :class:`~topology.Shell` and then into a -:class:`~topology.Solid`: - -.. code-block:: python - - heart = Solid( - Shell( - [ - top_right_surface, - top_left_surface, - bottom_right_surface, - bottom_left_surface, - left_side, - right_side, - ] - ) - ) - -.. image:: ./assets/token_heart_solid.png - :align: center - :alt: token heart solid +* :meth:`~topology.Face.make_bezier_surface` +* :meth:`~topology.Face.make_gordon_surface` +* :meth:`~topology.Face.make_surface` +* :meth:`~topology.Face.make_surface_from_array_of_points` +* :meth:`~topology.Face.make_surface_from_curves` +* :meth:`~topology.Face.make_surface_patch` .. note:: - When creating a Solid from a Shell, the Shell must be "water-tight," meaning it - should have no holes. For objects with complex Edges, it's best practice to reuse - Edges in adjoining Faces whenever possible to avoid slight mismatches that can - create openings. + Surface modeling is an advanced technique. Robust results usually come from + reusing the same :class:`~topology.Edge` objects across adjacent faces and + ensuring the final :class:`~topology.Shell` is *water‑tight* or *manifold* (no gaps). -Finally, we'll create the frame around the heart as a simple extrusion of a planar -shape defined by the perimeter of the heart and merge all of the components together: +.. toctree:: + :maxdepth: 1 - .. code-block:: python + tutorial_surface_heart_token.rst + tutorial_spitfire_wing_gordon.rst - with BuildPart() as heart_token: - with BuildSketch() as outline: - with BuildLine(): - add(l1) - add(l2) - add(l3) - Line(l3 @ 1, l1 @ 0) - make_face() - mirror(about=Plane.YZ) - center = outline.sketch - offset(amount=2, kind=Kind.INTERSECTION) - add(center, mode=Mode.SUBTRACT) - extrude(amount=2, both=True) - add(heart) - -Note that an additional planar line is used to close ``l1`` and ``l3`` so a ``Face`` -can be created. The :func:`~operations_generic.offset` function defines the outside of -the frame as a constant distance from the heart itself. - -Summary -------- - -In this tutorial, we've explored surface modeling techniques to create a non-planar -heart-shaped object using build123d. By utilizing methods from the :class:`~topology.Face` -class, such as :meth:`~topology.Face.make_surface`, we constructed the perimeter and -central point of the surface. We then assembled the complete boundary of the object -by creating the top, bottom, and sides, and combined them into a :class:`~topology.Shell` -and eventually a :class:`~topology.Solid`. Finally, we added a frame around the heart -using the :func:`~operations_generic.offset` function to maintain a constant distance -from the heart. \ No newline at end of file diff --git a/examples/tea_cup.py b/examples/tea_cup.py index 866ee1f..8bc8ed6 100644 --- a/examples/tea_cup.py +++ b/examples/tea_cup.py @@ -4,19 +4,19 @@ name: tea_cup.py by: Gumyr date: March 27th 2023 -desc: This example demonstrates the creation a tea cup, which serves as an example of +desc: This example demonstrates the creation a tea cup, which serves as an example of constructing complex, non-flat geometrical shapes programmatically. The tea cup model involves several CAD techniques, such as: - - Revolve Operations: There is 1 occurrence of a revolve operation. This is used - to create the main body of the tea cup by revolving a profile around an axis, + - Revolve Operations: There is 1 occurrence of a revolve operation. This is used + to create the main body of the tea cup by revolving a profile around an axis, a common technique for generating symmetrical objects like cups. - Sweep Operations: There are 2 occurrences of sweep operations. The handle are created by sweeping a profile along a path to generate non-planar surfaces. - Offset/Shell Operations: the bowl of the cup is hollowed out with the offset - operation leaving the top open. - - Fillet Operations: There is 1 occurrence of a fillet operation which is used to - round the edges for aesthetic improvement and to mimic real-world objects more + operation leaving the top open. + - Fillet Operations: There is 1 occurrence of a fillet operation which is used to + round the edges for aesthetic improvement and to mimic real-world objects more closely. license: