cookidooAI/converted_docs.md

1.5 MiB
Executable File
Raw Permalink Blame History

[]{#index.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} build123d logo{.align-center}

::: {#index.xhtml#about .section}

About

Build123d is a Python-based, parametric (BREP) modeling framework for 2D and 3D CAD. Built on the Open Cascade geometric kernel, it provides a clean, fully Pythonic interface for creating precise models suitable for 3D printing, CNC machining, laser cutting, and other manufacturing processes. Models can be exported to popular CAD tools such as FreeCAD and SolidWorks.

Designed for modern, maintainable CAD-as-code, build123d combines clear architecture with expressive, algebraic modeling. It offers:

  • Minimal or no internal state depending on mode

  • Explicit 1D, 2D, and 3D geometry classes with well-defined operations

  • Extensibility through subclassing and functional composition---no monkey patching

  • Standards-compliant code (PEP 8, mypy, pylint) with rich pylance type hints

  • Deep Python integration---selectors as lists, locations as iterables, and natural conversions (Solid(shell){.docutils .literal .notranslate}, tuple(Vector){.docutils .literal .notranslate})

  • Operator-driven modeling (obj += sub_obj{.docutils .literal .notranslate}, Plane.XZ * Pos(X=5) * Rectangle(1, 1){.docutils .literal .notranslate}) for algebraic, readable, and composable design logic

::: {.highlight-build123d .notranslate} ::: highlight ::: :::

With build123d, intricate parametric models can be created in just a few lines of readable Python code---as demonstrated by the tea cup example below.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Teacup Example]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} :::

</details>

::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show

wall_thickness = 3 * MM
fillet_radius = wall_thickness * 0.49

with BuildPart() as tea_cup:
    # Create the bowl of the cup as a revolved cross section
    with BuildSketch(Plane.XZ) as bowl_section:
        with BuildLine():
            # Start & end points with control tangents
            s = Spline(
                (30 * MM, 10 * MM),
                (69 * MM, 105 * MM),
                tangents=((1, 0.5), (0.7, 1)),
                tangent_scalars=(1.75, 1),
            )
            # Lines to finish creating ½ the bowl shape
            Polyline(s @ 0, s @ 0 + (10 * MM, -10 * MM), (0, 0), (0, (s @ 1).Y), s @ 1)
        make_face()  # Create a filled 2D shape
    revolve(axis=Axis.Z)
    # Hollow out the bowl with openings on the top and bottom
    offset(amount=-wall_thickness, openings=tea_cup.faces().filter_by(GeomType.PLANE))
    # Add a bottom to the bowl
    with Locations((0, 0, (s @ 0).Y)):
        Cylinder(radius=(s @ 0).X, height=wall_thickness)
    # Smooth out all the edges
    fillet(tea_cup.edges(), radius=fillet_radius)

    # Determine where the handle contacts the bowl
    handle_intersections = [
        tea_cup.part.find_intersection_points(
            Axis(origin=(0, 0, vertical_offset), direction=(1, 0, 0))
        )[-1][0]
        for vertical_offset in [35 * MM, 80 * MM]
    ]
    # Create a path for handle creation
    with BuildLine(Plane.XZ) as handle_path:
        Spline(
            handle_intersections[0] - (wall_thickness / 2, 0),
            handle_intersections[0] + (35 * MM, 30 * MM),
            handle_intersections[0] + (40 * MM, 60 * MM),
            handle_intersections[1] - (wall_thickness / 2, 0),
            tangents=((1, 1.25), (-0.2, -1)),
        )
    # Align the cross section to the beginning of the path
    with BuildSketch(handle_path.line ^ 0) as handle_cross_section:
        RectangleRounded(wall_thickness, 8 * MM, fillet_radius)
    sweep()  # Sweep handle cross section along path

assert abs(tea_cup.part.volume - 130326) < 1

show(tea_cup, names=["tea cup"])

::: :::

<script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js"></script>

<model-viewer poster="_images/tea_cup.png" src="_static/tea_cup.glb" alt="A tea cup modelled in build123d" auto-rotate camera-controls style="width: 100%; height: 50vh;">{=html}</model-viewer>{=html}

::: {.admonition .note} Note

This documentation is available in pdf{.reference .external}[ [https://build123d.readthedocs.io/_/downloads/en/latest/pdf/]]{.link-target} and epub{.reference .external}[ [https://build123d.readthedocs.io/_/downloads/en/latest/epub/]]{.link-target} formats for reference while offline. :::

::: {.admonition .note} Note

There is a Discord{.reference .external}[ [https://discord.com/invite/Bj9AQPsCfx]]{.link-target} server (shared with CadQuery) where you can ask for help in the build123d channel. ::: :::

::: {#index.xhtml#table-of-contents .section}

Table Of Contents

::: {.toctree-wrapper .compound}

::: {#index.xhtml#indices-and-tables .section}

Indices and tables

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#introduction.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#introduction.xhtml#introduction .section}

Introduction

::: {#introduction.xhtml#key-aspects .section}

Key Aspects

The following sections describe some of the key aspects of build123d and illustrate why one might choose this open source system over proprietary options like SolidWorks, OnShape, Fusion 360, or even other open source systems like Blender, or OpenSCAD.

::: {#introduction.xhtml#boundary-representation-brep-modelling .section}

Boundary Representation (BREP) Modelling

Boundary representation (BREP) and mesh-based CAD systems are both used to create and manipulate 3D models, but they differ in the way they represent and store the models.

Advantages of BREP-based CAD systems (e.g. build123d & SolidWorks):

  • Precision: BREP-based CAD systems use mathematical representations to define the shape of an object, which allows for more precise and accurate modeling of complex shapes.

  • Topology: BREP-based CAD systems maintain topological information of the 3D model, such as edges, faces and vertices. This allows for more robust and stable modeling, such as Boolean operations.

  • Analytical modeling: BREP-based CAD systems can take advantage of the topological information to perform analytical operations such as collision detection, mass properties calculations, and finite element analysis.

  • Features-based modeling: BREP-based CAD systems are often feature-based, which means that the model is built by creating and modifying individual features, such as holes, fillets, and chamfers. This allows for parametric design and easy modification of the model.

  • Efficient storage: BREP-based CAD systems use a compact representation to store the 3D model, which is more efficient than storing a large number of triangles used in mesh-based systems.

Advantages of Mesh-based CAD systems (e.g. Blender, OpenSCAD):

  • Simplicity: Mesh-based CAD systems use a large number of triangles to represent the surface of an object, which makes them easy to use and understand.

  • Real-time rendering: Mesh-based CAD systems can be rendered in real-time, which is useful for applications such as video games and virtual reality.

  • Flexibility: Mesh-based CAD systems can be easily exported to other 3D modeling and animation software, which makes them a good choice for use in the entertainment industry.

  • Handling of freeform surfaces: Mesh-based systems are better equipped to handle freeform surfaces, such as those found in organic shapes, as they do not rely on mathematical representation.

  • Handling of large datasets: Mesh-based systems are more suitable for handling large datasets such as point clouds, as they can be easily converted into a mesh representation. :::

::: {#introduction.xhtml#parameterized-models .section}

Parameterized Models

Parametrized CAD systems are more effective than non-parametric CAD systems in several ways:

  • Reusability: Parametrized CAD models can be easily modified by changing a set of parameters, such as the length or width of an object, rather than having to manually edit the geometry. This makes it easy to create variations of a design without having to start from scratch.

  • Design exploration: Parametrized CAD systems allow for easy exploration of different design options by changing the parameters and quickly visualizing the results. This can save a lot of time and effort during the design process.

  • Constraints and relationships: Parametrized CAD systems allow for the definition of constraints and relationships between different parameters. This ensures that the model remains valid and functional even when parameters are changed.

  • Automation: Parametrized CAD systems can be automated to perform repetitive tasks, such as generating detailed drawings or creating parts lists. This can save a lot of time and effort and reduce the risk of errors.

  • Collaboration: Parametrized CAD systems allow different team members to work on different aspects of a design simultaneously and ensure that the model remains consistent across different stages of the development process.

  • Document management: Parametrized CAD systems can generate engineering drawings, BOMs, and other documents automatically, which makes it easier to manage and track the design history.

In summary, parametrized CAD systems are more effective than non-parametric CAD systems because they provide a more efficient and flexible way to create and modify designs, and can be easily integrated into the design, manufacturing, and documentation process. :::

::: {#introduction.xhtml#python-programming-language .section}

Python Programming Language

Python is a popular, high-level programming language that has several advantages over other programming languages:

  • Readability: Python code is easy to read and understand, with a clear and consistent syntax. This makes it a great language for beginners and for teams of developers who need to collaborate on a project.

  • Versatility: Python is a general-purpose language that can be used for a wide range of tasks, including web development, scientific computing, data analysis, artificial intelligence, and more. This makes it a great choice for developers who need to work on multiple types of projects.

  • Large community: Python has a large and active community of developers who contribute to the language and its ecosystem. This means that there are many libraries and frameworks available for developers to use, which can save a lot of time and effort.

  • Good for data science, machine learning, and CAD: Python has a number of libraries such as numpy, pandas, scikit-learn, tensorflow, and cadquery which are popularly used in data science and machine learning and CAD.

  • High-level language: Python is a high-level language, which means it abstracts away many of the low-level details of the computer. This makes it easy to write code quickly and focus on solving the problem at hand.

  • Cross-platform: Python code runs on many different platforms, including Windows, Mac, and Linux, making it a great choice for developers who need to write code that runs on multiple operating systems.

  • Open-source: Python is an open-source programming language, which means it is free to use and distribute. This makes it accessible to developers of all levels and budgets.

  • Large number of libraries and modules: Python has a vast collection of libraries and modules that make it easy to accomplish complex tasks such as connecting to web servers, reading and modifying files, and connecting to databases. :::

::: {#introduction.xhtml#open-source-software .section}

Open Source Software

Open source and proprietary software systems are different in several ways: B Licensing: Open source software is licensed in a way that allows users to view, modify, and distribute the source code, while proprietary software is closed source and the source code is not available to the public.

  • Ownership: Open source software is usually developed and maintained by a community of developers, while proprietary software is owned by a company or individual.

  • Cost: Open source software is typically free to use, while proprietary software may require payment for a license or subscription. Customization: Open source software can be modified and customized by users and developers, while proprietary software is typically not modifiable by users.

  • Support: Open source software may have a larger community of users who can provide support, while proprietary software may have a smaller community and relies on the company for support. Security: Open source software can be audited by a large community of developers, which can make it more secure, while proprietary software may have fewer eyes on the code and may be more vulnerable to security issues.

  • Interoperability: Open source software may have better interoperability with other software and platforms, while proprietary software may have more limited compatibility.

  • Reliability: Open source software can be considered as reliable as proprietary software. It is usually used by large companies, governments, and organizations and has been tested by a large number of users.

In summary, open source and proprietary software systems are different in terms of licensing, ownership, cost, customization, support, security, interoperability, and reliability. Open source software is typically free to use and can be modified by users and developers, while proprietary software is closed-source and may require payment for a license or subscription. Open source software may have a larger community of users who can provide support, while proprietary software may have a smaller community and relies on the company for support. :::

::: {#introduction.xhtml#source-code-control-systems .section}

Source Code Control Systems

Most GUI based CAD systems provide version control systems which represent the CAD design and its history. They allows developers to see changes made to the design over time, in a format that is easy to understand.

On the other hand, a source code control system like Git, is a command-line tool and it provides more granular control over the code. This makes it suitable for more advanced users and developers who are comfortable working with command-line interfaces. A source code control system like Git is more flexible and allows developers to perform tasks like branching and merging, which are not easily done with a GUI version control system. Systems like Git have several advantages, including:

  • Version control: Git allows developers to keep track of changes made to the code over time, making it easy to revert to a previous version if necessary.

  • Collaboration: Git makes it easy for multiple developers to work on the same codebase simultaneously, with the ability to merge changes from different branches of development.

  • Backup: Git provides a way to backup and store the codebase in a remote repository, like GitHub. This can serve as a disaster recovery mechanism, in case of data loss.

  • Branching: Git allows developers to create multiple branches of a project for different features or bug fixes, which can be easily merged into the main codebase once they are complete.

  • Auditing: Git allows you to see who made changes to the code, when and what changes were made, which is useful for auditing and debugging.

  • Open-source development: Git makes it easy for open-source developers to contribute to a project and share their work with the community.

  • Flexibility: Git is a distributed version control system, which means that developers can work independently and offline. They can then push their changes to a remote repository when they are ready to share them with others.

In summary, GUI version control systems are generally more user-friendly and easier to use, while source code control systems like Git offer more flexibility and control over the code. Both can be used to achieve the same goal, but they cater to different types of users and use cases. :::

::: {#introduction.xhtml#automated-testing .section}

Automated Testing

Users of source based CAD systems can benefit from automated testing which improves their source code by:

  • Finding bugs: Automated tests can detect bugs in the code, which can then be fixed before the code is released. This helps to ensure that the code is of higher quality and less likely to cause issues when used.

  • Regression testing: Automated tests can be used to detect regressions, which are bugs that are introduced by changes to the codebase. This helps to ensure that changes to the code do not break existing functionality.

  • Documenting code behavior: Automated tests can serve as documentation for how the code is supposed to behave. This makes it easier for developers to understand the code and make changes without breaking it.

  • Improving code design: Writing automated tests often requires a good understanding of the code and how it is supposed to behave. This can lead to a better design of the code, as developers will have a better understanding of the requirements and constraints.

  • Saving time and cost: Automated testing can save time and cost by reducing the need for manual testing. Automated tests can be run quickly and often, which means that bugs can be found and fixed early in the development process, which is less expensive than finding them later.

  • Continuous integration and delivery: Automated testing can be integrated into a continuous integration and delivery (CI/CD) pipeline. This means that tests are run automatically every time code is committed and can be integrated with other tools such as code coverage, static analysis and more.

  • Improving maintainability: Automated tests can improve the maintainability of the code by making it easier to refactor and change the codebase. This is because automated tests provide a safety net that ensures that changes to the code do not introduce new bugs.

Overall, automated testing is an essential part of the software development process, it helps to improve the quality of the code by detecting bugs early, documenting code behavior, and reducing the cost of maintaining and updating the code. :::

::: {#introduction.xhtml#automated-documentation .section}

Automated Documentation

The Sphinx automated documentation system was used to create the page you are reading now and can be used for user design documentation as well. Such systems are used for several reasons:

  • Consistency: Sphinx and other automated documentation systems can generate documentation in a consistent format and style, which makes it easier to understand and use.

  • Automation: Sphinx can automatically generate documentation from source code and comments, which saves time and effort compared to manually writing documentation.

  • Up-to-date documentation: Automated documentation systems like Sphinx can update the documentation automatically when the code changes, ensuring that the documentation stays up-to-date with the code.

  • Searchability: Sphinx and other automated documentation systems can include search functionality, which makes it easy to find the information you need.

  • Cross-referencing: Sphinx can automatically create links between different parts of the documentation, making it easy to navigate and understand the relationships between different parts of the code.

  • Customizable: Sphinx and other automated documentation systems can be customized to match the look and feel of your company's documentation.

  • Multiple output formats: Sphinx can generate documentation in multiple formats such as HTML, PDF, ePub, and more.

  • Support for multiple languages: Sphinx can generate documentation in multiple languages, which can make it easier to support international users.

  • Integration with code management: Sphinx can be integrated with code management tools like Git, which allows documentation to be versioned along with the code.

In summary, automated documentation systems like Sphinx are used to generate consistent, up-to-date, and searchable documentation from source code and comments. They save time and effort compared to manual documentation, and can be customized to match the look and feel of your company's documentation. They also provide multiple output formats, support for multiple languages and can be integrated with code management tools. ::: :::

::: {#introduction.xhtml#advantages-over-cadquery .section}

Advantages Over CadQuery

As mentioned previously, the most significant advantage is that build123d is more pythonic. Specifically:

::: {#introduction.xhtml#standard-python-context-manager .section}

Standard Python Context Manager

The creation of standard instance variables, looping and other normal python operations is enabled by the replacement of method chaining (fluent programming) with a standard python context manager.

::: {.highlight-python .notranslate} ::: highlight # CadQuery Fluent API pillow_block = (cq.Workplane("XY") .box(height, width, thickness) .edges("|Z") .fillet(fillet) .faces(">Z") .workplane() ... ) ::: :::

::: {.highlight-build123d .notranslate} ::: highlight # build123d API with BuildPart() as pillow_block: with BuildSketch() as plan: Rectangle(width, height) fillet(plan.vertices(), radius=fillet) extrude(thickness) ... ::: :::

The use of the standard <cite>{=html}with</cite>{=html} block allows standard python instructions to be inserted anyway in the code flow. One can insert a CQ-editor <cite>{=html}debug</cite>{=html} or standard <cite>{=html}print</cite>{=html} statement anywhere in the code without impacting functionality. Simple python <cite>{=html}for</cite>{=html} loops can be used to repetitively create objects instead of forcing users into using more complex <cite>{=html}lambda</cite>{=html} and <cite>{=html}iter</cite>{=html} operations. :::

::: {#introduction.xhtml#instantiated-objects .section}

Instantiated Objects

Each object and operation is now a class instantiation that interacts with the active context implicitly for the user. These instantiations can be assigned to an instance variable as with standard python programming for direct use.

::: {.highlight-build123d .notranslate} ::: highlight with BuildSketch() as plan: r = Rectangle(width, height) print(r.area) ... ::: ::: :::

::: {#introduction.xhtml#operators .section}

Operators

New operators have been created to extract information from objects created previously in the code. The <cite>{=html}@</cite>{=html} operator extracts the position along an Edge or Wire while the <cite>{=html}%</cite>{=html} operator extracts the tangent along an Edge or Wire. The position parameter are float values between 0.0 and 1.0 which represent the beginning and end of the line. In the following example, a spline is created from the end of l5 (<cite>{=html}l5 @ 1</cite>{=html}) to the beginning of l6 (<cite>{=html}l6 @ 0</cite>{=html}) with tangents equal to the tangents of l5 and l6 at their end and beginning respectively. Being able to extract information from existing features allows the user to "snap" new features to these points without knowing their numeric values.

::: {.highlight-build123d .notranslate} ::: highlight with BuildLine() as outline: ... l5 = Polyline(...) l6 = Polyline(...) Spline(l5 @ 1, l6 @ 0, tangents=(l5 % 1, l6 % 0)) ::: ::: :::

::: {#introduction.xhtml#last-operation-objects .section}

Last Operation Objects

All of the <cite>{=html}vertices()</cite>{=html}, <cite>{=html}edges()</cite>{=html}, <cite>{=html}faces()</cite>{=html}, and <cite>{=html}solids()</cite>{=html} methods of the builders can either return all of the objects requested or just the objects changed during the last operation. This allows the user to easily access features for further refinement, as shown in the following code where the final line selects the edges that were added by the last operation and fillets them. Such a selection would be quite difficult otherwise.

::: {.highlight-build123d .notranslate} ::: highlight from build123d import *

with BuildPart() as pipes:
    box = Box(10, 10, 10, rotation=(10, 20, 30))
    with BuildSketch(*box.faces()) as pipe:
        Circle(4)
    extrude(amount=-5, mode=Mode.SUBTRACT)
    with BuildSketch(*box.faces()) as pipe:
        Circle(4.5)
        Circle(4, mode=Mode.SUBTRACT)
    extrude(amount=10)
    fillet(pipes.edges(Select.LAST), 0.2)

::: ::: :::

::: {#introduction.xhtml#extensions .section}

Extensions

Extending build123d is relatively simple in that custom objects or operations can be created as new classes without the need to monkey patch any of the core functionality. These new classes will be seen in IDEs which is not possible with monkey patching the core CadQuery classes. :::

::: {#introduction.xhtml#enums .section}

Enums

All <cite>{=html}Literal</cite>{=html} strings have been replaced with <cite>{=html}Enum</cite>{=html} which allows IDEs to prompt users for valid options without having to refer to documentation. :::

::: {#introduction.xhtml#selectors-replaced-by-lists .section}

Selectors replaced by Lists

String based selectors have been replaced with standard python filters and sorting which opens up the full functionality of python lists. To aid the user, common operations have been optimized as shown here along with a fully custom selection:

::: {.highlight-build123d .notranslate} ::: highlight top = rail.faces().filter_by(Axis.Z)[-1] ... outside_vertices = filter( lambda v: (v.Y == 0.0 or v.Y == height) and -width / 2 < v.X < width / 2, din.vertices(), ) ::: ::: ::: ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#installation.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#installation.xhtml#installation .section}

Installation

The recommended method for most users to install build123d is:

::: {.highlight-pycon .notranslate} ::: highlight >>> pip install build123d ::: :::

::: {.admonition .note} Note

The ocp-vscode{.reference .external}[ [https://github.com/bernhard-42/vscode-ocp-cad-viewer]]{.link-target} viewer has the ability to install build123d. :::

::: {#installation.xhtml#install-build123d-from-github .section}

Install build123d from GitHub:

To get the latest non-released version of build123d one can install from GitHub using one of the following two commands:

In Linux/MacOS, use the following command:

::: {.highlight-pycon .notranslate} ::: highlight >>> python3 -m pip install git+https://github.com/gumyr/build123d ::: :::

In Windows, use the following command:

::: {.highlight-pycon .notranslate} ::: highlight >>> python -m pip install git+https://github.com/gumyr/build123d ::: :::

If you receive errors about conflicting dependencies, you can retry the installation after having upgraded pip to the latest version with the following command:

::: {.highlight-pycon .notranslate} ::: highlight >>> python3 -m pip install --upgrade pip ::: :::

If you use poetry{.reference .external}[ [https://python-poetry.org/]]{.link-target} to install build123d, you can simply use:

::: {.highlight-pycon .notranslate} ::: highlight >>> poetry add build123d ::: :::

However, if you want the latest commit from GitHub you might need to specify the branch that is used for git-based installs; until quite recently, poetry used to checkout the <cite>{=html}master</cite>{=html} branch when none was specified, and this fails on build123d that uses a <cite>{=html}dev</cite>{=html} branch.

Pip does not suffer from this issue because it correctly fetches the repository default branch.

If you are a poetry user, you can work around this issue by installing build123d in the following way:

::: {.highlight-pycon .notranslate} ::: highlight >>> poetry add git+https://github.com/gumyr/build123d.git@dev ::: :::

Please note that always suffixing the URL with @dev{.docutils .literal .notranslate} is safe and will work with both older and recent versions of poetry. :::

::: {#installation.xhtml#development-install-of-build123d .section}

Development install of build123d:

Warning: it is highly recommended to upgrade pip to the latest version before installing build123d, especially in development mode. This can be done with the following command:

::: {.highlight-pycon .notranslate} ::: highlight >>> python3 -m pip install --upgrade pip ::: :::

Once pip is up-to-date, you can install build123d in development mode{.reference .external}[ [https://setuptools.pypa.io/en/latest/userguide/development_mode.html]]{.link-target} with the following commands:

::: {.highlight-pycon .notranslate} ::: highlight >>> git clone https://github.com/gumyr/build123d.git >>> cd build123d >>> python3 -m pip install -e . ::: :::

Please substitute python3{.docutils .literal .notranslate} with python{.docutils .literal .notranslate} in the lines above if you are using Windows.

If you're working directly with the OpenCascade OCP{.docutils .literal .notranslate} layer you will likely want to install the OCP stubs as follows:

::: {.highlight-pycon .notranslate} ::: highlight >>> python3 -m pip install git+https://github.com/CadQuery/OCP-stubs@7.7.0 ::: ::: :::

::: {#installation.xhtml#test-your-build123d-installation .section}

Test your build123d installation:

If all has gone well, you can open a command line/prompt, and type:

::: {.highlight-pycon .notranslate} ::: highlight >>> python >>> from build123d import * >>> print(Solid.make_box(1,2,3).show_topology(limit_class="Face")) ::: :::

Which should return something similar to:

::: {.highlight-default .notranslate} ::: highlight Solid at 0x165e75379f0, Center(0.5, 1.0, 1.5) └── Shell at 0x165eab056f0, Center(0.5, 1.0, 1.5) ├── Face at 0x165b35a3570, Center(0.0, 1.0, 1.5) ├── Face at 0x165e77957f0, Center(1.0, 1.0, 1.5) ├── Face at 0x165b3e730f0, Center(0.5, 0.0, 1.5) ├── Face at 0x165e8821570, Center(0.5, 2.0, 1.5) ├── Face at 0x165e88218f0, Center(0.5, 1.0, 0.0) └── Face at 0x165eb21ee70, Center(0.5, 1.0, 3.0) ::: ::: :::

::: {#installation.xhtml#adding-a-nicer-gui .section}

Adding a nicer GUI

If you prefer to have a GUI available, your best option is to choose one from here: [External Tools and Libraries]{.std .std-ref}{.reference .internal} ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#key_concepts.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#key_concepts.xhtml#key-concepts .section}

Key Concepts

The following key concepts will help new users understand build123d quickly.

::: {#key_concepts.xhtml#topology .section} []{#key_concepts.xhtml#id1}

Topology

Topology, in the context of 3D modeling and computational geometry, is the branch of mathematics that deals with the properties and relationships of geometric objects that are preserved under continuous deformations. In the context of CAD and modeling software like build123d, topology refers to the hierarchical structure of geometric elements (vertices, edges, faces, etc.) and their relationships in a 3D model. This structure defines how the components of a model are connected, enabling operations like Boolean operations, transformations, and analysis of complex shapes. Topology provides a formal framework for understanding and manipulating geometric data in a consistent and reliable manner.

The following are the topological objects that compose build123d objects:

Vertex{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}

A Vertex is a data structure representing a 0D topological element. It defines a precise point in 3D space, often at the endpoints or intersections of edges in a 3D model. These vertices are part of the topological structure used to represent complex shapes in build123d.

Edge{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}

An Edge in build123d is a fundamental geometric entity representing a 1D element in a 3D model. It defines the shape and position of a 1D curve within the model. Edges play a crucial role in defining the boundaries of faces and in constructing complex 3D shapes.

Wire{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}

A Wire in build123d is a topological construct that represents a connected sequence of Edges, forming a 1D closed or open loop within a 3D model. Wires define the boundaries of faces and can be used to create complex shapes, making them essential for modeling in build123d.

Face{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}

A Face in build123d represents a 2D surface in a 3D model. It defines the boundary of a region and can have associated geometric and topological data. Faces are vital for shaping solids, providing surfaces where other elements like edges and wires are connected to form complex structures.

Shell{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}

A Shell in build123d represents a collection of Faces, defining a closed, connected volume in 3D space. It acts as a container for organizing and grouping faces into a single shell, essential for defining complex 3D shapes like solids or assemblies within the build123d modeling framework.

Solid{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}

A Solid in build123d is a 3D geometric entity that represents a bounded volume with well-defined interior and exterior surfaces. It encapsulates a closed and watertight shape, making it suitable for modeling solid objects and enabling various Boolean operations such as union, intersection, and subtraction.

Compound{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}

A Compound in build123d is a container for grouping multiple geometric shapes. It can hold various types of entities, such as vertices, edges, wires, faces, shells, or solids, into a single structure. This makes it a versatile tool for managing and organizing complex assemblies or collections of shapes within a single container.

Shape{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}

A Shape in build123d represents a fundamental building block in 3D modeling. It encompasses various topological elements like vertices, edges, wires, faces, shells, solids, and compounds. The Shape class is the base class for all of the above topological classes.

One can use the show_topology(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} method to display the topology of a shape as shown here for a unit cube:

::: {.highlight-default .notranslate} ::: highlight Solid at 0x7f94c55430f0, Center(0.5, 0.5, 0.5) └── Shell at 0x7f94b95835f0, Center(0.5, 0.5, 0.5) ├── Face at 0x7f94b95836b0, Center(0.0, 0.5, 0.5) │ └── Wire at 0x7f94b9583730, Center(0.0, 0.5, 0.5) │ ├── Edge at 0x7f94b95838b0, Center(0.0, 0.0, 0.5) │ │ ├── Vertex at 0x7f94b9583470, Center(0.0, 0.0, 1.0) │ │ └── Vertex at 0x7f94b9583bb0, Center(0.0, 0.0, 0.0) │ ├── Edge at 0x7f94b9583a30, Center(0.0, 0.5, 1.0) │ │ ├── Vertex at 0x7f94b9583030, Center(0.0, 1.0, 1.0) │ │ └── Vertex at 0x7f94b9583e70, Center(0.0, 0.0, 1.0) │ ├── Edge at 0x7f94b9583770, Center(0.0, 1.0, 0.5) │ │ ├── Vertex at 0x7f94b9583bb0, Center(0.0, 1.0, 1.0) │ │ └── Vertex at 0x7f94b9583e70, Center(0.0, 1.0, 0.0) │ └── Edge at 0x7f94b9583db0, Center(0.0, 0.5, 0.0) │ ├── Vertex at 0x7f94b9583e70, Center(0.0, 1.0, 0.0) │ └── Vertex at 0x7f94b95862f0, Center(0.0, 0.0, 0.0) ... └── Face at 0x7f94b958d3b0, Center(0.5, 0.5, 1.0) └── Wire at 0x7f94b958d670, Center(0.5, 0.5, 1.0) ├── Edge at 0x7f94b958e130, Center(0.0, 0.5, 1.0) │ ├── Vertex at 0x7f94b958e330, Center(0.0, 1.0, 1.0) │ └── Vertex at 0x7f94b958e770, Center(0.0, 0.0, 1.0) ├── Edge at 0x7f94b958e630, Center(0.5, 1.0, 1.0) │ ├── Vertex at 0x7f94b958e8b0, Center(1.0, 1.0, 1.0) │ └── Vertex at 0x7f94b958ea70, Center(0.0, 1.0, 1.0) ├── Edge at 0x7f94b958e7b0, Center(1.0, 0.5, 1.0) │ ├── Vertex at 0x7f94b958ebb0, Center(1.0, 1.0, 1.0) │ └── Vertex at 0x7f94b958ed70, Center(1.0, 0.0, 1.0) └── Edge at 0x7f94b958eab0, Center(0.5, 0.0, 1.0) ├── Vertex at 0x7f94b958eeb0, Center(1.0, 0.0, 1.0) └── Vertex at 0x7f94b9592170, Center(0.0, 0.0, 1.0) ::: :::

Users of build123d will often reference topological objects as part of the process of creating the object as described below. :::

::: {#key_concepts.xhtml#location .section}

Location

A Location{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} represents a combination of translation and rotation applied to a topological or geometric object. It encapsulates information about the spatial orientation and position of a shape within its reference coordinate system. This allows for efficient manipulation of shapes within complex assemblies or transformations. The location is typically used to position shapes accurately within a 3D scene, enabling operations like assembly, and boolean operations. It's an essential component in build123d for managing the spatial relationships of geometric entities, providing a foundation for precise 3D modeling and engineering applications.

The topological classes (sub-classes of Shape{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}) and the geometric classes Axis{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and Plane{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} all have a location{.docutils .literal .notranslate} property. The Location{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} class itself has position{.docutils .literal .notranslate} and orientation{.docutils .literal .notranslate} properties that have setters and getters as shown below:

::: {.highlight-pycon .notranslate} ::: highlight >>> from build123d import * >>> # Create an object and extract its location >>> b = Box(1, 1, 1) >>> box_location = b.location >>> box_location (p=(0.00, 0.00, 0.00), o=(-0.00, 0.00, -0.00)) >>> # Set position and orientation independently >>> box_location.position = (1, 2, 3) >>> box_location.orientation = (30, 40, 50) >>> box_location.position Vector: (1.0, 2.0, 3.0) >>> box_location.orientation Vector: (29.999999999999993, 40.00000000000002, 50.000000000000036) ::: :::

Combining the getter and setter enables relative changes as follows:

::: {.highlight-pycon .notranslate} ::: highlight >>> # Relative change >>> box_location.position += (3, 2, 1) >>> box_location.position Vector: (4.0, 4.0, 4.0) ::: :::

There are also four methods that are used to change the location of objects:

Locations can be combined with the *{.docutils .literal .notranslate} operator and have their direction flipped with the -{.docutils .literal .notranslate} operator. :::

::: {#key_concepts.xhtml#selectors .section}

Selectors

When using a GUI based CAD system the user will often click on a feature to select it for some operation. How does a user "click" when CAD is done entirely in code? Selectors are recipes for how to isolate a feature from a design using python filter and sorting methods typically implemented as a set of custom python operations.

::: {#key_concepts.xhtml#quick-reference .section}

Quick Reference

The following tables describes the build123d selectors:

Selector Applicability Description Example


vertices() BuildLine, BuildSketch, BuildPart Vertex extraction <cite>{=html}part.vertices()</cite>{=html} edges() BuildLine, BuildSketch, BuildPart Edge extraction <cite>{=html}part.edges()</cite>{=html} wires() BuildLine, BuildSketch, BuildPart Wire extraction <cite>{=html}part.wires()</cite>{=html} faces() BuildSketch, BuildPart Face extraction <cite>{=html}part.faces()</cite>{=html} solids() BuildPart Solid extraction <cite>{=html}part.solids()</cite>{=html}

Operator Operand Method Description Example


> SortBy, Axis sort_by Sort ShapeList by operand <cite>{=html}part.vertices() > Axis.Z</cite>{=html} < SortBy, Axis sort_by Reverse sort ShapeList by operand <cite>{=html}part.faces() < Axis.Z</cite>{=html} >> SortBy, Axis group_by Group ShapeList by operand and return last value <cite>{=html}part.solids() >> Axis.X</cite>{=html} << SortBy, Axis group_by Group ShapeList by operand and return first value <cite>{=html}part.faces() << Axis.Y</cite>{=html} | Axis, Plane, GeomType filter_by Filter and sort ShapeList by Axis, Plane, or GeomType <cite>{=html}part.faces() | Axis.Z</cite>{=html}

         Axis                    filter_by_position   Filter ShapeList by Axis & mix / max values             `<cite>`{=html}part.faces()..filter_by_position(Axis.Z, 1, 2, inclusive=(False, True))`</cite>`{=html}

The operand types are: Axis, Plane, SortBy, and GeomType. An Axis is a base object with an origin and a direction with several predefined values such as Axis.X{.docutils .literal .notranslate}, Axis.Y{.docutils .literal .notranslate}, and Axis.Z{.docutils .literal .notranslate}; however, any Axis could be used as an operand (e.g. Axis((1,2,3),(0.5,0,-0.5)){.docutils .literal .notranslate} is valid) - see Axis{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} for a complete description. A Plane is a coordinate system defined by an origin, x_dir (X direction), y_dir (Y direction), and z_dir (Z direction). See Plane{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} for a complete description. Filtering by a Plane will return faces/edges parallel to it. SortBy and GeomType are python Enum class described here:

GeomType{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}

BEZIER, BSPLINE, CIRCLE, CONE, CYLINDER, ELLIPSE, EXTRUSION, HYPERBOLA, LINE, OFFSET, OTHER, PARABOLA, PLANE, REVOLUTION, SPHERE, TORUS

SortBy{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}

LENGTH, RADIUS, AREA, VOLUME, DISTANCE :::

::: {#key_concepts.xhtml#shapelist-class .section}

ShapeList Class

The builders include methods to extract Edges, Faces, Solids, Vertices, or Wires from the objects they are building. All of these methods return objects of a subclass of <cite>{=html}list</cite>{=html}, a ShapeList{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} with custom filtering and sorting methods and operations as follows. :::

::: {#key_concepts.xhtml#custom-sorting-and-filtering .section}

Custom Sorting and Filtering

It is important to note that standard list methods such as <cite>{=html}sorted</cite>{=html} or <cite>{=html}filtered</cite>{=html} can be used to easily build complex selectors beyond what is available with the predefined sorts and filters. Here is an example of a custom filters:

::: {.highlight-build123d .notranslate} ::: highlight with BuildSketch() as din: ... outside_vertices = filter( lambda v: (v.Y == 0.0 or v.Y == height) and -overall_width / 2 < v.X < overall_width / 2, din.vertices(), ) ::: :::

The filter_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} method can take lambda expressions as part of a fluent chain of operations which enables integration of custom filters into a larger change of selectors as shown in this example:

::: {.highlight-build123d .notranslate} ::: highlight obj = Box(1, 1, 1) - Cylinder(0.2, 1) faces_with_holes = obj.faces().filter_by(lambda f: f.inner_wires()) ::: :::

Here the two faces with "inner_wires" (i.e. holes) have been selected independent of orientation. ::: ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#key_concepts_builder.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#key_concepts_builder.xhtml#key-concepts-builder-mode .section}

Key Concepts (builder mode)

There are two primary APIs provided by build123d: builder and algebra. The builder API may be easier for new users as it provides some assistance and shortcuts; however, if you know what a Quaternion is you might prefer the algebra API which allows CAD objects to be created in the style of mathematical equations. Both API can be mixed in the same model with the exception that the algebra API can't be used from within a builder context. As with music, there is no "best" genre or API, use the one you prefer or both if you like.

The following key concepts will help new users understand build123d quickly.

::: {#key_concepts_builder.xhtml#understanding-the-builder-paradigm .section}

Understanding the Builder Paradigm

The Builder paradigm in build123d provides a powerful and intuitive way to construct complex geometric models. At its core, the Builder works like adding a column of numbers on a piece of paper: a running "total" is maintained internally as each new object is added or modified. This approach simplifies the process of constructing models by breaking it into smaller, incremental steps.

::: {#key_concepts_builder.xhtml#how-the-builder-works .section}

How the Builder Works

When using a Builder (such as BuildLine, BuildSketch, or BuildPart), the following principles apply:

  1. Running Total: - The Builder maintains an internal "total," which represents the current state of the object being built. - Each operation updates this total by combining the new object with the existing one.

  2. Combination Modes: - Just as numbers in a column may have a <cite>{=html}+</cite>{=html} or <cite>{=html}-</cite>{=html} sign to indicate addition or subtraction, Builders use modes to control how each object is combined with the current total. - Common modes include:

    • ADD: Adds the new object to the current total.

    • SUBTRACT: Removes the new object from the current total.

    • INTERSECT: Keeps only the overlapping regions of the new object and the current total.

    • REPLACE: Entirely replace the running total.

    • PRIVATE: Don't change the running total at all.

    • The mode can be set dynamically for each operation, allowing for flexible and precise modeling.
  3. Extracting the Result: - At the end of the building process, the final object is accessed through the Builder's attributes, such as .line{.docutils .literal .notranslate}, .sketch{.docutils .literal .notranslate}, or .part{.docutils .literal .notranslate}, depending on the Builder type. - For example:

    • BuildLine: Use .line{.docutils .literal .notranslate} to retrieve the final wireframe geometry.

    • BuildSketch: Use .sketch{.docutils .literal .notranslate} to extract the completed 2D profile.

    • BuildPart: Use .part{.docutils .literal .notranslate} to obtain the 3D solid.

:::

::: {#key_concepts_builder.xhtml#example-workflow .section}

Example Workflow

Here is an example of using a Builder to create a simple part:

::: {.highlight-build123d .notranslate} ::: highlight from build123d import *

# Using BuildPart to create a 3D model
with BuildPart() as example_part:
    with BuildSketch() as base_sketch:
        Rectangle(20, 20)
    extrude(amount=10)  # Create a base block
    with BuildSketch(Plane(example_part.faces().sort_by(Axis.Z).last)) as cut_sketch:
        Circle(5)
    extrude(amount=-5, mode=Mode.SUBTRACT)  # Subtract a cylinder

# Access the final part
result_part = example_part.part

::: ::: :::

::: {#key_concepts_builder.xhtml#key-concepts .section}

Key Concepts

  • Incremental Construction: Builders allow you to build objects step-by-step, maintaining clarity and modularity.

  • Dynamic Mode Switching: The mode parameter gives you precise control over how each operation modifies the current total.

  • Seamless Extraction: The Builder paradigm simplifies the retrieval of the final object, ensuring that you always have access to the most up-to-date result. :::

::: {#key_concepts_builder.xhtml#analogy-adding-numbers-on-paper .section}

Analogy: Adding Numbers on Paper

Think of the Builder as a running tally when adding numbers on a piece of paper:

  • Each number represents an operation or object.

  • The +{.docutils .literal .notranslate} or -{.docutils .literal .notranslate} sign corresponds to the ADD or SUBTRACT mode.

  • At the end, the total is the sum of all operations, which you can retrieve by referencing the Builder's output.

By adopting this approach, build123d ensures a natural, intuitive workflow for constructing 2D and 3D models. ::: :::

::: {#key_concepts_builder.xhtml#builders .section}

Builders

The three builders, BuildLine{.docutils .literal .notranslate}, BuildSketch{.docutils .literal .notranslate}, and BuildPart{.docutils .literal .notranslate} are tools to create new objects - not the objects themselves. Each of the objects and operations applicable to these builders create objects of the standard CadQuery Direct API, most commonly Compound{.docutils .literal .notranslate} objects. This is opposed to CadQuery's Fluent API which creates objects of the Workplane{.docutils .literal .notranslate} class which frequently needed to be converted back to base class for further processing.

One can access the objects created by these builders by referencing the appropriate instance variable. For example:

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as my_part: ...

show_object(my_part.part)

::: :::

::: {.highlight-build123d .notranslate} ::: highlight with BuildSketch() as my_sketch: ...

show_object(my_sketch.sketch)

::: :::

::: {.highlight-build123d .notranslate} ::: highlight with BuildLine() as my_line: ...

show_object(my_line.line)

::: ::: :::

::: {#key_concepts_builder.xhtml#implicit-builder-instance-variables .section}

Implicit Builder Instance Variables

One might expect to have to reference a builder's instance variable when using objects or operations that impact that builder like this:

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as part_builder: Box(part_builder, 10,10,10) ::: :::

Instead, build123d determines from the scope of the object or operation which builder it applies to thus eliminating the need for the user to provide this information - as follows:

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as part_builder: Box(10,10,10) with BuildSketch() as sketch_builder: Circle(2) ::: :::

In this example, Box{.docutils .literal .notranslate} is in the scope of part_builder{.docutils .literal .notranslate} while Circle{.docutils .literal .notranslate} is in the scope of sketch_builder{.docutils .literal .notranslate}. :::

::: {#key_concepts_builder.xhtml#workplanes .section}

Workplanes

As build123d is a 3D CAD package one must be able to position objects anywhere. As one frequently will work in the same plane for a sequence of operations, the first parameter(s) of the builders is a (sequence of) workplane(s) which is (are) used to aid in the location of features. The default workplane in most cases is the Plane.XY{.docutils .literal .notranslate} where a tuple of numbers represent positions on the x and y axes. However workplanes can be generated on any plane which allows users to put a workplane where they are working and then work in local 2D coordinate space.

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart(Plane.XY) as example: ... # a 3D-part with BuildSketch(example.faces().sort_by(sort_by=Axis.Z)[0]) as bottom: ... with BuildSketch(Plane.XZ) as vertical: ... with BuildSketch(example.faces().sort_by(sort_by=Axis.Z)[-1]) as top: ... ::: :::

When BuildPart{.docutils .literal .notranslate} is invoked it creates the workplane provided as a parameter (which has a default of the Plane.XY{.docutils .literal .notranslate}). The bottom{.docutils .literal .notranslate} sketch is therefore created on the Plane.XY{.docutils .literal .notranslate} but with the normal reversed to point down. Subsequently the user has created the vertical{.docutils .literal .notranslate} (Plane.XZ{.docutils .literal .notranslate}) sketch. All objects or operations within the scope of a workplane will automatically be orientated with respect to this plane so the user only has to work with local coordinates.

As shown above, workplanes can be created from faces as well. The top{.docutils .literal .notranslate} sketch is positioned on top of example{.docutils .literal .notranslate} by selecting its faces and finding the one with the greatest z value.

One is not limited to a single workplane at a time. In the following example all six faces of the first box are used to define workplanes which are then used to position rotated boxes.

::: {.highlight-build123d .notranslate} ::: highlight import build123d as bd

with bd.BuildPart() as bp:
    bd.Box(3, 3, 3)
    with bd.BuildSketch(*bp.faces()):
        bd.Rectangle(1, 2, rotation=45)
    bd.extrude(amount=0.1)

::: :::

This is the result:

{.align-center} :::

::: {#key_concepts_builder.xhtml#locations-context .section} []{#key_concepts_builder.xhtml#location-context-link}

Locations Context

When positioning objects or operations within a builder Location Contexts are used. These function in a very similar was to the builders in that they create a context where one or more locations are active within a scope. For example:

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart(): with Locations((0,10),(0,-10)): Box(1,1,1) with GridLocations(x_spacing=5, y_spacing=5, x_count=2, y_count=2): Sphere(1) Cylinder(1,1) ::: :::

In this example Locations{.docutils .literal .notranslate} creates two positions on the current workplane at (0,10) and (0,-10). Since Box{.docutils .literal .notranslate} is within the scope of Locations{.docutils .literal .notranslate}, two boxes are created at these locations. The GridLocations{.docutils .literal .notranslate} context creates four positions which apply to the Sphere{.docutils .literal .notranslate}. The Cylinder{.docutils .literal .notranslate} is out of the scope of GridLocations{.docutils .literal .notranslate} but in the scope of Locations{.docutils .literal .notranslate} so two cylinders are created.

Note that these contexts are creating Location objects not just simple points. The difference isn't obvious until the PolarLocations{.docutils .literal .notranslate} context is used which can also rotate objects within its scope - much as the hour and minute indicator on an analogue clock.

Also note that the locations are local to the current location(s) - i.e. Locations{.docutils .literal .notranslate} can be nested. It's easy for a user to retrieve the global locations:

::: {.highlight-build123d .notranslate} ::: highlight with Locations(Plane.XY, Plane.XZ): locs = GridLocations(1, 1, 2, 2) for l in locs: print(l) ::: :::

::: {.highlight-default .notranslate} ::: highlight Location(p=(-0.50,-0.50,0.00), o=(0.00,-0.00,0.00)) Location(p=(-0.50,0.50,0.00), o=(0.00,-0.00,0.00)) Location(p=(0.50,-0.50,0.00), o=(0.00,-0.00,0.00)) Location(p=(0.50,0.50,0.00), o=(0.00,-0.00,0.00)) Location(p=(-0.50,-0.00,-0.50), o=(90.00,-0.00,0.00)) Location(p=(-0.50,0.00,0.50), o=(90.00,-0.00,0.00)) Location(p=(0.50,0.00,-0.50), o=(90.00,-0.00,0.00)) Location(p=(0.50,0.00,0.50), o=(90.00,-0.00,0.00)) ::: ::: :::

::: {#key_concepts_builder.xhtml#operation-inputs .section}

Operation Inputs

When one is operating on an existing object, e.g. adding a fillet to a part, an iterable of objects is often required (often a ShapeList).

Here is the definition of fillet(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} to help illustrate:

::: {.highlight-build123d .notranslate} ::: highlight def fillet( objects: Union[Union[Edge, Vertex], Iterable[Union[Edge, Vertex]]], radius: float, ): ::: :::

To use this fillet operation, an edge or vertex or iterable of edges or vertices must be provided followed by a fillet radius with or without the keyword as follows:

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as pipes: Box(10, 10, 10, rotation=(10, 20, 30)) ... fillet(pipes.edges(Select.LAST), radius=0.2) ::: :::

Here the fillet accepts the iterable ShapeList of edges from the last operation of the pipes{.docutils .literal .notranslate} builder and a radius is provided as a keyword argument. :::

::: {#key_concepts_builder.xhtml#combination-modes .section}

Combination Modes

Almost all objects or operations have a mode{.docutils .literal .notranslate} parameter which is defined by the Mode{.docutils .literal .notranslate} Enum class as follows:

::: {.highlight-build123d .notranslate} ::: highlight class Mode(Enum): ADD = auto() SUBTRACT = auto() INTERSECT = auto() REPLACE = auto() PRIVATE = auto() ::: :::

The mode{.docutils .literal .notranslate} parameter describes how the user would like the object or operation to interact with the object within the builder. For example, Mode.ADD{.docutils .literal .notranslate} will integrate a new object(s) in with an existing part{.docutils .literal .notranslate}. Note that a part doesn't necessarily have to be a single object so multiple distinct objects could be added resulting is multiple objects stored as a Compound{.docutils .literal .notranslate} object. As one might expect Mode.SUBTRACT{.docutils .literal .notranslate}, Mode.INTERSECT{.docutils .literal .notranslate}, and Mode.REPLACE{.docutils .literal .notranslate} subtract, intersect, or replace (from) the builder's object. Mode.PRIVATE{.docutils .literal .notranslate} instructs the builder that this object should not be combined with the builder's object in any way.

Most commonly, the default mode{.docutils .literal .notranslate} is Mode.ADD{.docutils .literal .notranslate} but this isn't always true. For example, the Hole{.docutils .literal .notranslate} classes use a default Mode.SUBTRACT{.docutils .literal .notranslate} as they remove a volume from the part under normal circumstances. However, the mode{.docutils .literal .notranslate} used in the Hole{.docutils .literal .notranslate} classes can be specified as Mode.ADD{.docutils .literal .notranslate} or Mode.INTERSECT{.docutils .literal .notranslate} to help in inspection or debugging. :::

::: {#key_concepts_builder.xhtml#using-locations-rotating-objects .section}

Using Locations & Rotating Objects

build123d stores points (to be specific Location{.docutils .literal .notranslate} (s)) internally to be used as positions for the placement of new objects. By default, a single location will be created at the origin of the given workplane such that:

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as pipes: Box(10, 10, 10, rotation=(10, 20, 30)) ::: :::

will create a single 10x10x10 box centered at (0,0,0) - by default objects are centered. One can create multiple objects by pushing points prior to creating objects as follows:

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as pipes: with Locations((-10, -10, -10), (10, 10, 10)): Box(10, 10, 10, rotation=(10, 20, 30)) ::: :::

which will create two boxes.

To orient a part, a rotation{.docutils .literal .notranslate} parameter is available on BuildSketch`{.docutils .literal .notranslate} and BuildPart{.docutils .literal .notranslate} APIs. When working in a sketch, the rotation is a single angle in degrees so the parameter is a float. When working on a part, the rotation is a three dimensional Rotation{.docutils .literal .notranslate} object of the form Rotation(<about x>, <about y>, <about z>){.docutils .literal .notranslate} although a simple three tuple of floats can be used as input. As 3D rotations are not cumulative, one can combine rotations with the <cite>{=html}*</cite>{=html} operator like this: Rotation(10, 20, 30) * Rotation(0, 90, 0){.docutils .literal .notranslate} to generate any desired rotation.

::: {.admonition .hint} Hint

Experts Only

Locations{.docutils .literal .notranslate} will accept Location{.docutils .literal .notranslate} objects for input which allows one to specify both the position and orientation. However, the orientation is often determined by the Plane{.docutils .literal .notranslate} that an object was created on. Rotation{.docutils .literal .notranslate} is a subclass of Location{.docutils .literal .notranslate} and therefore will also accept a position component. ::: :::

::: {#key_concepts_builder.xhtml#builder-s-pending-objects .section}

Builder's Pending Objects

When a builder exits, it will push the object created back to its parent if there was one. Here is an example:

::: {.highlight-build123d .notranslate} ::: highlight height, width, thickness, f_rad = 60, 80, 20, 10

with BuildPart() as pillow_block:
    with BuildSketch() as plan:
        Rectangle(width, height)
        fillet(plan.vertices(), radius=f_rad)
    extrude(amount=thickness)

::: :::

BuildSketch{.docutils .literal .notranslate} exits after the fillet{.docutils .literal .notranslate} operation and when doing so it transfers the sketch to the pillow_block{.docutils .literal .notranslate} instance of BuildPart{.docutils .literal .notranslate} as the internal instance variable pending_faces{.docutils .literal .notranslate}. This allows the extrude{.docutils .literal .notranslate} operation to be immediately invoked as it extrudes these pending faces into Solid{.docutils .literal .notranslate} objects. Likewise, loft{.docutils .literal .notranslate} would take all of the pending_faces{.docutils .literal .notranslate} and attempt to create a single Solid{.docutils .literal .notranslate} object from them.

Normally the user will not need to interact directly with pending objects; however, one can see pending Edges and Faces with <builder_instance>.pending_edges{.docutils .literal .notranslate} and <builder_instance>.pending_faces{.docutils .literal .notranslate} attributes. In the above example, by adding a print(pillow_block.pending_faces){.docutils .literal .notranslate} prior to the extrude(amount=thickness){.docutils .literal .notranslate} the pending Face{.docutils .literal .notranslate} from the BuildSketch{.docutils .literal .notranslate} will be displayed. ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#key_concepts_algebra.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#key_concepts_algebra.xhtml#key-concepts-algebra-mode .section}

Key Concepts (algebra mode)

Build123d's algebra mode works on objects of the classes Shape{.docutils .literal .notranslate}, Part{.docutils .literal .notranslate}, Sketch{.docutils .literal .notranslate} and Curve{.docutils .literal .notranslate} and is based on two concepts:

  1. Object arithmetic

  2. Placement arithmetic

::: {#key_concepts_algebra.xhtml#object-arithmetic .section}

Object arithmetic

  • Creating a box and a cylinder centered at (0, 0, 0){.docutils .literal .notranslate}

    ::: {.highlight-build123d .notranslate} ::: highlight b = Box(1, 2, 3) c = Cylinder(0.2, 5) ::: :::

  • Fusing a box and a cylinder

    ::: {.highlight-build123d .notranslate} ::: highlight r = Box(1, 2, 3) + Cylinder(0.2, 5) ::: :::

  • Cutting a cylinder from a box

    ::: {.highlight-build123d .notranslate} ::: highlight r = Box(1, 2, 3) - Cylinder(0.2, 5) ::: :::

  • Intersecting a box and a cylinder

    ::: {.highlight-build123d .notranslate} ::: highlight r = Box(1, 2, 3) & Cylinder(0.2, 5) ::: :::

Notes:

  • <cite>{=html}b</cite>{=html}, <cite>{=html}c</cite>{=html} and <cite>{=html}r</cite>{=html} are instances of class Compound{.docutils .literal .notranslate} and can be viewed with every viewer that can show build123d.Compound{.docutils .literal .notranslate} objects.

  • A discussion around performance can be found in [Performance considerations in algebra mode]{.std .std-ref}{.reference .internal}.

  • A mathematically formal definition of the algebra can be found in [Algebraic definition]{.std .std-ref}{.reference .internal}. :::

::: {#key_concepts_algebra.xhtml#placement-arithmetic .section}

Placement arithmetic

A Part{.docutils .literal .notranslate}, Sketch{.docutils .literal .notranslate} or Curve{.docutils .literal .notranslate} does not have any location or rotation parameter. The rationale is that an object defines its topology (shape, sizes and its center), but does not know where in space it will be located. Instead, it will be relocated with the *{.docutils .literal .notranslate} operator onto a plane and to location relative to the plane (similar moved{.docutils .literal .notranslate}).

The generic forms of object placement are:

  1. Placement on plane{.docutils .literal .notranslate} or at location{.docutils .literal .notranslate} relative to XY plane:

    ::: {.highlight-build123d .notranslate} ::: highlight plane * alg_compound location * alg_compound ::: :::

2. Placement on the plane{.docutils .literal .notranslate} and then moved relative to the plane{.docutils .literal .notranslate} by location{.docutils .literal .notranslate} (the location is relative to the local coordinate system of the plane).

::: {.highlight-build123d .notranslate} ::: highlight plane * location * alg_compound ::: :::

Details can be found in [Location arithmetic for algebra mode]{.std .std-ref}{.reference .internal}.

Examples:

  • Box on the XY{.docutils .literal .notranslate} plane, centered at <cite>{=html}(0, 0, 0)</cite>{=html} (both forms are equivalent):

    ::: {.highlight-build123d .notranslate} ::: highlight Plane.XY * Box(1, 2, 3)

    Box(1, 2, 3)
    

    ::: :::

    Note: On the XY{.docutils .literal .notranslate} plane no placement is needed (mathematically Plane.XY *{.docutils .literal .notranslate} will not change the location of an object).

  • Box on the XY{.docutils .literal .notranslate} plane centered at <cite>{=html}(0, 1, 0)</cite>{=html} (all three are equivalent):

    ::: {.highlight-build123d .notranslate} ::: highlight Plane.XY * Pos(0, 1, 0) * Box(1, 2, 3)

    Pos(0, 1, 0) * Box(1, 2, 3)
    
    Pos(Y=1) * Box(1, 2, 3)
    

    ::: :::

    Note: Again, Plane.XY{.docutils .literal .notranslate} can be omitted.

  • Box on plane Plane.XZ{.docutils .literal .notranslate}:

    ::: {.highlight-build123d .notranslate} ::: highlight Plane.XZ * Box(1, 2, 3) ::: :::

  • Box on plane Plane.XZ{.docutils .literal .notranslate} with a location (X=1, Y=2, Z=3){.docutils .literal .notranslate} relative to the XZ{.docutils .literal .notranslate} plane, i.e., using the x-, y- and z-axis of the XZ{.docutils .literal .notranslate} plane:

    ::: {.highlight-build123d .notranslate} ::: highlight Plane.XZ * Pos(1, 2, 3) * Box(1, 2, 3) ::: :::

  • Box on plane Plane.XZ{.docutils .literal .notranslate} moved to (X=1, Y=2, Z=3){.docutils .literal .notranslate} relative to this plane and rotated there by the angles <cite>{=html}(X=0, Y=100, Z=45)</cite>{=html} around Plane.XZ{.docutils .literal .notranslate} axes:

    ::: {.highlight-build123d .notranslate} ::: highlight Plane.XZ * Pos(1, 2, 3) * Rot(0, 100, 45) * Box(1, 2, 3)

    Location((1, 2, 3), (0, 100, 45)) * Box(1, 2, 3)
    

    ::: :::

    Note: Pos * Rot{.docutils .literal .notranslate} is the same as using Location{.docutils .literal .notranslate} directly

  • Box on plane Plane.XZ{.docutils .literal .notranslate} rotated on this plane by the angles (X=0, Y=100, Z=45){.docutils .literal .notranslate} (using the x-, y- and z-axis of the XZ{.docutils .literal .notranslate} plane) and then moved to (X=1, Y=2, Z=3){.docutils .literal .notranslate} relative to the XZ{.docutils .literal .notranslate} plane:

    ::: {.highlight-build123d .notranslate} ::: highlight Plane.XZ * Rot(0, 100, 45) * Pos(0,1,2) * Box(1, 2, 3) ::: ::: :::

::: {#key_concepts_algebra.xhtml#combing-both-concepts .section}

Combing both concepts

Object arithmetic and Placement at locations can be combined:

::: {.highlight-build123d .notranslate} ::: highlight b = Plane.XZ * Rot(X=30) * Box(1, 2, 3) + Plane.YZ * Pos(X=-1) * Cylinder(0.2, 5) ::: :::

Note: In Python *{.docutils .literal .notranslate} binds stronger then +{.docutils .literal .notranslate}, -{.docutils .literal .notranslate}, &{.docutils .literal .notranslate}, hence brackets are not needed. ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#moving_objects.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#moving_objects.xhtml#moving-objects .section}

Moving Objects

In build123d, there are several methods to move objects. These methods vary based on the mode of operation and provide flexibility for object placement and orientation. Below, we outline the three main approaches to moving objects: builder mode, algebra mode, and direct manipulation methods.

::: {#moving_objects.xhtml#builder-mode .section}

Builder Mode

In builder mode, object locations are defined before the objects themselves are created. This approach ensures that objects are positioned correctly during the construction process. The following tools are commonly used to specify locations:

  1. Locations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Use this to define a specific location for the objects within the <cite>{=html}with</cite>{=html} block.

  2. GridLocations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Arrange objects in a grid pattern.

  3. PolarLocations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Position objects in a circular pattern.

  4. HexLocations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Arrange objects in a hexagonal grid.

::: {.admonition .note} Note

The location(s) of an object must be defined prior to its creation when using builder mode. :::

Example:

::: {.highlight-build123d .notranslate} ::: highlight with Locations((10, 20, 30)): Box(5, 5, 5) ::: ::: :::

::: {#moving_objects.xhtml#algebra-mode .section}

Algebra Mode

In algebra mode, object movement is expressed using algebraic operations. The Pos{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} function, short for Position, represents a location, which can be combined with objects or planes to define placement.

  1. Pos() * shape{.docutils .literal .notranslate}: Applies a position to a shape.

  2. Plane() * Pos() * shape{.docutils .literal .notranslate}: Combines a plane with a position and applies it to a shape.

Rotation is an important concept in this mode. A Rotation{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} represents a location with orientation values set, which can be used to define a new location or modify an existing one.

Example:

::: {.highlight-build123d .notranslate} ::: highlight rotated_box = Rotation(45, 0, 0) * box ::: ::: :::

::: {#moving_objects.xhtml#direct-manipulation-methods .section}

Direct Manipulation Methods

The following methods allow for direct manipulation of a shape's location and orientation after it has been created. These methods offer a mix of absolute and relative transformations.

::: {#moving_objects.xhtml#position .section}

Position

  • Absolute Position: Set the position directly.

::: {.highlight-build123d .notranslate} ::: highlight shape.position = (x, y, z) ::: :::

  • Relative Position: Adjust the position incrementally.

::: {.highlight-build123d .notranslate} ::: highlight shape.position += (x, y, z) shape.position -= (x, y, z) ::: ::: :::

::: {#moving_objects.xhtml#orientation .section}

Orientation

  • Absolute Orientation: Set the orientation directly.

::: {.highlight-build123d .notranslate} ::: highlight shape.orientation = (X, Y, Z) ::: :::

  • Relative Orientation: Adjust the orientation incrementally.

::: {.highlight-build123d .notranslate} ::: highlight shape.orientation += (X, Y, Z) shape.orientation -= (X, Y, Z) ::: ::: :::

::: {#moving_objects.xhtml#movement-methods .section}

Movement Methods

  • Relative Move:

::: {.highlight-build123d .notranslate} ::: highlight shape.move(Location) ::: :::

  • Relative Move of Copy:

::: {.highlight-build123d .notranslate} ::: highlight relocated_shape = shape.moved(Location) ::: :::

  • Absolute Move:

::: {.highlight-build123d .notranslate} ::: highlight shape.locate(Location) ::: :::

  • Absolute Move of Copy:

::: {.highlight-build123d .notranslate} ::: highlight relocated_shape = shape.located(Location) ::: ::: :::

::: {#moving_objects.xhtml#transformation-a-k-a-translation-and-rotation .section}

Transformation a.k.a. Translation and Rotation

::: {.admonition .note} Note

These methods don't work in the same way as the previous methods in that they don't just change the object's internal Location{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} but transform the base object itself which is quite slow and potentially problematic. :::

  • Translation: Move a shape relative to its current position.

::: {.highlight-build123d .notranslate} ::: highlight relocated_shape = shape.translate(x, y, z) ::: :::

  • Rotation: Rotate a shape around a specified axis by a given angle.

::: {.highlight-build123d .notranslate} ::: highlight rotated_shape = shape.rotate(Axis, angle_in_degrees) ::: ::: ::: ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#OpenSCAD.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#OpenSCAD.xhtml#transitioning-from-openscad .section}

Transitioning from OpenSCAD

Welcome to build123d! If you're familiar with OpenSCAD, you'll notice key differences in how models are constructed. This guide is designed to help you adapt your design approach and understand the fundamental differences in modeling philosophies. While OpenSCAD relies heavily on Constructive Solid Geometry (CSG) to combine primitive 3D shapes like cubes and spheres, build123d encourages a more flexible and efficient workflow based on building lower-dimensional objects.

::: {#OpenSCAD.xhtml#why-transition-to-build123d .section}

Why Transition to build123d?

Transitioning to build123d allows you to harness a modern and efficient approach to 3D modeling. By starting with lower-dimensional objects and leveraging powerful transformation tools, you can create precise, complex designs with ease. This workflow emphasizes modularity and maintainability, enabling quick modifications and reducing computational complexity. :::

::: {#OpenSCAD.xhtml#moving-beyond-constructive-solid-geometry-csg .section}

Moving Beyond Constructive Solid Geometry (CSG)

OpenSCAD's modeling paradigm heavily relies on Constructive Solid Geometry (CSG) to build models by combining and subtracting 3D solids. While build123d supports similar operations, its design philosophy encourages a fundamentally different, often more efficient approach: starting with lower-dimensional entities like faces and edges and then transforming them into solids.

::: {#OpenSCAD.xhtml#why-transition-away-from-csg .section}

Why Transition Away from CSG?

CSG is a powerful method for creating 3D models, but it has limitations when dealing with complex designs. build123d's approach offers several advantages:

  • Simplified Complexity Management: Working with 2D profiles and faces instead of directly manipulating 3D solids simplifies your workflow. In large models, the number of operations on solids can grow exponentially, making it difficult to manage and debug. Building with 2D profiles helps keep designs modular and organized.

  • Improved Robustness: Operations on 2D profiles are inherently less computationally intensive and less error-prone than equivalent operations on 3D solids. This robustness ensures smoother workflows and reduces the likelihood of failing operations in complex models.

  • Enhanced Efficiency: Constructing models from 2D profiles using operations like extruding, lofting, sweeping, or revolving is computationally faster. These methods also provide greater design flexibility, enabling you to create intricate forms with ease.

  • Better Precision and Control: Starting with 2D profiles allows for more precise geometric control. Constraints, dimensions, and relationships between entities can be established more effectively in 2D, ensuring a solid foundation for your 3D design. ::: :::

::: {#OpenSCAD.xhtml#using-a-more-traditional-cad-design-workflow .section}

Using a More Traditional CAD Design Workflow

Most industry-standard CAD packages recommend starting with a sketch (a 2D object) and transforming it into a 3D model---a design philosophy that is central to build123d.

In build123d, the design process typically begins with defining the outline of an object. This might involve creating a complex 1D object using BuildLine, which provides tools for constructing intricate wireframe geometries. The next step involves converting these 1D objects into 2D sketches using BuildSketch, which offers a wide range of 2D primitives and advanced capabilities, such as:

  • make_face: Converts a 1D BuildLine object into a planar 2D face.

  • make_hull: Generates a convex hull from a 1D BuildLine object.

Once a 2D profile is created, it can be transformed into 3D objects in a BuildPart context using operations such as:

  • Extrusion: Extends a 2D profile along a straight path to create a 3D shape.

  • Revolution: Rotates a 2D profile around an axis to form a symmetrical 3D object.

  • Lofting: Connects multiple 2D profiles along a path to create smooth transitions between shapes.

  • Sweeping: Moves a 2D profile along a defined path to create a 3D form.

::: {#OpenSCAD.xhtml#refining-the-model .section}

Refining the Model

After creating the initial 3D shape, you can refine the model by adding details or making modifications using build123d's advanced features, such as:

  • Fillets and Chamfers: Smooth or bevel edges to enhance the design.

  • Boolean Operations: Combine, subtract, or intersect 3D shapes to achieve the desired geometry. :::

::: {#OpenSCAD.xhtml#example-comparison .section}

Example Comparison

To illustrate the advantages of this approach, compare a simple model in OpenSCAD and build123d of a piece of angle iron:

OpenSCAD Approach

::: {.highlight-openscad .notranslate} ::: highlight $fn = 100; // Increase the resolution for smooth fillets

// Dimensions
length = 100;  // 10 cm long
width = 30;    // 3 cm wide
thickness = 4; // 4 mm thick
fillet = 5;    // 5 mm fillet radius
delta = 0.001; // a small number

// Create the angle iron
difference() {
    // Outer shape
    cube([width, length, width], center = false);
    // Inner shape
    union() {
        translate([thickness+fillet,-delta,thickness+fillet])
            rotate([-90,0,0])
                cylinder(length+2*delta, fillet,fillet);
        translate([thickness,-delta,thickness+fillet])
            cube([width-thickness,length+2*delta,width-fillet],center=false);
        translate([thickness+fillet,-delta,thickness])
            cube([width-fillet,length+2*delta,width-thickness],center=false);

    }
}

::: :::

build123d Approach

::: {.highlight-build123d .notranslate} ::: highlight # Builder mode with BuildPart() as angle_iron: with BuildSketch() as profile: Rectangle(3 * CM, 4 * MM, align=Align.MIN) Rectangle(4 * MM, 3 * CM, align=Align.MIN) extrude(amount=10 * CM) fillet(angle_iron.edges().filter_by(lambda e: e.is_interior), 5 * MM) ::: :::

::: {.highlight-build123d .notranslate} ::: highlight # Algebra mode profile = Rectangle(3 * CM, 4 * MM, align=Align.MIN) profile += Rectangle(4 * MM, 3 * CM, align=Align.MIN) angle_iron = extrude(profile, 10 * CM) angle_iron = fillet(angle_iron.edges().filter_by(lambda e: e.is_interior), 5 * MM) ::: :::

OpenSCAD and build123d offer distinct paradigms for creating 3D models, as demonstrated by the angle iron example. OpenSCAD relies on Constructive Solid Geometry (CSG) operations, combining and subtracting 3D shapes like cubes and cylinders. Fillets are approximated by manually adding high-resolution cylinders, making adjustments cumbersome and less precise. This static approach can handle simple models but becomes challenging for complex or iterative designs.

In contrast, build123d emphasizes a profile-driven workflow. It starts with a 2D sketch, defining the geometry's outline, which is then extruded or otherwise transformed into a 3D model. Features like fillets are applied dynamically by querying topological elements, such as edges, using intuitive filtering methods. This approach ensures precision and flexibility, making changes straightforward without the need for manual repositioning or realignment.

The build123d methodology is computationally efficient, leveraging mathematical precision for features like fillets. By separating the design into manageable steps---sketching, extruding, and refining---it aligns with traditional CAD practices and enhances readability, modularity, and maintainability. Unlike OpenSCAD, build123d's dynamic querying of topological features allows for easy updates and adjustments, making it better suited for modern, complex, and iterative design workflows.

In summary, build123d's sketch-based paradigm and topological querying capabilities provide superior precision, flexibility, and efficiency compared to OpenSCAD's static, CSG-centric approach, making it a better choice for robust and adaptable CAD modeling. ::: :::

::: {#OpenSCAD.xhtml#tips-for-transitioning .section}

Tips for Transitioning

  • Think in Lower Dimensions: Begin with 1D curves or 2D sketches as the foundation and progressively build upwards into 3D shapes.

  • Leverage Topological References: Use build123d's powerful selector system to reference features of existing objects for creating new ones. For example, apply inside or outside fillets and chamfers to vertices and edges of an existing part with precision.

  • Operational Equivalency and Beyond: Build123d provides equivalents to almost all features available in OpenSCAD, with the exception of the 3D minkowski operation. However, a 2D equivalent, make_hull, is available in build123d. Beyond operational equivalency, build123d offers a wealth of additional functionality, including advanced features like topological queries, dynamic filtering, and robust tools for creating complex geometries. By exploring build123d's extensive operations, you can unlock new possibilities and take your designs far beyond the capabilities of OpenSCAD.

  • Explore the Documentation: Dive into build123d's comprehensive API documentation to unlock its full potential and discover advanced features.

By shifting your design mindset from solid-based CSG to a profile-driven approach, you can fully harness build123d's capabilities to create precise, efficient, and complex models. Welcome aboard, and happy designing! :::

::: {#OpenSCAD.xhtml#conclusion .section}

Conclusion

While OpenSCAD and build123d share the goal of empowering users to create parametric 3D models, their approaches differ significantly. Embracing build123d's workflow of building with lower-dimensional objects and applying extrusion, lofting, sweeping, or revolution will unlock its full potential and lead to better design outcomes. ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#introductory_examples.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#introductory_examples.xhtml#introductory-examples .section}

Introductory Examples

The examples on this page can help you learn how to build objects with build123d, and are intended as a general overview of build123d.

They are organized from simple to complex, so working through them in order is the best way to absorb them.

::: {.admonition .note} Note

Some important lines are omitted below to save space, so you will most likely need to add 1 & 2 to the provided code below for them to work:

  1. from build123d import *{.docutils .literal .notranslate}

  2. If you are using build123d builder mode or algebra mode,

    • in ocp_vscode simply use e.g. show(ex15){.docutils .literal .notranslate} to the end of your design to view parts, sketches and curves. show_all(){.docutils .literal .notranslate} can be used to automatically show all objects with their variable names as labels.

    • in CQ-editor add e.g. show_object(ex15.part){.docutils .literal .notranslate}, show_object(ex15.sketch){.docutils .literal .notranslate} or show_object(ex15.line){.docutils .literal .notranslate} to the end of your design to view parts, sketches or lines.

  3. If you want to save your resulting object as an STL from builder mode, you can use e.g. export_stl(ex15.part, "file.stl"){.docutils .literal .notranslate}.

  4. If you want to save your resulting object as an STL from algebra mode, you can use e.g. export_stl(ex15, "file.stl"){.docutils .literal .notranslate}

  5. build123d also supports exporting to multiple other file formats including STEP, see here for further information: Import/Export Formats{.reference .external}[ [https://build123d.readthedocs.io/en/latest/import_export.html]]{.link-target}

:::

<nav class="contents" id="list-of-examples">

List of Examples

</nav>

::: {#introductory_examples.xhtml#simple-rectangular-plate .section} []{#introductory_examples.xhtml#ex-1}

1. Simple Rectangular Plate

Just about the simplest possible example, a rectangular Box{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}.

{.align-center}

  • Builder mode

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    with BuildPart() as ex1:
        Box(length, width, thickness)
    

    ::: :::

  • Algebra mode

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    ex1 = Box(length, width, thickness)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#plate-with-hole .section} []{#introductory_examples.xhtml#ex-2}

2. Plate with Hole

A rectangular box, but with a hole added.

{.align-center}

:::

::: {#introductory_examples.xhtml#an-extruded-prismatic-solid .section} []{#introductory_examples.xhtml#ex-3}

3. An extruded prismatic solid

Build a prismatic solid using extrusion.

{.align-center}

:::

::: {#introductory_examples.xhtml#building-profiles-using-lines-and-arcs .section} []{#introductory_examples.xhtml#ex-4}

4. Building Profiles using lines and arcs

Sometimes you need to build complex profiles using lines and arcs. This example builds a prismatic solid from 2D operations. It is not necessary to create variables for the line segments, but it will be useful in a later example.

{.align-center}

Note that to build a closed face it requires line segments that form a closed shape. :::

::: {#introductory_examples.xhtml#moving-the-current-working-point .section} []{#introductory_examples.xhtml#ex-5}

5. Moving the current working point

{.align-center}

  • Builder mode

    Using Locations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} we can place one (or multiple) objects at one (or multiple) places.

    ::: {.highlight-build123d .notranslate} ::: highlight a, b, c, d = 90, 45, 15, 7.5

    with BuildPart() as ex5:
        with BuildSketch() as ex5_sk:
            Circle(a)
            with Locations((b, 0.0)):
                Rectangle(c, c, mode=Mode.SUBTRACT)
            with Locations((0, b)):
                Circle(d, mode=Mode.SUBTRACT)
        extrude(amount=c)
    

    ::: :::

  • Algebra mode

    Using the pattern Pos(x, y, z=0) * obj{.docutils .literal .notranslate} (with geometry.Pos{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}) we can move an object to the provided position. Using Rot(x_angle, y_angle, z_angle) * obj{.docutils .literal .notranslate} (with geometry.Rot{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}) would rotate the object.

    ::: {.highlight-build123d .notranslate} ::: highlight a, b, c, d = 90, 45, 15, 7.5

    sk5 = Circle(a) - Pos(b, 0.0) * Rectangle(c, c) - Pos(0.0, b) * Circle(d)
    ex5 = extrude(sk5, c)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#using-point-lists .section} []{#introductory_examples.xhtml#ex-6}

6. Using Point Lists

Sometimes you need to create a number of features at various Locations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}.

{.align-center}

  • Builder mode

    You can use a list of points to construct multiple objects at once.

    ::: {.highlight-build123d .notranslate} ::: highlight a, b, c = 80, 60, 10

    with BuildPart() as ex6:
        with BuildSketch() as ex6_sk:
            Circle(a)
            with Locations((b, 0), (0, b), (-b, 0), (0, -b)):
                Circle(c, mode=Mode.SUBTRACT)
        extrude(amount=c)
    

    ::: :::

  • Algebra mode

    You can use loops to iterate over these Locations or list comprehensions as in the example.

    The algebra operations are vectorized, which means obj - [obj1, obj2, obj3]{.docutils .literal .notranslate} is short for obj - obj1 - obj2 - ob3{.docutils .literal .notranslate} (and more efficient, see [Performance considerations in algebra mode]{.std .std-ref}{.reference .internal}).

    ::: {.highlight-build123d .notranslate} ::: highlight a, b, c = 80, 60, 10

    sk6 = [loc * Circle(c) for loc in Locations((b, 0), (0, b), (-b, 0), (0, -b))]
    ex6 = extrude(Circle(a) - sk6, c)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#polygons .section} []{#introductory_examples.xhtml#ex-7}

7. Polygons

{.align-center}

  • Builder mode

    You can create RegularPolygon{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} for each stack point if you would like.

    ::: {.highlight-build123d .notranslate} ::: highlight a, b, c = 60, 80, 5

    with BuildPart() as ex7:
        with BuildSketch() as ex7_sk:
            Rectangle(a, b)
            with Locations((0, 3 * c), (0, -3 * c)):
                RegularPolygon(radius=2 * c, side_count=6, mode=Mode.SUBTRACT)
        extrude(amount=c)
    

    ::: :::

  • Algebra mode

    You can apply locations to RegularPolygon{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} instances for each location via loops or list comprehensions.

    ::: {.highlight-build123d .notranslate} ::: highlight a, b, c = 60, 80, 5

    polygons = [
        loc * RegularPolygon(radius=2 * c, side_count=6)
        for loc in Locations((0, 3 * c), (0, -3 * c))
    ]
    sk7 = Rectangle(a, b) - polygons
    ex7 = extrude(sk7, amount=c)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#polylines .section} []{#introductory_examples.xhtml#ex-8}

8. Polylines

Polyline{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} allows creating a shape from a large number of chained points connected by lines. This example uses a polyline to create one half of an i-beam shape, which is mirror(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ed to create the final profile.

{.align-center}

  • Builder mode

    ::: {.highlight-build123d .notranslate} ::: highlight (L, H, W, t) = (100.0, 20.0, 20.0, 1.0) pts = [ (0, H / 2.0), (W / 2.0, H / 2.0), (W / 2.0, (H / 2.0 - t)), (t / 2.0, (H / 2.0 - t)), (t / 2.0, (t - H / 2.0)), (W / 2.0, (t - H / 2.0)), (W / 2.0, H / -2.0), (0, H / -2.0), ]

    with BuildPart() as ex8:
        with BuildSketch(Plane.YZ) as ex8_sk:
            with BuildLine() as ex8_ln:
                Polyline(pts)
                mirror(ex8_ln.line, about=Plane.YZ)
            make_face()
        extrude(amount=L)
    

    ::: :::

  • Algebra mode

    ::: {.highlight-build123d .notranslate} ::: highlight (L, H, W, t) = (100.0, 20.0, 20.0, 1.0) pts = [ (0, H / 2.0), (W / 2.0, H / 2.0), (W / 2.0, (H / 2.0 - t)), (t / 2.0, (H / 2.0 - t)), (t / 2.0, (t - H / 2.0)), (W / 2.0, (t - H / 2.0)), (W / 2.0, H / -2.0), (0, H / -2.0), ]

    ln = Polyline(pts)
    ln += mirror(ln, Plane.YZ)
    
    sk8 = make_face(Plane.YZ * ln)
    ex8 = extrude(sk8, -L).clean()
    

    ::: :::

:::

::: {#introductory_examples.xhtml#selectors-fillets-and-chamfers .section} []{#introductory_examples.xhtml#ex-9}

9. Selectors, Fillets, and Chamfers

This example introduces multiple useful and important concepts. Firstly chamfer(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and fillet(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} can be used to "bevel" and "round" edges respectively. Secondly, these two methods require an edge or a list of edges to operate on. To select all edges, you could simply pass in ex9.edges(){.docutils .literal .notranslate}.

{.align-center}

  • Builder mode

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    with BuildPart() as ex9:
        Box(length, width, thickness)
        chamfer(ex9.edges().group_by(Axis.Z)[-1], length=4)
        fillet(ex9.edges().filter_by(Axis.Z), radius=5)
    

    ::: :::

  • Algebra mode

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    ex9 = Part() + Box(length, width, thickness)
    ex9 = chamfer(ex9.edges().group_by(Axis.Z)[-1], length=4)
    ex9 = fillet(ex9.edges().filter_by(Axis.Z), radius=5)
    

    ::: :::

Note that group_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} (Axis.Z){.docutils .literal .notranslate} returns a list of lists of edges that is grouped by their z-position. In this case we want to use the [-1]{.docutils .literal .notranslate} group which, by convention, will be the highest z-dimension group. :::

::: {#introductory_examples.xhtml#select-last-and-hole .section} []{#introductory_examples.xhtml#ex-10}

10. Select Last and Hole

{.align-center}

  • Builder mode

    Using Select{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} .LAST{.docutils .literal .notranslate} you can select the most recently modified edges. It is used to perform a fillet(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} in this example. This example also makes use of Hole{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} which automatically cuts through the entire part.

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    with BuildPart() as ex10:
        Box(length, width, thickness)
        Hole(radius=width / 4)
        fillet(ex10.edges(Select.LAST).group_by(Axis.Z)[-1], radius=2)
    

    ::: :::

  • Algebra mode

    Using the pattern snapshot = obj.edges(){.docutils .literal .notranslate} before and last_edges = obj.edges() - snapshot{.docutils .literal .notranslate} after an operation allows to select the most recently modified edges (same for faces{.docutils .literal .notranslate}, vertices{.docutils .literal .notranslate}, ...). It is used to perform a fillet(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} in this example. This example also makes use of Hole{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}. Different to the context mode, you have to add the depth{.docutils .literal .notranslate} of the whole.

    ::: {.highlight-build123d .notranslate} ::: highlight ex10 = Part() + Box(length, width, thickness)

    snapshot = ex10.edges()
    ex10 -= Hole(radius=width / 4, depth=thickness)
    last_edges = ex10.edges() - snapshot
    ex10 = fillet(last_edges.group_by(Axis.Z)[-1], 2)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#use-a-face-as-a-plane-for-buildsketch-and-introduce-gridlocations .section} []{#introductory_examples.xhtml#ex-11}

11. Use a face as a plane for BuildSketch and introduce GridLocations

{.align-center}

  • Builder mode

    BuildSketch{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} accepts a Plane or a Face, so in this case we locate the Sketch on the top of the part. Note that the face used as input to BuildSketch needs to be Planar or unpredictable behavior can result. Additionally GridLocations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} can be used to create a grid of points that are simultaneously used to place 4 pentagons.

    Lastly, extrude(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} can be used with a negative amount and Mode.SUBTRACT{.docutils .literal .notranslate} to cut these from the parent.

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    with BuildPart() as ex11:
        Box(length, width, thickness)
        chamfer(ex11.edges().group_by(Axis.Z)[-1], length=4)
        fillet(ex11.edges().filter_by(Axis.Z), radius=5)
        Hole(radius=width / 4)
        fillet(ex11.edges(Select.LAST).sort_by(Axis.Z)[-1], radius=2)
        with BuildSketch(ex11.faces().sort_by(Axis.Z)[-1]) as ex11_sk:
            with GridLocations(length / 2, width / 2, 2, 2):
                RegularPolygon(radius=5, side_count=5)
        extrude(amount=-thickness, mode=Mode.SUBTRACT)
    

    ::: :::

  • Algebra mode

    The pattern plane * obj{.docutils .literal .notranslate} can be used to locate an object on a plane. Furthermore, the pattern plane * location * obj{.docutils .literal .notranslate} first places the object on a plane and then moves it relative to plane according to location{.docutils .literal .notranslate}.

    GridLocations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} creates a grid of points that can be used in loops or list comprehensions as described earlier.

    Lastly, extrude(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} can be used with a negative amount and cut (-{.docutils .literal .notranslate}) from the parent.

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    ex11 = Part() + Box(length, width, thickness)
    ex11 = chamfer(ex11.edges().group_by()[-1], 4)
    ex11 = fillet(ex11.edges().filter_by(Axis.Z), 5)
    last = ex11.edges()
    ex11 -= Hole(radius=width / 4, depth=thickness)
    ex11 = fillet((ex11.edges() - last).sort_by().last, 2)
    
    plane = Plane(ex11.faces().sort_by().last)
    polygons = Sketch() + [
        plane * loc * RegularPolygon(radius=5, side_count=5)
        for loc in GridLocations(length / 2, width / 2, 2, 2)
    ]
    ex11 -= extrude(polygons, -thickness)
    

    ::: :::

Note that the direction implied by positive or negative inputs to amount is relative to the normal direction of the face or plane. As a result of this, unexpected behavior can occur if the extrude direction and mode/operation (ADD / +{.docutils .literal .notranslate} or SUBTRACT / -{.docutils .literal .notranslate}) are not correctly set. :::

::: {#introductory_examples.xhtml#defining-an-edge-with-a-spline .section} []{#introductory_examples.xhtml#ex-12}

12. Defining an Edge with a Spline

This example defines a side using a spline curve through a collection of points. Useful when you have an edge that needs a complex profile.

{.align-center}

  • Builder mode

    ::: {.highlight-build123d .notranslate} ::: highlight pts = [ (55, 30), (50, 35), (40, 30), (30, 20), (20, 25), (10, 20), (0, 20), ]

    with BuildPart() as ex12:
        with BuildSketch() as ex12_sk:
            with BuildLine() as ex12_ln:
                l1 = Spline(pts)
                l2 = Line((55, 30), (60, 0))
                l3 = Line((60, 0), (0, 0))
                l4 = Line((0, 0), (0, 20))
            make_face()
        extrude(amount=10)
    

    ::: :::

  • Algebra mode

    ::: {.highlight-build123d .notranslate} ::: highlight pts = [ (55, 30), (50, 35), (40, 30), (30, 20), (20, 25), (10, 20), (0, 20), ]

    l1 = Spline(pts)
    l2 = Line(l1 @ 0, (60, 0))
    l3 = Line(l2 @ 1, (0, 0))
    l4 = Line(l3 @ 1, l1 @ 1)
    
    sk12 = make_face([l1, l2, l3, l4])
    ex12 = extrude(sk12, 10)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#counterboreholes-countersinkholes-and-polarlocations .section} []{#introductory_examples.xhtml#ex-13}

13. CounterBoreHoles, CounterSinkHoles, and PolarLocations

Counter-sink and counter-bore holes are useful for creating recessed areas for fasteners.

{.align-center}

  • Builder mode

    We use a face to establish a location for Locations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}.

    ::: {.highlight-build123d .notranslate} ::: highlight a, b = 40, 4 with BuildPart() as ex13: Cylinder(radius=50, height=10) with Locations(ex13.faces().sort_by(Axis.Z)[-1]): with PolarLocations(radius=a, count=4): CounterSinkHole(radius=b, counter_sink_radius=2 * b) with PolarLocations(radius=a, count=4, start_angle=45, angular_range=360): CounterBoreHole(radius=b, counter_bore_radius=2 * b, counter_bore_depth=b) ::: :::

  • Algebra mode

    We use a face to establish a plane that is used later in the code for locating objects onto this plane.

    ::: {.highlight-build123d .notranslate} ::: highlight a, b = 40, 4

    ex13 = Cylinder(radius=50, height=10)
    plane = Plane(ex13.faces().sort_by().last)
    
    ex13 -= (
        plane
        * PolarLocations(radius=a, count=4)
        * CounterSinkHole(radius=b, counter_sink_radius=2 * b, depth=10)
    )
    ex13 -= (
        plane
        * PolarLocations(radius=a, count=4, start_angle=45, angular_range=360)
        * CounterBoreHole(
            radius=b, counter_bore_radius=2 * b, depth=10, counter_bore_depth=b
        )
    )
    

    ::: :::

PolarLocations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} creates a list of points that are radially distributed. :::

::: {#introductory_examples.xhtml#position-on-a-line-with-and-introduce-sweep .section} []{#introductory_examples.xhtml#ex-14}

14. Position on a line with '@', '%' and introduce Sweep

build123d includes a feature for finding the position along a line segment. This is normalized between 0 and 1 and can be accessed using the position_at(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} (<cite>{=html}@</cite>{=html}) operator. Similarly the tangent_at(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} (<cite>{=html}%</cite>{=html}) operator returns the line direction at a given point.

These two features are very powerful for chaining line segments together without having to repeat dimensions again and again, which is error prone, time consuming, and more difficult to maintain. The pending faces must lie on the path, please see example 37 for a way to make this placement easier.

{.align-center}

  • Builder mode

    The sweep(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} method takes any pending faces and sweeps them through the provided path (in this case the path is taken from the pending edges from ex14_ln{.docutils .literal .notranslate}). revolve(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} requires a single connected wire.

    ::: {.highlight-build123d .notranslate} ::: highlight a, b = 40, 20

    with BuildPart() as ex14:
        with BuildLine() as ex14_ln:
            l1 = JernArc(start=(0, 0), tangent=(0, 1), radius=a, arc_size=180)
            l2 = JernArc(start=l1 @ 1, tangent=l1 % 1, radius=a, arc_size=-90)
            l3 = Line(l2 @ 1, l2 @ 1 + (-a, a))
        with BuildSketch(Plane.XZ) as ex14_sk:
            Rectangle(b, b)
        sweep()
    

    ::: :::

  • Algebra mode

    The sweep(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} method takes any faces and sweeps them through the provided path (in this case the path is taken from ex14_ln{.docutils .literal .notranslate}).

    ::: {.highlight-build123d .notranslate} ::: highlight a, b = 40, 20

    l1 = JernArc(start=(0, 0), tangent=(0, 1), radius=a, arc_size=180)
    l2 = JernArc(start=l1 @ 1, tangent=l1 % 1, radius=a, arc_size=-90)
    l3 = Line(l2 @ 1, l2 @ 1 + (-a, a))
    ex14_ln = l1 + l2 + l3
    
    sk14 = Plane.XZ * Rectangle(b, b)
    ex14 = sweep(sk14, path=ex14_ln)
    

    ::: :::

It is also possible to use tuple or Vector{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} addition (and other vector math operations) as seen in the l3{.docutils .literal .notranslate} variable. :::

::: {#introductory_examples.xhtml#mirroring-symmetric-geometry .section} []{#introductory_examples.xhtml#ex-15}

15. Mirroring Symmetric Geometry

Here mirror is used on the BuildLine to create a symmetric shape with fewer line segment commands. Additionally the '@' operator is used to simplify the line segment commands.

(l4 @ 1).Y{.docutils .literal .notranslate} is used to extract the y-component of the l4 @ 1{.docutils .literal .notranslate} vector.

{.align-center}

  • Builder mode

    ::: {.highlight-build123d .notranslate} ::: highlight a, b, c = 80, 40, 20

    with BuildPart() as ex15:
        with BuildSketch() as ex15_sk:
            with BuildLine() as ex15_ln:
                l1 = Line((0, 0), (a, 0))
                l2 = Line(l1 @ 1, l1 @ 1 + (0, b))
                l3 = Line(l2 @ 1, l2 @ 1 + (-c, 0))
                l4 = Line(l3 @ 1, l3 @ 1 + (0, -c))
                l5 = Line(l4 @ 1, (0, (l4 @ 1).Y))
                mirror(ex15_ln.line, about=Plane.YZ)
            make_face()
        extrude(amount=c)
    

    ::: :::

  • Algebra mode

    Combine lines via the pattern Curve() + [l1, l2, l3, l4, l5]{.docutils .literal .notranslate}

    ::: {.highlight-build123d .notranslate} ::: highlight a, b, c = 80, 40, 20

    l1 = Line((0, 0), (a, 0))
    l2 = Line(l1 @ 1, l1 @ 1 + (0, b))
    l3 = Line(l2 @ 1, l2 @ 1 + (-c, 0))
    l4 = Line(l3 @ 1, l3 @ 1 + (0, -c))
    l5 = Line(l4 @ 1, (0, (l4 @ 1).Y))
    ln = Curve() + [l1, l2, l3, l4, l5]
    ln += mirror(ln, Plane.YZ)
    
    sk15 = make_face(ln)
    ex15 = extrude(sk15, c)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#mirroring-3d-objects .section} []{#introductory_examples.xhtml#ex-16}

16. Mirroring 3D Objects

Mirror can also be used with BuildPart (and BuildSketch) to mirror 3D objects. The Plane.offset(){.docutils .literal .notranslate} method shifts the plane in the normal direction (positive or negative).

{.align-center}

  • Builder mode

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    with BuildPart() as ex16_single:
        with BuildSketch(Plane.XZ) as ex16_sk:
            Rectangle(length, width)
            fillet(ex16_sk.vertices(), radius=length / 10)
            with GridLocations(x_spacing=length / 4, y_spacing=0, x_count=3, y_count=1):
                Circle(length / 12, mode=Mode.SUBTRACT)
            Rectangle(length, width, align=(Align.MIN, Align.MIN), mode=Mode.SUBTRACT)
        extrude(amount=length)
    
    with BuildPart() as ex16:
        add(ex16_single.part)
        mirror(ex16_single.part, about=Plane.XY.offset(width))
        mirror(ex16_single.part, about=Plane.YX.offset(width))
        mirror(ex16_single.part, about=Plane.YZ.offset(width))
        mirror(ex16_single.part, about=Plane.YZ.offset(-width))
    

    ::: :::

  • Algebra mode

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    sk16 = Rectangle(length, width)
    sk16 = fillet(sk16.vertices(), length / 10)
    
    circles = [loc * Circle(length / 12) for loc in GridLocations(length / 4, 0, 3, 1)]
    
    sk16 = sk16 - circles - Rectangle(length, width, align=(Align.MIN, Align.MIN))
    ex16_single = extrude(Plane.XZ * sk16, length)
    
    planes = [
        Plane.XY.offset(width),
        Plane.YX.offset(width),
        Plane.YZ.offset(width),
        Plane.YZ.offset(-width),
    ]
    objs = [mirror(ex16_single, plane) for plane in planes]
    ex16 = ex16_single + objs
    

    ::: :::

:::

::: {#introductory_examples.xhtml#mirroring-from-faces .section} []{#introductory_examples.xhtml#ex-17}

17. Mirroring From Faces

Here we select the farthest face in the Y-direction and turn it into a Plane{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} using the Plane(){.docutils .literal .notranslate} class.

{.align-center}

  • Builder mode

    ::: {.highlight-build123d .notranslate} ::: highlight a, b = 30, 20

    with BuildPart() as ex17:
        with BuildSketch() as ex17_sk:
            RegularPolygon(radius=a, side_count=5)
        extrude(amount=b)
        mirror(ex17.part, about=Plane(ex17.faces().group_by(Axis.Y)[0][0]))
    

    ::: :::

  • Algebra mode

    ::: {.highlight-build123d .notranslate} ::: highlight a, b = 30, 20

    sk17 = RegularPolygon(radius=a, side_count=5)
    ex17 = extrude(sk17, amount=b)
    ex17 += mirror(ex17, Plane(ex17.faces().sort_by(Axis.Y).first))
    

    ::: :::

:::

::: {#introductory_examples.xhtml#creating-workplanes-on-faces .section} []{#introductory_examples.xhtml#ex-18}

18. Creating Workplanes on Faces

Here we start with an earlier example, select the top face, draw a rectangle and then use Extrude with a negative distance.

{.align-center}

  • Builder mode

    We then use Mode.SUBTRACT{.docutils .literal .notranslate} to cut it out from the main body.

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0 a, b = 4, 5

    with BuildPart() as ex18:
        Box(length, width, thickness)
        chamfer(ex18.edges().group_by(Axis.Z)[-1], length=a)
        fillet(ex18.edges().filter_by(Axis.Z), radius=b)
        with BuildSketch(ex18.faces().sort_by(Axis.Z)[-1]):
            Rectangle(2 * b, 2 * b)
        extrude(amount=-thickness, mode=Mode.SUBTRACT)
    

    ::: :::

  • Algebra mode

    We then use -={.docutils .literal .notranslate} to cut it out from the main body.

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0 a, b = 4, 5

    ex18 = Part() + Box(length, width, thickness)
    ex18 = chamfer(ex18.edges().group_by()[-1], a)
    ex18 = fillet(ex18.edges().filter_by(Axis.Z), b)
    
    sk18 = Plane(ex18.faces().sort_by().first) * Rectangle(2 * b, 2 * b)
    ex18 -= extrude(sk18, -thickness)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#locating-a-workplane-on-a-vertex .section} []{#introductory_examples.xhtml#ex-19}

19. Locating a workplane on a vertex

Here a face is selected and two different strategies are used to select vertices. Firstly vtx{.docutils .literal .notranslate} uses group_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and Axis.X{.docutils .literal .notranslate} to select a particular vertex. The second strategy uses a custom defined Axis vtx2Axis{.docutils .literal .notranslate} that is pointing roughly in the direction of a vertex to select, and then sort_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} this custom Axis.

{.align-center}

  • Builder mode

    Then the X and Y positions of these vertices are selected and passed to Locations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} as center points for two circles that cut through the main part. Note that if you passed the variable vtx{.docutils .literal .notranslate} directly to Locations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} then the part would be offset from the workplane by the vertex z-position.

    ::: {.highlight-build123d .notranslate} ::: highlight length, thickness = 80.0, 10.0

    with BuildPart() as ex19:
        with BuildSketch() as ex19_sk:
            RegularPolygon(radius=length / 2, side_count=7)
        extrude(amount=thickness)
        topf = ex19.faces().sort_by(Axis.Z)[-1]
        vtx = topf.vertices().group_by(Axis.X)[-1][0]
        vtx2Axis = Axis((0, 0, 0), (-1, -0.5, 0))
        vtx2 = topf.vertices().sort_by(vtx2Axis)[-1]
        with BuildSketch(topf) as ex19_sk2:
            with Locations((vtx.X, vtx.Y), (vtx2.X, vtx2.Y)):
                Circle(radius=length / 8)
        extrude(amount=-thickness, mode=Mode.SUBTRACT)
    

    ::: :::

  • Algebra mode

    Then the X and Y positions of these vertices are selected and used to move two circles that cut through the main part. Note that if you passed the variable vtx{.docutils .literal .notranslate} directly to Pos{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} then the part would be offset from the workplane by the vertex z-position.

    ::: {.highlight-build123d .notranslate} ::: highlight length, thickness = 80.0, 10.0

    ex19_sk = RegularPolygon(radius=length / 2, side_count=7)
    ex19 = extrude(ex19_sk, thickness)
    
    topf = ex19.faces().sort_by().last
    
    vtx = topf.vertices().group_by(Axis.X)[-1][0]
    
    vtx2Axis = Axis((0, 0, 0), (-1, -0.5, 0))
    vtx2 = topf.vertices().sort_by(vtx2Axis)[-1]
    
    ex19_sk2 = Circle(radius=length / 8)
    ex19_sk2 = Pos(vtx.X, vtx.Y) * ex19_sk2 + Pos(vtx2.X, vtx2.Y) * ex19_sk2
    
    ex19 -= extrude(ex19_sk2, thickness)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#offset-sketch-workplane .section} []{#introductory_examples.xhtml#ex-20}

20. Offset Sketch Workplane

The plane{.docutils .literal .notranslate} variable is set to be coincident with the farthest face in the negative x-direction. The resulting Plane is offset from the original position.

{.align-center}

  • Builder mode

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    with BuildPart() as ex20:
        Box(length, width, thickness)
        plane = Plane(ex20.faces().group_by(Axis.X)[0][0])
        with BuildSketch(plane.offset(2 * thickness)):
            Circle(width / 3)
        extrude(amount=width)
    

    ::: :::

  • Algebra mode

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    ex20 = Box(length, width, thickness)
    plane = Plane(ex20.faces().sort_by(Axis.X).first).offset(2 * thickness)
    
    sk20 = plane * Circle(width / 3)
    ex20 += extrude(sk20, width)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#create-a-workplanes-in-the-center-of-another-shape .section} []{#introductory_examples.xhtml#ex-21}

21. Create a Workplanes in the center of another shape

One cylinder is created, and then the origin and z_dir of that part are used to create a new Plane for positioning another cylinder perpendicular and halfway along the first.

{.align-center}

  • Builder mode

    ::: {.highlight-build123d .notranslate} ::: highlight width, length = 10.0, 60.0

    with BuildPart() as ex21:
        with BuildSketch() as ex21_sk:
            Circle(width / 2)
        extrude(amount=length)
        with BuildSketch(Plane(origin=ex21.part.center(), z_dir=(-1, 0, 0))):
            Circle(width / 2)
        extrude(amount=length)
    

    ::: :::

  • Algebra mode

    ::: {.highlight-build123d .notranslate} ::: highlight width, length = 10.0, 60.0

    ex21 = extrude(Circle(width / 2), length)
    plane = Plane(origin=ex21.center(), z_dir=(-1, 0, 0))
    ex21 += plane * extrude(Circle(width / 2), length)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#rotated-workplanes .section} []{#introductory_examples.xhtml#ex-22}

22. Rotated Workplanes

It is also possible to create a rotated workplane, building upon some of the concepts in an earlier example.

{.align-center}

  • Builder mode

    Use the rotated(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} method to rotate the workplane.

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    with BuildPart() as ex22:
        Box(length, width, thickness)
        pln = Plane(ex22.faces().group_by(Axis.Z)[0][0]).rotated((0, -50, 0))
        with BuildSketch(pln) as ex22_sk:
            with GridLocations(length / 4, width / 4, 2, 2):
                Circle(thickness / 4)
        extrude(amount=-100, both=True, mode=Mode.SUBTRACT)
    

    ::: :::

  • Algebra mode

    Use the operator *{.docutils .literal .notranslate} to relocate the plane (post-multiplication!).

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    ex22 = Box(length, width, thickness)
    plane = Plane((ex22.faces().group_by(Axis.Z)[0])[0]) * Rot(0, 50, 0)
    
    holes = Sketch() + [
        plane * loc * Circle(thickness / 4)
        for loc in GridLocations(length / 4, width / 4, 2, 2)
    ]
    ex22 -= extrude(holes, -100, both=True)
    

    ::: :::

GridLocations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} places 4 Circles on 4 points on this rotated workplane, and then the Circles are extruded in the "both" (positive and negative) normal direction. :::

::: {#introductory_examples.xhtml#revolve .section} []{#introductory_examples.xhtml#ex-23}

23. Revolve

Here we build a sketch with a Polyline{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, Line{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, and a Circle{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}. It is absolutely critical that the sketch is only on one side of the axis of rotation before Revolve is called. To that end, split{.docutils .literal .notranslate} is used with Plane.ZY{.docutils .literal .notranslate} to keep only one side of the Sketch.

It is highly recommended to view your sketch before you attempt to call revolve.

{.align-center}

  • Builder mode

    ::: {.highlight-build123d .notranslate} ::: highlight pts = [ (-25, 35), (-25, 0), (-20, 0), (-20, 5), (-15, 10), (-15, 35), ]

    with BuildPart() as ex23:
        with BuildSketch(Plane.XZ) as ex23_sk:
            with BuildLine() as ex23_ln:
                l1 = Polyline(pts)
                l2 = Line(l1 @ 1, l1 @ 0)
            make_face()
            with Locations((0, 35)):
                Circle(25)
            split(bisect_by=Plane.ZY)
        revolve(axis=Axis.Z)
    

    ::: :::

  • Algebra mode

    ::: {.highlight-build123d .notranslate} ::: highlight pts = [ (-25, 35), (-25, 0), (-20, 0), (-20, 5), (-15, 10), (-15, 35), ]

    l1 = Polyline(pts)
    l2 = Line(l1 @ 1, l1 @ 0)
    sk23 = make_face([l1, l2])
    
    sk23 += Pos(0, 35) * Circle(25)
    sk23 = Plane.XZ * split(sk23, bisect_by=Plane.ZY)
    
    ex23 = revolve(sk23, Axis.Z)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#loft .section} []{#introductory_examples.xhtml#ex-24}

24. Loft

Loft is a very powerful tool that can be used to join dissimilar shapes. In this case we make a conical-like shape from a circle and a rectangle that is offset vertically. In this case loft(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} automatically takes the pending faces that were added by the two BuildSketches. Loft can behave unexpectedly when the input faces are not parallel to each other.

{.align-center}

  • Builder mode

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    with BuildPart() as ex24:
        Box(length, length, thickness)
        with BuildSketch(ex24.faces().group_by(Axis.Z)[0][0]) as ex24_sk:
            Circle(length / 3)
        with BuildSketch(ex24_sk.faces()[0].offset(length / 2)) as ex24_sk2:
            Rectangle(length / 6, width / 6)
        loft()
    

    ::: :::

  • Algebra mode

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    ex24 = Box(length, length, thickness)
    plane = Plane(ex24.faces().sort_by().last)
    
    faces = Sketch() + [
        plane * Circle(length / 3),
        plane.offset(length / 2) * Rectangle(length / 6, width / 6),
    ]
    
    ex24 += loft(faces)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#offset-sketch .section} []{#introductory_examples.xhtml#ex-25}

25. Offset Sketch

{.align-center}

  • Builder mode

    BuildSketch faces can be transformed with a 2D offset(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}.

    ::: {.highlight-build123d .notranslate} ::: highlight rad, offs = 50, 10

    with BuildPart() as ex25:
        with BuildSketch() as ex25_sk1:
            RegularPolygon(radius=rad, side_count=5)
        with BuildSketch(Plane.XY.offset(15)) as ex25_sk2:
            RegularPolygon(radius=rad, side_count=5)
            offset(amount=offs)
        with BuildSketch(Plane.XY.offset(30)) as ex25_sk3:
            RegularPolygon(radius=rad, side_count=5)
            offset(amount=offs, kind=Kind.INTERSECTION)
        extrude(amount=1)
    

    ::: :::

  • Algebra mode

    Sketch faces can be transformed with a 2D offset(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}.

    ::: {.highlight-build123d .notranslate} ::: highlight rad, offs = 50, 10

    sk25_1 = RegularPolygon(radius=rad, side_count=5)
    sk25_2 = Plane.XY.offset(15) * RegularPolygon(radius=rad, side_count=5)
    sk25_2 = offset(sk25_2, offs)
    sk25_3 = Plane.XY.offset(30) * RegularPolygon(radius=rad, side_count=5)
    sk25_3 = offset(sk25_3, offs, kind=Kind.INTERSECTION)
    
    sk25 = Sketch() + [sk25_1, sk25_2, sk25_3]
    ex25 = extrude(sk25, 1)
    

    ::: :::

They can be offset inwards or outwards, and with different techniques for extending the corners (see Kind{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} in the Offset docs). :::

::: {#introductory_examples.xhtml#offset-part-to-create-thin-features .section} []{#introductory_examples.xhtml#ex-26}

26. Offset Part To Create Thin features

Parts can also be transformed using an offset, but in this case with a 3D offset(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}. Also commonly known as a shell, this allows creating thin walls using very few operations. This can also be offset inwards or outwards. Faces can be selected to be "deleted" using the openings{.docutils .literal .notranslate} parameter of offset(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}.

Note that self intersecting edges and/or faces can break both 2D and 3D offsets.

{.align-center}

  • Builder mode

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness, wall = 80.0, 60.0, 10.0, 2.0

    with BuildPart() as ex26:
        Box(length, width, thickness)
        topf = ex26.faces().sort_by(Axis.Z)[-1]
        offset(amount=-wall, openings=topf)
    

    ::: :::

  • Algebra mode

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness, wall = 80.0, 60.0, 10.0, 2.0

    ex26 = Box(length, width, thickness)
    topf = ex26.faces().sort_by().last
    ex26 = offset(ex26, amount=-wall, openings=topf)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#splitting-an-object .section} []{#introductory_examples.xhtml#ex-27}

27. Splitting an Object

You can split an object using a plane, and retain either or both halves. In this case we select a face and offset half the width of the box.

{.align-center}

  • Builder mode

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    with BuildPart() as ex27:
        Box(length, width, thickness)
        with BuildSketch(ex27.faces().sort_by(Axis.Z)[0]) as ex27_sk:
            Circle(width / 4)
        extrude(amount=-thickness, mode=Mode.SUBTRACT)
        split(bisect_by=Plane(ex27.faces().sort_by(Axis.Y)[-1]).offset(-width / 2))
    

    ::: :::

  • Algebra mode

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    ex27 = Box(length, width, thickness)
    sk27 = Plane(ex27.faces().sort_by().first) * Circle(width / 4)
    ex27 -= extrude(sk27, -thickness)
    ex27 = split(ex27, Plane(ex27.faces().sort_by(Axis.Y).last).offset(-width / 2))
    

    ::: :::

:::

::: {#introductory_examples.xhtml#locating-features-based-on-faces .section} []{#introductory_examples.xhtml#ex-28}

28. Locating features based on Faces

{.align-center}

  • Builder mode

    We create a triangular prism with Mode{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} .PRIVATE{.docutils .literal .notranslate} and then later use the faces of this object to cut holes in a sphere.

    ::: {.highlight-build123d .notranslate} ::: highlight width, thickness = 80.0, 10.0

    with BuildPart() as ex28:
        with BuildSketch() as ex28_sk:
            RegularPolygon(radius=width / 4, side_count=3)
        ex28_ex = extrude(amount=thickness, mode=Mode.PRIVATE)
        midfaces = ex28_ex.faces().group_by(Axis.Z)[1]
        Sphere(radius=width / 2)
        for face in midfaces:
            with Locations(face):
                Hole(thickness / 2)
    

    ::: :::

  • Algebra mode

    We create a triangular prism and then later use the faces of this object to cut holes in a sphere.

    ::: {.highlight-build123d .notranslate} ::: highlight width, thickness = 80.0, 10.0

    sk28 = RegularPolygon(radius=width / 4, side_count=3)
    tmp28 = extrude(sk28, thickness)
    ex28 = Sphere(radius=width / 2)
    for p in [Plane(face) for face in tmp28.faces().group_by(Axis.Z)[1]]:
        ex28 -= p * Hole(thickness / 2, depth=width)
    

    ::: :::

We are able to create multiple workplanes by looping over the list of faces. :::

::: {#introductory_examples.xhtml#the-classic-occ-bottle .section} []{#introductory_examples.xhtml#ex-29}

29. The Classic OCC Bottle

build123d is based on the OpenCascade.org (OCC) modeling Kernel. Those who are familiar with OCC know about the famous 'bottle' example. We use a 3D Offset and the openings parameter to create the bottle opening.

{.align-center}

  • Builder mode

    ::: {.highlight-build123d .notranslate} ::: highlight L, w, t, b, h, n = 60.0, 18.0, 9.0, 0.9, 90.0, 6.0

    with BuildPart() as ex29:
        with BuildSketch(Plane.XY.offset(-b)) as ex29_ow_sk:
            with BuildLine() as ex29_ow_ln:
                l1 = Line((0, 0), (0, w / 2))
                l2 = ThreePointArc(l1 @ 1, (L / 2.0, w / 2.0 + t), (L, w / 2.0))
                l3 = Line(l2 @ 1, ((l2 @ 1).X, 0, 0))
                mirror(ex29_ow_ln.line)
            make_face()
        extrude(amount=h + b)
        fillet(ex29.edges(), radius=w / 6)
        with BuildSketch(ex29.faces().sort_by(Axis.Z)[-1]):
            Circle(t)
        extrude(amount=n)
        necktopf = ex29.faces().sort_by(Axis.Z)[-1]
        offset(ex29.solids()[0], amount=-b, openings=necktopf)
    

    ::: :::

  • Algebra mode

    ::: {.highlight-build123d .notranslate} ::: highlight L, w, t, b, h, n = 60.0, 18.0, 9.0, 0.9, 90.0, 8.0

    l1 = Line((0, 0), (0, w / 2))
    l2 = ThreePointArc(l1 @ 1, (L / 2.0, w / 2.0 + t), (L, w / 2.0))
    l3 = Line(l2 @ 1, ((l2 @ 1).X, 0, 0))
    ln29 = l1 + l2 + l3
    ln29 += mirror(ln29)
    sk29 = make_face(ln29)
    ex29 = extrude(sk29, -(h + b))
    ex29 = fillet(ex29.edges(), radius=w / 6)
    
    neck = Plane(ex29.faces().sort_by().last) * Circle(t)
    ex29 += extrude(neck, n)
    necktopf = ex29.faces().sort_by().last
    ex29 = offset(ex29, -b, openings=necktopf)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#bezier-curve .section} []{#introductory_examples.xhtml#ex-30}

30. Bezier Curve

Here pts{.docutils .literal .notranslate} is used as an input to both Polyline{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and Bezier{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and wts{.docutils .literal .notranslate} to Bezier alone. These two together create a closed line that is made into a face and extruded.

{.align-center}

  • Builder mode

    ::: {.highlight-build123d .notranslate} ::: highlight pts = [ (0, 0), (20, 20), (40, 0), (0, -40), (-60, 0), (0, 100), (100, 0), ]

    wts = [
        1.0,
        1.0,
        2.0,
        3.0,
        4.0,
        2.0,
        1.0,
    ]
    
    with BuildPart() as ex30:
        with BuildSketch() as ex30_sk:
            with BuildLine() as ex30_ln:
                l0 = Polyline(pts)
                l1 = Bezier(pts, weights=wts)
            make_face()
        extrude(amount=10)
    

    ::: :::

  • Algebra mode

    ::: {.highlight-build123d .notranslate} ::: highlight pts = [ (0, 0), (20, 20), (40, 0), (0, -40), (-60, 0), (0, 100), (100, 0), ]

    wts = [
        1.0,
        1.0,
        2.0,
        3.0,
        4.0,
        2.0,
        1.0,
    ]
    
    ex30_ln = Polyline(pts) + Bezier(pts, weights=wts)
    ex30_sk = make_face(ex30_ln)
    ex30 = extrude(ex30_sk, -10)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#nesting-locations .section} []{#introductory_examples.xhtml#ex-31}

31. Nesting Locations

Locations contexts can be nested to create groups of shapes. Here 24 triangles, 6 squares, and 1 hexagon are created and then extruded. Notably PolarLocations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} rotates any "children" groups by default.

{.align-center}

  • Builder mode

    ::: {.highlight-build123d .notranslate} ::: highlight a, b, c = 80.0, 5.0, 3.0

    with BuildPart() as ex31:
        with BuildSketch() as ex31_sk:
            with PolarLocations(a / 2, 6):
                with GridLocations(3 * b, 3 * b, 2, 2):
                    RegularPolygon(b, 3)
                RegularPolygon(b, 4)
            RegularPolygon(3 * b, 6, rotation=30)
        extrude(amount=c)
    

    ::: :::

  • Algebra mode

    ::: {.highlight-build123d .notranslate} ::: highlight a, b, c = 80.0, 5.0, 3.0

    ex31 = Rot(Z=30) * RegularPolygon(3 * b, 6)
    ex31 += PolarLocations(a / 2, 6) * (
        RegularPolygon(b, 4) + GridLocations(3 * b, 3 * b, 2, 2) * RegularPolygon(b, 3)
    )
    ex31 = extrude(ex31, 3)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#python-for-loop .section} []{#introductory_examples.xhtml#ex-32}

32. Python For-Loop

In this example, a standard python for-loop is used along with a list of faces extracted from a sketch to progressively modify the extrusion amount. There are 7 faces in the sketch, so this results in 7 separate calls to extrude(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}.

{.align-center}

  • Builder mode

    Mode{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} .PRIVATE{.docutils .literal .notranslate} is used in BuildSketch{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} to avoid adding these faces until the for-loop.

    ::: {.highlight-build123d .notranslate} ::: highlight a, b, c = 80.0, 10.0, 1.0

    with BuildPart() as ex32:
        with BuildSketch(mode=Mode.PRIVATE) as ex32_sk:
            RegularPolygon(2 * b, 6, rotation=30)
            with PolarLocations(a / 2, 6):
                RegularPolygon(b, 4)
        for idx, obj in enumerate(ex32_sk.sketch.faces()):
            add(obj)
            extrude(amount=c + 3 * idx)
    

    ::: :::

  • Algebra mode

    ::: {.highlight-build123d .notranslate} ::: highlight a, b, c = 80.0, 10.0, 1.0

    ex32_sk = RegularPolygon(2 * b, 6, rotation=30)
    ex32_sk += PolarLocations(a / 2, 6) * RegularPolygon(b, 4)
    ex32 = Part() + [extrude(obj, c + 3 * idx) for idx, obj in enumerate(ex32_sk.faces())]
    

    ::: :::

:::

::: {#introductory_examples.xhtml#python-function-and-for-loop .section} []{#introductory_examples.xhtml#ex-33}

33. Python Function and For-Loop

Building on the previous example, a standard python function is used to return a sketch as a function of several inputs to progressively modify the size of each square.

{.align-center}

  • Builder mode

    The function returns a BuildSketch{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}.

    ::: {.highlight-build123d .notranslate} ::: highlight a, b, c = 80.0, 5.0, 1.0

    def square(rad, loc):
        with BuildSketch() as sk:
            with Locations(loc):
                RegularPolygon(rad, 4)
        return sk.sketch
    
    
    with BuildPart() as ex33:
        with BuildSketch(mode=Mode.PRIVATE) as ex33_sk:
            locs = PolarLocations(a / 2, 6)
            for i, j in enumerate(locs):
                add(square(b + 2 * i, j))
        for idx, obj in enumerate(ex33_sk.sketch.faces()):
            add(obj)
            extrude(amount=c + 2 * idx)
    

    ::: :::

  • Algebra mode

    The function returns a Sketch{.docutils .literal .notranslate} object.

    ::: {.highlight-build123d .notranslate} ::: highlight a, b, c = 80.0, 5.0, 1.0

    def square(rad, loc):
        return loc * RegularPolygon(rad, 4)
    
    
    ex33 = Part() + [
        extrude(square(b + 2 * i, loc), c + 2 * i)
        for i, loc in enumerate(PolarLocations(a / 2, 6))
    ]
    

    ::: :::

:::

::: {#introductory_examples.xhtml#embossed-and-debossed-text .section} []{#introductory_examples.xhtml#ex-34}

34. Embossed and Debossed Text

{.align-center}

  • Builder mode

    The text "Hello" is placed on top of a rectangle and embossed (raised) by placing a BuildSketch on the top face (topf{.docutils .literal .notranslate}). Note that Align{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} is used to control the text placement. We re-use the topf{.docutils .literal .notranslate} variable to select the same face and deboss (indented) the text "World". Note that if we simply ran BuildSketch(ex34.faces().sort_by(Axis.Z)[-1]){.docutils .literal .notranslate} for both ex34_sk1 & 2{.docutils .literal .notranslate} it would incorrectly locate the 2nd "World" text on the top of the "Hello" text.

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness, fontsz, fontht = 80.0, 60.0, 10.0, 25.0, 4.0

    with BuildPart() as ex34:
        Box(length, width, thickness)
        topf = ex34.faces().sort_by(Axis.Z)[-1]
        with BuildSketch(topf) as ex34_sk:
            Text("Hello", font_size=fontsz, align=(Align.CENTER, Align.MIN))
        extrude(amount=fontht)
        with BuildSketch(topf) as ex34_sk2:
            Text("World", font_size=fontsz, align=(Align.CENTER, Align.MAX))
        extrude(amount=-fontht, mode=Mode.SUBTRACT)
    

    ::: :::

  • Algebra mode

    The text "Hello" is placed on top of a rectangle and embossed (raised) by placing a sketch on the top face (topf{.docutils .literal .notranslate}). Note that Align{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} is used to control the text placement. We re-use the topf{.docutils .literal .notranslate} variable to select the same face and deboss (indented) the text "World".

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness, fontsz, fontht = 80.0, 60.0, 10.0, 25.0, 4.0

    ex34 = Box(length, width, thickness)
    plane = Plane(ex34.faces().sort_by().last)
    ex34_sk = plane * Text("Hello", font_size=fontsz, align=(Align.CENTER, Align.MIN))
    ex34 += extrude(ex34_sk, amount=fontht)
    ex34_sk2 = plane * Text("World", font_size=fontsz, align=(Align.CENTER, Align.MAX))
    ex34 -= extrude(ex34_sk2, amount=-fontht)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#slots .section} []{#introductory_examples.xhtml#ex-35}

35. Slots

{.align-center}

  • Builder mode

    Here we create a SlotCenterToCenter{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and then use a BuildLine{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and RadiusArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} to create an arc for two instances of SlotArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}.

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    with BuildPart() as ex35:
        Box(length, length, thickness)
        topf = ex35.faces().sort_by(Axis.Z)[-1]
        with BuildSketch(topf) as ex35_sk:
            SlotCenterToCenter(width / 2, 10)
            with BuildLine(mode=Mode.PRIVATE) as ex35_ln:
                RadiusArc((-width / 2, 0), (0, width / 2), radius=width / 2)
            SlotArc(arc=ex35_ln.edges()[0], height=thickness, rotation=0)
            with BuildLine(mode=Mode.PRIVATE) as ex35_ln2:
                RadiusArc((0, -width / 2), (width / 2, 0), radius=-width / 2)
            SlotArc(arc=ex35_ln2.edges()[0], height=thickness, rotation=0)
        extrude(amount=-thickness, mode=Mode.SUBTRACT)
    

    ::: :::

  • Algebra mode

    Here we create a SlotCenterToCenter{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and then use a RadiusArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} to create an arc for two instances of SlotArc{.xref .py .py-class .docutils .literal .notranslate}.

    ::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0

    ex35 = Box(length, length, thickness)
    plane = Plane(ex35.faces().sort_by().last)
    ex35_sk = SlotCenterToCenter(width / 2, 10)
    ex35_ln = RadiusArc((-width / 2, 0), (0, width / 2), radius=width / 2)
    ex35_sk += SlotArc(arc=ex35_ln.edges()[0], height=thickness)
    ex35_ln2 = RadiusArc((0, -width / 2), (width / 2, 0), radius=-width / 2)
    ex35_sk += SlotArc(arc=ex35_ln2.edges()[0], height=thickness)
    ex35 -= extrude(plane * ex35_sk, -thickness)
    

    ::: :::

:::

::: {#introductory_examples.xhtml#extrude-until .section} []{#introductory_examples.xhtml#ex-36}

36. Extrude Until

Sometimes you will want to extrude until a given face that could be non planar or where you might not know easily the distance you have to extrude to. In such cases you can use extrude(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Until{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} with Until.NEXT{.docutils .literal .notranslate} or Until.LAST{.docutils .literal .notranslate}.

{.align-center}

  • Builder mode

    ::: {.highlight-build123d .notranslate} ::: highlight rad, rev = 6, 50

    with BuildPart() as ex36:
        with BuildSketch() as ex36_sk:
            with Locations((0, rev)):
                Circle(rad)
        revolve(axis=Axis.X, revolution_arc=180)
        with BuildSketch() as ex36_sk2:
            Rectangle(rad, rev)
        extrude(until=Until.NEXT)
    

    ::: :::

  • Algebra mode

    ::: {.highlight-build123d .notranslate} ::: highlight rad, rev = 6, 50

    ex36_sk = Pos(0, rev) * Circle(rad)
    ex36 = revolve(axis=Axis.X, profiles=ex36_sk, revolution_arc=180)
    ex36_sk2 = Rectangle(rad, rev)
    ex36 += extrude(ex36_sk2, until=Until.NEXT, target=ex36)
    

    ::: :::

::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#tutorials.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#tutorials.xhtml#tutorials .section}

Tutorials

There are several tutorials to help guide uses through the concepts of build123d in a step by step way. Working through these tutorials in order is recommended as later tutorials build on the concepts introduced in earlier ones.

::: {.toctree-wrapper .compound}

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#tutorial_design.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#tutorial_design.xhtml#designing-a-part-in-build123d .section} []{#tutorial_design.xhtml#design-tutorial}

Designing a Part in build123d

Designing a part with build123d involves a systematic approach that leverages the power of 2D profiles, extrusions, and revolutions. Where possible, always work in the lowest possible dimension, 1D lines before 2D sketches before 3D parts. The following guide will get you started:

As an example, we'll go through the design process for this bracket:

{.align-center}

::: {#tutorial_design.xhtml#step-1-examine-the-part-in-all-three-orientations .section}

Step 1. Examine the Part in All Three Orientations

Start by visualizing the part from the front, top, and side views. Identify any symmetries in these orientations, as symmetries can simplify the design by reducing the number of unique features you need to model.

In the following view of the bracket one can see two planes of symmetry so we'll only need to design one quarter of it.

{.align-center} :::

::: {#tutorial_design.xhtml#step-2-identify-rotational-symmetries .section}

Step 2. Identify Rotational Symmetries

Look for structures that could be created through the rotation of a 2D shape. For instance, cylindrical or spherical features are often the result of revolving a profile around an axis. Identify the axis of rotation and make a note of it.

There are no rotational structures in the example bracket. :::

::: {#tutorial_design.xhtml#step-3-select-a-convenient-origin .section}

Step 3. Select a Convenient Origin

Choose an origin point that minimizes the need to move or transform components later in the design process. Ideally, the origin should be placed at a natural center of symmetry or a critical reference point on the part.

The planes of symmetry for the bracket was identified in step 1, making it logical to place the origin at the intersection of these planes on the bracket's front face. Additionally, we'll define the coordinate system we'll be working in: Plane.XY (the default), where the origin is set at the global (0,0,0) position. In this system, the x-axis aligns with the front of the bracket, and the z-axis corresponds to its width. It's important to note that all coordinate systems/planes in build123d adhere to the right-hand rule{.reference .external}[ [https://en.wikipedia.org/wiki/Right-hand_rule]]{.link-target} meaning the y-axis is automatically determined by this convention.

{.align-center} :::

::: {#tutorial_design.xhtml#step-4-create-2d-profiles .section}

Step 4. Create 2D Profiles

Design the 2D profiles of your part in the appropriate orientation(s). These profiles are the foundation of the part's geometry and can often represent cross-sections of the part. Mirror parts of profiles across any axes of symmetry identified earlier.

The 2D profile of the bracket is as follows:

{.align-center}

The build123d code to generate this profile is as follows:

::: {.highlight-build123d .notranslate} ::: highlight with BuildSketch() as sketch: with BuildLine() as profile: FilletPolyline( (0, 0), (length / 2, 0), (length / 2, height), radius=bend_radius ) offset(amount=thickness, side=Side.LEFT) make_face() mirror(about=Plane.YZ) ::: :::

This code creates a 2D sketch of a mirrored profile in the build123d CAD system. Here's a step-by-step explanation of what it does:

with BuildSketch() as sketch:
This starts a context for creating a 2D sketch, which defines the overall boundary and geometric features. The sketch will be stored in the variable sketch.
with BuildLine() as profile:
This starts another context, this time for drawing lines (or profiles) within the sketch. The profile consists of connected line segments, arcs, or polylines.
FilletPolyline((0, 0), (length / 2, 0), (length / 2, height), radius=bend_radius)
This object draws a polyline with three points: (0,0), (length/2, 0), and (length/2, height). A fillet (curved corner) with a radius of bend_radius is added where applicable between the segments of the polyline.
offset(amount=thickness, side=Side.LEFT)
This applies an offset to the polyline created earlier. The offset creates a parallel line at a distance of thickness to the left side of the original polyline. This operation essentially thickens the profile by a given amount.
make_face()
This command creates a 2D face from the closed profile. The offset operation ensures that the profile is closed, allowing the creation of a solid face from the boundary defined.
mirror(about=Plane.YZ)
This mirrors the entire face about the YZ plane (which runs along the center of the sketch), creating a symmetrical counterpart of the face. The mirrored geometry will complete the final shape.

:::

::: {#tutorial_design.xhtml#step-5-use-extrusion-for-prismatic-features .section}

Step 5. Use Extrusion for Prismatic Features

For solid or prismatic shapes, extrude the 2D profiles along the necessary axis. You can also combine multiple extrusions by intersecting or unionizing them to form complex shapes. Use the resulting geometry as sub-parts if needed.

The next step in implementing our design in build123d is to convert the above sketch into a part by extruding it as shown in this code:

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as bracket: with BuildSketch() as sketch: with BuildLine() as profile: FilletPolyline( (0, 0), (length / 2, 0), (length / 2, height), radius=bend_radius ) offset(amount=thickness, side=Side.LEFT) make_face() mirror(about=Plane.YZ) extrude(amount=width / 2) mirror(about=Plane.XY) ::: :::

In this example, we've wrapped the sketch within a BuildPart context, which is used for creating 3D parts. We utilized the extrude function to extend the 2D sketch into a solid object, turning it into a 3D part. Additionally, we applied the mirror function to replicate the partial part across a plane of symmetry, ensuring a symmetrical design. :::

::: {#tutorial_design.xhtml#step-6-generate-revolved-features .section}

Step 6. Generate Revolved Features

If any part of the geometry can be created by revolving a 2D profile around an axis, use the revolve operation. This is particularly useful for parts that include cylindrical, conical, or spherical features. Combine these revolved sub-parts with existing features using additive, subtractive, or intersecting operations.

Our example has no revolved features. :::

::: {#tutorial_design.xhtml#step-7-combine-sub-parts-intelligently .section}

Step 7. Combine Sub-parts Intelligently

When combining multiple sub-parts, keep in mind whether they need to be added, subtracted, or intersected. Subtracting or intersecting can create more refined details, while addition is useful for creating complex assemblies.

Out example only has one sub-part but further sub-parts could be created in the BuildPart context by defining more sketches and extruding or revolving them. :::

::: {#tutorial_design.xhtml#step-8-apply-chamfers-and-fillets .section}

Step 8. Apply Chamfers and Fillets

Identify critical edges or vertices that need chamfering or filleting. Use build123d's selectors to apply these operations accurately. Always visually inspect the results to ensure the correct edges have been modified.

The back corners of the bracket need to be rounded off or filleted so the edges that define these corners need to be isolated. The following code, placed to follow the previous code block, captures just these edges:

::: {.highlight-build123d .notranslate} ::: highlight corners = bracket.edges().filter_by(Axis.X).group_by(Axis.Y)[-1] fillet(corners, fillet_radius) ::: :::

These lines isolates specific corner edges that are then filleted.

corners = bracket.edges().filter_by(Axis.X).group_by(Axis.Y)[-1]
This line is used to select specific edges from the 3D part (bracket) that was created by the extrusion.
  • bracket.edges() retrieves all the edges of the bracket part.

  • filter_by(Axis.X) filters the edges to only those that are aligned along the X-axis.

  • group_by(Axis.Y) groups the edges by their positions along the Y-axis. This operation essentially organizes the filtered X-axis edges into groups based on their Y-coordinate positions.

  • -1
fillet(corners, fillet_radius)
This function applies a fillet (a rounded edge) to the selected corners, with a specified radius (fillet_radius). The fillet smooths the sharp edges at the corners, giving the part a more refined shape.

:::

::: {#tutorial_design.xhtml#step-9-design-for-assembly .section}

Step 9. Design for Assembly

If the part is intended to connect with others, add features like joints, holes, or other attachment points. Ensure that these features are precisely located to ensure proper fitment and functionality in the final assembly.

Our example has two circular holes and a slot that need to be created. First we'll create the two circular holes:

::: {.highlight-build123d .notranslate} ::: highlight with Locations(bracket.faces().sort_by(Axis.X)[-1]): Hole(hole_diameter / 2) ::: :::

This code creates a hole in a specific face of the bracket part.

with Locations(bracket.faces().sort_by(Axis.X)[-1]):
This context sets a location(s) for subsequent operations.
  • bracket.faces() retrieves all the faces of the bracket part.

  • sort_by(Axis.X) sorts these faces based on their position along the X-axis (from one side of the bracket to the other).

  • -1
  • Locations() creates a new local context or coordinate system at the selected face, effectively setting this face as the working location for any subsequent operations inside the with block.

Hole(hole_diameter / 2)
This creates a hole in the selected face. The radius of the hole is specified as hole_diameter / 2. The hole is placed at the origin of the selected face, based on the local coordinate system created by Locations(). As the depth of the hole is not provided it is assumed to go entirely through the part.

Next the slot needs to be created in the bracket with will be done by sketching a slot on the front of the bracket and extruding the sketch through the part.

::: {.highlight-build123d .notranslate} ::: highlight with BuildSketch(bracket.faces().sort_by(Axis.Y)[0]): SlotOverall(20 * MM, hole_diameter) extrude(amount=-thickness, mode=Mode.SUBTRACT) ::: :::

Here's a detailed explanation of what each part does:

with BuildSketch(bracket.faces().sort_by(Axis.Y)[0]):
This line sets up a sketching context.
  • bracket.faces() retrieves all the faces of the bracket part.

  • sort_by(Axis.Y) sorts the faces along the Y-axis, arranging them from the lowest Y-coordinate to the highest.

  • 0
  • BuildSketch() creates a new sketching context on this selected face, where 2D geometry will be drawn.

SlotOverall(20, hole_diameter)
This command draws a slot (a rounded rectangle or elongated hole) on the selected face. The slot has a total length of 20 mm and a width equal to hole_diameter. The slot is defined within the 2D sketch on the selected face of the bracket.
extrude(amount=-thickness, mode=Mode.SUBTRACT)
extrude() takes the 2D sketch (the slot) and extends it into the 3D space by a distance equal to -thickness, creating a cut into the part. The negative value (-thickness) indicates that the extrusion is directed inward into the part (a cut). mode=Mode.SUBTRACT specifies that the extrusion is a subtractive operation, meaning it removes material from the bracket, effectively cutting the slot through the face of the part.

Although beyond the scope of this tutorial, joints could be defined for each of the holes to allow programmatic connection to other parts. :::

::: {#tutorial_design.xhtml#step-10-plan-for-parametric-flexibility .section}

Step 10. Plan for Parametric Flexibility

Wherever possible, make your design parametric, allowing dimensions and features to be easily adjusted later. This flexibility can be crucial if the design needs modifications or if variations of the part are needed.

The dimensions of the bracket are defined as follows:

::: {.highlight-build123d .notranslate} ::: highlight thickness = 3 * MM width = 25 * MM length = 50 * MM height = 25 * MM hole_diameter = 5 * MM bend_radius = 5 * MM fillet_radius = 2 * MM ::: ::: :::

::: {#tutorial_design.xhtml#step-11-test-fit-and-tolerances .section}

Step 11. Test Fit and Tolerances

Visualize the fit of the part within its intended assembly. Consider tolerances for manufacturing, such as clearance between moving parts or shrinkage for 3D-printed parts. Adjust the design as needed to ensure real-world functionality. :::

::: {#tutorial_design.xhtml#summary .section}

Summary

These steps should guide you through a logical and efficient workflow in build123d (or any CAD tool), helping you to design parts with accuracy and ease.

The entire code block for the bracket example is shown here:

::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show_all

thickness = 3 * MM
width = 25 * MM
length = 50 * MM
height = 25 * MM
hole_diameter = 5 * MM
bend_radius = 5 * MM
fillet_radius = 2 * MM

with BuildPart() as bracket:
    with BuildSketch() as sketch:
        with BuildLine() as profile:
            FilletPolyline(
                (0, 0), (length / 2, 0), (length / 2, height), radius=bend_radius
            )
            offset(amount=thickness, side=Side.LEFT)
        make_face()
        mirror(about=Plane.YZ)
    extrude(amount=width / 2)
    mirror(about=Plane.XY)
    corners = bracket.edges().filter_by(Axis.X).group_by(Axis.Y)[-1]
    fillet(corners, fillet_radius)
    with Locations(bracket.faces().sort_by(Axis.X)[-1]):
        Hole(hole_diameter / 2)
    with BuildSketch(bracket.faces().sort_by(Axis.Y)[0]):
        SlotOverall(20 * MM, hole_diameter)
    extrude(amount=-thickness, mode=Mode.SUBTRACT)

show_all()

::: :::

{.align-center} ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#tutorial_selectors.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#tutorial_selectors.xhtml#selector-tutorial .section}

Selector Tutorial

This tutorial provides a step by step guide in using selectors as we create this part:

{.align-center}

::: {.admonition .note} Note

One can see any object in the following tutorial by using the ocp_vscode{.docutils .literal .notranslate} (or any other supported viewer) by using the show(object_to_be_viewed){.docutils .literal .notranslate} command. Alternatively, the show_all(){.docutils .literal .notranslate} command will display all objects that have been assigned an identifier. :::

::: {#tutorial_selectors.xhtml#step-1-setup .section}

Step 1: Setup

Before getting to the CAD operations, this selector script needs to import the build123d environment.

::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import * ::: ::: :::

::: {#tutorial_selectors.xhtml#step-2-create-base-with-buildpart .section}

Step 2: Create Base with BuildPart

To start off, the part will be based on a cylinder so we'll use the Cylinder{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} object of BuildPart{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}:

::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import *

with BuildPart() as example:
    Cylinder(radius=10, height=3)

::: ::: :::

::: {#tutorial_selectors.xhtml#step-3-place-sketch-on-top-of-base .section}

Step 3: Place Sketch on top of base

The next set of features in this design will be created on the top of the cylinder and be described by a planar sketch (BuildSketch{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} is the tool for drawing on planar surfaces) , so we'll create a sketch centered on the top of the cylinder. To locate this sketch we'll use the cylinder's top Face as shown here:

::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import *

with BuildPart() as example:
    Cylinder(radius=10, height=3)
    with BuildSketch(example.faces().sort_by(Axis.Z)[-1]):

::: :::

Here we're using selectors to find that top Face - let's break down example.faces().sort_by(Axis.Z)[-1]{.docutils .literal .notranslate}:

::: {#tutorial_selectors.xhtml#step-3a-extract-faces-from-a-part .section}

Step 3a: Extract Faces from a part

The first sub-step is the extraction of all of the Faces from the part that we're building. The BuildPart{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} instance was assigned the identifier example{.docutils .literal .notranslate} so example.faces(){.docutils .literal .notranslate} will extract all of the Faces from that part into a custom python list{.docutils .literal .notranslate} - a ShapeList{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}. :::

::: {#tutorial_selectors.xhtml#step-3b-get-top-face .section}

Step 3b: Get top Face

The next sub-step is to sort the ShapeList of Faces by their position with respect to the Z Axis. The sort_by{.docutils .literal .notranslate} method will sort the list by relative position of the object's center to the Axis.Z{.docutils .literal .notranslate} and [-1]{.docutils .literal .notranslate} selects the last item on that list - or return the top Face of the example{.docutils .literal .notranslate} part. ::: :::

::: {#tutorial_selectors.xhtml#step-4-create-hole-shape .section}

Step 4: Create hole shape

The object has a hexagonal hole in the top with a central cylinder which we'll describe in the sketch.

::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import *

with BuildPart() as example:
    Cylinder(radius=10, height=3)
    with BuildSketch(example.faces().sort_by(Axis.Z)[-1]):
        RegularPolygon(radius=7, side_count=6)
        Circle(radius=4, mode=Mode.SUBTRACT)

::: :::

::: {#tutorial_selectors.xhtml#step-4a-draw-a-hexagon .section}

Step 4a: Draw a hexagon

We'll create a hexagon with the use of RegularPolygon{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} object with six sides. :::

::: {#tutorial_selectors.xhtml#step-4b-create-a-hole-in-the-hexagon .section}

Step 4b: Create a hole in the hexagon

To create the hole we'll subtract a Circle{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} from the sketch by using mode=Mode.SUBTRACT{.docutils .literal .notranslate}. The sketch now described the hexagonal hole that we want to make in the Cylinder{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}. ::: :::

::: {#tutorial_selectors.xhtml#step-5-create-the-hole .section}

Step 5: Create the hole

To create the hole we'll extrude(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} the sketch we just created into the Cylinder{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and subtract it.

::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import *

with BuildPart() as example:
    Cylinder(radius=10, height=3)
    with BuildSketch(example.faces().sort_by(Axis.Z)[-1]):
        RegularPolygon(radius=7, side_count=6)
        Circle(radius=4, mode=Mode.SUBTRACT)
    extrude(amount=-2, mode=Mode.SUBTRACT)

::: :::

Note that amount=-2{.docutils .literal .notranslate} indicates extruding into the part and - just like with the sketch - mode=Mode.SUBTRACT{.docutils .literal .notranslate} instructs the builder to subtract this hexagonal shape from the part under construction.

At this point the part looks like:

{.align-center} :::

::: {#tutorial_selectors.xhtml#step-6-fillet-the-top-perimeter-edge .section}

Step 6: Fillet the top perimeter Edge

The final step is to apply a fillet to the top perimeter.

::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import *

with BuildPart() as example:
    Cylinder(radius=10, height=3)
    with BuildSketch(example.faces().sort_by(Axis.Z)[-1]):
        RegularPolygon(radius=7, side_count=6)
        Circle(radius=4, mode=Mode.SUBTRACT)
    extrude(amount=-2, mode=Mode.SUBTRACT)
    fillet(
        example.edges()
        .filter_by(GeomType.CIRCLE)
        .sort_by(SortBy.RADIUS)[-2:]
        .sort_by(Axis.Z)[-1],
        radius=1,
    )

show(example)

::: :::

Here we're using the fillet(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} operation which needs two things: the edge(s) to fillet and the radius of the fillet. To provide the edge, we'll use more selectors as described in the following sub-steps.

::: {#tutorial_selectors.xhtml#step-6a-extract-all-the-edges .section}

Step 6a: Extract all the Edges

Much like selecting Faces in Step 3a, we'll select all of the example{.docutils .literal .notranslate} part's edges with example.edges(){.docutils .literal .notranslate}. :::

::: {#tutorial_selectors.xhtml#step-6b-filter-the-edges-for-circles .section}

Step 6b: Filter the Edges for circles

Since we know that the edge we're looking for is a circle, we can filter the edges selected in Step 6a for just those that are of geometric type CIRCLE{.docutils .literal .notranslate} with example.edges().filter_by(GeomType.CIRCLE){.docutils .literal .notranslate}. This step removes all of the Edges of the hexagon hole. :::

::: {#tutorial_selectors.xhtml#step-6c-sort-the-circles-by-radius .section}

Step 6c: Sort the circles by radius

The perimeter are the largest circles - the central cylinder must be excluded - so we'll sort all of the circles by their radius with: example.edges().filter_by(GeomType.CIRCLE).sort_by(SortBy.RADIUS){.docutils .literal .notranslate}. :::

::: {#tutorial_selectors.xhtml#step-6d-slice-the-list-to-get-the-two-largest .section}

Step 6d: Slice the list to get the two largest

We know that the example{.docutils .literal .notranslate} part has two perimeter circles so we'll select just the top two edges from the sorted circle list with: example.edges().filter_by(GeomType.CIRCLE).sort_by(SortBy.RADIUS)[-2:]{.docutils .literal .notranslate}. The syntax of this slicing operation is standard python list slicing. :::

::: {#tutorial_selectors.xhtml#step-6e-select-the-top-edge .section}

Step 6e: Select the top Edge

The last sub-step is to select the top perimeter edge, the one with the greatest Z value which we'll do with the sort_by(Axis.Z)[-1]{.docutils .literal .notranslate} method just like Step 3b - note that these methods work on all Shape objects (Edges, Wires, Faces, Solids, and Compounds) - with: example.edges().filter_by(GeomType.CIRCLE).sort_by(SortBy.RADIUS)[-2:].sort_by(Axis.Z)[-1]{.docutils .literal .notranslate}. ::: :::

::: {#tutorial_selectors.xhtml#conclusion .section}

Conclusion

By using selectors as we have in this example we've used methods of identifying features that are robust to features changing within the part. We've also avoided the classic CAD "Topological naming problem" by never referring to features with names or tags that could become obsolete as the part changes.

When possible, avoid using static list indices to refer to features extracted from methods like edges(){.docutils .literal .notranslate} as the order within the list is not guaranteed to remain the same. ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#tutorial_lego.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#tutorial_lego.xhtml#lego-tutorial .section}

Lego Tutorial

This tutorial provides a step by step guide to creating a script to build a parametric Lego block as shown here:

{.align-center}

::: {#tutorial_lego.xhtml#step-1-setup .section}

Step 1: Setup

Before getting to the CAD operations, this Lego script needs to import the build123d environment. There are over 100 python classes in build123d so we'll just import them all with a from build123d import *{.docutils .literal .notranslate} but [there are other options]{.std .std-ref}{.reference .internal} that we won't explore here.

The dimensions of the Lego block follow. A key parameter is pip_count{.docutils .literal .notranslate}, the length of the Lego blocks in pips. This parameter must be at least 2.

::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show_object pip_count = 6

lego_unit_size = 8
pip_height = 1.8
pip_diameter = 4.8
block_length = lego_unit_size * pip_count
block_width = 16
base_height = 9.6
block_height = base_height + pip_height
support_outer_diameter = 6.5
support_inner_diameter = 4.8
ridge_width = 0.6
ridge_depth = 0.3
wall_thickness = 1.2

::: ::: :::

::: {#tutorial_lego.xhtml#step-2-part-builder .section}

Step 2: Part Builder

The Lego block will be created by the BuildPart{.docutils .literal .notranslate} builder as it's a discrete three dimensional part; therefore, we'll instantiate a BuildPart{.docutils .literal .notranslate} with the name lego{.docutils .literal .notranslate}.

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as lego: ::: ::: :::

::: {#tutorial_lego.xhtml#step-3-sketch-builder .section}

Step 3: Sketch Builder

Lego blocks have quite a bit of internal structure. To create this structure we'll draw a two dimensional sketch that will later be extruded into a three dimensional object. As this sketch will be part of the lego part, we'll create a sketch builder in the context of the part builder as follows:

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as lego: # Draw the bottom of the block with BuildSketch() as plan: ::: :::

Note that builder instance names are optional - we'll use plan{.docutils .literal .notranslate} to reference the sketch. Also note that all sketch objects are filled or 2D faces not just perimeter lines. :::

::: {#tutorial_lego.xhtml#step-4-perimeter-rectangle .section}

Step 4: Perimeter Rectangle

The first object in the sketch is going to be a rectangle with the dimensions of the outside of the Lego block. The following step is going to refer to this rectangle, so it will be assigned the identifier perimeter{.docutils .literal .notranslate}.

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as lego: # Draw the bottom of the block with BuildSketch() as plan: # Start with a Rectangle the size of the block perimeter = Rectangle(width=block_length, height=block_width) ::: :::

Once the Rectangle{.docutils .literal .notranslate} object is created the sketch appears as follows:

{.align-center} :::

::: {#tutorial_lego.xhtml#step-5-offset-to-create-walls .section}

Step 5: Offset to Create Walls

To create the walls of the block the rectangle that we've created needs to be hollowed out. This will be done with the Offset{.docutils .literal .notranslate} operation which is going to create a new object from perimeter{.docutils .literal .notranslate}.

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as lego: # Draw the bottom of the block with BuildSketch() as plan: # Start with a Rectangle the size of the block perimeter = Rectangle(width=block_length, height=block_width) # Subtract an offset to create the block walls offset( perimeter, -wall_thickness, kind=Kind.INTERSECTION, mode=Mode.SUBTRACT, ) ::: :::

The first parameter to Offset{.docutils .literal .notranslate} is the reference object. The amount{.docutils .literal .notranslate} is a negative value to indicate that the offset should be internal. The kind{.docutils .literal .notranslate} parameter controls the shape of the corners - Kind.INTERSECTION{.docutils .literal .notranslate} will create square corners. Finally, the mode{.docutils .literal .notranslate} parameter controls how this object will be placed in the sketch - in this case subtracted from the existing sketch. The result is shown here:

{.align-center}

Now the sketch consists of a hollow rectangle. :::

::: {#tutorial_lego.xhtml#step-6-create-internal-grid .section}

Step 6: Create Internal Grid

The interior of the Lego block has small ridges on all four internal walls. These ridges will be created as a grid of thin rectangles so the positions of the centers of these rectangles need to be defined. A pair of GridLocations{.docutils .literal .notranslate} location contexts will define these positions, one for the horizontal bars and one for the vertical bars. As the Rectangle{.docutils .literal .notranslate} objects are in the scope of a location context (GridLocations{.docutils .literal .notranslate} in this case) that defined multiple points, multiple rectangles are created.

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as lego: # Draw the bottom of the block with BuildSketch() as plan: # Start with a Rectangle the size of the block perimeter = Rectangle(width=block_length, height=block_width) # Subtract an offset to create the block walls offset( perimeter, -wall_thickness, kind=Kind.INTERSECTION, mode=Mode.SUBTRACT, ) # 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) ::: :::

Here we can see that the first GridLocations{.docutils .literal .notranslate} creates two positions which causes two horizontal rectangles to be created. The second GridLocations{.docutils .literal .notranslate} works in the same way but creates pip_count{.docutils .literal .notranslate} positions and therefore pip_count{.docutils .literal .notranslate} rectangles. Note that keyword parameter are optional in this case.

The result looks like this:

{.align-center} :::

::: {#tutorial_lego.xhtml#step-7-create-ridges .section}

Step 7: Create Ridges

To convert the internal grid to ridges, the center needs to be removed. This will be done with another Rectangle{.docutils .literal .notranslate}.

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as lego: # Draw the bottom of the block with BuildSketch() as plan: # Start with a Rectangle the size of the block perimeter = Rectangle(width=block_length, height=block_width) # Subtract an offset to create the block walls offset( perimeter, -wall_thickness, kind=Kind.INTERSECTION, mode=Mode.SUBTRACT, ) # 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) # Subtract 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, ) ::: :::

The Rectangle{.docutils .literal .notranslate} is subtracted from the sketch to leave the ridges as follows:

{.align-center} :::

::: {#tutorial_lego.xhtml#step-8-hollow-circles .section}

Step 8: Hollow Circles

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{.docutils .literal .notranslate}.

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as lego: # Draw the bottom of the block with BuildSketch() as plan: # Start with a Rectangle the size of the block perimeter = Rectangle(width=block_length, height=block_width) # Subtract an offset to create the block walls offset( perimeter, -wall_thickness, kind=Kind.INTERSECTION, mode=Mode.SUBTRACT, ) # 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) # Subtract 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, ) # 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) ::: :::

Here another GridLocations{.docutils .literal .notranslate} is used to position the centers of the circles. Note that since both Circle{.docutils .literal .notranslate} objects are in the scope of the location context, both Circles will be positioned at these locations.

Once the Circles are added, the sketch is complete and looks as follows:

{.align-center} :::

::: {#tutorial_lego.xhtml#step-9-extruding-sketch-into-walls .section}

Step 9: Extruding Sketch into Walls

Now that the sketch is complete it needs to be extruded into the three dimensional wall object.

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as lego: # Draw the bottom of the block with BuildSketch() as plan: # Start with a Rectangle the size of the block perimeter = Rectangle(width=block_length, height=block_width) # Subtract an offset to create the block walls offset( perimeter, -wall_thickness, kind=Kind.INTERSECTION, mode=Mode.SUBTRACT, ) # 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) # Subtract 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, ) # 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) # Extrude this base sketch to the height of the walls extrude(amount=base_height - wall_thickness) ::: :::

Note how the Extrude{.docutils .literal .notranslate} operation is no longer in the BuildSketch{.docutils .literal .notranslate} scope and has returned back into the BuildPart{.docutils .literal .notranslate} scope. This causes BuildSketch{.docutils .literal .notranslate} to exit and transfer the sketch that we've created to BuildPart{.docutils .literal .notranslate} for further processing by Extrude{.docutils .literal .notranslate}.

The result is:

{.align-center} :::

::: {#tutorial_lego.xhtml#step-10-adding-a-top .section}

Step 10: Adding a Top

Now that the walls are complete, the top of the block needs to be added. Although this could be done with another sketch, we'll add a box to the top of the walls.

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as lego: # Draw the bottom of the block with BuildSketch() as plan: # Start with a Rectangle the size of the block perimeter = Rectangle(width=block_length, height=block_width) # Subtract an offset to create the block walls offset( perimeter, -wall_thickness, kind=Kind.INTERSECTION, mode=Mode.SUBTRACT, ) # 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) # Subtract 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, ) # 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) # Extrude this base sketch to the height of the walls extrude(amount=base_height - wall_thickness) # 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 Box( length=block_length, width=block_width, height=wall_thickness, align=(Align.CENTER, Align.CENTER, Align.MIN), ) ::: :::

To position the top, we'll describe the top center of the lego walls with a Locations{.docutils .literal .notranslate} context. To determine the height we'll extract that from the lego.part{.docutils .literal .notranslate} by using the vertices(){.docutils .literal .notranslate} method which returns a list of the positions of all of the vertices of the Lego block so far. Since we're interested in the top, we'll sort by the vertical (Z) axis and take the top of the list sort_by(Axis.Z)[-1]{.docutils .literal .notranslate}. Finally, the Z{.docutils .literal .notranslate} property of this vertex will return just the height of the top. Note that the X{.docutils .literal .notranslate} and Y{.docutils .literal .notranslate} values are not used from the selected vertex as there are no vertices in the center of the block.

Within the scope of this Locations{.docutils .literal .notranslate} context, a Box{.docutils .literal .notranslate} is created, centered at the intersection of the x and y axis but not in the z thus aligning with the top of the walls.

The base is closed now as shown here:

{.align-center} :::

::: {#tutorial_lego.xhtml#step-11-adding-pips .section}

Step 11: Adding Pips

The final step is to add the pips to the top of the Lego block. To do this we'll create a new workplane on top of the block where we can position the pips.

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as lego: # Draw the bottom of the block with BuildSketch() as plan: # Start with a Rectangle the size of the block perimeter = Rectangle(width=block_length, height=block_width) # Subtract an offset to create the block walls offset( perimeter, -wall_thickness, kind=Kind.INTERSECTION, mode=Mode.SUBTRACT, ) # 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) # Subtract 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, ) # 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) # Extrude this base sketch to the height of the walls extrude(amount=base_height - wall_thickness) # 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 Box( length=block_length, width=block_width, height=wall_thickness, align=(Align.CENTER, Align.CENTER, Align.MIN), ) # Create a workplane on the top of the block with BuildPart(lego.faces().sort_by(Axis.Z)[-1]): # Create a grid of pips with GridLocations(lego_unit_size, lego_unit_size, pip_count, 2): Cylinder( radius=pip_diameter / 2, height=pip_height, align=(Align.CENTER, Align.CENTER, Align.MIN), ) ::: :::

In this case, the workplane is created from the top Face of the Lego block by using the faces{.docutils .literal .notranslate} method and then sorted vertically and taking the top one sort_by(Axis.Z)[-1]{.docutils .literal .notranslate}.

On the new workplane, a grid of locations is created and a number of Cylinder{.docutils .literal .notranslate}'s are positioned at each location.

{.align-center}

This completes the Lego block. To access the finished product, refer to the builder's internal object as shown here:

Builder Object


BuildLine line BuildSketch sketch BuildPart part

so in this case the Lego block is lego.part{.docutils .literal .notranslate}. To display the part use show_object(lego.part){.docutils .literal .notranslate} or show(lego.part){.docutils .literal .notranslate} depending on the viewer. The part could also be exported to a STL or STEP file by referencing lego.part{.docutils .literal .notranslate}.

::: {.admonition .note} Note

Viewers that don't directly support build123d my require a raw OpenCascade object. In this case, append .wrapped{.docutils .literal .notranslate} to the object (e.g.) show_object(lego.part.wrapped){.docutils .literal .notranslate}. ::: ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#tutorial_joints.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#tutorial_joints.xhtml#joint-tutorial .section} []{#tutorial_joints.xhtml#id1}

Joint Tutorial

This tutorial provides a step by step guide in using Joint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}'s as we create a box with a hinged lid to illustrate the use of three different Joint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} types.

{.align-center}

::: {#tutorial_joints.xhtml#step-1-setup .section}

Step 1: Setup

Before getting to the CAD operations, this selector script needs to import the build123d environment.

::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import * ::: ::: :::

::: {#tutorial_joints.xhtml#step-2-create-hinge .section}

Step 2: Create Hinge

This example uses a common Butt Hinge to connect the lid to the box base so a Hinge{.docutils .literal .notranslate} class is used to create that can create either of the two hinge leaves. As the focus of this tutorial is the joints and not the CAD operations to create objects, this code is not described in detail.

::: {.highlight-build123d .notranslate} ::: highlight class Hinge(Compound): """Hinge

    Half a simple hinge with several joints. The joints are:
    - "leaf": RigidJoint where hinge attaches to object
    - "hinge_axis": RigidJoint (inner) or RevoluteJoint (outer)
    - "hole0", "hole1", "hole2": CylindricalJoints for attachment screws

    Args:
        width (float): width of one leaf
        length (float): hinge length
        barrel_diameter (float): size of hinge pin barrel
        thickness (float): hinge leaf thickness
        pin_diameter (float): hinge pin diameter
        inner (bool, optional): inner or outer half of hinge . Defaults to True.
    """

    def __init__(
        self,
        width: float,
        length: float,
        barrel_diameter: float,
        thickness: float,
        pin_diameter: float,
        inner: bool = True,
    ):
        # The profile of the hinge used to create the tabs
        with BuildPart() as hinge_profile:
            with BuildSketch():
                for i, loc in enumerate(
                    GridLocations(0, length / 5, 1, 5, align=(Align.MIN, Align.MIN))
                ):
                    if i % 2 == inner:
                        with Locations(loc):
                            Rectangle(width, length / 5, align=(Align.MIN, Align.MIN))
                Rectangle(
                    width - barrel_diameter,
                    length,
                    align=(Align.MIN, Align.MIN),
                )
            extrude(amount=-barrel_diameter)

        # The hinge pin
        with BuildPart() as pin:
            Cylinder(
                radius=pin_diameter / 2,
                height=length,
                align=(Align.CENTER, Align.CENTER, Align.MIN),
            )
            with BuildPart(pin.part.faces().sort_by(Axis.Z)[-1]) as pin_head:
                Cylinder(
                    radius=barrel_diameter / 2,
                    height=pin_diameter,
                    align=(Align.CENTER, Align.CENTER, Align.MIN),
                )
            fillet(
                pin_head.edges(Select.LAST).filter_by(GeomType.CIRCLE),
                radius=pin_diameter / 3,
            )

        # Either the external and internal leaf with joints
        with BuildPart() as leaf_builder:
            with BuildSketch():
                with BuildLine():
                    l1 = Line((0, 0), (width - barrel_diameter / 2, 0))
                    l2 = RadiusArc(
                        l1 @ 1,
                        l1 @ 1 + Vector(0, barrel_diameter),
                        -barrel_diameter / 2,
                    )
                    l3 = RadiusArc(
                        l2 @ 1,
                        (
                            width - barrel_diameter,
                            barrel_diameter / 2,
                        ),
                        -barrel_diameter / 2,
                    )
                    l4 = Line(l3 @ 1, (width - barrel_diameter, thickness))
                    l5 = Line(l4 @ 1, (0, thickness))
                    Line(l5 @ 1, l1 @ 0)
                make_face()
                with Locations(
                    (width - barrel_diameter / 2, barrel_diameter / 2)
                ) as pin_center:
                    Circle(pin_diameter / 2 + 0.1 * MM, mode=Mode.SUBTRACT)
            extrude(amount=length)
            add(hinge_profile.part, rotation=(90, 0, 0), mode=Mode.INTERSECT)

            # Create holes for fasteners
            with Locations(leaf_builder.part.faces().filter_by(Axis.Y)[-1]):
                with GridLocations(0, length / 3, 1, 3):
                    holes = CounterSinkHole(3 * MM, 5 * MM)
            # Add the hinge pin to the external leaf
            if not inner:
                with Locations(pin_center.locations[0]):
                    add(pin.part)

::: :::

Once the two leaves have been created they will look as follows:

{style="width: 40%;"} {style="width: 40%;"}

Note that the XYZ indicators and a circle around the hinge pin indicate joints that are discussed below. :::

::: {#tutorial_joints.xhtml#step-3-add-joints-to-the-hinge-leaf .section}

Step 3: Add Joints to the Hinge Leaf

The hinge includes five joints:

  • A RigidJoint{.xref .py .py-class .docutils .literal .notranslate} to attach the leaf

  • A RigidJoint{.xref .py .py-class .docutils .literal .notranslate} or RevoluteJoint{.xref .py .py-class .docutils .literal .notranslate} as the hinge Axis

  • Three CylindricalJoint{.xref .py .py-class .docutils .literal .notranslate}'s for the countersunk screws

::: {#tutorial_joints.xhtml#step-3a-leaf-joint .section}

Step 3a: Leaf Joint

The first joint to add is a RigidJoint{.xref .py .py-class .docutils .literal .notranslate} that is used to fix the hinge leaf to the box or lid.

::: {.highlight-build123d .notranslate} ::: highlight # # Leaf attachment RigidJoint( label="leaf", joint_location=Location( (width - barrel_diameter, 0, length / 2), (90, 0, 0) ), ) ::: :::

Each joint has a label which identifies it - here the string "leaf" is used, the to_part{.docutils .literal .notranslate} binds the joint to leaf_builder.part{.docutils .literal .notranslate} (i.e. the part being built), and joint_location{.docutils .literal .notranslate} is specified as middle of the leaf along the edge of the pin. Note that Location{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} objects describe both a position and orientation which is why there are two tuples (the orientation listed is rotate about the X axis 90 degrees). :::

::: {#tutorial_joints.xhtml#step-3b-hinge-joint .section}

Step 3b: Hinge Joint

The second joint to add is either a RigidJoint{.xref .py .py-class .docutils .literal .notranslate} (on the inner leaf) or a RevoluteJoint{.xref .py .py-class .docutils .literal .notranslate} (on the outer leaf) that describes the hinge axis.

::: {.highlight-build123d .notranslate} ::: highlight # # Leaf attachment RigidJoint( label="leaf", joint_location=Location( (width - barrel_diameter, 0, length / 2), (90, 0, 0) ), ) # [Hinge Axis] (fixed with inner) if inner: RigidJoint( "hinge_axis", joint_location=Location( (width - barrel_diameter / 2, barrel_diameter / 2, 0) ), ) else: RevoluteJoint( "hinge_axis", axis=Axis( (width - barrel_diameter / 2, barrel_diameter / 2, 0), (0, 0, 1) ), angular_range=(90, 270), ) ::: :::

The inner leaf just pivots around the outer leaf and therefore the simple RigidJoint{.xref .py .py-class .docutils .literal .notranslate} is used to define the Location of this pivot. The outer leaf contains the more complex RevoluteJoint{.xref .py .py-class .docutils .literal .notranslate} which defines an axis of rotation and angular limits to that rotation (90 and 270 in this example as the two leaves will interfere with each other outside of this range). Note that the maximum angle must be greater than the minimum angle and therefore may be greater than 360°. Other types of joints have linear ranges as well as angular ranges. :::

::: {#tutorial_joints.xhtml#step-3c-fastener-joints .section}

Step 3c: Fastener Joints

The third set of joints to add are CylindricalJoint{.xref .py .py-class .docutils .literal .notranslate}'s that describe how the countersunk screws used to attach the leaves move.

::: {.highlight-build123d .notranslate} ::: highlight hole_locations = [hole.location for hole in holes] for hole, hole_location in enumerate(hole_locations): CylindricalJoint( label="hole" + str(hole), axis=Axis(hole_location), linear_range=(-2 * CM, 2 * CM), angular_range=(0, 360), ) ::: :::

Much like the RevoluteJoint{.xref .py .py-class .docutils .literal .notranslate}, a CylindricalJoint{.xref .py .py-class .docutils .literal .notranslate} has an Axis of motion but this type of joint allows both movement around and along this axis - exactly as a screw would move. Here is the Axis is setup such that a position of 0 aligns with the screw being fully set in the hole and positive numbers indicate the distance the head of the screw is above the leaf surface. One could have reversed the direction of the Axis such that negative position values would correspond to a screw now fully in the hole - whatever makes sense to the situation. The angular range of this joint is set to (0°, 360°) as there is no limit to the angular rotation of the screw (one could choose to model thread pitch and calculate position from angle or vice-versa). :::

::: {#tutorial_joints.xhtml#step-3d-call-super .section}

Step 3d: Call Super

To finish off, the base class for the Hinge class is initialized:

::: {.highlight-build123d .notranslate} ::: highlight super().init(leaf_builder.part.wrapped, joints=leaf_builder.part.joints) ::: ::: :::

::: {#tutorial_joints.xhtml#step-3e-instantiate-hinge-leaves .section}

Step 3e: Instantiate Hinge Leaves

Now that the Hinge class is complete it can be used to instantiate the two hinge leaves required to attach the box and lid together.

::: {.highlight-build123d .notranslate} ::: highlight hinge_inner = Hinge( width=5 * CM, length=12 * CM, barrel_diameter=1 * CM, thickness=2 * MM, pin_diameter=4 * MM, ) hinge_outer = Hinge( width=5 * CM, length=12 * CM, barrel_diameter=1 * CM, thickness=2 * MM, pin_diameter=4 * MM, inner=False, ) ::: ::: ::: :::

::: {#tutorial_joints.xhtml#step-4-create-the-box .section}

Step 4: Create the Box

The box is created with BuildPart{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} as a simple object - as shown below - let's focus on the joint used to attach the outer hinge leaf.

{.align-center}

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as box_builder: box = Box(30 * CM, 30 * CM, 10 * CM) offset(amount=-1 * CM, openings=box_builder.faces().sort_by(Axis.Z)[-1]) # Create a notch for the hinge with Locations((-15 * CM, 0, 5 * CM)): Box(2 * CM, 12 * CM, 4 * MM, mode=Mode.SUBTRACT) bbox = box.bounding_box() with Locations( Plane(origin=(bbox.min.X, 0, bbox.max.Z - 30 * MM), z_dir=(-1, 0, 0)) ): with GridLocations(0, 40 * MM, 1, 3): Hole(3 * MM, 1 * CM) RigidJoint( "hinge_attachment", joint_location=Location((-15 * CM, 0, 4 * CM), (180, 90, 0)), ) ::: :::

Since the hinge will be fixed to the box another RigidJoint{.xref .py .py-class .docutils .literal .notranslate} is used mark where the hinge will go. Note that the orientation of this Joint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} will control how the hinge leaf is attached and is independent of the orientation of the hinge as it was constructed.

::: {#tutorial_joints.xhtml#step-4a-relocate-box .section}

Step 4a: Relocate Box

Note that the position and orientation of the box's joints are given as a global Location{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} when created but will be translated to a relative Location{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} internally to allow the Joint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} to "move" with the parent object. This allows users the freedom to relocate objects without having to recreate or modify Joint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}'s. Here is the box is moved upwards to show this property.

::: {.highlight-build123d .notranslate} ::: highlight box = box_builder.part.moved(Location((0, 0, 5 * CM))) ::: ::: ::: :::

::: {#tutorial_joints.xhtml#step-5-create-the-lid .section}

Step 5: Create the Lid

Much like the box, the lid is created in a BuildPart{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} context and is assigned a RigidJoint{.xref .py .py-class .docutils .literal .notranslate}.

{.align-center}

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as lid_builder: Box(30 * CM, 30 * CM, 1 * CM, align=(Align.MIN, Align.CENTER, Align.MIN)) with Locations((2 * CM, 0, 0)): with GridLocations(0, 40 * MM, 1, 3): Hole(3 * MM, 1 * CM) RigidJoint( "hinge_attachment", joint_location=Location((0, 0, 0), (0, 0, 180)), ) lid = lid_builder.part ::: :::

Again, the original orientation of the lid and hinge inner leaf are not important, when the joints are connected together the parts will move into the correct position. :::

::: {#tutorial_joints.xhtml#step-6-import-a-screw-and-bind-a-joint-to-it .section}

Step 6: Import a Screw and bind a Joint to it

Joint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}'s can be bound to simple objects the a Compound{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} imported - in this case a screw.

  • screw STEP model: M6-1x12-countersunk-screw.step{.xref .download .docutils .literal .notranslate}

{.align-center}

::: {.highlight-build123d .notranslate} ::: highlight m6_screw = import_step("M6-1x12-countersunk-screw.step") m6_joint = RigidJoint("head", m6_screw, Location((0, 0, 0), (0, 0, 0))) ::: :::

Here a simple RigidJoint{.xref .py .py-class .docutils .literal .notranslate} is bound to the top of the screw head such that it can be connected to the hinge's CylindricalJoint{.xref .py .py-class .docutils .literal .notranslate}. :::

::: {#tutorial_joints.xhtml#step-7-connect-the-joints-together .section}

Step 7: Connect the Joints together

This last step is the most interesting. Now that all of the joints have been defined and bound to their parent objects, they can be connected together.

::: {#tutorial_joints.xhtml#step-7a-hinge-to-box .section}

Step 7a: Hinge to Box

To start, the outer hinge leaf will be connected to the box, as follows:

::: {.highlight-build123d .notranslate} ::: highlight box.joints["hinge_attachment"].connect_to(hinge_outer.joints["leaf"]) ::: :::

Here the hinge_attachment{.docutils .literal .notranslate} joint of the box{.docutils .literal .notranslate} is connected to the leaf{.docutils .literal .notranslate} joint of hinge_outer{.docutils .literal .notranslate}. Note that the hinge leaf is the object to move. Once this line is executed, we get the following:

{.align-center} :::

::: {#tutorial_joints.xhtml#step-7b-hinge-to-hinge .section}

Step 7b: Hinge to Hinge

Next, the hinge inner leaf is connected to the hinge outer leaf which is attached to the box.

::: {.highlight-build123d .notranslate} ::: highlight hinge_outer.joints["hinge_axis"].connect_to(hinge_inner.joints["hinge_axis"], angle=120) ::: :::

As hinge_outer.joints["hinge_axis"]{.docutils .literal .notranslate} is a RevoluteJoint{.xref .py .py-class .docutils .literal .notranslate} there is an angle{.docutils .literal .notranslate} parameter that can be set (angles default to the minimum range value) - here to 120°. This is what that looks like:

{.align-center} :::

::: {#tutorial_joints.xhtml#step-7c-lid-to-hinge .section}

Step 7c: Lid to Hinge

Now the lid{.docutils .literal .notranslate} is connected to the hinge_inner{.docutils .literal .notranslate}:

::: {.highlight-build123d .notranslate} ::: highlight hinge_inner.joints["leaf"].connect_to(lid.joints["hinge_attachment"]) ::: :::

which results in:

{.align-center}

Note how the lid is now in an open position. To close the lid just change the above angle{.docutils .literal .notranslate} parameter from 120° to 90°. :::

::: {#tutorial_joints.xhtml#step-7d-screw-to-hinge .section}

Step 7d: Screw to Hinge

The last step in this example is to place a screw in one of the hinges:

::: {.highlight-build123d .notranslate} ::: highlight hinge_outer.joints["hole2"].connect_to(m6_joint, position=5 * MM, angle=30) ::: :::

As the position is a positive number the screw is still proud of the hinge face as shown here:

{.align-center}

Try changing these position and angle values to "tighten" the screw. ::: :::

::: {#tutorial_joints.xhtml#conclusion .section}

Conclusion

Use a Joint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} to locate two objects relative to each other with some degree of motion. Keep in mind that when using the connect_to{.docutils .literal .notranslate} method, self{.docutils .literal .notranslate} is always fixed and other{.docutils .literal .notranslate} will move to the appropriate Location{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}.

::: {.admonition .note} Note

The joint symbols can be displayed as follows (your viewer may use show{.docutils .literal .notranslate} instead of show_object{.docutils .literal .notranslate}):

::: {.highlight-python .notranslate} ::: highlight show_object(box.joints["hinge_attachment"].symbol, name="box attachment point") ::: :::

or

::: {.highlight-python .notranslate} ::: highlight show_object(m6_joint.symbol, name="m6 screw symbol") ::: :::

or, with the ocp_vscode viewer

::: {.highlight-python .notranslate} ::: highlight show(box, render_joints=True) ::: ::: ::: ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#examples_1.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#examples_1.xhtml#the-build123d-examples .section}

The build123d Examples

::: {#examples_1.xhtml#overview .section}

Overview

In the GitHub repository you will find an examples folder{.reference .external}[ [https://github.com/42sol-eu/build123d/tree/examples]]{.link-target}.

Most of the examples show the builder and algebra modes.

::: {.sd-container-fluid .sd-sphinx-override .sd-mb-4 .docutils} ::: {.sd-row .sd-row-cols-3 .sd-row-cols-xs-3 .sd-row-cols-sm-3 .sd-row-cols-md-3 .sd-row-cols-lg-3 .docutils} ::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Benchy 🔨 ::: :::

[Benchy]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Bicycle Tire 🔨 ::: :::

[Bicycle Tire]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Canadian Flag Blowing in The Wind 🔨 ✏️ ::: :::

[Canadian Flag Blowing in The Wind]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Cast Bearing Unit 🔨 ::: :::

[Cast Bearing Unit]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Circuit Board With Holes 🔨 ✏️ ::: :::

[Circuit Board With Holes]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Clock Face 🔨 ✏️ ::: :::

[Clock Face]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Fast Grid Holes ✏️ ::: :::

[Fast Grid Holes]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Handle 🔨 ✏️ ::: :::

[Handle]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Heat Exchanger 🔨 ✏️ ::: :::

[Heat Exchanger]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Key Cap 🔨 ✏️ ::: :::

[Key Cap]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} (former) build123d Logo 🔨 ✏️ ::: :::

[Former build123d Logo]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Maker Coin 🔨 ::: :::

[Maker Coin]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Multi-Sketch Loft 🔨 ✏️ ::: :::

[Multi-Sketch Loft]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Peg Board J Hook 🔨 ✏️ ::: :::

[Peg Board Hook]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Platonic Solids ✏️ ::: :::

[Platonic Solids]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Playing Cards 🔨 ::: :::

[Playing Cards]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Stud Wall ✏️ ::: :::

[Stud Wall]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Tea Cup 🔨 ✏️ ::: :::

[Tea Cup]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Toy Truck 🔨 ::: :::

[Toy Truck]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Vase 🔨 ✏️ ::: :::

[Vase]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: ::: ::: ::: :::

::: {#examples_1.xhtml#benchy .section} []{#examples_1.xhtml#examples-benchy}

Benchy

{.align-center}

The Benchy examples shows how to import a STL model as a <cite>{=html}Solid</cite>{=html} object with the class <cite>{=html}Mesher</cite>{=html} and modify it by replacing chimney with a BREP version.

  • Benchy STL model: low_poly_benchy.stl{.xref .download .docutils .literal .notranslate}
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Gallery]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} {.align-center} {.align-center} :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[🔨 Reference Implementation (Builder Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight # Import the benchy as a Solid model importer = Mesher() benchy_stl = importer.read("low_poly_benchy.stl")[0]

with BuildPart() as benchy:
    add(benchy_stl)

    # Determine the plane that defines the top of the roof
    vertices = benchy.vertices()
    roof_vertices = vertices.filter_by_position(Axis.Z, 38, 42)
    roof_plane_vertices = [
        roof_vertices.group_by(Axis.Y, tol_digits=2)[-1].sort_by(Axis.X)[0],
        roof_vertices.sort_by(Axis.Z)[0],
        roof_vertices.group_by(Axis.Y, tol_digits=2)[0].sort_by(Axis.X)[0],
    ]
    roof_plane = Plane(
        Face(Wire.make_polygon([v.to_tuple() for v in roof_plane_vertices]))
    )
    # Remove the faceted smoke stack
    split(bisect_by=roof_plane, keep=Keep.BOTTOM)

    # Determine the position and size of the smoke stack
    smoke_stack_vertices = vertices.group_by(Axis.Z, tol_digits=0)[-1]
    smoke_stack_center = sum(
        [Vector(v.X, v.Y, v.Z) for v in smoke_stack_vertices], Vector()
    ) * (1 / len(smoke_stack_vertices))
    smoke_stack_radius = max(
        [
            (Vector(*v.to_tuple()) - smoke_stack_center).length
            for v in smoke_stack_vertices
        ]
    )

    # Create the new smoke stack
    with BuildSketch(Plane(smoke_stack_center)):
        Circle(smoke_stack_radius)
        Circle(smoke_stack_radius - 2 * MM, mode=Mode.SUBTRACT)
    extrude(amount=-3 * MM)
    with BuildSketch(Plane(smoke_stack_center)):
        Circle(smoke_stack_radius - 0.5 * MM)
        Circle(smoke_stack_radius - 2 * MM, mode=Mode.SUBTRACT)
    extrude(amount=roof_plane_vertices[1].Z - smoke_stack_center.Z)

show(benchy)

::: ::: :::

</details>

:::

::: {#examples_1.xhtml#bicycle-tire .section} []{#examples_1.xhtml#examples-bicycle-tire}

Bicycle Tire

{.align-center}

This example demonstrates how to model a realistic bicycle tire with a patterned tread using build123d. The key concept showcased here is the use of wrap_faces to project 2D planar geometry onto a curved 3D surface.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[🔨 Reference Implementation (Builder Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight import copy from build123d import * from ocp_vscode import show

wheel_diameter = 740 * MM

with BuildSketch() as tire_profile:
    with BuildLine() as build_profile:
        l00 = Bezier((0.0, 0.0), (7.05, 0.0), (12.18, 1.54), (15.13, 4.54))
        l01 = Bezier(l00 @ 1, (15.81, 5.22), (15.98, 5.44), (16.5, 6.23))
        l02 = Bezier(l01 @ 1, (18.45, 9.19), (19.61, 13.84), (19.94, 20.06))
        l03 = Bezier(l02 @ 1, (20.1, 23.24), (19.93, 27.48), (19.56, 29.45))
        l04 = Bezier(l03 @ 1, (19.13, 31.69), (18.23, 33.67), (16.91, 35.32))
        l05 = Bezier(l04 @ 1, (16.26, 36.12), (15.57, 36.77), (14.48, 37.58))
        l06 = Bezier(l05 @ 1, (12.77, 38.85), (11.51, 40.28), (10.76, 41.78))
        l07 = Bezier(l06 @ 1, (10.07, 43.16), (10.15, 43.81), (11.03, 43.98))
        l08 = Bezier(l07 @ 1, (11.82, 44.13), (12.15, 44.55), (12.08, 45.33))
        l09 = Bezier(l08 @ 1, (12.01, 46.07), (11.84, 46.43), (11.43, 46.69))
        l10 = Bezier(l09 @ 1, (10.98, 46.97), (10.07, 46.7), (9.47, 46.1))
        l11 = Bezier(l10 @ 1, (9.03, 45.65), (8.88, 45.31), (8.84, 44.65))
        l12 = Bezier(l11 @ 1, (8.78, 43.6), (9.11, 42.26), (9.72, 41.0))
        l13 = Bezier(l12 @ 1, (10.43, 39.54), (11.52, 38.2), (12.78, 37.22))
        l14 = Bezier(l13 @ 1, (15.36, 35.23), (16.58, 33.76), (17.45, 31.62))
        l15 = Bezier(l14 @ 1, (17.91, 30.49), (18.22, 29.27), (18.4, 27.8))
        l16 = Bezier(l15 @ 1, (18.53, 26.78), (18.52, 23.69), (18.37, 22.61))
        l17 = Bezier(l16 @ 1, (17.8, 18.23), (16.15, 14.7), (13.39, 11.94))
        l18 = Bezier(l17 @ 1, (11.89, 10.45), (10.19, 9.31), (8.09, 8.41))
        l19 = Bezier(l18 @ 1, (3.32, 6.35), (0.0, 6.64))
        mirror(about=Plane.YZ)
    make_face()

tire = revolve(Pos(Y=-wheel_diameter / 2) * tire_profile.face(), Axis.X)

with BuildSketch() as tread_pattern:
    with Locations((1, 1)):
        Trapezoid(15, 12, 60, 120, align=Align.MIN)
    with Locations((1, 8)):
        with GridLocations(0, 5, 1, 2):
            Rectangle(50, 2, mode=Mode.SUBTRACT)

# Define the surface and path that the tread pattern will be wrapped onto
half_road_surface = Face.revolve(Pos(Y=-wheel_diameter / 2) * l00, 360, Axis.X)
tread_path = half_road_surface.edges().sort_by(Axis.X)[0]

# Wrap the planar tread pattern onto the tire's outside surface
tread_faces = half_road_surface.wrap_faces(tread_pattern.faces(), tread_path)

# Mirror the faces to the other half of the tire
tread_faces.extend([mirror(t, Plane.YZ) for t in tread_faces])

# Thicken the tread to become solid nubs
# tread_prime = [Solid.thicken(f, 3 * MM) for f in tread_faces]
tread_prime = [thicken(f, 3 * MM) for f in tread_faces]

# Copy the nubs around the whole tire
tread = [Rot(X=r) * copy.copy(t) for t in tread_prime for r in range(0, 360, 2)]

show(tire, tread)

::: ::: :::

</details>

:::

::: {#examples_1.xhtml#former-build123d-logo .section} []{#examples_1.xhtml#examples-build123d-logo}

{.align-center}

This example creates the former build123d logo (new logo was created in the end of 2023).

Using text and lines to create the first build123d logo. The builder mode example also generates the SVG file <cite>{=html}logo.svg</cite>{=html}.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[🔨 Reference Implementation (Builder Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight with BuildSketch() as logo_text: Text("123d", font_size=10, align=(Align.MIN, Align.MIN)) font_height = logo_text.vertices().sort_by(Axis.Y)[-1].Y

with BuildSketch() as build_text:
    Text("build", font_size=5, align=(Align.CENTER, Align.CENTER))
    build_bb = bounding_box(build_text.sketch, mode=Mode.PRIVATE)
    build_vertices = build_bb.vertices().sort_by(Axis.X)
    build_width = build_vertices[-1].X - build_vertices[0].X

with BuildLine() as one:
    l1 = Line((font_height * 0.3, 0), (font_height * 0.3, font_height))
    TangentArc(l1 @ 1, (0, font_height * 0.7), tangent=(l1 % 1) * -1)

with BuildSketch() as two:
    with Locations((font_height * 0.35, 0)):
        Text("2", font_size=10, align=(Align.MIN, Align.MIN))

with BuildPart() as three_d:
    with BuildSketch(Plane((font_height * 1.1, 0))):
        Text("3d", font_size=10, align=(Align.MIN, Align.MIN))
    extrude(amount=font_height * 0.3)
    logo_width = three_d.vertices().sort_by(Axis.X)[-1].X

with BuildLine() as arrow_left:
    t1 = TangentArc((0, 0), (1, 0.75), tangent=(1, 0))
    mirror(t1, Plane.XZ)

ext_line_length = font_height * 0.5
dim_line_length = (logo_width - build_width - 2 * font_height * 0.05) / 2
with BuildLine() as extension_lines:
    l1 = Line((0, -font_height * 0.1), (0, -ext_line_length - font_height * 0.1))
    l2 = Line(
        (logo_width, -font_height * 0.1),
        (logo_width, -ext_line_length - font_height * 0.1),
    )
    with Locations(l1 @ 0.5):
        add(arrow_left.line)
    with Locations(l2 @ 0.5):
        add(arrow_left.line, rotation=180.0)
    Line(l1 @ 0.5, l1 @ 0.5 + Vector(dim_line_length, 0))
    Line(l2 @ 0.5, l2 @ 0.5 - Vector(dim_line_length, 0))

# Precisely center the build Faces
with BuildSketch() as build:
    with Locations(
        (l1 @ 0.5 + l2 @ 0.5) / 2
        - Vector((build_vertices[-1].X + build_vertices[0].X) / 2, 0)
    ):
        add(build_text.sketch)


if True:
    logo = Compound(
        children=[
            one.line,
            two.sketch,
            three_d.part,
            extension_lines.line,
            build.sketch,
        ]
    )

    # logo.export_step("logo.step")
    def add_svg_shape(svg: ExportSVG, shape: Shape, color: tuple[float, float, float]):
        global counter
        try:
            counter += 1
        except:
            counter = 1

        visible, _hidden = shape.project_to_viewport(
            (-5, 1, 10), viewport_up=(0, 1, 0), look_at=(0, 0, 0)
        )
        if color is not None:
            svg.add_layer(str(counter), fill_color=color, line_weight=1)
        else:
            svg.add_layer(str(counter), line_weight=1)
        svg.add_shape(visible, layer=str(counter))

    svg = ExportSVG(scale=20)
    add_svg_shape(svg, logo, None)
    # add_svg_shape(svg, Compound(children=[one.line, extension_lines.line]), None)
    # add_svg_shape(svg, Compound(children=[two.sketch, build.sketch]), (170, 204, 255))
    # add_svg_shape(svg, three_d.part, (85, 153, 255))
    svg.write("logo.svg")

show_object(one, name="one")
show_object(two, name="two")
show_object(three_d, name="three_d")
show_object(extension_lines, name="extension_lines")
show_object(build, name="build")

::: ::: :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[✏️ Reference Implementation (Algebra Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight logo_text = Text("123d", font_size=10, align=Align.MIN) font_height = logo_text.vertices().sort_by(Axis.Y).last.Y

build_text = Text("build", font_size=5, align=Align.CENTER)
build_bb = build_text.bounding_box()
build_width = build_bb.max.X - build_bb.min.X

l1 = Line((font_height * 0.3, 0), (font_height * 0.3, font_height))
one = l1 + TangentArc(l1 @ 1, (0, font_height * 0.7), tangent=(l1 % 1) * -1)

two = Pos(font_height * 0.35, 0) * Text("2", font_size=10, align=Align.MIN)

three_d = Text("3d", font_size=10, align=Align.MIN)
three_d = Pos(font_height * 1.1, 0) * extrude(three_d, amount=font_height * 0.3)
logo_width = three_d.vertices().sort_by(Axis.X).last.X

t1 = TangentArc((0, 0), (1, 0.75), tangent=(1, 0))
arrow_left = t1 + mirror(t1, Plane.XZ)

ext_line_length = font_height * 0.5
dim_line_length = (logo_width - build_width - 2 * font_height * 0.05) / 2

l1 = Line((0, -font_height * 0.1), (0, -ext_line_length - font_height * 0.1))
l2 = Line(
    (logo_width, -font_height * 0.1),
    (logo_width, -ext_line_length - font_height * 0.1),
)
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))
extension_lines += Line(l2 @ 0.5, l2 @ 0.5 - Vector(dim_line_length, 0))

# Precisely center the build Faces
p1 = Pos((l1 @ 0.5 + l2 @ 0.5) / 2 - Vector((build_bb.max.X + build_bb.min.X) / 2, 0))
build = p1 * build_text

cmpd = Compound([three_d, two, one, build, extension_lines])

show_object(cmpd, name="compound")

::: ::: :::

</details>

:::

::: {#examples_1.xhtml#cast-bearing-unit .section} []{#examples_1.xhtml#examples-cast-bearing-unit}

Cast Bearing Unit

{.align-center}

This example demonstrates the creation of a castable flanged bearing housing using the <cite>{=html}draft</cite>{=html} operation to add appropriate draft angles for mold release.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[🔨 Reference Implementation (Builder Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show

A, A1, Db2, H, J = 26, 11, 57, 98.5, 76.5
with BuildPart() as oval_flanged_bearing_unit:
    with BuildSketch() as plan:
        housing = Circle(Db2 / 2)
        with GridLocations(J, 0, 2, 1) as bolt_centers:
            Circle((H - J) / 2)
        make_hull()
    extrude(amount=A1)
    extrude(housing, amount=A)
    drafted_faces = oval_flanged_bearing_unit.faces().filter_by(Axis.Z, reverse=True)
    draft(drafted_faces, Plane.XY, 4)
    fillet(oval_flanged_bearing_unit.edges(), 1)
    with Locations(oval_flanged_bearing_unit.faces().sort_by(Axis.Z)[-1]):
        CounterBoreHole(14 / 2, 47 / 2, 14)
    with Locations(*bolt_centers):
        Hole(5)

oval_flanged_bearing_unit.part.color = Color(0x4C6377)

show(oval_flanged_bearing_unit)

::: ::: :::

</details>

:::

::: {#examples_1.xhtml#canadian-flag-blowing-in-the-wind .section} []{#examples_1.xhtml#examples-canadian-flag}

Canadian Flag Blowing in The Wind

{.align-center}

A Canadian Flag blowing in the wind created by projecting planar faces onto a non-planar face (the_wind).

This example also demonstrates building complex lines that snap to existing features.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[More Images]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} {.align-center} {.align-center} :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[🔨 Reference Implementation (Builder Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight def surface(amplitude, u, v): """Calculate the surface displacement of the flag at a given position""" return v * amplitude / 20 * cos(3.5 * pi * u) + amplitude / 10 * v * sin( 1.1 * pi * v )

# Note that the surface to project on must be a little larger than the faces
# being projected onto it to create valid projected faces
the_wind = Face.make_surface_from_array_of_points(
    [
        [
            Vector(
                width * (v * 1.1 / 40 - 0.05),
                height * (u * 1.2 / 40 - 0.1),
                height * surface(wave_amplitude, u / 40, v / 40) / 2,
            )
            for u in range(41)
        ]
        for v in range(41)
    ]
)
with BuildSketch(Plane.XY.offset(10)) as west_field_builder:
    Rectangle(width / 4, height, align=(Align.MIN, Align.MIN))
west_field_planar = west_field_builder.sketch.faces()[0]
east_field_planar = west_field_planar.mirror(Plane.YZ.offset(width / 2))

with BuildSketch(Plane((width / 2, 0, 10))) as center_field_builder:
    Rectangle(width / 2, height, align=(Align.CENTER, Align.MIN))
    with BuildSketch(
        Plane((width / 2, 0, 10)), mode=Mode.SUBTRACT
    ) as maple_leaf_builder:
        with BuildLine() as outline:
            l1 = Polyline((0.0000, 0.0771), (0.0187, 0.0771), (0.0094, 0.2569))
            l2 = Polyline((0.0325, 0.2773), (0.2115, 0.2458), (0.1873, 0.3125))
            RadiusArc(l1 @ 1, l2 @ 0, 0.0271)
            l3 = Polyline((0.1915, 0.3277), (0.3875, 0.4865), (0.3433, 0.5071))
            TangentArc(l2 @ 1, l3 @ 0, tangent=l2 % 1)
            l4 = Polyline((0.3362, 0.5235), (0.375, 0.6427), (0.2621, 0.6188))
            SagittaArc(l3 @ 1, l4 @ 0, 0.003)
            l5 = Polyline((0.2469, 0.6267), (0.225, 0.6781), (0.1369, 0.5835))
            ThreePointArc(
                l4 @ 1, (l4 @ 1 + l5 @ 0) * 0.5 + Vector(-0.002, -0.002), l5 @ 0
            )
            l6 = Polyline((0.1138, 0.5954), (0.1562, 0.8146), (0.0881, 0.7752))
            Spline(
                l5 @ 1,
                l6 @ 0,
                tangents=(l5 % 1, l6 % 0),
                tangent_scalars=(2, 2),
            )
            l7 = Line((0.0692, 0.7808), (0.0000, 0.9167))
            TangentArc(l6 @ 1, l7 @ 0, tangent=l6 % 1)
            mirror(outline.edges(), Plane.YZ)
        make_face()
        scale(by=height)
maple_leaf_planar = maple_leaf_builder.sketch.faces()[0]
center_field_planar = center_field_builder.sketch.faces()[0]

west_field = west_field_planar.project_to_shape(the_wind, (0, 0, -1))[0]
west_field.color = Color("red")
east_field = east_field_planar.project_to_shape(the_wind, (0, 0, -1))[0]
east_field.color = Color("red")
center_field = center_field_planar.project_to_shape(the_wind, (0, 0, -1))[0]
center_field.color = Color("white")
maple_leaf = maple_leaf_planar.project_to_shape(the_wind, (0, 0, -1))[0]
maple_leaf.color = Color("red")

canadian_flag = Compound(children=[west_field, east_field, center_field, maple_leaf])
show(Rot(90, 0, 0) * canadian_flag)

::: ::: :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[✏️ Reference Implementation (Algebra Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight def surface(amplitude, u, v): """Calculate the surface displacement of the flag at a given position""" return v * amplitude / 20 * cos(3.5 * pi * u) + amplitude / 10 * v * sin( 1.1 * pi * v )

# Note that the surface to project on must be a little larger than the faces
# being projected onto it to create valid projected faces
the_wind = Face.make_surface_from_array_of_points(
    [
        [
            Vector(
                width * (v * 1.1 / 40 - 0.05),
                height * (u * 1.2 / 40 - 0.1),
                height * surface(wave_amplitude, u / 40, v / 40) / 2,
            )
            for u in range(41)
        ]
        for v in range(41)
    ]
)

field_planar = Plane.XY.offset(10) * Rectangle(width / 4, height, align=Align.MIN)
west_field_planar = field_planar.faces()[0]
east_field_planar = mirror(west_field_planar, Plane.YZ.offset(width / 2))

l1 = Polyline((0.0000, 0.0771), (0.0187, 0.0771), (0.0094, 0.2569))
l2 = Polyline((0.0325, 0.2773), (0.2115, 0.2458), (0.1873, 0.3125))
r1 = RadiusArc(l1 @ 1, l2 @ 0, 0.0271)
l3 = Polyline((0.1915, 0.3277), (0.3875, 0.4865), (0.3433, 0.5071))
r2 = TangentArc(l2 @ 1, l3 @ 0, tangent=l2 % 1)
l4 = Polyline((0.3362, 0.5235), (0.375, 0.6427), (0.2621, 0.6188))
r3 = SagittaArc(l3 @ 1, l4 @ 0, 0.003)
l5 = Polyline((0.2469, 0.6267), (0.225, 0.6781), (0.1369, 0.5835))
r4 = ThreePointArc(l4 @ 1, (l4 @ 1 + l5 @ 0) * 0.5 + Vector(-0.002, -0.002), l5 @ 0)
l6 = Polyline((0.1138, 0.5954), (0.1562, 0.8146), (0.0881, 0.7752))
s = Spline(
    l5 @ 1,
    l6 @ 0,
    tangents=(l5 % 1, l6 % 0),
    tangent_scalars=(2, 2),
)
l7 = Line((0.0692, 0.7808), (0.0000, 0.9167))
r5 = TangentArc(l6 @ 1, l7 @ 0, tangent=l6 % 1)

outline = l1 + [l2, r1, l3, r2, l4, r3, l5, r4, l6, s, l7, r5]
outline += mirror(outline, Plane.YZ)

maple_leaf_planar = make_face(outline)

center_field_planar = (
    Rectangle(1, 1, align=(Align.CENTER, Align.MIN)) - maple_leaf_planar
)


def scale_move(obj):
    return Plane((width / 2, 0, 10)) * scale(obj, height)


def project(obj):
    return obj.faces()[0].project_to_shape(the_wind, (0, 0, -1))[0]


maple_leaf_planar = scale_move(maple_leaf_planar)
center_field_planar = scale_move(center_field_planar)

west_field = project(west_field_planar)
west_field.color = Color("red")
east_field = project(east_field_planar)
east_field.color = Color("red")
center_field = project(center_field_planar)
center_field.color = Color("white")
maple_leaf = project(maple_leaf_planar)
maple_leaf.color = Color("red")

canadian_flag = Compound(children=[west_field, east_field, center_field, maple_leaf])
show(Rot(90, 0, 0) * canadian_flag)

::: ::: :::

</details>

:::

::: {#examples_1.xhtml#circuit-board-with-holes .section} []{#examples_1.xhtml#examples-circuit-board}

Circuit Board With Holes

{.align-center}

This example demonstrates placing holes around a part.

  • Builder mode uses <cite>{=html}Locations</cite>{=html} context to place the positions.

  • Algebra mode uses <cite>{=html}product</cite>{=html} and <cite>{=html}range</cite>{=html} to calculate the positions.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[More Images]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} {.align-center} :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[🔨 Reference Implementation (Builder Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as pcb: with BuildSketch(): Rectangle(pcb_length, pcb_width)

        for i in range(65 // 5):
            x = i * 5 - 30
            with Locations((x, -15), (x, -10), (x, 10), (x, 15)):
                Circle(1, mode=Mode.SUBTRACT)
        for i in range(30 // 5 - 1):
            y = i * 5 - 10
            with Locations((30, y), (35, y)):
                Circle(1, mode=Mode.SUBTRACT)
        with GridLocations(60, 20, 2, 2):
            Circle(2, mode=Mode.SUBTRACT)
    extrude(amount=pcb_height)

show_object(pcb.part.wrapped)

::: ::: :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[✏️ Reference Implementation (Algebra Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight x_coords = product(range(65 // 5), (-15, -10, 10, 15)) y_coords = product((30, 35), range(30 // 5 - 1))

pcb = Rectangle(pcb_length, pcb_width)
pcb -= [Pos(i * 5 - 30, y) * Circle(1) for i, y in x_coords]
pcb -= [Pos(x, i * 5 - 10) * Circle(1) for x, i in y_coords]
pcb -= [loc * Circle(2) for loc in GridLocations(60, 20, 2, 2)]

pcb = extrude(pcb, pcb_height)

show(pcb)

::: ::: :::

</details>

:::

::: {#examples_1.xhtml#clock-face .section} []{#examples_1.xhtml#id1}

Clock Face

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[🔨 Reference Implementation (Builder Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show

clock_radius = 10
with BuildSketch() as minute_indicator:
    with BuildLine() as outline:
        l1 = CenterArc((0, 0), clock_radius * 0.975, 0.75, 4.5)
        l2 = CenterArc((0, 0), clock_radius * 0.925, 0.75, 4.5)
        Line(l1 @ 0, l2 @ 0)
        Line(l1 @ 1, l2 @ 1)
    make_face()
    fillet(minute_indicator.vertices(), radius=clock_radius * 0.01)

with BuildSketch() as clock_face:
    Circle(clock_radius)
    with PolarLocations(0, 60):
        add(minute_indicator.sketch, mode=Mode.SUBTRACT)
    with PolarLocations(clock_radius * 0.875, 12):
        SlotOverall(clock_radius * 0.05, clock_radius * 0.025, mode=Mode.SUBTRACT)
    for hour in range(1, 13):
        with PolarLocations(clock_radius * 0.75, 1, -hour * 30 + 90, 360, rotate=False):
            Text(
                str(hour),
                font_size=clock_radius * 0.175,
                font_style=FontStyle.BOLD,
                mode=Mode.SUBTRACT,
            )

show(clock_face)

::: ::: :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[✏️ Reference Implementation (Algebra Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show

clock_radius = 10

l1 = CenterArc((0, 0), clock_radius * 0.975, 0.75, 4.5)
l2 = CenterArc((0, 0), clock_radius * 0.925, 0.75, 4.5)
l3 = Line(l1 @ 0, l2 @ 0)
l4 = Line(l1 @ 1, l2 @ 1)
minute_indicator = make_face([l1, l3, l2, l4])
minute_indicator = fillet(minute_indicator.vertices(), radius=clock_radius * 0.01)

clock_face = Circle(clock_radius)
clock_face -= PolarLocations(0, 60) * minute_indicator
clock_face -= PolarLocations(clock_radius * 0.875, 12) * SlotOverall(
    clock_radius * 0.05, clock_radius * 0.025
)

clock_face -= [
    loc
    * Text(
        str(hour + 1),
        font_size=clock_radius * 0.175,
        font_style=FontStyle.BOLD,
        align=Align.CENTER,
    )
    for hour, loc in enumerate(
        PolarLocations(clock_radius * 0.75, 12, 60, -360, rotate=False)
    )
]

show(clock_face)

::: ::: :::

</details>

The Python code utilizes the build123d library to create a 3D model of a clock face. It defines a minute indicator with arcs and lines, applying fillets, and then integrates it into the clock face sketch. The clock face includes a circular outline, hour labels, and slots at specified positions. The resulting 3D model represents a detailed and visually appealing clock design.

PolarLocations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} are used to position features on the clock face. :::

::: {#examples_1.xhtml#fast-grid-holes .section} []{#examples_1.xhtml#id2}

Fast Grid Holes

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[✏️ Reference Implementation (Algebra Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight import timeit from build123d import * from ocp_vscode import show

start_time = timeit.default_timer()

# Calculate the locations of 625 holes
major_r = 10
hole_locs = HexLocations(major_r, 25, 25)

# Create wires for both the perimeter and all the holes
face_perimeter = Rectangle(500, 600).wire()
hex_hole = RegularPolygon(major_r - 1, 6, major_radius=True).wire()
holes = hole_locs * hex_hole

# Create a new Face from the perimeter and hole wires
grid_pattern = Face(face_perimeter, holes)

# Extrude to a 3D part
grid = extrude(grid_pattern, 1)

print(f"Time: {timeit.default_timer() - start_time:0.3f}s")
show(grid)

::: ::: :::

</details>

This example demonstrates an efficient approach to creating a large number of holes (625 in this case) in a planar part using build123d.

Instead of modeling and subtracting 3D solids for each hole---which is computationally expensive---this method constructs a 2D Face from an outer perimeter wire and a list of hole wires. The entire face is then extruded in a single operation to form the final 3D object. This approach significantly reduces modeling time and complexity.

The hexagonal hole pattern is generated using HexLocations, and each location is populated with a hexagonal wire. These wires are passed directly to the Face constructor as holes. On a typical Linux laptop, this script completes in approximately 1.02 seconds, compared to substantially longer runtimes for boolean subtraction of individual holes in 3D. :::

::: {#examples_1.xhtml#handle .section} []{#examples_1.xhtml#id3}

Handle

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[🔨 Reference Implementation (Builder Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show_object

segment_count = 6

with BuildPart() as handle:
    # Create a path for the sweep along the handle - added to pending_edges
    with BuildLine() as handle_center_line:
        Spline(
            (-10, 0, 0),
            (0, 0, 5),
            (10, 0, 0),
            tangents=((0, 0, 1), (0, 0, -1)),
            tangent_scalars=(1.5, 1.5),
        )

    # Create the cross sections - added to pending_faces
    for i in range(segment_count + 1):
        with BuildSketch(handle_center_line.line ^ (i / segment_count)) as section:
            if i % segment_count == 0:
                Circle(1)
            else:
                Rectangle(1.25, 3)
                fillet(section.vertices(), radius=0.2)
    # Record the sections for display
    sections = handle.pending_faces

    # Create the handle by sweeping along the path
    sweep(multisection=True)

assert abs(handle.part.volume - 94.77361455046953) < 1e-3

show_object(handle_center_line.line, name="handle_center_line")
for i, section in enumerate(sections):
    show_object(section, name="section" + str(i))
show_object(handle.part, name="handle", options=dict(alpha=0.6))

::: ::: :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[✏️ Reference Implementation (Algebra Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show_object

segment_count = 6

# Create a path for the sweep along the handle - added to pending_edges
handle_center_line = Spline(
    (-10, 0, 0),
    (0, 0, 5),
    (10, 0, 0),
    tangents=((0, 0, 1), (0, 0, -1)),
    tangent_scalars=(1.5, 1.5),
)

# Create the cross sections - added to pending_faces
sections = Sketch()
for i in range(segment_count + 1):
    location = handle_center_line ^ (i / segment_count)
    if i % segment_count == 0:
        circle = location * Circle(1)
    else:
        circle = location * Rectangle(1.25, 3)
        circle = fillet(circle.vertices(), radius=0.2)
    sections += circle

# Create the handle by sweeping along the path
handle = sweep(sections, path=handle_center_line, multisection=True)

show_object(handle_center_line, name="handle_path")
for i, circle in enumerate(sections):
    show_object(circle, name="section" + str(i))
show_object(handle, name="handle", options=dict(alpha=0.6))

::: ::: :::

</details>

This example demonstrates multisection sweep creating a drawer handle. :::

::: {#examples_1.xhtml#heat-exchanger .section} []{#examples_1.xhtml#id4}

Heat Exchanger

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[🔨 Reference Implementation (Builder Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show

exchanger_diameter = 10 * CM
exchanger_length = 30 * CM
plate_thickness = 5 * MM
# 149 tubes
tube_diameter = 5 * MM
tube_spacing = 2 * MM
tube_wall_thickness = 0.5 * MM
tube_extension = 3 * MM
bundle_diameter = exchanger_diameter - 2 * tube_diameter
fillet_radius = tube_spacing / 3
assert tube_extension > fillet_radius

# Build the heat exchanger
with BuildPart() as heat_exchanger:
    # Generate list of tube locations
    tube_locations = [
        l
        for l in HexLocations(
            radius=(tube_diameter + tube_spacing) / 2,
            x_count=exchanger_diameter // tube_diameter,
            y_count=exchanger_diameter // tube_diameter,
        )
        if l.position.length < bundle_diameter / 2
    ]
    tube_count = len(tube_locations)
    with BuildSketch() as tube_plan:
        with Locations(*tube_locations):
            Circle(radius=tube_diameter / 2)
            Circle(radius=tube_diameter / 2 - tube_wall_thickness, mode=Mode.SUBTRACT)
    extrude(amount=exchanger_length / 2)
    with BuildSketch(
        Plane(
            origin=(0, 0, exchanger_length / 2 - tube_extension - plate_thickness),
            z_dir=(0, 0, 1),
        )
    ) as plate_plan:
        Circle(radius=exchanger_diameter / 2)
        with Locations(*tube_locations):
            Circle(radius=tube_diameter / 2 - tube_wall_thickness, mode=Mode.SUBTRACT)
    extrude(amount=plate_thickness)
    half_volume_before_fillet = heat_exchanger.part.volume
    # Simulate welded tubes by adding a fillet to the outside radius of the tubes
    fillet(
        heat_exchanger.edges()
        .filter_by(GeomType.CIRCLE)
        .sort_by(SortBy.RADIUS)
        .sort_by(Axis.Z, reverse=True)[2 * tube_count : 3 * tube_count],
        radius=fillet_radius,
    )
    half_volume_after_fillet = heat_exchanger.part.volume
    mirror(about=Plane.XY)

fillet_volume = 2 * (half_volume_after_fillet - half_volume_before_fillet)
assert abs(fillet_volume - 469.88331045553787) < 1e-3

show(heat_exchanger)

::: ::: :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[✏️ Reference Implementation (Algebra Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show

exchanger_diameter = 10 * CM
exchanger_length = 30 * CM
plate_thickness = 5 * MM
# 149 tubes
tube_diameter = 5 * MM
tube_spacing = 2 * MM
tube_wall_thickness = 0.5 * MM
tube_extension = 3 * MM
bundle_diameter = exchanger_diameter - 2 * tube_diameter
fillet_radius = tube_spacing / 3
assert tube_extension > fillet_radius

# Build the heat exchanger
tube_locations = [
    l
    for l in HexLocations(
        radius=(tube_diameter + tube_spacing) / 2,
        x_count=exchanger_diameter // tube_diameter,
        y_count=exchanger_diameter // tube_diameter,
    )
    if l.position.length < bundle_diameter / 2
]

ring = Circle(tube_diameter / 2) - Circle(tube_diameter / 2 - tube_wall_thickness)
tube_plan = Sketch() + tube_locations * ring

heat_exchanger = extrude(tube_plan, exchanger_length / 2)

plate_plane = Plane(
    origin=(0, 0, exchanger_length / 2 - tube_extension - plate_thickness),
    z_dir=(0, 0, 1),
)
plate = Circle(radius=exchanger_diameter / 2) - tube_locations * Circle(
    radius=tube_diameter / 2 - tube_wall_thickness
)

heat_exchanger += extrude(plate_plane * plate, plate_thickness)
edges = (
    heat_exchanger.edges()
    .filter_by(GeomType.CIRCLE)
    .group_by(SortBy.RADIUS)[1]
    .group_by()[2]
)
half_volume_before_fillet = heat_exchanger.volume
heat_exchanger = fillet(edges, radius=fillet_radius)
half_volume_after_fillet = heat_exchanger.volume
heat_exchanger += mirror(heat_exchanger, Plane.XY)

fillet_volume = 2 * (half_volume_after_fillet - half_volume_before_fillet)
assert abs(fillet_volume - 469.88331045553787) < 1e-3

show(heat_exchanger)

::: ::: :::

</details>

This example creates a model of a parametric heat exchanger core. The positions of the tubes are defined with HexLocations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and further limited to fit within the circular end caps. The ends of the tubes are filleted to the end plates to simulate welding. :::

::: {#examples_1.xhtml#key-cap .section} []{#examples_1.xhtml#id5}

Key Cap

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[🔨 Reference Implementation (Builder Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import *

with BuildPart() as key_cap:
    # Start with the plan of the key cap and extrude it
    with BuildSketch() as plan:
        Rectangle(18 * MM, 18 * MM)
    extrude(amount=10 * MM, taper=15)
    # Create a dished top
    with Locations((0, -3 * MM, 47 * MM)):
        Sphere(40 * MM, mode=Mode.SUBTRACT, rotation=(90, 0, 0))
    # Fillet all the edges except the bottom
    fillet(
        key_cap.edges().filter_by_position(Axis.Z, 0, 30 * MM, inclusive=(False, True)),
        radius=1 * MM,
    )
    # Hollow out the key by subtracting a scaled version
    scale(by=(0.925, 0.925, 0.85), mode=Mode.SUBTRACT)

    # Add supporting ribs while leaving room for switch activation
    with BuildSketch(Plane(origin=(0, 0, 4 * MM))):
        Rectangle(15 * MM, 0.5 * MM)
        Rectangle(0.5 * MM, 15 * MM)
        Circle(radius=5.5 * MM / 2)
    # Extrude the mount and ribs to the key cap underside
    extrude(until=Until.NEXT)
    # Find the face on the bottom of the ribs to build onto
    rib_bottom = key_cap.faces().filter_by_position(Axis.Z, 4 * MM, 4 * MM)[0]
    # Add the switch socket
    with BuildSketch(rib_bottom) as cruciform:
        Circle(radius=5.5 * MM / 2)
        Rectangle(4.1 * MM, 1.17 * MM, mode=Mode.SUBTRACT)
        Rectangle(1.17 * MM, 4.1 * MM, mode=Mode.SUBTRACT)
    extrude(amount=3.5 * MM, mode=Mode.ADD)

assert abs(key_cap.part.volume - 644.8900473617498) < 1e-3

show(key_cap, alphas=[0.3])

::: ::: :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[✏️ Reference Implementation (Algebra Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import *

# Taper Extrude and Extrude to "next" while creating a Cherry MX key cap
# See: https://www.cherrymx.de/en/dev.html

plan = Rectangle(18 * MM, 18 * MM)
key_cap = extrude(plan, amount=10 * MM, taper=15)

# Create a dished top
key_cap -= Location((0, -3 * MM, 47 * MM), (90, 0, 0)) * Sphere(40 * MM)

# Fillet all the edges except the bottom
key_cap = fillet(
    key_cap.edges().filter_by_position(Axis.Z, 0, 30 * MM, inclusive=(False, True)),
    radius=1 * MM,
)

# Hollow out the key by subtracting a scaled version
key_cap -= scale(key_cap, (0.925, 0.925, 0.85))


# Add supporting ribs while leaving room for switch activation
ribs = Rectangle(17.5 * MM, 0.5 * MM)
ribs += Rectangle(0.5 * MM, 17.5 * MM)
ribs += Circle(radius=5.51 * MM / 2)

# Extrude the mount and ribs to the key cap underside
key_cap += extrude(Pos(0, 0, 4 * MM) * ribs, until=Until.NEXT, target=key_cap)


# Find the face on the bottom of the ribs to build onto
rib_bottom = key_cap.faces().filter_by_position(Axis.Z, 4 * MM, 4 * MM)[0]

# Add the switch socket
socket = Circle(radius=5.5 * MM / 2)
socket -= Rectangle(4.1 * MM, 1.17 * MM)
socket -= Rectangle(1.17 * MM, 4.1 * MM)
key_cap += extrude(Plane(rib_bottom) * socket, amount=3.5 * MM)

show(key_cap, alphas=[0.3])

::: ::: :::

</details>

This example demonstrates the design of a Cherry MX key cap by using extrude with a taper and extrude until next. :::

::: {#examples_1.xhtml#maker-coin .section} []{#examples_1.xhtml#id6}

Maker Coin

{.align-center}

This example creates the maker coin as defined by Angus on the Maker's Muse YouTube channel. There are two key features:

  1. the use of DoubleTangentArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} to create a smooth transition from the central dish to the outside arc, and

  2. embossing the text into the top of the coin not just as a simple extrude but from a projection which results in text with even depth.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[🔨 Reference Implementation (Builder Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight # Coin Parameters diameter, thickness = 50 * MM, 10 * MM

with BuildPart() as maker_coin:
    # On XZ plane draw the profile of half the coin
    with BuildSketch(Plane.XZ) as profile:
        with BuildLine() as outline:
            l1 = Polyline((0, thickness * 0.6), (0, 0), ((diameter - thickness) / 2, 0))
            l2 = JernArc(
                start=l1 @ 1, tangent=l1 % 1, radius=thickness / 2, arc_size=300
            )  # extend the arc beyond the intersection but not closed
            l3 = DoubleTangentArc(l1 @ 0, tangent=(1, 0), other=l2)
        make_face()  # make it a 2D shape
    revolve()  # revolve 360°

    # Pattern the detents around the coin
    with BuildSketch() as detents:
        with PolarLocations(radius=(diameter + 5) / 2, count=8):
            Circle(thickness * 1.4 / 2)
    extrude(amount=thickness, mode=Mode.SUBTRACT)  # cut away the detents

    fillet(maker_coin.edges(Select.NEW), 2)  # fillet the cut edges

    # Add an embossed label
    with BuildSketch(Plane.XY.offset(thickness)) as label:  # above coin
        Text("OS", font_size=15)
    project()  # label on top of coin
    extrude(amount=-thickness / 5, mode=Mode.SUBTRACT)  # emboss label

show(maker_coin)

::: ::: :::

</details>

:::

::: {#examples_1.xhtml#multi-sketch-loft .section} []{#examples_1.xhtml#id7}

Multi-Sketch Loft

{.align-center}

This example demonstrates lofting a set of sketches, selecting the top and bottom by type, and shelling.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[🔨 Reference Implementation (Builder Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from math import pi, sin from build123d import * from ocp_vscode import show

with BuildPart() as art:
    slice_count = 10
    for i in range(slice_count + 1):
        with BuildSketch(Plane(origin=(0, 0, i * 3), z_dir=(0, 0, 1))) as slice:
            Circle(10 * sin(i * pi / slice_count) + 5)
    loft()
    top_bottom = art.faces().filter_by(GeomType.PLANE)
    offset(openings=top_bottom, amount=0.5)

want = 1306.3405290344635
got = art.part.volume
delta = abs(got - want)
tolerance = want * 1e-5
assert delta < tolerance, f"{delta=} is greater than {tolerance=}; {got=}, {want=}"

show(art, names=["art"])

::: ::: :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[✏️ Reference Implementation (Algebra Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from math import pi, sin from build123d import * from ocp_vscode import show

slice_count = 10

art = Sketch()
for i in range(slice_count + 1):
    plane = Plane(origin=(0, 0, i * 3), z_dir=(0, 0, 1))
    art += plane * Circle(10 * sin(i * pi / slice_count) + 5)

art = loft(art)
top_bottom = art.faces().filter_by(GeomType.PLANE)
art = offset(art, openings=top_bottom, amount=0.5)

show(art, names=["art"])

::: ::: :::

</details>

:::

::: {#examples_1.xhtml#peg-board-hook .section} []{#examples_1.xhtml#id8}

Peg Board Hook

{.align-center}

This script creates a a J-shaped pegboard hook. These hooks are commonly used for organizing tools in garages, workshops, or other spaces where tools and equipment need to be stored neatly and accessibly. The hook is created by defining a complex path and then sweeping it to define the hook. The sides of the hook are flattened to aid 3D printing.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[🔨 Reference Implementation (Builder Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show

pegd = 6.35 + 0.1  # mm ~0.25inch
c2c = 25.4  # mm 1.0inch
arcd = 7.2
both = 10
topx = 6
midx = 8
maind = 0.82 * pegd
midd = 1.0 * pegd
hookd = 23
hookx = 10
splitz = maind / 2 - 0.1
topangs = 70

with BuildPart() as mainp:
    with BuildLine(mode=Mode.PRIVATE) as sprof:
        l1 = Line((-both, 0), (c2c - arcd / 2 - 0.5, 0))
        l2 = JernArc(start=l1 @ 1, tangent=l1 % 1, radius=arcd / 2, arc_size=topangs)
        l3 = PolarLine(
            start=l2 @ 1,
            length=topx,
            direction=l2 % 1,
        )
        l4 = JernArc(start=l3 @ 1, tangent=l3 % 1, radius=arcd / 2, arc_size=-topangs)
        l5 = PolarLine(
            start=l4 @ 1,
            length=topx,
            direction=l4 % 1,
        )
        l6 = JernArc(
            start=l1 @ 0, tangent=(l1 % 0).reverse(), radius=hookd / 2, arc_size=170
        )
        l7 = PolarLine(
            start=l6 @ 1,
            length=hookx,
            direction=l6 % 1,
        )
    with BuildSketch(Plane.YZ):
        Circle(radius=maind / 2)
    sweep(path=sprof.wires()[0])
    with BuildLine(mode=Mode.PRIVATE) as stub:
        l7 = Line((0, 0), (0, midx + maind / 2))
    with BuildSketch(Plane.XZ):
        Circle(radius=midd / 2)
    sweep(path=stub.wires()[0])
    # splits help keep the object 3d printable by reducing overhang
    split(bisect_by=Plane(origin=(0, 0, -splitz)))
    split(bisect_by=Plane(origin=(0, 0, splitz)), keep=Keep.BOTTOM)

show(mainp)

::: ::: :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[✏️ Reference Implementation (Algebra Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show

pegd = 6.35 + 0.1  # mm ~0.25inch
c2c = 25.4  # mm 1.0inch
arcd = 7.2
both = 10
topx = 6
midx = 8
maind = 0.82 * pegd
midd = 1.0 * pegd
hookd = 23
hookx = 10
splitz = maind / 2 - 0.1
topangs = 70

l1 = Line((-both, 0), (c2c - arcd / 2 - 0.5, 0))
l2 = JernArc(start=l1 @ 1, tangent=l1 % 1, radius=arcd / 2, arc_size=topangs)
l3 = PolarLine(
    start=l2 @ 1,
    length=topx,
    direction=l2 % 1,
)
l4 = JernArc(start=l3 @ 1, tangent=l3 % 1, radius=arcd / 2, arc_size=-topangs)
l5 = PolarLine(
    start=l4 @ 1,
    length=topx,
    direction=l4 % 1,
)
l6 = JernArc(start=l1 @ 0, tangent=(l1 % 0).reverse(), radius=hookd / 2, arc_size=170)
l7 = PolarLine(
    start=l6 @ 1,
    length=hookx,
    direction=l6 % 1,
)
sprof = Curve() + (l1, l2, l3, l4, l5, l6, l7)
wire = Wire(sprof.edges())  #  TODO sprof.wires() fails
mainp = sweep(Plane.YZ * Circle(radius=maind / 2), path=wire)

stub = Line((0, 0), (0, midx + maind / 2))
mainp += sweep(Plane.XZ * Circle(radius=midd / 2), path=stub)


# splits help keep the object 3d printable by reducing overhang
mainp = split(mainp, Plane(origin=(0, 0, -splitz)))
mainp = split(mainp, Plane(origin=(0, 0, splitz)), keep=Keep.BOTTOM)

show(mainp)

::: ::: :::

</details>

:::

::: {#examples_1.xhtml#platonic-solids .section} []{#examples_1.xhtml#id9}

Platonic Solids

{.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.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[✏️ Reference Implementation (Algebra Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight 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(Wire.make_polygon(corner_vertices)))

        # Create the solid from the Faces
        platonic_solid = Solid(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)

::: ::: :::

</details>

:::

::: {#examples_1.xhtml#playing-cards .section} []{#examples_1.xhtml#id10}

Playing Cards

{.align-center}

This example creates a customs Sketch objects: Club, Spade, Heart, Diamond, and PlayingCard in addition to a two part playing card box which has suit cutouts in the lid. The four suits are created with Bézier curves that were imported as code from an SVG file and modified to the code found here.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[🔨 Reference Implementation (Builder Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from typing import Literal from build123d import * from ocp_vscode import show_object

# [Club]
class Club(BaseSketchObject):
    def __init__(
        self,
        height: float,
        rotation: float = 0,
        align: tuple[Align, Align] = (Align.CENTER, Align.CENTER),
        mode: Mode = Mode.ADD,
    ):
        with BuildSketch() as club:
            with BuildLine():
                l0 = Line((0, -188), (76, -188))
                b0 = Bezier(l0 @ 1, (61, -185), (33, -173), (17, -81))
                b1 = Bezier(b0 @ 1, (49, -128), (146, -145), (167, -67))
                b2 = Bezier(b1 @ 1, (187, 9), (94, 52), (32, 18))
                b3 = Bezier(b2 @ 1, (92, 57), (113, 188), (0, 188))
                mirror(about=Plane.YZ)
            make_face()
            scale(by=height / club.sketch.bounding_box().size.Y)
        super().__init__(obj=club.sketch, rotation=rotation, align=align, mode=mode)


# [Club]


class Spade(BaseSketchObject):
    def __init__(
        self,
        height: float,
        rotation: float = 0,
        align: tuple[Align, Align] = (Align.CENTER, Align.CENTER),
        mode: Mode = Mode.ADD,
    ):
        with BuildSketch() as spade:
            with BuildLine():
                b0 = Bezier((0, 198), (6, 190), (41, 127), (112, 61))
                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))
                mirror(about=Plane.YZ)
            make_face()
            scale(by=height / spade.sketch.bounding_box().size.Y)
        super().__init__(obj=spade.sketch, rotation=rotation, align=align, mode=mode)


class Heart(BaseSketchObject):
    def __init__(
        self,
        height: float,
        rotation: float = 0,
        align: tuple[Align, Align] = (Align.CENTER, Align.CENTER),
        mode: Mode = Mode.ADD,
    ):
        with BuildSketch() as heart:
            with BuildLine():
                b1 = Bezier((0, 146), (20, 169), (67, 198), (97, 198))
                b2 = Bezier(b1 @ 1, (125, 198), (151, 186), (168, 167))
                b3 = Bezier(b2 @ 1, (197, 133), (194, 88), (158, 31))
                b4 = Bezier(b3 @ 1, (126, -13), (94, -48), (62, -95))
                b5 = Bezier(b4 @ 1, (40, -128), (0, -198))
                mirror(about=Plane.YZ)
            make_face()
            scale(by=height / heart.sketch.bounding_box().size.Y)
        super().__init__(obj=heart.sketch, rotation=rotation, align=align, mode=mode)


class Diamond(BaseSketchObject):
    def __init__(
        self,
        height: float,
        rotation: float = 0,
        align: tuple[Align, Align] = (Align.CENTER, Align.CENTER),
        mode: Mode = Mode.ADD,
    ):
        with BuildSketch() as diamond:
            with BuildLine():
                Bezier((135, 0), (94, 69), (47, 134), (0, 198))
                mirror(about=Plane.XZ)
                mirror(about=Plane.YZ)
            make_face()
            scale(by=height / diamond.sketch.bounding_box().size.Y)
        super().__init__(obj=diamond.sketch, rotation=rotation, align=align, mode=mode)


card_width = 2.5 * IN
card_length = 3.5 * IN
deck = 0.5 * IN
wall = 4 * MM
gap = 0.5 * MM

with BuildPart() as box_builder:
    with BuildSketch() as plan:
        Rectangle(card_width + 2 * wall, card_length + 2 * wall)
        fillet(plan.vertices(), radius=card_width / 15)
    extrude(amount=wall / 2)
    with BuildSketch(box_builder.faces().sort_by(Axis.Z)[-1]) as walls:
        add(plan.sketch)
        offset(plan.sketch, amount=-wall, mode=Mode.SUBTRACT)
    extrude(amount=deck / 2)
    with BuildSketch(box_builder.faces().sort_by(Axis.Z)[-1]) as inset_walls:
        offset(plan.sketch, amount=-(wall + gap) / 2, mode=Mode.ADD)
        offset(plan.sketch, amount=-wall, mode=Mode.SUBTRACT)
    extrude(amount=deck / 2)

with BuildPart() as lid_builder:
    with BuildSketch() as outset_walls:
        add(plan.sketch)
        offset(plan.sketch, amount=-(wall - gap) / 2, mode=Mode.SUBTRACT)
    extrude(amount=deck / 2)
    with BuildSketch(lid_builder.faces().sort_by(Axis.Z)[-1]) as top:
        add(plan.sketch)
    extrude(amount=wall / 2)
    with BuildSketch(lid_builder.faces().sort_by(Axis.Z)[-1]):
        holes = GridLocations(
            3 * card_width / 5, 3 * card_length / 5, 2, 2
        ).local_locations
        for i, hole in enumerate(holes):
            with Locations(hole) as hole_loc:
                if i == 0:
                    Heart(card_length / 5)
                elif i == 1:
                    Diamond(card_length / 5)
                elif i == 2:
                    Spade(card_length / 5)
                elif i == 3:
                    Club(card_length / 5)
    extrude(amount=-wall, mode=Mode.SUBTRACT)

box = Compound(
    [box_builder.part, lid_builder.part.moved(Location((0, 0, (wall + deck) / 2)))]
)
visible, hidden = box.project_to_viewport((70, -50, 120))
max_dimension = max(*Compound(children=visible + hidden).bounding_box().size)
exporter = ExportSVG(scale=100 / max_dimension)
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(f"assets/card_box.svg")


class PlayingCard(BaseSketchObject):
    """PlayingCard

    A standard playing card modelled as a Face.

    Args:
        rank (Literal['A', '2' .. '10', 'J', 'Q', 'K']): card rank
        suit (Literal['Clubs', 'Spades', 'Hearts', 'Diamonds']): card suit
    """

    width = 2.5 * IN
    height = 3.5 * IN
    suits = {"Clubs": Club, "Spades": Spade, "Hearts": Heart, "Diamonds": Diamond}
    ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]

    def __init__(
        self,
        rank: Literal["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"],
        suit: Literal["Clubs", "Spades", "Hearts", "Diamonds"],
        rotation: float = 0,
        align: tuple[Align, Align] = (Align.CENTER, Align.CENTER),
        mode: Mode = Mode.ADD,
    ):
        with BuildSketch() as playing_card:
            Rectangle(
                PlayingCard.width, PlayingCard.height, align=(Align.MIN, Align.MIN)
            )
            fillet(playing_card.vertices(), radius=PlayingCard.width / 15)
            with Locations(
                (
                    PlayingCard.width / 7,
                    8 * PlayingCard.height / 9,
                )
            ):
                Text(
                    txt=rank,
                    font_size=PlayingCard.width / 7,
                    mode=Mode.SUBTRACT,
                )
            with Locations(
                (
                    PlayingCard.width / 7,
                    7 * PlayingCard.height / 9,
                )
            ):
                PlayingCard.suits[suit](
                    height=PlayingCard.width / 12, mode=Mode.SUBTRACT
                )
            with Locations(
                (
                    6 * PlayingCard.width / 7,
                    1 * PlayingCard.height / 9,
                )
            ):
                Text(
                    txt=rank,
                    font_size=PlayingCard.width / 7,
                    rotation=180,
                    mode=Mode.SUBTRACT,
                )
            with Locations(
                (
                    6 * PlayingCard.width / 7,
                    2 * PlayingCard.height / 9,
                )
            ):
                PlayingCard.suits[suit](
                    height=PlayingCard.width / 12, rotation=180, mode=Mode.SUBTRACT
                )
            rank_int = PlayingCard.ranks.index(rank) + 1
            rank_int = rank_int if rank_int < 10 else 1
            with Locations((PlayingCard.width / 2, PlayingCard.height / 2)):
                center_radius = 0 if rank_int == 1 else PlayingCard.width / 3.5
                suit_rotation = 0 if rank_int == 1 else -90
                suit_height = (
                    0.00159 * rank_int**2 - 0.0380 * rank_int + 0.37
                ) * PlayingCard.width
                with PolarLocations(
                    radius=center_radius,
                    count=rank_int,
                    start_angle=90 if rank_int > 1 else 0,
                ):
                    PlayingCard.suits[suit](
                        height=suit_height,
                        rotation=suit_rotation,
                        mode=Mode.SUBTRACT,
                    )
        super().__init__(
            obj=playing_card.sketch, rotation=rotation, align=align, mode=mode
        )


ace_spades = PlayingCard(rank="A", suit="Spades", align=Align.MIN)
ace_spades.color = Color("white")
king_hearts = PlayingCard(rank="K", suit="Hearts", align=Align.MIN)
king_hearts.color = Color("white")
queen_clubs = PlayingCard(rank="Q", suit="Clubs", align=Align.MIN)
queen_clubs.color = Color("white")
jack_diamonds = PlayingCard(rank="J", suit="Diamonds", align=Align.MIN)
jack_diamonds.color = Color("white")
ten_spades = PlayingCard(rank="10", suit="Spades", align=Align.MIN)
ten_spades.color = Color("white")

hand = Compound(
    children=[
        Rot(0, 0, -20) * Pos(0, 0, 0) * ace_spades,
        Rot(0, 0, -10) * Pos(0, 0, -1) * king_hearts,
        Rot(0, 0, 0) * Pos(0, 0, -2) * queen_clubs,
        Rot(0, 0, 10) * Pos(0, 0, -3) * jack_diamonds,
        Rot(0, 0, 20) * Pos(0, 0, -4) * ten_spades,
    ]
)

show_object(Pos(-20, 40) * hand)
show_object(box_builder.part, "box_builder")
show_object(
    Pos(0, 0, (wall + deck) / 2) * lid_builder.part,
    "lid_builder",
    options={"alpha": 0.7},
)

::: ::: :::

</details>

:::

::: {#examples_1.xhtml#stud-wall .section} []{#examples_1.xhtml#id11}

Stud Wall

{.align-center}

This example demonstrates creating custom <cite>{=html}Part</cite>{=html} objects and putting them into assemblies. The custom object is a <cite>{=html}Stud</cite>{=html} used in the building industry while the assembly is a <cite>{=html}StudWall</cite>{=html} created from copies of <cite>{=html}Stud</cite>{=html} objects for efficiency. Both the <cite>{=html}Stud</cite>{=html} and <cite>{=html}StudWall</cite>{=html} objects use <cite>{=html}RigidJoints</cite>{=html} to define snap points which are used to position all of objects.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[✏️ Reference Implementation (Algebra Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight 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)

::: ::: :::

</details>

:::

::: {#examples_1.xhtml#tea-cup .section} []{#examples_1.xhtml#id12}

Tea Cup

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[🔨 Reference Implementation (Builder Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show

wall_thickness = 3 * MM
fillet_radius = wall_thickness * 0.49

with BuildPart() as tea_cup:
    # Create the bowl of the cup as a revolved cross section
    with BuildSketch(Plane.XZ) as bowl_section:
        with BuildLine():
            # Start & end points with control tangents
            s = Spline(
                (30 * MM, 10 * MM),
                (69 * MM, 105 * MM),
                tangents=((1, 0.5), (0.7, 1)),
                tangent_scalars=(1.75, 1),
            )
            # Lines to finish creating ½ the bowl shape
            Polyline(s @ 0, s @ 0 + (10 * MM, -10 * MM), (0, 0), (0, (s @ 1).Y), s @ 1)
        make_face()  # Create a filled 2D shape
    revolve(axis=Axis.Z)
    # Hollow out the bowl with openings on the top and bottom
    offset(amount=-wall_thickness, openings=tea_cup.faces().filter_by(GeomType.PLANE))
    # Add a bottom to the bowl
    with Locations((0, 0, (s @ 0).Y)):
        Cylinder(radius=(s @ 0).X, height=wall_thickness)
    # Smooth out all the edges
    fillet(tea_cup.edges(), radius=fillet_radius)

    # Determine where the handle contacts the bowl
    handle_intersections = [
        tea_cup.part.find_intersection_points(
            Axis(origin=(0, 0, vertical_offset), direction=(1, 0, 0))
        )[-1][0]
        for vertical_offset in [35 * MM, 80 * MM]
    ]
    # Create a path for handle creation
    with BuildLine(Plane.XZ) as handle_path:
        Spline(
            handle_intersections[0] - (wall_thickness / 2, 0),
            handle_intersections[0] + (35 * MM, 30 * MM),
            handle_intersections[0] + (40 * MM, 60 * MM),
            handle_intersections[1] - (wall_thickness / 2, 0),
            tangents=((1, 1.25), (-0.2, -1)),
        )
    # Align the cross section to the beginning of the path
    with BuildSketch(handle_path.line ^ 0) as handle_cross_section:
        RectangleRounded(wall_thickness, 8 * MM, fillet_radius)
    sweep()  # Sweep handle cross section along path

assert abs(tea_cup.part.volume - 130326) < 1

show(tea_cup, names=["tea cup"])

::: ::: :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[✏️ Reference Implementation (Algebra Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show

wall_thickness = 3 * MM
fillet_radius = wall_thickness * 0.49

# Create the bowl of the cup as a revolved cross section

# Start & end points with control tangents
s = Spline(
    (30 * MM, 10 * MM),
    (69 * MM, 105 * MM),
    tangents=((1, 0.5), (0.7, 1)),
    tangent_scalars=(1.75, 1),
)
# Lines to finish creating ½ the bowl shape
s += Polyline(s @ 0, s @ 0 + (10 * MM, -10 * MM), (0, 0), (0, (s @ 1).Y), s @ 1)
bowl_section = Plane.XZ * make_face(s)  # Create a filled 2D shape
tea_cup = revolve(bowl_section, axis=Axis.Z)

# Hollow out the bowl with openings on the top and bottom
tea_cup = offset(
    tea_cup, -wall_thickness, openings=tea_cup.faces().filter_by(GeomType.PLANE)
)

# Add a bottom to the bowl
tea_cup += Pos(0, 0, (s @ 0).Y) * Cylinder(radius=(s @ 0).X, height=wall_thickness)

# Smooth out all the edges
tea_cup = fillet(tea_cup.edges(), radius=fillet_radius)

# Determine where the handle contacts the bowl
handle_intersections = [
    tea_cup.find_intersection_points(
        Axis(origin=(0, 0, vertical_offset), direction=(1, 0, 0))
    )[-1][0]
    for vertical_offset in [35 * MM, 80 * MM]
]

# Create a path for handle creation
path_spline = Spline(
    handle_intersections[0] - (wall_thickness / 2, 0, 0),
    handle_intersections[0] + (35 * MM, 0, 30 * MM),
    handle_intersections[0] + (40 * MM, 0, 60 * MM),
    handle_intersections[1] - (wall_thickness / 2, 0, 0),
    tangents=((1, 0, 1.25), (-0.2, 0, -1)),
)

# Align the cross section to the beginning of the path
location = path_spline ^ 0
handle_cross_section = location * RectangleRounded(wall_thickness, 8 * MM, fillet_radius)

# Sweep handle cross section along path
tea_cup += sweep(handle_cross_section, path=path_spline)

# assert abs(tea_cup.part.volume - 130326.77052487945) < 1e-3

show(tea_cup, names=["tea cup"])

::: ::: :::

</details>

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, 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 closely. :::

::: {#examples_1.xhtml#toy-truck .section} []{#examples_1.xhtml#id13}

Toy Truck

{.align-center} {.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[🔨 Reference Implementation (Builder Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show

# 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(body.part, cab.part)

::: ::: :::

</details>

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. :::

::: {#examples_1.xhtml#vase .section} []{#examples_1.xhtml#id14}

Vase

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[🔨 Reference Implementation (Builder Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show_object

with BuildPart() as vase:
    with BuildSketch() as profile:
        with BuildLine() as outline:
            l1 = Line((0, 0), (12, 0))
            l2 = RadiusArc(l1 @ 1, (15, 20), 50)
            l3 = Spline(l2 @ 1, (22, 40), (20, 50), tangents=(l2 % 1, (-0.75, 1)))
            l4 = RadiusArc(l3 @ 1, l3 @ 1 + Vector(0, 5), 5)
            l5 = Spline(
                l4 @ 1,
                l4 @ 1 + Vector(2.5, 2.5),
                l4 @ 1 + Vector(0, 5),
                tangents=(l4 % 1, (-1, 0)),
            )
            Polyline(
                l5 @ 1,
                l5 @ 1 + Vector(0, 1),
                (0, (l5 @ 1).Y + 1),
                l1 @ 0,
            )
        make_face()
    revolve(axis=Axis.Y)
    offset(openings=vase.faces().filter_by(Axis.Y)[-1], amount=-1)
    top_edges = (
        vase.edges().filter_by_position(Axis.Y, 60, 62).filter_by(GeomType.CIRCLE)
    )
    fillet(top_edges, radius=0.25)
    fillet(vase.edges().sort_by(Axis.Y)[0], radius=0.5)


show_object(Rot(90, 0, 0) * vase.part, name="vase")

::: ::: :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[✏️ Reference Implementation (Algebra Mode)]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show_object

l1 = Line((0, 0), (12, 0))
l2 = RadiusArc(l1 @ 1, (15, 20), 50)
l3 = Spline(l2 @ 1, (22, 40), (20, 50), tangents=(l2 % 1, (-0.75, 1)))
l4 = RadiusArc(l3 @ 1, l3 @ 1 + Vector(0, 5), 5)
l5 = Spline(
    l4 @ 1,
    l4 @ 1 + Vector(2.5, 2.5),
    l4 @ 1 + Vector(0, 5),
    tangents=(l4 % 1, (-1, 0)),
)
outline = l1 + l2 + l3 + l4 + l5
outline += Polyline(
    l5 @ 1,
    l5 @ 1 + Vector(0, 1),
    (0, (l5 @ 1).Y + 1),
    l1 @ 0,
)
profile = make_face(outline.edges())
vase = revolve(profile, Axis.Y)
vase = offset(vase, openings=vase.faces().sort_by(Axis.Y).last, amount=-1)

top_edges = vase.edges().filter_by(GeomType.CIRCLE).filter_by_position(Axis.Y, 60, 62)
vase = fillet(top_edges, radius=0.25)

vase = fillet(vase.edges().sort_by(Axis.Y).first, radius=0.5)

show_object(Rot(90, 0, 0) * vase, name="vase")

::: ::: :::

</details>

This example demonstrates the build123d techniques involving the creation of a vase. Specifically, it showcases the processes of revolving a sketch, shelling (creating a hollow object by removing material from its interior), and selecting edges by position range and type for the application of fillets (rounding off the edges).

  • Sketching: Drawing a 2D profile or outline that represents the side view of the vase.

  • Revolving: Rotating the sketch around an axis to create a 3D object. This step transforms the 2D profile into a 3D vase shape.

  • Offset/Shelling: Removing material from the interior of the solid vase to create a hollow space, making it resemble a real vase more closely.

  • Edge Filleting: Selecting specific edges of the vase for filleting, which involves rounding those edges. The edges are selected based on their position and type. ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#tttt.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#tttt.xhtml#too-tall-toby-ttt-tutorials .section}

Too Tall Toby (TTT) Tutorials

{.align-center}

To enhance users' proficiency with Build123D, this section offers a series of challenges. In these challenges, users are presented with a CAD drawing and tasked with designing the part. Their goal is to match the part's mass to a specified target.

These drawings were skillfully crafted and generously provided to Build123D by Too Tall Toby, a renowned figure in the realm of 3D CAD. Too Tall Toby is the host of the World Championship of 3D CAD Speedmodeling. For additional 3D CAD challenges and content, be sure to visit Toby's youtube channel{.reference .external}[ [https://www.Youtube.com/TooTallToby]]{.link-target}.

Feel free to click on the parts below to embark on these engaging challenges.

::: {.sd-container-fluid .sd-sphinx-override .sd-mb-4 .docutils} ::: {.sd-row .sd-row-cols-3 .sd-row-cols-xs-3 .sd-row-cols-sm-3 .sd-row-cols-md-3 .sd-row-cols-lg-3 .docutils} ::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Party Pack 01-01 Bearing Bracket ::: :::

[Party Pack 01-01 Bearing Bracket]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Party Pack 01-02 Post Cap ::: :::

[Party Pack 01-02 Post Cap]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Party Pack 01-03 C Clamp Base ::: :::

[Party Pack 01-03 C Clamp Base]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Party Pack 01-04 Angle Bracket ::: :::

[Party Pack 01-04 Angle Bracket]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Party Pack 01-05 Paste Sleeve ::: :::

[Party Pack 01-05 Paste Sleeve]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Party Pack 01-06 Bearing Jig ::: :::

[Party Pack 01-06 Bearing Jig]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Party Pack 01-07 Flanged Hub ::: :::

[Party Pack 01-07 Flanged Hub]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Party Pack 01-08 Tie Plate ::: :::

[Party Pack 01-08 Tie Plate]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Party Pack 01-09 Corner Tie ::: :::

[Party Pack 01-09 Corner Tie]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Party Pack 01-10 Light Cap ::: :::

[Party Pack 01-10 Light Cap]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} 23-02-02 SM Hanger ::: :::

[23-02-02 SM Hanger]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} 23-T-24 Curved Support ::: :::

[23-T-24 Curved Support]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} 24-SPO-06 Buffer Stand ::: :::

[24-SPO-06 Buffer Stand]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: ::: ::: :::

::: {#tttt.xhtml#party-pack-01-01-bearing-bracket .section} []{#tttt.xhtml#ttt-ppp0101}

Party Pack 01-01 Bearing Bracket

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Object Mass]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} 797.15 g :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Reference Implementation]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight """ Too Tall Toby Party Pack 01-01 Bearing Bracket """

from build123d import *
from ocp_vscode import *

densa = 7800 / 1e6  # carbon steel density g/mm^3
densb = 2700 / 1e6  # aluminum alloy
densc = 1020 / 1e6  # ABS

with BuildPart() as p:
    with BuildSketch() as s:
        Rectangle(115, 50)
        with Locations((5 / 2, 0)):
            SlotOverall(90, 12, mode=Mode.SUBTRACT)
    extrude(amount=15)

    with BuildSketch(Plane.XZ.offset(50 / 2)) as s3:
        with Locations((-115 / 2 + 26, 15)):
            SlotOverall(42 + 2 * 26 + 12, 2 * 26, rotation=90)
    zz = extrude(amount=-12)
    split(bisect_by=Plane.XY)
    edgs = p.part.edges().filter_by(Axis.Y).group_by(Axis.X)[-2]
    fillet(edgs, 9)

    with Locations(zz.faces().sort_by(Axis.Y)[0]):
        with Locations((42 / 2 + 6, 0)):
            CounterBoreHole(24 / 2, 34 / 2, 4)
    mirror(about=Plane.XZ)

    with BuildSketch() as s4:
        RectangleRounded(115, 50, 6)
    extrude(amount=80, mode=Mode.INTERSECT)
    # fillet does not work right, mode intersect is safer

    with BuildSketch(Plane.YZ) as s4:
        with BuildLine() as bl:
            l1 = Line((0, 0), (18 / 2, 0))
            l2 = PolarLine(l1 @ 1, 8, 60, length_mode=LengthMode.VERTICAL)
            l3 = Line(l2 @ 1, (0, 8))
            mirror(about=Plane.YZ)
        make_face()
    extrude(amount=115/2, both=True, mode=Mode.SUBTRACT)

show_object(p)


got_mass = p.part.volume*densa
want_mass = 797.15
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

::: ::: :::

</details>

:::

::: {#tttt.xhtml#party-pack-01-02-post-cap .section} []{#tttt.xhtml#ttt-ppp0102}

Party Pack 01-02 Post Cap

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Object Mass]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} 43.09 g :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Reference Implementation]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight """ Too Tall Toby Party Pack 01-02 Post Cap """

from build123d import *
from ocp_vscode import *

densa = 7800 / 1e6  # carbon steel density g/mm^3
densb = 2700 / 1e6  # aluminum alloy
densc = 1020 / 1e6  # ABS


# TTT Party Pack 01: PPP0102, mass(abs) = 43.09g
with BuildPart() as p:
    with BuildSketch(Plane.XZ) as sk1:
        Rectangle(49, 48 - 8, align=(Align.CENTER, Align.MIN))
        Rectangle(9, 48, align=(Align.CENTER, Align.MIN))
        with Locations((9 / 2, 40)):
            Ellipse(20, 8)
        split(bisect_by=Plane.YZ)
    revolve(axis=Axis.Z)

    with BuildSketch(Plane.YZ.offset(-15)) as xc1:
        with Locations((0, 40 / 2 - 17)):
            Ellipse(10 / 2, 4 / 2)
        with BuildLine(Plane.XZ) as l1:
            CenterArc((-15, 40 / 2), 17, 90, 180)
    sweep(path=l1)

    fillet(p.edges().filter_by(GeomType.CIRCLE, reverse=True).group_by(Axis.X)[0], 1)

    with BuildLine(mode=Mode.PRIVATE) as lc1:
        PolarLine(
            (42 / 2, 0), 37, 94, length_mode=LengthMode.VERTICAL
        )  # construction line

    pts = [
        (0, 0),
        (42 / 2, 0),
        ((lc1.line @ 1).X, (lc1.line @ 1).Y),
        (0, (lc1.line @ 1).Y),
    ]
    with BuildSketch(Plane.XZ) as sk2:
        Polygon(*pts, align=None)
        fillet(sk2.vertices().group_by(Axis.X)[1], 3)
    revolve(axis=Axis.Z, mode=Mode.SUBTRACT)

show(p)


got_mass = p.part.volume*densc
want_mass = 43.09
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

::: ::: :::

</details>

:::

::: {#tttt.xhtml#party-pack-01-03-c-clamp-base .section} []{#tttt.xhtml#ttt-ppp0103}

Party Pack 01-03 C Clamp Base

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Object Mass]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} 96.13 g :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Reference Implementation]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight """ Too Tall Toby Party Pack 01-03 C Clamp Base """

from build123d import *
from ocp_vscode import *

densa = 7800 / 1e6  # carbon steel density g/mm^3
densb = 2700 / 1e6  # aluminum alloy
densc = 1020 / 1e6  # ABS


with BuildPart() as ppp0103:
    with BuildSketch() as sk1:
        RectangleRounded(34 * 2, 95, 18)
        with Locations((0, -2)):
            RectangleRounded((34 - 16) * 2, 95 - 18 - 14, 7, mode=Mode.SUBTRACT)
        with Locations((-34 / 2, 0)):
            Rectangle(34, 95, 0, mode=Mode.SUBTRACT)
    extrude(amount=16)
    with BuildSketch(Plane.XZ.offset(-95 / 2)) as cyl1:
        with Locations((0, 16 / 2)):
            Circle(16 / 2)
    extrude(amount=18)
    with BuildSketch(Plane.XZ.offset(95 / 2 - 14)) as cyl2:
        with Locations((0, 16 / 2)):
            Circle(16 / 2)
    extrude(amount=23)
    with Locations(Plane.XZ.offset(95 / 2 + 9)):
        with Locations((0, 16 / 2)):
            CounterSinkHole(5.5 / 2, 11.2 / 2, None, 90)

show(ppp0103)

got_mass = ppp0103.part.volume*densb
want_mass = 96.13
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

::: ::: :::

</details>

:::

::: {#tttt.xhtml#party-pack-01-04-angle-bracket .section} []{#tttt.xhtml#ttt-ppp0104}

Party Pack 01-04 Angle Bracket

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Object Mass]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} 310.00 g :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Reference Implementation]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight """ Too Tall Toby Party Pack 01-04 Angle Bracket """

from build123d import *
from ocp_vscode import *

densa = 7800 / 1e6  # carbon steel density g/mm^3
densb = 2700 / 1e6  # aluminum alloy
densc = 1020 / 1e6  # ABS

d1, d2, d3 = 38, 26, 16
h1, h2, h3, h4 = 20, 8, 7, 23
w1, w2, w3 = 80, 10, 5
f1, f2, f3 = 4, 10, 5
sloth1, sloth2 = 18, 12
slotw1, slotw2 = 17, 14

with BuildPart() as p:
    with BuildSketch() as s:
        Circle(d1 / 2)
    extrude(amount=h1)
    with BuildSketch(Plane.XY.offset(h1)) as s2:
        Circle(d2 / 2)
    extrude(amount=h2)
    with BuildSketch(Plane.YZ) as s3:
        Rectangle(d1 + 15, h3, align=(Align.CENTER, Align.MIN))
    extrude(amount=w1 - d1 / 2)
    # fillet workaround \/
    ped = p.part.edges().group_by(Axis.Z)[2].filter_by(GeomType.CIRCLE)
    fillet(ped, f1)
    with BuildSketch(Plane.YZ) as s3a:
        Rectangle(d1 + 15, 15, align=(Align.CENTER, Align.MIN))
        Rectangle(d1, 15, mode=Mode.SUBTRACT, align=(Align.CENTER, Align.MIN))
    extrude(amount=w1 - d1 / 2, mode=Mode.SUBTRACT)
    # end fillet workaround /\
    with BuildSketch() as s4:
        Circle(d3 / 2)
    extrude(amount=h1 + h2, mode=Mode.SUBTRACT)
    with BuildSketch() as s5:
        with Locations((w1 - d1 / 2 - w2 / 2, 0)):
            Rectangle(w2, d1)
    extrude(amount=-h4)
    fillet(p.part.edges().group_by(Axis.X)[-1].sort_by(Axis.Z)[-1], f2)
    fillet(p.part.edges().group_by(Axis.X)[-4].sort_by(Axis.Z)[-2], f3)
    pln = Plane.YZ.offset(w1 - d1 / 2)
    with BuildSketch(pln) as s6:
        with Locations((0, -h4)):
            SlotOverall(slotw1 * 2, sloth1, 90)
    extrude(amount=-w3, mode=Mode.SUBTRACT)
    with BuildSketch(pln) as s6b:
        with Locations((0, -h4)):
            SlotOverall(slotw2 * 2, sloth2, 90)
    extrude(amount=-w2, mode=Mode.SUBTRACT)

show(p)


got_mass = p.part.volume*densa
want_mass = 310
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

::: ::: :::

</details>

:::

::: {#tttt.xhtml#party-pack-01-05-paste-sleeve .section} []{#tttt.xhtml#ttt-ppp0105}

Party Pack 01-05 Paste Sleeve

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Object Mass]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} 57.08 g :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Reference Implementation]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight """ Too Tall Toby Party Pack 01-05 Paste Sleeve """

from build123d import *
from ocp_vscode import *

densa = 7800 / 1e6  # carbon steel density g/mm^3
densb = 2700 / 1e6  # aluminum alloy
densc = 1020 / 1e6  # ABS

with BuildPart() as p:
    with BuildSketch() as s:
        SlotOverall(45, 38)
        offset(amount=3)
    with BuildSketch(Plane.XY.offset(133 - 30)) as s2:
        SlotOverall(60, 4)
        offset(amount=3)
    loft()

    with BuildSketch() as s3:
        SlotOverall(45, 38)
    with BuildSketch(Plane.XY.offset(133 - 30)) as s4:
        SlotOverall(60, 4)
    loft(mode=Mode.SUBTRACT)

    extrude(p.part.faces().sort_by(Axis.Z)[0], amount=30)

show(p)


got_mass = p.part.volume*densc
want_mass = 57.08
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

::: ::: :::

</details>

:::

::: {#tttt.xhtml#party-pack-01-06-bearing-jig .section} []{#tttt.xhtml#ttt-ppp0106}

Party Pack 01-06 Bearing Jig

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Object Mass]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} 328.02 g :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Reference Implementation]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight """ Too Tall Toby Party Pack 01-06 Bearing Jig """

from build123d import *
from ocp_vscode import *

densa = 7800 / 1e6  # carbon steel density g/mm^3
densb = 2700 / 1e6  # aluminum alloy
densc = 1020 / 1e6  # ABS

r1, r2, r3, r4, r5 = 30 / 2, 13 / 2, 12 / 2, 10, 6  # radii used
x1 = 44  # lengths used
y1, y2, y3, y4, y_tot = 36, 36 - 22 / 2, 22 / 2, 42, 69  # widths used

with BuildSketch(Location((0, -r1, y3))) as sk_body:
    with BuildLine() as l:
        c1 = Line((r1, 0), (r1, y_tot), mode=Mode.PRIVATE)  # construction line
        m1 = Line((0, y_tot), (x1 / 2, y_tot))
        m2 = JernArc(m1 @ 1, m1 % 1, r4, -90 - 45)
        m3 = IntersectingLine(m2 @ 1, m2 % 1, c1)
        m4 = Line(m3 @ 1, (r1, r1))
        m5 = JernArc(m4 @ 1, m4 % 1, r1, -90)
        mirror(about=Plane.YZ)
    make_face()
    fillet(sk_body.vertices().group_by(Axis.Y)[1], 12)
    with Locations((x1 / 2, y_tot - 10), (-x1 / 2, y_tot - 10)):
        Circle(r2, mode=Mode.SUBTRACT)
    # Keyway
    with Locations((0, r1)):
        Circle(r3, mode=Mode.SUBTRACT)
        Rectangle(4, 3 + 6, align=(Align.CENTER, Align.MIN), mode=Mode.SUBTRACT)

with BuildPart() as p:
    Box(200, 200, 22)  # Oversized plate
    # Cylinder underneath
    Cylinder(r1, y2, align=(Align.CENTER, Align.CENTER, Align.MAX))
    fillet(p.edges(Select.NEW), r5)  # Weld together
    extrude(sk_body.sketch, amount=-y1, mode=Mode.INTERSECT)  # Cut to shape
    # Remove slot
    with Locations((0, y_tot - r1 - y4, 0)):
        Box(
            y_tot,
            y_tot,
            10,
            align=(Align.CENTER, Align.MIN, Align.CENTER),
            mode=Mode.SUBTRACT,
        )

show(p)


got_mass = p.part.volume*densa
want_mass = 328.02
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

::: ::: :::

</details>

:::

::: {#tttt.xhtml#party-pack-01-07-flanged-hub .section} []{#tttt.xhtml#ttt-ppp0107}

Party Pack 01-07 Flanged Hub

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Object Mass]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} 372.99 g :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Reference Implementation]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight """ Too Tall Toby Party Pack 01-07 Flanged Hub """

from build123d import *
from ocp_vscode import *

densa = 7800 / 1e6  # carbon steel density g/mm^3
densb = 2700 / 1e6  # aluminum alloy
densc = 1020 / 1e6  # ABS

with BuildPart() as p:
    with BuildSketch() as s:
        Circle(130 / 2)
    extrude(amount=8)
    with BuildSketch(Plane.XY.offset(8)) as s2:
        Circle(84 / 2)
    extrude(amount=25 - 8)
    with BuildSketch(Plane.XY.offset(25)) as s3:
        Circle(35 / 2)
    extrude(amount=52 - 25)
    with BuildSketch() as s4:
        Circle(73 / 2)
    extrude(amount=18, mode=Mode.SUBTRACT)
    pln2 = p.part.faces().sort_by(Axis.Z)[5]
    with BuildSketch(Plane.XY.offset(52)) as s5:
        Circle(20 / 2)
    extrude(amount=-52, mode=Mode.SUBTRACT)
    fillet(
        p.part.edges()
        .filter_by(GeomType.CIRCLE)
        .sort_by(Axis.Z)[2:-2]
        .sort_by(SortBy.RADIUS)[1:],
        3,
    )
    pln = Plane(pln2)
    pln.origin = pln.origin + Vector(20 / 2, 0, 0)
    pln = pln.rotated((0, 45, 0))
    pln = pln.offset(-25 + 3 + 0.10)
    with BuildSketch(pln) as s6:
        Rectangle((73 - 35) / 2 * 1.414 + 5, 3)
    zz = extrude(amount=15, taper=-20 / 2, mode=Mode.PRIVATE)
    zz2 = split(zz, bisect_by=Plane.XY.offset(25), mode=Mode.PRIVATE)
    zz3 = split(zz2, bisect_by=Plane.YZ.offset(35 / 2 - 1), mode=Mode.PRIVATE)
    with PolarLocations(0, 3):
        add(zz3)
    with Locations(Plane.XY.offset(8)):
        with PolarLocations(107.95 / 2, 6):
            CounterBoreHole(6 / 2, 13 / 2, 4)

show(p)


got_mass = p.part.volume*densb
want_mass = 372.99
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

::: ::: :::

</details>

:::

::: {#tttt.xhtml#party-pack-01-08-tie-plate .section} []{#tttt.xhtml#ttt-ppp0108}

Party Pack 01-08 Tie Plate

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Object Mass]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} 3387.06 g :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Reference Implementation]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight """ Too Tall Toby Party Pack 01-08 Tie Plate """

from build123d import *
from ocp_vscode import *

densa = 7800 / 1e6  # carbon steel density g/mm^3
densb = 2700 / 1e6  # aluminum alloy
densc = 1020 / 1e6  # ABS

with BuildPart() as p:
    with BuildSketch() as s1:
        Rectangle(188 / 2 - 33, 162, align=(Align.MIN, Align.CENTER))
        with Locations((188 / 2 - 33, 0)):
            SlotOverall(190, 33 * 2, rotation=90)
        mirror(about=Plane.YZ)
        with GridLocations(188 - 2 * 33, 190 - 2 * 33, 2, 2):
            Circle(29 / 2, mode=Mode.SUBTRACT)
        Circle(84 / 2, mode=Mode.SUBTRACT)
    extrude(amount=16)

    with BuildPart() as p2:
        with BuildSketch(Plane.XZ) as s2:
            with BuildLine() as l1:
                l1 = Polyline(
                    (222 / 2 + 14 - 40 - 40, 0),
                    (222 / 2 + 14 - 40, -35 + 16),
                    (222 / 2 + 14, -35 + 16),
                    (222 / 2 + 14, -35 + 16 + 30),
                    (222 / 2 + 14 - 40 - 40, -35 + 16 + 30),
                    close=True,
                )
            make_face()
            with Locations((222 / 2, -35 + 16 + 14)):
                Circle(11 / 2, mode=Mode.SUBTRACT)
        extrude(amount=20 / 2, both=True)
        with BuildSketch() as s3:
            with Locations(l1 @ 0):
                Rectangle(40 + 40, 8, align=(Align.MIN, Align.CENTER))
                with Locations((40, 0)):
                    Rectangle(40, 20, align=(Align.MIN, Align.CENTER))
        extrude(amount=30, both=True, mode=Mode.INTERSECT)
        mirror(about=Plane.YZ)

show(p)


got_mass = p.part.volume*densa
want_mass = 3387.06
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

::: ::: :::

</details>

:::

::: {#tttt.xhtml#party-pack-01-09-corner-tie .section} []{#tttt.xhtml#ttt-ppp0109}

Party Pack 01-09 Corner Tie

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Object Mass]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} 307.23 g :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Reference Implementation]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight """ Too Tall Toby Party Pack 01-09 Corner Tie """

from math import sqrt
from build123d import *
from ocp_vscode import *

densa = 7800 / 1e6  # carbon steel density g/mm^3
densb = 2700 / 1e6  # aluminum alloy
densc = 1020 / 1e6  # ABS

with BuildPart() as ppp109:
    with BuildSketch() as one:
        Rectangle(69, 75, align=(Align.MAX, Align.CENTER))
        fillet(one.vertices().group_by(Axis.X)[0], 17)
    extrude(amount=13)
    centers = [
        arc.arc_center
        for arc in ppp109.edges().filter_by(GeomType.CIRCLE).group_by(Axis.Z)[-1]
    ]
    with Locations(*centers):
        CounterBoreHole(radius=8 / 2, counter_bore_radius=15 / 2, counter_bore_depth=4)

    with BuildSketch(Plane.YZ) as two:
        with Locations((0, 45)):
            Circle(15)
        with BuildLine() as bl:
            c = Line((75 / 2, 0), (75 / 2, 60), mode=Mode.PRIVATE)
            u = two.edge().find_tangent(75 / 2 + 90)[0]  # where is the slope 75/2?
            l1 = IntersectingLine(
                two.edge().position_at(u), -two.edge().tangent_at(u), other=c
            )
            Line(l1 @ 0, (0, 45))
            Polyline((0, 0), c @ 0, l1 @ 1)
            mirror(about=Plane.YZ)
        make_face()
        with Locations((0, 45)):
            Circle(12 / 2, mode=Mode.SUBTRACT)
    extrude(amount=-13)

    with BuildSketch(Plane((0, 0, 0), x_dir=(1, 0, 0), z_dir=(1, 0, 1))) as three:
        Rectangle(45 * 2 / sqrt(2) - 37.5, 75, align=(Align.MIN, Align.CENTER))
        with Locations(three.edges().sort_by(Axis.X)[-1].center()):
            Circle(37.5)
            Circle(33 / 2, mode=Mode.SUBTRACT)
        split(bisect_by=Plane.YZ)
    extrude(amount=6)
    f = ppp109.faces().filter_by(Axis((0, 0, 0), (-1, 0, 1)))[0]
    extrude(f, until=Until.NEXT)
    fillet(ppp109.edges().filter_by(Axis.Y).sort_by(Axis.Z)[2], 16)
    # extrude(f, amount=10)
    # fillet(ppp109.edges(Select.NEW), 16)


show(ppp109)

got_mass = ppp109.part.volume * densb
want_mass = 307.23
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f"{got_mass=}, {want_mass=}, {delta=}, {tolerance=}"

::: ::: :::

</details>

:::

::: {#tttt.xhtml#party-pack-01-10-light-cap .section} []{#tttt.xhtml#ttt-ppp0110}

Party Pack 01-10 Light Cap

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Object Mass]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} 211.30 g :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Reference Implementation]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight """ Too Tall Toby Party Pack 01-10 Light Cap """

from math import sqrt, asin, pi
from build123d import *
from ocp_vscode import *

densa = 7800 / 1e6  # carbon steel density g/mm^3
densb = 2700 / 1e6  # aluminum alloy
densc = 1020 / 1e6  # ABS

# The smaller cross-section is defined as having R40, height 46,
# and base width 84, so clearly it's not entirely a half-circle or
# similar; the base's extreme points need to connect via tangents
# to the R40 arc centered 6mm above the baseline.
#
# Compute the angle of the tangent line (working with the
# left/negativeX side, given symmetry) by observing the tangent
# point (T), the circle's center (O), and the baseline's edge (P)
# form a right triangle, so:

OT=40
OP=sqrt((-84/2)**2+(-6)**2)
TP=sqrt(OP**2-40**2)
OPT_degrees = asin(OT/OP) * 180/pi
# Correct for the fact that OP isn't horizontal.
OP_to_X_axis_degrees = asin(6/OP) * 180/pi
left_tangent_degrees = OPT_degrees + OP_to_X_axis_degrees
left_tangent_length = TP
with BuildPart() as outer:
    with BuildSketch(Plane.XZ) as sk:
        with BuildLine():
            l1 = PolarLine(start=(-84/2, 0), length=left_tangent_length, angle=left_tangent_degrees)
            l2 = TangentArc(l1@1, (0, 46), tangent=l1%1)
            l3 = offset(amount=-8, side=Side.RIGHT, closed=False, mode=Mode.ADD)
            l4 = Line(l1@0, l3@1)
            l5 = Line(l3@0, l2@1)
            l6 = Line(l3@0, (0, 46-16))
            l7 = IntersectingLine(start=l6@1, direction=(-1,0), other=l3)
        make_face()
    revolve(axis=Axis.Z)
sk = sk.sketch & Plane.XZ*Rectangle(1000, 1000, align=[Align.CENTER, Align.MIN])
positive_Z = Box(100, 100, 100, align=[Align.CENTER, Align.MIN, Align.MIN])
p = outer.part & positive_Z
cross_section = sk + mirror(sk, about=Plane.YZ)
p += extrude(cross_section, amount=50)
p += mirror(p, about=Plane.XZ.offset(50))
p += fillet(p.edges().filter_by(GeomType.LINE).filter_by(Axis.Y).group_by(Axis.Z)[-1], radius=8)
ppp0110 = p

got_mass = ppp0110.volume*densc
want_mass = 211.30
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.1f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

show(ppp0110)

::: ::: :::

</details>

:::

::: {#tttt.xhtml#sm-hanger .section} []{#tttt.xhtml#ttt-23-02-02-sm-hanger}

23-02-02 SM Hanger

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Object Mass]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} 1028g +/- 10g :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Reference Implementation]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight """ Creation of a complex sheet metal part

name: ttt_sm_hanger.py
by:   Gumyr
date: July 17, 2023

desc:
    This example implements the sheet metal part described in Too Tall Toby's
    sm_hanger CAD challenge.

    Notably, a BuildLine/Curve object is filleted by providing all the vertices
    and allowing the fillet operation filter out the end vertices. The 
    make_brake_formed operation is used both in Algebra and Builder mode to
    create a sheet metal part from just an outline and some dimensions.
    license:

    Copyright 2023 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 *

sheet_thickness = 4 * MM

# Create the main body from a side profile
with BuildPart() as side:
    d = Vector(1, 0, 0).rotate(Axis.Y, 60)
    with BuildLine(Plane.XZ) as side_line:
        l1 = Line((0, 65), (170 / 2, 65))
        l2 = PolarLine(l1 @ 1, length=65, direction=d, length_mode=LengthMode.VERTICAL)
        l3 = Line(l2 @ 1, (170 / 2, 0))
        fillet(side_line.vertices(), 7)
    make_brake_formed(
        thickness=sheet_thickness,
        station_widths=[40, 40, 40, 112.52 / 2, 112.52 / 2, 112.52 / 2],
        side=Side.RIGHT,
    )
    fe = side.edges().filter_by(Axis.Z).group_by(Axis.Z)[0].sort_by(Axis.Y)[-1]
    fillet(fe, radius=7)

# Create the "wings" at the top
with BuildPart() as wing:
    with BuildLine(Plane.YZ) as wing_line:
        l1 = Line((0, 65), (80 / 2 + 1.526 * sheet_thickness, 65))
        PolarLine(l1 @ 1, 20.371288916, direction=Vector(0, 1, 0).rotate(Axis.X, -75))
        fillet(wing_line.vertices(), 7)
    make_brake_formed(
        thickness=sheet_thickness,
        station_widths=110 / 2,
        side=Side.RIGHT,
    )
    bottom_edge = wing.edges().group_by(Axis.X)[-1].sort_by(Axis.Z)[0]
    fillet(bottom_edge, radius=7)

# Create the tab at the top in Algebra mode
tab_line = Plane.XZ * Polyline(
    (20, 65 - sheet_thickness), (56 / 2, 65 - sheet_thickness), (56 / 2, 88)
)
tab_line = fillet(tab_line.vertices(), 7)
tab = make_brake_formed(sheet_thickness, 8, tab_line, Side.RIGHT)
tab = fillet(tab.edges().filter_by(Axis.X).group_by(Axis.Z)[-1].sort_by(Axis.Y)[-1], 5)
tab -= Pos((0, 0, 80)) * Rot(0, 90, 0) * Hole(5, 100)

# Combine the parts together
with BuildPart() as sm_hanger:
    add([side.part, wing.part])
    mirror(about=Plane.XZ)
    with BuildSketch(Plane.XY.offset(65)) as h1:
        with Locations((20, 0)):
            Rectangle(30, 30, align=(Align.MIN, Align.CENTER))
            fillet(h1.vertices().group_by(Axis.X)[-1], 7)
        SlotCenterPoint((154, 0), (154 / 2, 0), 20)
    extrude(amount=-40, mode=Mode.SUBTRACT)
    with BuildSketch() as h2:
        SlotCenterPoint((206, 0), (206 / 2, 0), 20)
    extrude(amount=40, mode=Mode.SUBTRACT)
    add(tab)
    mirror(about=Plane.YZ)
    mirror(about=Plane.XZ)

got_mass = sm_hanger.part.volume*7800*1e-6
want_mass = 1028
tolerance = 10
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.1f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

assert abs(got_mass - 1028) < 10, f'{got_mass=}, want=1028, tolerance=10'

show(sm_hanger)

::: ::: :::

</details>

:::

::: {#tttt.xhtml#t-24-curved-support .section} []{#tttt.xhtml#ttt-23-t-24}

23-T-24 Curved Support

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Object Mass]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} 1294 g :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Reference Implementation]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight """ Too Tall Toby challenge 23-T-24 CURVED SUPPORT """

from math import sin, cos, tan, radians
from build123d import *
from ocp_vscode import *
import sympy

# This problem uses the sympy symbolic math solver

# Define the symbols for the unknowns
# - the center of the radius 30 arc (x30, y30)
# - the center of the radius 66 arc (x66, y66)
# - end of the 8° line (l8x, l8y)
# - the point with the radius 30 and 66 arc meet i30_66
# - the start of the horizontal line lh
y30, x66, xl8, yl8 = sympy.symbols("y30 x66 xl8 yl8")
x30 = 77 - 55 / 2
y66 = 66 + 32

# There are 4 unknowns so we need 4 equations
equations = [
    (x66 - x30) ** 2 + (y66 - y30) ** 2 - (66 + 30) ** 2,  # distance between centers
    xl8 - (x30 + 30 * sin(radians(8))),  # 8 degree slope
    yl8 - (y30 + 30 * cos(radians(8))),  # 8 degree slope
    (yl8 - 50) / (55 / 2 - xl8) - tan(radians(8)),  # 8 degree slope
]
# There are two solutions but we want the 2nd one
solution = {k: float(v) for k,v in sympy.solve(equations, dict=True)[1].items()}

# Create the critical points
c30 = Vector(x30, solution[y30])
c66 = Vector(solution[x66], y66)
l8 = Vector(solution[xl8], solution[yl8])
i30_66 = Line(c30, c66) @ (30 / (30 + 66))
lh = Vector(c66.X, 32)

with BuildLine() as profile:
    l1 = Line((55 / 2, 50), l8)
    l2 = RadiusArc(l1 @ 1, i30_66, 30)
    l3 = RadiusArc(l2 @ 1, lh, -66)
    l4 = Polyline(l3 @ 1, (125, 32), (125, 0), (0, 0), (0, (l1 @ 0).Y), l1 @ 0)

with BuildPart() as curved_support:
    with BuildSketch() as base_plan:
        c_8_degrees = Circle(55 / 2)
        with Locations((0, 125)):
            Circle(30 / 2)
        base_hull = make_hull(mode=Mode.PRIVATE)
    extrude(amount=32)
    extrude(c_8_degrees, amount=60)
    extrude(base_hull, amount=11)
    with BuildSketch(Plane.YZ) as bridge:
        make_face(profile.edges())
    extrude(amount=11 / 2, both=True)
    Hole(35 / 2)
    with Locations((0, 125)):
        Hole(20 / 2)

got_mass = curved_support.part.volume * 7800e-6
want_mass = 1294
delta = abs(got_mass - want_mass)
tolerance = 3
print(f"Mass: {got_mass:0.1f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

show(curved_support)

::: ::: :::

</details>

:::

::: {#tttt.xhtml#spo-06-buffer-stand .section} []{#tttt.xhtml#ttt-24-spo-06}

24-SPO-06 Buffer Stand

{.align-center}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Object Mass]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} 3.92 lbs :::

</details>
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Reference Implementation]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show

with BuildPart() as p:
    with BuildSketch() as xy:
        with BuildLine():
            l1 = ThreePointArc((5 / 2, -1.25), (5.5 / 2, 0), (5 / 2, 1.25))
            Polyline(l1 @ 0, (0, -1.25), (0, 1.25), l1 @ 1)
        make_face()
    extrude(amount=4)

    with BuildSketch(Plane.YZ) as yz:
        Trapezoid(2.5, 4, 90 - 6, align=(Align.CENTER, Align.MIN))
        full_round(yz.edges().sort_by(SortBy.LENGTH)[0])
        circle_edge = yz.edges().filter_by(GeomType.CIRCLE)[0]
        arc_center = circle_edge.arc_center
        arc_radius = circle_edge.radius
    extrude(amount=10, mode=Mode.INTERSECT)

    # To avoid OCCT problems, don't attempt to extend the top arc, remove instead
    with BuildPart(mode=Mode.SUBTRACT) as internals:
        y = p.edges().filter_by(Axis.X).sort_by(Axis.Z)[-1].center().Z

        with BuildSketch(Plane.YZ.offset(4.25 / 2)) as yz:
            Trapezoid(2.5, y, 90 - 6, align=(Align.CENTER, Align.MIN))
            with Locations(arc_center):
                Circle(arc_radius, mode=Mode.SUBTRACT)
        extrude(amount=-(4.25 - 3.5) / 2)

        with BuildSketch(Plane.YZ.offset(3.5 / 2)) as yz:
            Trapezoid(2.5, 4, 90 - 6, align=(Align.CENTER, Align.MIN))
        extrude(amount=-3.5 / 2)

        with BuildSketch(Plane.XZ.offset(-2)) as xz:
            with Locations((0, 4)):
                RectangleRounded(4.25, 7.5, 0.5)
        extrude(amount=4, mode=Mode.INTERSECT)

    with Locations(p.faces(Select.LAST).filter_by(GeomType.PLANE).sort_by(Axis.Z)[-1]):
        CounterBoreHole(0.625 / 2, 1.25 / 2, 0.5)

    with BuildSketch(Plane.YZ) as rib:
        with Locations((0, 0.25)):
            Trapezoid(0.5, 1, 90 - 8, align=(Align.CENTER, Align.MIN))
        full_round(rib.edges().sort_by(SortBy.LENGTH)[0])
    extrude(amount=4.25 / 2)

    mirror(about=Plane.YZ)

part = scale(p.part, IN)


got_mass = part.volume * 7800e-6 / LB
want_mass = 3.923
tolerance = 0.02
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.1f} lbs")
assert delta < tolerance, f"{got_mass=}, {want_mass=}, {delta=}, {tolerance=}"

show(p)

::: ::: :::

</details>

::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#tutorial_surface_modeling.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#tutorial_surface_modeling.xhtml#surface-modeling .section}

Surface Modeling

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.

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 Shell{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}---the watertight surface of a volume. If this shell is properly oriented and encloses a finite region of space, the model becomes a solid.

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.

This section provides: - A concise overview of surfacebuilding tools in build123d - Handson tutorials, from fundamentals to advanced techniques like Gordon surfaces

Available surface methods

Methods on Face{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} for creating nonplanar surfaces:

::: {.admonition .note} Note

Surface modeling is an advanced technique. Robust results usually come from reusing the same Edge{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} objects across adjacent faces and ensuring the final Shell{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} is watertight or manifold (no gaps). :::

::: {.toctree-wrapper .compound}

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#tutorial_surface_heart_token.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#tutorial_surface_heart_token.xhtml#tutorial-heart-token-basics .section}

Tutorial: Heart Token (Basics)

This handson tutorial introduces the fundamentals of surface modeling by building a heartshaped token from a small set of nonplanar faces. We'll create nonplanar surfaces, mirror them, add side faces, and assemble a closed shell into a solid.

As described in the <cite>{=html}topology_</cite>{=html} 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:

<script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js"></script>

<model-viewer poster="_images/heart_token.png" src="_static/heart_token.glb" alt="Game Token" auto-rotate camera-controls style="width: 100%; height: 50vh;">{=html}</model-viewer>{=html}

Useful Face{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} creation methods include make_surface(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, make_bezier_surface(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, and make_surface_from_array_of_points(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}. See the [Surface Modeling]{.doc}{.reference .internal} overview for the full list.

In this case, we'll use the make_surface{.docutils .literal .notranslate} 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:

::: {.highlight-build123d .notranslate} ::: highlight 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])

::: :::

Note that l4{.docutils .literal .notranslate} is not in the same plane as the other lines; it defines the center line of the heart and archs up off Plane.XY{.docutils .literal .notranslate}.

token perimeter{.align-center}

In preparation for creating the surface, we'll define a point on the surface:

::: {.highlight-build123d .notranslate} ::: highlight # Create a point elevated off the center surface_pnt = l2.arc_center + (0, 0, 1.5) ::: :::

We will then use this point to create a non-planar Face{.docutils .literal .notranslate}:

::: {.highlight-build123d .notranslate} ::: highlight # Create the surface from the edges and point top_right_surface = Pos(Z=0.5) * -Face.make_surface(heart_half, [surface_pnt]) ::: :::

token perimeter{.align-center}

Note that the surface was raised up by 0.5 using an Algebra expression with Pos. Also, note that the -{.docutils .literal .notranslate} in front of Face{.docutils .literal .notranslate} 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:

::: {.highlight-build123d .notranslate} ::: highlight # 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) ::: :::

The sides of the heart are going to be created by extruding the outside of the perimeter as follows:

::: {.highlight-build123d .notranslate} ::: highlight # 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) ::: :::

token sides{.align-center}

With the top, bottom, and sides, the complete boundary of the object is defined. We can now put them together, first into a Shell{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and then into a Solid{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}:

::: {.highlight-build123d .notranslate} ::: highlight # 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, ] ) ) ::: :::

token heart solid{.align-center}

::: {.admonition .note} 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:

::: {.highlight-build123d .notranslate} ::: highlight # 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)

::: :::

Note that an additional planar line is used to close l1{.docutils .literal .notranslate} and l3{.docutils .literal .notranslate} so a Face{.docutils .literal .notranslate} can be created. The offset(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} function defines the outside of the frame as a constant distance from the heart itself.

::: {#tutorial_surface_heart_token.xhtml#summary .section}

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 Face{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} class, such as make_surface(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, 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 Shell{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and eventually a Solid{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}. Finally, we added a frame around the heart using the offset(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} function to maintain a constant distance from the heart. :::

::: {#tutorial_surface_heart_token.xhtml#next-steps .section}

Next steps

Continue to [Tutorial: Spitfire Wing with Gordon Surface]{.doc}{.reference .internal} for an advanced example using make_gordon_surface(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} to create a Supermarine Spitfire wing. ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#tutorial_spitfire_wing_gordon.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#tutorial_spitfire_wing_gordon.xhtml#tutorial-spitfire-wing-with-gordon-surface .section}

Tutorial: Spitfire Wing with Gordon Surface

In this advanced tutorial we construct a Supermarine Spitfire wing as a make_gordon_surface(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}---a powerful technique for surfacing from intersecting profiles and guides. A Gordon surface blends a grid of curves into a smooth, coherent surface as long as the profiles and guides intersect consistently.

::: {.admonition .note} Note

Gordon surfaces work best when each profile intersects each guide exactly once, producing a wellformed curve network. :::

::: {#tutorial_spitfire_wing_gordon.xhtml#overview .section}

Overview

We will:

  1. Define overall wing dimensions and elliptic leading/trailing edge guide curves

  2. Sample the guides to size the root and tip airfoils (different NACA profiles)

  3. Build the Gordon surface from the airfoil profiles and wingedge guides

  4. Close the root with a planar face and build the final Solid{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}

<script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js"></script>

<model-viewer poster="_images/spitfire_wing.png" src="_static/spitfire_wing.glb" alt="A tea cup modelled in build123d" auto-rotate camera-controls style="width: 100%; height: 50vh;">{=html}</model-viewer>{=html} :::

::: {#tutorial_spitfire_wing_gordon.xhtml#step-1-dimensions-and-guide-curves .section}

Step 1 --- Dimensions and guide curves

We model a single wing (halfspan), with an elliptic leading and trailing edge. These two edges act as the guides for the Gordon surface.

::: {.highlight-build123d .notranslate} ::: highlight 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
)

::: ::: :::

::: {#tutorial_spitfire_wing_gordon.xhtml#step-2-root-and-tip-airfoil-sizing .section}

Step 2 --- Root and tip airfoil sizing

We intersect the guides with planes normal to the span to size the airfoil sections. The resulting chord lengths define uniform scales for each airfoil curve.

::: {.highlight-build123d .notranslate} ::: highlight # 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) ::: ::: :::

::: {#tutorial_spitfire_wing_gordon.xhtml#step-3-build-airfoil-profiles-root-and-tip .section}

Step 3 --- Build airfoil profiles (root and tip)

We place two different NACA airfoils on Plane.YZ{.xref .py .py-data .docutils .literal .notranslate}---with the airfoil origins shifted so the leading edge fraction is aligned---then scale to the chord lengths from Step 2.

::: {.highlight-build123d .notranslate} ::: highlight # 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]) ) ::: ::: :::

::: {#tutorial_spitfire_wing_gordon.xhtml#step-4-gordon-surface-construction .section}

Step 4 --- Gordon surface construction

A Gordon surface needs profiles and guides. Here the airfoil edges are the profiles; the elliptic edges are the guides. We also add the wing tip section so the profile grid closes at the tip.

::: {.highlight-build123d .notranslate} ::: highlight # 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))) ::: :::

Elliptic leading/trailing guides{.align-center} :::

::: {#tutorial_spitfire_wing_gordon.xhtml#step-5-cap-the-root-and-create-the-solid .section}

Step 5 --- Cap the root and create the solid

We extract the closed root edge loop, make a planar cap, and form a solid shell.

::: {.highlight-build123d .notranslate} ::: highlight # Create the wing Solid wing = Solid(Shell([wing_surface, wing_root])) wing.color = 0x99A3B9 # Azure Blue

show(wing)

::: :::

Final wing solid{.align-center}

::: {#tutorial_spitfire_wing_gordon.xhtml#tips-for-robust-gordon-surfaces .section}

Tips for robust Gordon surfaces

  • Ensure each profile intersects each guide once and only once

  • Keep the curve network coherent (no duplicated or missing intersections)

  • When possible, reuse the same Edge{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} objects across adjacent faces ::: :::

::: {#tutorial_spitfire_wing_gordon.xhtml#complete-listing .section}

Complete listing

For convenience, here is the full script in one block:

::: {.highlight-build123d .notranslate} ::: highlight 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)

::: ::: ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#tech_drawing_tutorial.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#tech_drawing_tutorial.xhtml#technical-drawing-tutorial .section} []{#tech_drawing_tutorial.xhtml#tech-drawing-tutorial}

Technical Drawing Tutorial

This example demonstrates how to generate a standard technical drawing of a 3D part using <cite>{=html}build123d</cite>{=html}. It creates orthographic and isometric views of a Nema 23 stepper motor and exports the result as an SVG file suitable for printing or inspection.

::: {#tech_drawing_tutorial.xhtml#overview .section}

Overview

A technical drawing represents a 3D object in 2D using a series of standardized views. These include:

  • Plan (Top View) -- as seen from directly above (Z-axis down)

  • Front Elevation -- looking at the object head-on (Y-axis forward)

  • Side Elevation (Right Side) -- viewed from the right (X-axis)

  • Isometric Projection -- a 3D perspective view to help visualize depth

Each view is aligned to a position on the page and optionally scaled or annotated. :::

::: {#tech_drawing_tutorial.xhtml#how-it-works .section}

How It Works

The script uses the <cite>{=html}project_to_viewport</cite>{=html} method to project the 3D part geometry into 2D. A helper function, <cite>{=html}project_to_2d</cite>{=html}, sets up the viewport (camera origin and up direction) and places the result onto a virtual drawing sheet.

The steps involved are:

  1. Load or construct a 3D part (in this case, a stepper motor).

  2. Define a <cite>{=html}TechnicalDrawing</cite>{=html} border and title block using A4 page size.

  3. Generate each of the standard views and apply transformations to place them.

  4. Add dimensions using <cite>{=html}ExtensionLine</cite>{=html} and labels using <cite>{=html}Text</cite>{=html}.

  5. Export the drawing using <cite>{=html}ExportSVG</cite>{=html}, separating visible and hidden edges by layer and style. :::

::: {#tech_drawing_tutorial.xhtml#result .section}

Result

Stepper motor technical drawing{.align-center style="width: 80%;"} :::

::: {#tech_drawing_tutorial.xhtml#try-it-yourself .section}

Try It Yourself

You can modify the script to:

  • Replace the part with your own <cite>{=html}Part</cite>{=html} model

  • Adjust camera angles and scale

  • Add other views (bottom, rear)

  • Enhance with more labels and dimensions :::

::: {#tech_drawing_tutorial.xhtml#code .section}

Code

::: {.highlight-build123d .notranslate} ::: highlight 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()
shaft_top_corner = vis.edges().sort_by(Axis.Y)[-1].vertices().sort_by(Axis.X)[-1]
body_bottom_corner = (side_bbox.max.X, side_bbox.min.Y)
d4 = ExtensionLine(
    border=(shaft_top_corner, body_bottom_corner),
    offset=-(side_bbox.max.X - shaft_top_corner.X) - 1 * CM,  # offset to outside view.
    measurement_direction=(0, 1, 0),
    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)

::: ::: :::

::: {#tech_drawing_tutorial.xhtml#dependencies .section}

Dependencies

This example depends on the following packages:

  • <cite>{=html}build123d</cite>{=html}

  • <cite>{=html}bd_warehouse</cite>{=html} (for the <cite>{=html}StepperMotor</cite>{=html} part)

  • <cite>{=html}ocp_vscode</cite>{=html} (for local preview) ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#objects.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#objects.xhtml#objects .section}

Objects

Objects are Python classes that take parameters as inputs and create 1D, 2D or 3D Shapes. For example, a Torus{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} is defined by a major and minor radii. In Builder mode, objects are positioned with Locations{.docutils .literal .notranslate} while in Algebra mode, objects are positioned with the *{.docutils .literal .notranslate} operator and shown in these examples:

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as disk: with BuildSketch(): Circle(a) with Locations((b, 0.0)): Rectangle(c, c, mode=Mode.SUBTRACT) with Locations((0, b)): Circle(d, mode=Mode.SUBTRACT) extrude(amount=c) ::: :::

::: {.highlight-build123d .notranslate} ::: highlight sketch = Circle(a) - Pos(b, 0.0) * Rectangle(c, c) - Pos(0.0, b) * Circle(d) disk = extrude(sketch, c) ::: :::

The following sections describe the 1D, 2D and 3D objects:

::: {#objects.xhtml#align .section}

Align

2D/Sketch and 3D/Part objects can be aligned relative to themselves, either centered, or justified right or left of each Axis. The following diagram shows how this alignment works in 2D:

{.align-center}

For example:

::: {.highlight-build123d .notranslate} ::: highlight with BuildSketch(): Circle(1, align=(Align.MIN, Align.MIN)) ::: :::

creates a circle who's minimal X and Y values are on the X and Y axis and is located in the top right corner. The Align{.docutils .literal .notranslate} enum has values: MIN{.docutils .literal .notranslate}, CENTER{.docutils .literal .notranslate} and MAX{.docutils .literal .notranslate}.

In 3D the align{.docutils .literal .notranslate} parameter also contains a Z align value but otherwise works in the same way.

Note that the align{.docutils .literal .notranslate} will also accept a single Align{.docutils .literal .notranslate} value which will be used on all axes - as shown here:

::: {.highlight-build123d .notranslate} ::: highlight with BuildSketch(): Circle(1, align=Align.MIN) ::: ::: :::

::: {#objects.xhtml#mode .section}

Mode

With the Builder API the mode{.docutils .literal .notranslate} parameter controls how objects are combined with lines, sketches, or parts under construction. The Mode{.docutils .literal .notranslate} enum has values:

  • ADD{.docutils .literal .notranslate}: fuse this object to the object under construction

  • SUBTRACT{.docutils .literal .notranslate}: cut this object from the object under construction

  • INTERSECT{.docutils .literal .notranslate}: intersect this object with the object under construction

  • REPLACE{.docutils .literal .notranslate}: replace the object under construction with this object

  • PRIVATE{.docutils .literal .notranslate}: don't interact with the object under construction at all

The Algebra API doesn't use the mode{.docutils .literal .notranslate} parameter - users combine objects with operators. :::

::: {#objects.xhtml#d-objects .section}

1D Objects

The following objects all can be used in BuildLine contexts. Note that 1D objects are not affected by Locations{.docutils .literal .notranslate} in Builder mode.

::: {.sd-container-fluid .sd-sphinx-override .sd-mb-4 .docutils} ::: {.sd-row .sd-row-cols-3 .sd-row-cols-xs-3 .sd-row-cols-sm-3 .sd-row-cols-md-3 .sd-row-cols-lg-3 .docutils} ::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Airfoil{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Airfoil described by 4 digit NACA profile ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Bezier{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Curve defined by control points and weights ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} BlendCurve{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Curve blending curvature of two curves ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} CenterArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Arc defined by center, radius, & angles ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} DoubleTangentArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Arc defined by point/tangent pair & other curve ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} EllipticalCenterArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Elliptical arc defined by center, radii & angles ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} ParabolicCenterArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Parabolic arc defined by vertex, focal length & angles ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} HyperbolicCenterArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Hyperbolic arc defined by center, radii & angles ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} FilletPolyline{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Polyline with filleted corners defined by pts and radius ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Helix{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Helix defined pitch, radius and height ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} IntersectingLine{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Intersecting line defined by start, direction & other line ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} JernArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Arc define by start point, tangent, radius and angle ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Line{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Line defined by end points ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} PolarLine{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Line defined by start, angle and length ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Polyline{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Multiple line segments defined by points ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} RadiusArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Arc defined by two points and a radius ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} SagittaArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Arc defined by two points and a sagitta ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Spline{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Curve define by points ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} TangentArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Arc defined by two points and a tangent ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} ThreePointArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Arc defined by three points ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} ArcArcTangentLine{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Line tangent defined by two arcs ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} ArcArcTangentArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Arc tangent defined by two arcs ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} PointArcTangentLine{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Line tangent defined by a point and arc ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} PointArcTangentArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Arc tangent defined by a point, direction, and arc ::: ::: ::: ::: :::

::: {#objects.xhtml#module-objects_curve .section} []{#objects.xhtml#reference}

Reference

[class]{.pre}[ ]{.w}[[BaseLineObject]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[curve:]{.pre} [~build123d.topology.one_d.Wire]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

BaseLineObject specialized for Wire.

Parameters[:]{.colon}
  • curve (Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- wire to create

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[Airfoil]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[airfoil_code:]{.pre} [str]{.pre}]{.n}, [[n_points:]{.pre} [int]{.pre} [=]{.pre} [50]{.pre}]{.n}, [[finite_te:]{.pre} [bool]{.pre} [=]{.pre} [False]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Create an airfoil described by a 4-digit (or fractional) NACA airfoil (e.g. '2412' or '2213.323').

The NACA four-digit wing sections define the airfoil_code by: - First digit describing maximum camber as percentage of the chord. - Second digit describing the distance of maximum camber from the airfoil leading edge in tenths of the chord. - Last two digits describing maximum thickness of the airfoil as percent of the chord.

Parameters[:]{.colon}
  • airfoil_code -- str The NACA 4-digit (or fractional) airfoil code (e.g. '2213.323').

  • n_points -- int Number of points per upper/lower surface.

  • finite_te -- bool If True, enforces a finite trailing edge (default False).

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

[property]{.pre}[ ]{.w}[[camber_line]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Edge]{.pre}

Camber line of the airfoil as an Edge.

[[camber_pos]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

Chordwise position of max camber (0--1)

[[code]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[str]{.pre}

NACA code string (e.g. "2412")

[[finite_te]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[bool]{.pre}

If True, trailing edge is finite

[[max_camber]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

Maximum camber as fraction of chord

[static]{.pre}[ ]{.w}[[parse_naca4]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[value]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[float]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Parse NACA 4-digit (or fractional) airfoil code into parameters.

[[thickness]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

Maximum thickness as fraction of chord

<!-- -->
[class]{.pre}[ ]{.w}[[Bezier]{.pre}]{.sig-name .descname}[(]{.sig-paren}[*cntl_pnts:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [weights:]{.pre} [list[float]]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Bezier Curve

Create a non-rational bezier curve defined by a sequence of points and include optional weights to create a rational bezier curve. The number of weights must match the number of control points.

Parameters[:]{.colon}
  • cntl_pnts (sequence[VectorLike]) -- points defining the curve

  • weights (list[float], optional) -- control point weights. Defaults to None

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[BlendCurve]{.pre}]{.sig-name .descname}[(]{.sig-paren}[curve0:]{.pre} [~build123d.topology.one_d.Edge,]{.pre} [curve1:]{.pre} [~build123d.topology.one_d.Edge,]{.pre} [continuity:]{.pre} [~build123d.build_enums.ContinuityLevel]{.pre} [=]{.pre} [ContinuityLevel.C2,]{.pre} [end_points:]{.pre} [tuple[~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]]]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [tangent_scalars:]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: BlendCurve

Create a smooth Bézier-based transition curve between two existing edges.

The blend is constructed as a cubic (C1) or quintic (C2) Bézier curve whose control points are determined from the position, first derivative, and (for C2) second derivative of the input curves at the chosen endpoints. Optional scalar multipliers can be applied to the endpoint tangents to control the "tension" of the blend.

Parameters[:]{.colon}
  • curve0 (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- First curve to blend from.

  • curve1 (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- Second curve to blend to.

  • continuity (ContinuityLevel, optional) -- Desired geometric continuity at the join: - ContinuityLevel.C0: position match only (straight line) - ContinuityLevel.C1: match position and tangent direction (cubic Bézier) - ContinuityLevel.C2: match position, tangent, and curvature (quintic Bézier) Defaults to ContinuityLevel.C2.

  • end_points (tuple[VectorLike, VectorLike] | None, optional) -- Pair of points specifying the connection points on <cite>{=html}curve0</cite>{=html} and <cite>{=html}curve1</cite>{=html}. Each must coincide (within TOLERANCE) with the start or end of the respective curve. If None, the closest pair of endpoints is chosen. Defaults to None.

  • tangent_scalars (tuple[float, float] | None, optional) -- Scalar multipliers applied to the first derivatives at the start of <cite>{=html}curve0</cite>{=html} and the end of <cite>{=html}curve1</cite>{=html} before computing control points. Useful for adjusting the pull/tension of the blend without altering the base curves. Defaults to (1.0, 1.0).

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Boolean operation mode when used in a BuildLine context. Defaults to Mode.ADD.

Raises[:]{.colon}
  • ValueError -- <cite>{=html}tangent_scalars</cite>{=html} must be a pair of float values.

  • ValueError -- If specified <cite>{=html}end_points</cite>{=html} are not coincident with the start or end of their respective curves.

Example

::: {.doctest .highlight-default .notranslate} ::: highlight >>> blend = BlendCurve(curve_a, curve_b, ContinuityLevel.C1, tangent_scalars=(1.2, 0.8)) >>> show(blend) ::: :::

<!-- -->
[class]{.pre}[ ]{.w}[[CenterArc]{.pre}]{.sig-name .descname}[(]{.sig-paren}[center:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [radius:]{.pre} [float,]{.pre} [start_angle:]{.pre} [float,]{.pre} [arc_size:]{.pre} [float,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Center Arc

Create a circular arc defined by a center point and radius.

Parameters[:]{.colon}
  • center (VectorLike) -- center point of arc

  • radius (float) -- arc radius

  • start_angle (float) -- arc starting angle from x-axis

  • arc_size (float) -- angular size of arc

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[DoubleTangentArc]{.pre}]{.sig-name .descname}[(]{.sig-paren}[pnt:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [tangent:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [other:]{.pre} [~build123d.topology.composite.Curve]{.pre} [|]{.pre} [~build123d.topology.one_d.Edge]{.pre} [|]{.pre} [~build123d.topology.one_d.Wire,]{.pre} [keep:]{.pre} [~build123d.build_enums.Keep]{.pre} [=]{.pre} [<Keep.TOP>,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Double Tangent Arc

Create a circular arc defined by a point/tangent pair and another line find a tangent to.

The arc specified with TOP or BOTTOM depends on the geometry and isn't predictable.

Contains a solver.

Parameters[:]{.colon}
  • pnt (VectorLike) -- start point

  • tangent (VectorLike) -- tangent at start point

  • other (Curve{.hxr-hoverxref .hxr-tooltip .reference .internal} | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- line object to tangent

  • keep (Keep{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- specify which arc if more than one, TOP or BOTTOM. Defaults to Keep.TOP

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

Raises[:]{.colon}

RunTimeError -- no double tangent arcs found

<!-- -->
[class]{.pre}[ ]{.w}[[EllipticalCenterArc]{.pre}]{.sig-name .descname}[(]{.sig-paren}[center:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [x_radius:]{.pre} [float,]{.pre} [y_radius:]{.pre} [float,]{.pre} [start_angle:]{.pre} [float]{.pre} [=]{.pre} [0.0,]{.pre} [end_angle:]{.pre} [float]{.pre} [=]{.pre} [90.0,]{.pre} [rotation:]{.pre} [float]{.pre} [=]{.pre} [0.0,]{.pre} [angular_direction:]{.pre} [~build123d.build_enums.AngularDirection]{.pre} [=]{.pre} [<AngularDirection.COUNTER_CLOCKWISE>,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Elliptical Center Arc

Create an elliptical arc defined by a center point, x- and y- radii.

Parameters[:]{.colon}
  • center (VectorLike) -- ellipse center

  • x_radius (float) -- x radius of the ellipse (along the x-axis of plane)

  • y_radius (float) -- y radius of the ellipse (along the y-axis of plane)

  • start_angle (float, optional) -- arc start angle from x-axis. Defaults to 0.0

  • end_angle (float, optional) -- arc end angle from x-axis. Defaults to 90.0

  • rotation (float, optional) -- angle to rotate arc. Defaults to 0.0

  • angular_direction (AngularDirection, optional) -- arc direction. Defaults to AngularDirection.COUNTER_CLOCKWISE

  • plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- base plane. Defaults to Plane.XY

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[ParabolicCenterArc]{.pre}]{.sig-name .descname}[(]{.sig-paren}[vertex:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [focal_length:]{.pre} [float,]{.pre} [start_angle:]{.pre} [float]{.pre} [=]{.pre} [0.0,]{.pre} [end_angle:]{.pre} [float]{.pre} [=]{.pre} [90.0,]{.pre} [rotation:]{.pre} [float]{.pre} [=]{.pre} [0.0,]{.pre} [angular_direction:]{.pre} [~build123d.build_enums.AngularDirection]{.pre} [=]{.pre} [<AngularDirection.COUNTER_CLOCKWISE>,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Parabolic Center Arc

Create a parabolic arc defined by a vertex point and focal length (distance from focus to vertex).

Parameters[:]{.colon}
  • vertex (VectorLike) -- parabola vertex

  • focal_length (float) -- focal length the parabola (distance from the vertex to focus along the x-axis of plane)

  • start_angle (float, optional) -- arc start angle. Defaults to 0.0

  • end_angle (float, optional) -- arc end angle. Defaults to 90.0

  • rotation (float, optional) -- angle to rotate arc. Defaults to 0.0

  • angular_direction (AngularDirection, optional) -- arc direction. Defaults to AngularDirection.COUNTER_CLOCKWISE

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[HyperbolicCenterArc]{.pre}]{.sig-name .descname}[(]{.sig-paren}[center:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [x_radius:]{.pre} [float,]{.pre} [y_radius:]{.pre} [float,]{.pre} [start_angle:]{.pre} [float]{.pre} [=]{.pre} [0.0,]{.pre} [end_angle:]{.pre} [float]{.pre} [=]{.pre} [90.0,]{.pre} [rotation:]{.pre} [float]{.pre} [=]{.pre} [0.0,]{.pre} [angular_direction:]{.pre} [~build123d.build_enums.AngularDirection]{.pre} [=]{.pre} [<AngularDirection.COUNTER_CLOCKWISE>,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Hyperbolic Center Arc

Create a hyperbolic arc defined by a center point and focal length (distance from focus to vertex).

Parameters[:]{.colon}
  • center (VectorLike) -- hyperbola center

  • x_radius (float) -- x radius of the ellipse (along the x-axis of plane)

  • y_radius (float) -- y radius of the ellipse (along the y-axis of plane)

  • start_angle (float, optional) -- arc start angle from x-axis. Defaults to 0.0

  • end_angle (float, optional) -- arc end angle from x-axis. Defaults to 90.0

  • rotation (float, optional) -- angle to rotate arc. Defaults to 0.0

  • angular_direction (AngularDirection, optional) -- arc direction. Defaults to AngularDirection.COUNTER_CLOCKWISE

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[FilletPolyline]{.pre}]{.sig-name .descname}[(]{.sig-paren}[*pts:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]]{.pre} [|]{.pre} [~collections.abc.Iterable[~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]],]{.pre} [radius:]{.pre} [float]{.pre} [|]{.pre} [~collections.abc.Iterable[float],]{.pre} [close:]{.pre} [bool]{.pre} [=]{.pre} [False,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Fillet Polyline Create a sequence of straight lines defined by successive points that are filleted to a given radius.

Parameters[:]{.colon}
  • pts (VectorLike | Iterable[VectorLike]) -- sequence of two or more points

  • radius (float | Iterable[float]) -- radius to fillet at each vertex or a single value for all vertices. A radius of 0 will create a sharp corner (vertex without fillet).

  • close (bool, optional) -- close end points with extra Edge and corner fillets. Defaults to False

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

Raises[:]{.colon}
  • ValueError -- Two or more points not provided

  • ValueError -- radius must be non-negative

<!-- -->
[class]{.pre}[ ]{.w}[[Helix]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[pitch:]{.pre} [float]{.pre}]{.n}, [[height:]{.pre} [float]{.pre}]{.n}, [[radius:]{.pre} [float]{.pre}]{.n}, [[center:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, float{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, [[float]{.pre}]{.n}, float{.pre} [|]{.pre} [~collections.abc.Sequence[float]]{.pre} [=]{.pre} [(0]{.pre}]{.n}, [[0]{.pre}]{.n}, [[0)]{.pre}]{.n}, [[direction:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, float{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, [[float]{.pre}]{.n}, float{.pre} [|]{.pre} [~collections.abc.Sequence[float]]{.pre} [=]{.pre} [(0]{.pre}]{.n}, [[0]{.pre}]{.n}, [[1)]{.pre}]{.n}, [[cone_angle:]{.pre} [float]{.pre} [=]{.pre} [0]{.pre}]{.n}, [[lefthand:]{.pre} [bool]{.pre} [=]{.pre} [False]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Line Object: Helix

Create a helix defined by pitch, height, and radius. The helix may have a taper defined by cone_angle.

If cone_angle is not 0, radius is the initial helix radius at center. cone_angle > 0 increases the final radius. cone_angle < 0 decreases the final radius.

Parameters[:]{.colon}
  • pitch (float) -- distance between loops

  • height (float) -- helix height

  • radius (float) -- helix radius

  • center (VectorLike, optional) -- center point. Defaults to (0, 0, 0)

  • direction (VectorLike, optional) -- direction of central axis. Defaults to (0, 0, 1)

  • cone_angle (float, optional) -- conical angle from direction. Defaults to 0

  • lefthand (bool, optional) -- left handed helix. Defaults to False

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[IntersectingLine]{.pre}]{.sig-name .descname}[(]{.sig-paren}[start:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [direction:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [other:]{.pre} [~build123d.topology.composite.Curve]{.pre} [|]{.pre} [~build123d.topology.one_d.Edge]{.pre} [|]{.pre} [~build123d.topology.one_d.Wire,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Intersecting Line Object: Line

Create a straight line defined by a point/direction pair and another line to intersect.

Parameters[:]{.colon}
  • start (VectorLike) -- start point

  • direction (VectorLike) -- direction to make line

  • other (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- line object to intersect

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[JernArc]{.pre}]{.sig-name .descname}[(]{.sig-paren}[start:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [tangent:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [radius:]{.pre} [float,]{.pre} [arc_size:]{.pre} [float,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Jern Arc

Create a circular arc defined by a start point/tangent pair, radius and arc size.

Parameters[:]{.colon}
  • start (VectorLike) -- start point

  • tangent (VectorLike) -- tangent at start point

  • radius (float) -- arc radius

  • arc_size (float) -- angular size of arc (negative to change direction)

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

Variables[:]{.colon}
  • start (Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- start point

  • end_of_arc (Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- end point of arc

  • center_point (Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- center of arc

<!-- -->
[class]{.pre}[ ]{.w}[[Line]{.pre}]{.sig-name .descname}[(]{.sig-paren}[*pts:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]]{.pre} [|]{.pre} [~collections.abc.Iterable[~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]],]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Line

Create a straight line defined by two points.

Parameters[:]{.colon}
  • pts (VectorLike | Iterable[VectorLike]) -- sequence of two points

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

Raises[:]{.colon}

ValueError -- Two point not provided

<!-- -->
[class]{.pre}[ ]{.w}[[PolarLine]{.pre}]{.sig-name .descname}[(]{.sig-paren}[start:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [length:]{.pre} [float,]{.pre} [angle:]{.pre} [float]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [direction:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [length_mode:]{.pre} [~build123d.build_enums.LengthMode]{.pre} [=]{.pre} [<LengthMode.DIAGONAL>,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Polar Line

Create a straight line defined by a start point, length, and angle. The length can specify the DIAGONAL, HORIZONTAL, or VERTICAL component of the triangle defined by the angle.

Parameters[:]{.colon}
  • start (VectorLike) -- start point

  • length (float) -- line length

  • angle (float, optional) -- angle from the local x-axis

  • direction (VectorLike, optional) -- vector direction to determine angle

  • length_mode (LengthMode, optional) -- how length defines the line. Defaults to LengthMode.DIAGONAL

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

Raises[:]{.colon}

ValueError -- Either angle or direction must be provided

<!-- -->
[class]{.pre}[ ]{.w}[[Polyline]{.pre}]{.sig-name .descname}[(]{.sig-paren}[*pts:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]]{.pre} [|]{.pre} [~collections.abc.Iterable[~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]],]{.pre} [close:]{.pre} [bool]{.pre} [=]{.pre} [False,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Polyline

Create a sequence of straight lines defined by successive points.

Parameters[:]{.colon}
  • pts (VectorLike | Iterable[VectorLike]) -- sequence of two or more points

  • close (bool, optional) -- close by generating an extra Edge. Defaults to False

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

Raises[:]{.colon}

ValueError -- Two or more points not provided

<!-- -->
[class]{.pre}[ ]{.w}[[RadiusArc]{.pre}]{.sig-name .descname}[(]{.sig-paren}[start_point:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [end_point:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [radius:]{.pre} [float,]{.pre} [short_sagitta:]{.pre} [bool]{.pre} [=]{.pre} [True,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Radius Arc

Create a circular arc defined by two points and a radius.

Parameters[:]{.colon}
  • start_point (VectorLike) -- start point

  • end_point (VectorLike) -- end point

  • radius (float) -- arc radius

  • short_sagitta (bool) -- If True selects the short sagitta (height of arc from chord), else the long sagitta crossing the center. Defaults to True

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

Raises[:]{.colon}

ValueError -- Insufficient radius to connect end points

<!-- -->
[class]{.pre}[ ]{.w}[[SagittaArc]{.pre}]{.sig-name .descname}[(]{.sig-paren}[start_point:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [end_point:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [sagitta:]{.pre} [float,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Sagitta Arc

Create a circular arc defined by two points and the sagitta (height of the arc from chord).

Parameters[:]{.colon}
  • start_point (VectorLike) -- start point

  • end_point (VectorLike) -- end point

  • sagitta (float) -- arc height from chord between points

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[Spline]{.pre}]{.sig-name .descname}[(]{.sig-paren}[*pts:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]]{.pre} [|]{.pre} [~collections.abc.Iterable[~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]],]{.pre} [tangents:]{.pre} [~collections.abc.Iterable[~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]]]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [tangent_scalars:]{.pre} [~collections.abc.Iterable[float]]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [periodic:]{.pre} [bool]{.pre} [=]{.pre} [False,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Spline

Create a spline defined by a sequence of points, optionally constrained by tangents. Tangents and tangent scalars must have length of 2 for only the end points or a length of the number of points.

Parameters[:]{.colon}
  • pts (VectorLike | Iterable[VectorLike]) -- sequence of two or more points

  • tangents (Iterable[VectorLike], optional) -- tangent directions. Defaults to None

  • tangent_scalars (Iterable[float], optional) -- tangent scales. Defaults to None

  • periodic (bool, optional) -- make the spline periodic (closed). Defaults to False

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[TangentArc]{.pre}]{.sig-name .descname}[(]{.sig-paren}[*pts:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]]{.pre} [|]{.pre} [~collections.abc.Iterable[~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]],]{.pre} [tangent:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [tangent_from_first:]{.pre} [bool]{.pre} [=]{.pre} [True,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Tangent Arc

Create a circular arc defined by two points and a tangent.

Parameters[:]{.colon}
  • pts (VectorLike | Iterable[VectorLike]) -- sequence of two points

  • tangent (VectorLike) -- tangent to constrain arc

  • tangent_from_first (bool, optional) -- apply tangent to first point. Applying tangent to end point will flip the orientation of the arc. Defaults to True

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

Raises[:]{.colon}

ValueError -- Two points are required

<!-- -->
[class]{.pre}[ ]{.w}[[ThreePointArc]{.pre}]{.sig-name .descname}[(]{.sig-paren}[*pts:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]]{.pre} [|]{.pre} [~collections.abc.Iterable[~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]],]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Three Point Arc

Create a circular arc defined by three points.

Parameters[:]{.colon}
  • pts (VectorLike | Iterable[VectorLike]) -- sequence of three points

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

Raises[:]{.colon}

ValueError -- Three points must be provided

<!-- -->
[class]{.pre}[ ]{.w}[[ArcArcTangentLine]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[start_arc:]{.pre} [~build123d.topology.composite.Curve]{.pre} [|]{.pre} [~build123d.topology.one_d.Edge]{.pre} [|]{.pre} [~build123d.topology.one_d.Wire]{.pre}]{.n}, [[end_arc:]{.pre} [~build123d.topology.composite.Curve]{.pre} [|]{.pre} [~build123d.topology.one_d.Edge]{.pre} [|]{.pre} [~build123d.topology.one_d.Wire]{.pre}]{.n}, [[side:]{.pre} [~build123d.build_enums.Side]{.pre} [=]{.pre} [<Side.LEFT>]{.pre}]{.n}, [[keep:]{.pre} [~build123d.build_enums.Keep]{.pre} [=]{.pre} [<Keep.INSIDE>]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Line Object: Arc Arc Tangent Line

Create a straight line tangent to two arcs.

Parameters[:]{.colon}
  • start_arc (Curve{.hxr-hoverxref .hxr-tooltip .reference .internal} | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- starting arc, must be GeomType.CIRCLE

  • end_arc (Curve{.hxr-hoverxref .hxr-tooltip .reference .internal} | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- ending arc, must be GeomType.CIRCLE

  • side (Side) -- side of arcs to place tangent arc center, LEFT or RIGHT. Defaults to Side.LEFT

  • keep (Keep{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- which tangent arc to keep, INSIDE or OUTSIDE. Defaults to Keep.INSIDE

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[ArcArcTangentArc]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[start_arc:]{.pre} [~build123d.topology.composite.Curve]{.pre} [|]{.pre} [~build123d.topology.one_d.Edge]{.pre} [|]{.pre} [~build123d.topology.one_d.Wire]{.pre}]{.n}, [[end_arc:]{.pre} [~build123d.topology.composite.Curve]{.pre} [|]{.pre} [~build123d.topology.one_d.Edge]{.pre} [|]{.pre} [~build123d.topology.one_d.Wire]{.pre}]{.n}, [[radius:]{.pre} [float]{.pre}]{.n}, [[side:]{.pre} [~build123d.build_enums.Side]{.pre} [=]{.pre} [<Side.LEFT>]{.pre}]{.n}, [[keep:]{.pre} [~build123d.build_enums.Keep]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Keep]{.pre}]{.n}, ~build123d.build_enums.Keep{.pre} [=]{.pre} [(<Keep.INSIDE>]{.pre}]{.n}, [[<Keep.INSIDE>)]{.pre}]{.n}, [[short_sagitta:]{.pre} [bool]{.pre} [=]{.pre} [True]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Line Object: Arc Arc Tangent Arc

Create an arc tangent to two arcs and a radius.

keep specifies tangent arc position with a Keep pair: (placement, type)

  • placement: start_arc is tangent INSIDE or OUTSIDE the tangent arc. BOTH is a special case for overlapping arcs with type INSIDE

  • type: tangent arc is INSIDE or OUTSIDE start_arc and end_arc

Parameters[:]{.colon}
  • start_arc (Curve{.hxr-hoverxref .hxr-tooltip .reference .internal} | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- starting arc, must be GeomType.CIRCLE

  • end_arc (Curve{.hxr-hoverxref .hxr-tooltip .reference .internal} | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- ending arc, must be GeomType.CIRCLE

  • radius (float) -- radius of tangent arc

  • side (Side) -- side of arcs to place tangent arc center, LEFT or RIGHT. Defaults to Side.LEFT

  • keep (Keep{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Keep{.hxr-hoverxref .hxr-tooltip .reference .internal}, Keep{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- which tangent arc to keep, INSIDE or OUTSIDE. Defaults to (Keep.INSIDE, Keep.INSIDE)

  • short_sagitta (bool) -- If True selects the short sagitta (height of arc from chord), else the long sagitta crossing the center. Defaults to True

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

ArcArcTangentArc keep table{.align-center}

[class]{.pre}[ ]{.w}[[PointArcTangentLine]{.pre}]{.sig-name .descname}[(]{.sig-paren}[point:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [arc:]{.pre} [~build123d.topology.composite.Curve]{.pre} [|]{.pre} [~build123d.topology.one_d.Edge]{.pre} [|]{.pre} [~build123d.topology.one_d.Wire,]{.pre} [side:]{.pre} [~build123d.build_enums.Side]{.pre} [=]{.pre} [<Side.LEFT>,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Point Arc Tangent Line

Create a straight, tangent line from a point to a circular arc.

Parameters[:]{.colon}
  • point (VectorLike) -- intersection point for tangent

  • arc (Curve{.hxr-hoverxref .hxr-tooltip .reference .internal} | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- circular arc to tangent, must be GeomType.CIRCLE

  • side (Side, optional) -- side of arcs to place tangent arc center, LEFT or RIGHT. Defaults to Side.LEFT

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[PointArcTangentArc]{.pre}]{.sig-name .descname}[(]{.sig-paren}[point:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [direction:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [arc:]{.pre} [~build123d.topology.composite.Curve]{.pre} [|]{.pre} [~build123d.topology.one_d.Edge]{.pre} [|]{.pre} [~build123d.topology.one_d.Wire,]{.pre} [side:]{.pre} [~build123d.build_enums.Side]{.pre} [=]{.pre} [<Side.LEFT>,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Line Object: Point Arc Tangent Arc

Create an arc defined by a point/tangent pair and another line which the other end is tangent to.

Parameters[:]{.colon}
  • point (VectorLike) -- starting point of tangent arc

  • direction (VectorLike) -- direction at starting point of tangent arc

  • arc (Union[Curve{.hxr-hoverxref .hxr-tooltip .reference .internal}, Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}, Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- ending arc, must be GeomType.CIRCLE

  • side (Side, optional) -- select which arc to keep Defaults to Side.LEFT

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

Raises[:]{.colon}
  • ValueError -- Arc must have GeomType.CIRCLE

  • ValueError -- Point is already tangent to arc

  • RuntimeError -- No tangent arc found ::: :::

::: {#objects.xhtml#id1 .section}

2D Objects

::: {.sd-container-fluid .sd-sphinx-override .sd-mb-4 .docutils} ::: {.sd-row .sd-row-cols-3 .sd-row-cols-xs-3 .sd-row-cols-sm-3 .sd-row-cols-md-3 .sd-row-cols-lg-3 .docutils} ::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Arrow{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Arrow with head and path for shaft ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} ArrowHead{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Arrow head with multiple types ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Circle{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Circle defined by radius ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} DimensionLine{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Dimension line ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Ellipse{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Ellipse defined by major and minor radius ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} ExtensionLine{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Extension lines for distance or angles ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Polygon{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Polygon defined by points ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Rectangle{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Rectangle defined by width and height ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} RectangleRounded{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Rectangle with rounded corners defined by width, height, and radius ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} RegularPolygon{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} RegularPolygon defined by radius and number of sides ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} SlotArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} SlotArc defined by arc and height ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} SlotCenterPoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} SlotCenterPoint defined by two points and a height ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} SlotCenterToCenter{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} SlotCenterToCenter defined by center separation and height ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} SlotOverall{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} SlotOverall defined by end-to-end length and height ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} TechnicalDrawing{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} A technical drawing with descriptions ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Text{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Text defined by string and font parameters ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Trapezoid{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Trapezoid defined by width, height and interior angles ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Triangle{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Triangle defined by one side & two other sides or interior angles ::: ::: ::: ::: :::

::: {#objects.xhtml#id2 .section}

Reference

[class]{.pre}[ ]{.w}[[BaseSketchObject]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj:]{.pre} [~build123d.topology.composite.Compound]{.pre} [|]{.pre} [~build123d.topology.two_d.Face]{.pre}]{.n}, [[rotation:]{.pre} [float]{.pre} [=]{.pre} [0]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Base class for all BuildSketch objects

Parameters[:]{.colon}
  • face (Face{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- face to create

  • rotation (float, optional) -- angle to rotate object. Defaults to 0

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- align MIN, CENTER, or MAX of object. Defaults to None

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[Arrow]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[arrow_size:]{.pre} [float]{.pre}]{.n}, [[shaft_path:]{.pre} [~build123d.topology.one_d.Edge]{.pre} [|]{.pre} [~build123d.topology.one_d.Wire]{.pre}]{.n}, [[shaft_width:]{.pre} [float]{.pre}]{.n}, [[head_at_start:]{.pre} [bool]{.pre} [=]{.pre} [True]{.pre}]{.n}, [[head_type:]{.pre} [~build123d.build_enums.HeadType]{.pre} [=]{.pre} [<HeadType.CURVED>]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Sketch Object: Arrow with shaft

Parameters[:]{.colon}
  • arrow_size (float) -- arrow head tip to tail length

  • shaft_path (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- line describing the shaft shape

  • shaft_width (float) -- line width of shaft

  • head_at_start (bool, optional) -- Defaults to True.

  • head_type (HeadType, optional) -- arrow head shape. Defaults to HeadType.CURVED.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- _description_. Defaults to Mode.ADD.

<!-- -->
[class]{.pre}[ ]{.w}[[ArrowHead]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[size:]{.pre} [float]{.pre}]{.n}, [[head_type:]{.pre} [~build123d.build_enums.HeadType]{.pre} [=]{.pre} [<HeadType.CURVED>]{.pre}]{.n}, [[rotation:]{.pre} [float]{.pre} [=]{.pre} [0]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Sketch Object: ArrowHead

Parameters[:]{.colon}
  • size (float) -- tip to tail length

  • head_type (HeadType, optional) -- arrow head shape. Defaults to HeadType.CURVED.

  • rotation (float, optional) -- rotation in degrees. Defaults to 0.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

<!-- -->
[class]{.pre}[ ]{.w}[[Circle]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[radius:]{.pre} [float]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [(<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>)]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Sketch Object: Circle

Create a circle defined by radius.

Parameters[:]{.colon}
  • radius (float) -- circle radius

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- align MIN, CENTER, or MAX of object. Defaults to (Align.CENTER, Align.CENTER)

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[DimensionLine]{.pre}]{.sig-name .descname}[(]{.sig-paren}[path:]{.pre} [~build123d.topology.one_d.Wire]{.pre} [|]{.pre} [~build123d.topology.one_d.Edge]{.pre} [|]{.pre} [list[~build123d.geometry.Vector]{.pre} [|]{.pre} [~build123d.topology.zero_d.Vertex]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]],]{.pre} [draft:]{.pre} [~drafting.Draft,]{.pre} [sketch:]{.pre} [~build123d.topology.composite.Sketch]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [label:]{.pre} [str]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [arrows:]{.pre} [tuple[bool,]{.pre} [bool]]{.pre} [=]{.pre} [(True,]{.pre} [True),]{.pre} [tolerance:]{.pre} [float]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [label_angle:]{.pre} [bool]{.pre} [=]{.pre} [False,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Sketch Object: DimensionLine

Create a dimension line typically for internal measurements. Typically used for (but not restricted to) inside dimensions, a dimension line often as arrows on either side of a dimension or label.

There are three options depending on the size of the text and length of the dimension line: Type 1) The label and arrows fit within the length of the path Type 2) The text fit within the path and the arrows go outside Type 3) Neither the text nor the arrows fit within the path

Parameters[:]{.colon}
  • path (PathDescriptor) -- a very general type of input used to describe the path the dimension line will follow.

  • draft (Draft) -- instance of Draft dataclass

  • sketch (Sketch{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- the Sketch being created to check for possible overlaps. In builder mode the active Sketch will be used if None is provided.

  • label (str, optional) -- a text string which will replace the length (or arc length) that would otherwise be extracted from the provided path. Providing a label is useful when illustrating a parameterized input where the name of an argument is desired not an actual measurement. Defaults to None.

  • arrows (tuple[bool, bool], optional) -- a pair of boolean values controlling the placement of the start and end arrows. Defaults to (True, True).

  • tolerance (float | tuple[float, float], optional) -- an optional tolerance value to add to the extracted length value. If a single tolerance value is provided it is shown as ± the provided value while a pair of values are shown as separate + and - values. Defaults to None.

  • label_angle (bool, optional) -- a flag indicating that instead of an extracted length value, the size of the circular arc extracted from the path should be displayed in degrees.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

Raises[:]{.colon}
  • ValueError -- Only 2 points allowed for dimension lines

  • ValueError -- No output - no arrows selected

[[dimension]{.pre}]{.sig-name .descname}

length of the dimension

<!-- -->
[class]{.pre}[ ]{.w}[[Ellipse]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[x_radius:]{.pre} [float]{.pre}]{.n}, [[y_radius:]{.pre} [float]{.pre}]{.n}, [[rotation:]{.pre} [float]{.pre} [=]{.pre} [0]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [(<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>)]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Sketch Object: Ellipse

Create an ellipse defined by x- and y- radii.

Parameters[:]{.colon}
  • x_radius (float) -- x radius of the ellipse (along the x-axis of plane)

  • y_radius (float) -- y radius of the ellipse (along the y-axis of plane)

  • rotation (float, optional) -- angle to rotate object. Defaults to 0

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- align MIN, CENTER, or MAX of object. Defaults to (Align.CENTER, Align.CENTER)

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[ExtensionLine]{.pre}]{.sig-name .descname}[(]{.sig-paren}[border:]{.pre} [~build123d.topology.one_d.Wire]{.pre} [|]{.pre} [~build123d.topology.one_d.Edge]{.pre} [|]{.pre} [list[~build123d.geometry.Vector]{.pre} [|]{.pre} [~build123d.topology.zero_d.Vertex]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]],]{.pre} [offset:]{.pre} [float,]{.pre} [draft:]{.pre} [~drafting.Draft,]{.pre} [sketch:]{.pre} [~build123d.topology.composite.Sketch]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [label:]{.pre} [str]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [arrows:]{.pre} [tuple[bool,]{.pre} [bool]]{.pre} [=]{.pre} [(True,]{.pre} [True),]{.pre} [tolerance:]{.pre} [float]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [label_angle:]{.pre} [bool]{.pre} [=]{.pre} [False,]{.pre} [measurement_direction:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Sketch Object: Extension Line

Create a dimension line with two lines extending outward from the part to dimension. Typically used for (but not restricted to) outside dimensions, with a pair of lines extending from the edge of a part to a dimension line.

Parameters[:]{.colon}
  • border (PathDescriptor) -- a very general type of input defining the object to be dimensioned. Typically this value would be extracted from the part but is not restricted to this use.

  • offset (float) -- a distance to displace the dimension line from the edge of the object

  • draft (Draft) -- instance of Draft dataclass

  • label (str, optional) -- a text string which will replace the length (or arc length) that would otherwise be extracted from the provided path. Providing a label is useful when illustrating a parameterized input where the name of an argument is desired not an actual measurement. Defaults to None.

  • arrows (tuple[bool, bool], optional) -- a pair of boolean values controlling the placement of the start and end arrows. Defaults to (True, True).

  • tolerance (float | tuple[float, float], optional) -- an optional tolerance value to add to the extracted length value. If a single tolerance value is provided it is shown as ± the provided value while a pair of values are shown as separate + and - values. Defaults to None.

  • label_angle (bool, optional) -- a flag indicating that instead of an extracted length value, the size of the circular arc extracted from the path should be displayed in degrees. Defaults to False.

  • measurement_direction (VectorLike, optional) -- Vector line which to project the dimension against. Offset start point is the position of the start of border. Defaults to None.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

[[dimension]{.pre}]{.sig-name .descname}

length of the dimension

<!-- -->
[class]{.pre}[ ]{.w}[[Polygon]{.pre}]{.sig-name .descname}[(]{.sig-paren}[*pts:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]]{.pre} [|]{.pre} [~collections.abc.Iterable[~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]],]{.pre} [rotation:]{.pre} [float]{.pre} [=]{.pre} [0,]{.pre} [align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align,]{.pre} [~build123d.build_enums.Align]]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [(<Align.CENTER>,]{.pre} [<Align.CENTER>),]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Sketch Object: Polygon

Create a polygon defined by given sequence of points.

Note: the order of the points defines the resulting normal of the Face in Algebra mode, where counter-clockwise order creates an upward normal while clockwise order a downward normal. In Builder mode, the Face is added with an upward normal.

Parameters[:]{.colon}
  • pts (VectorLike | Iterable[VectorLike]) -- sequence of points defining the vertices of the polygon

  • rotation (float, optional) -- angle to rotate object. Defaults to 0

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- align MIN, CENTER, or MAX of object. Defaults to (Align.CENTER, Align.CENTER)

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[Rectangle]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[width:]{.pre} [float]{.pre}]{.n}, [[height:]{.pre} [float]{.pre}]{.n}, [[rotation:]{.pre} [float]{.pre} [=]{.pre} [0]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [(<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>)]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Sketch Object: Rectangle

Create a rectangle defined by width and height.

Parameters[:]{.colon}
  • width (float) -- rectangle width

  • height (float) -- rectangle height

  • rotation (float, optional) -- angle to rotate object. Defaults to 0

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- align MIN, CENTER, or MAX of object. Defaults to (Align.CENTER, Align.CENTER)

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[RectangleRounded]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[width:]{.pre} [float]{.pre}]{.n}, [[height:]{.pre} [float]{.pre}]{.n}, [[radius:]{.pre} [float]{.pre}]{.n}, [[rotation:]{.pre} [float]{.pre} [=]{.pre} [0]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [(<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>)]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Sketch Object: Rectangle Rounded

Create a rectangle defined by width and height with filleted corners.

Parameters[:]{.colon}
  • width (float) -- rectangle width

  • height (float) -- rectangle height

  • radius (float) -- fillet radius

  • rotation (float, optional) -- angle to rotate object. Defaults to 0

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- align MIN, CENTER, or MAX of object. Defaults to (Align.CENTER, Align.CENTER)

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[RegularPolygon]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[radius:]{.pre} [float]{.pre}]{.n}, [[side_count:]{.pre} [int]{.pre}]{.n}, [[major_radius:]{.pre} [bool]{.pre} [=]{.pre} [True]{.pre}]{.n}, [[rotation:]{.pre} [float]{.pre} [=]{.pre} [0]{.pre}]{.n}, [[align:]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [=]{.pre} [(<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>)]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Sketch Object: Regular Polygon

Create a regular polygon defined by radius and side count. Use major_radius to define whether the polygon circumscribes (along the vertices) or inscribes (along the sides) the radius circle.

Parameters[:]{.colon}
  • radius (float) -- construction radius

  • side_count (int) -- number of sides

  • major_radius (bool) -- If True the radius is the major radius (circumscribed circle), else the radius is the minor radius (inscribed circle). Defaults to True

  • rotation (float, optional) -- angle to rotate object. Defaults to 0

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- align MIN, CENTER, or MAX of object. Defaults to (Align.CENTER, Align.CENTER)

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

[[apothem]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

radius of the inscribed circle or minor radius

[[radius]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

radius of the circumscribed circle or major radius

<!-- -->
[class]{.pre}[ ]{.w}[[SlotArc]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[arc:]{.pre} [~build123d.topology.one_d.Edge]{.pre} [|]{.pre} [~build123d.topology.one_d.Wire]{.pre}]{.n}, [[height:]{.pre} [float]{.pre}]{.n}, [[rotation:]{.pre} [float]{.pre} [=]{.pre} [0]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Sketch Object: Slot Arc

Create a slot defined by a line and height. May be an arc, stright line, spline, etc.

Parameters[:]{.colon}
  • arc (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- center line of slot

  • height (float) -- diameter of end arcs

  • rotation (float, optional) -- angle to rotate object. Defaults to 0

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[SlotCenterPoint]{.pre}]{.sig-name .descname}[(]{.sig-paren}[center:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [point:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [height:]{.pre} [float,]{.pre} [rotation:]{.pre} [float]{.pre} [=]{.pre} [0,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren}

Sketch Object: Slot Center Point

Create a slot defined by the center of the slot and the center of one end arc. The slot will be symmetric about the center point.

Parameters[:]{.colon}
  • center (VectorLike) -- center point

  • point (VectorLike) -- center of arc point

  • height (float) -- diameter of end arcs

  • rotation (float, optional) -- angle to rotate object. Defaults to 0

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[SlotCenterToCenter]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[center_separation:]{.pre} [float]{.pre}]{.n}, [[height:]{.pre} [float]{.pre}]{.n}, [[rotation:]{.pre} [float]{.pre} [=]{.pre} [0]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Sketch Object: Slot Center To Center

Create a slot defined by the distance between the centers of the two end arcs.

Parameters[:]{.colon}
  • center_separation (float) -- distance between arc centers

  • height (float) -- diameter of end arcs

  • rotation (float, optional) -- angle to rotate object. Defaults to 0

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[SlotOverall]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[width:]{.pre} [float]{.pre}]{.n}, [[height:]{.pre} [float]{.pre}]{.n}, [[rotation:]{.pre} [float]{.pre} [=]{.pre} [0]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [(<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>)]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Sketch Object: Slot Overall

Create a slot defined by the overall width and height.

Parameters[:]{.colon}
  • width (float) -- overall width of slot

  • height (float) -- diameter of end arcs

  • rotation (float, optional) -- angle to rotate object. Defaults to 0

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- align MIN, CENTER, or MAX of object. Defaults to (Align.CENTER, Align.CENTER)

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[TechnicalDrawing]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[designed_by:]{.pre} [str]{.pre} [=]{.pre} ['build123d']{.pre}]{.n}, [[design_date:]{.pre} [~datetime.date]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[page_size:]{.pre} [~build123d.build_enums.PageSize]{.pre} [=]{.pre} [<PageSize.A4>]{.pre}]{.n}, [[title:]{.pre} [str]{.pre} [=]{.pre} ['Title']{.pre}]{.n}, [[sub_title:]{.pre} [str]{.pre} [=]{.pre} ['Sub]{.pre} [Title']{.pre}]{.n}, [[drawing_number:]{.pre} [str]{.pre} [=]{.pre} ['B3D-1']{.pre}]{.n}, [[sheet_number:]{.pre} [int]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[drawing_scale:]{.pre} [float]{.pre} [=]{.pre} [1.0]{.pre}]{.n}, [[nominal_text_size:]{.pre} [float]{.pre} [=]{.pre} [10.0]{.pre}]{.n}, [[line_width:]{.pre} [float]{.pre} [=]{.pre} [0.5]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Sketch Object: TechnicalDrawing

The border of a technical drawing with external frame and text box.

Parameters[:]{.colon}
  • designed_by (str, optional) -- Defaults to "build123d".

  • design_date (date, optional) -- Defaults to date.today().

  • page_size (PageSize, optional) -- Defaults to PageSize.A4.

  • title (str, optional) -- drawing title. Defaults to "Title".

  • sub_title (str, optional) -- drawing sub title. Defaults to "Sub Title".

  • drawing_number (str, optional) -- Defaults to "B3D-1".

  • sheet_number (int, optional) -- Defaults to None.

  • drawing_scale (float, optional) -- displays as 1:value. Defaults to 1.0.

  • nominal_text_size (float, optional) -- size of title text. Defaults to 10.0.

  • line_width (float, optional) -- Defaults to 0.5.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

[[margin]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[5]{.pre}
[[page_sizes]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[{<PageSize.A0>:]{.pre} [(1189,]{.pre} [841),]{.pre} [<PageSize.A10>:]{.pre} [(37,]{.pre} [26),]{.pre} [<PageSize.A1>:]{.pre} [(841,]{.pre} [594),]{.pre} [<PageSize.A2>:]{.pre} [(594,]{.pre} [420),]{.pre} [<PageSize.A3>:]{.pre} [(420,]{.pre} [297),]{.pre} [<PageSize.A4>:]{.pre} [(297,]{.pre} [210),]{.pre} [<PageSize.A5>:]{.pre} [(210,]{.pre} [148.5),]{.pre} [<PageSize.A6>:]{.pre} [(148.5,]{.pre} [105),]{.pre} [<PageSize.A7>:]{.pre} [(105,]{.pre} [74),]{.pre} [<PageSize.A8>:]{.pre} [(74,]{.pre} [52),]{.pre} [<PageSize.A9>:]{.pre} [(52,]{.pre} [37),]{.pre} [<PageSize.LEDGER>:]{.pre} [(431.79999999999995,]{.pre} [279.4),]{.pre} [<PageSize.LEGAL>:]{.pre} [(355.59999999999997,]{.pre} [215.89999999999998),]{.pre} [<PageSize.LETTER>:]{.pre} [(279.4,]{.pre} [215.89999999999998)}]{.pre}
<!-- -->
[class]{.pre}[ ]{.w}[[Text]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[txt:]{.pre} [str]{.pre}]{.n}, [[font_size:]{.pre} [float]{.pre}]{.n}, [[font:]{.pre} [str]{.pre} [=]{.pre} ['Arial']{.pre}]{.n}, [[font_path:]{.pre} [str]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[font_style:]{.pre} [~build123d.build_enums.FontStyle]{.pre} [=]{.pre} [<FontStyle.REGULAR>]{.pre}]{.n}, [[text_align:]{.pre} [tuple[~build123d.build_enums.TextAlign]{.pre}]{.n}, ~build123d.build_enums.TextAlign{.pre} [=]{.pre} [(<TextAlign.CENTER>]{.pre}]{.n}, [[<TextAlign.CENTER>)]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[path:]{.pre} [~build123d.topology.one_d.Edge]{.pre} [|]{.pre} [~build123d.topology.one_d.Wire]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[position_on_path:]{.pre} [float]{.pre} [=]{.pre} [0.0]{.pre}]{.n}, [[rotation:]{.pre} [float]{.pre} [=]{.pre} [0.0]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Sketch Object: Text

Create text defined by text string and font size.

Fonts installed to the system can be specified by name and FontStyle. Fonts with subfamilies not in FontStyle should be specified with the subfamily name, e.g. "Arial Black". Alternatively, a specific font file can be specified with font_path.

Use <cite>{=html}available_fonts()</cite>{=html} to list available font names for <cite>{=html}font</cite>{=html} and FontStyles. Note: on Windows, fonts must be installed with "Install for all users" to be found by name.

Not all fonts have every FontStyle available, however ITALIC and BOLDITALIC will still italicize the font if the respective font file is not available.

text_align specifies alignment of text inside the bounding box, while align the aligns the bounding box itself.

Optionally, the Text can be positioned on a non-linear edge or wire with a path and position_on_path.

Parameters[:]{.colon}
  • txt (str) -- text to render

  • font_size (float) -- size of the font in model units

  • font (str, optional) -- font name. Defaults to "Arial"

  • font_path (str, optional) -- system path to font file. Defaults to None

  • font_style (Font_Style, optional) -- font style, REGULAR, BOLD, BOLDITALIC, or ITALIC. Defaults to Font_Style.REGULAR

  • text_align (tuple[TextAlign, TextAlign], optional) -- horizontal text align LEFT, CENTER, or RIGHT. Vertical text align BOTTOM, CENTER, TOP, or TOPFIRSTLINE. Defaults to (TextAlign.CENTER, TextAlign.CENTER)

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- align MIN, CENTER, or MAX of object. Defaults to None

  • path (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- path for text to follow. Defaults to None

  • position_on_path (float, optional) -- the relative location on path to position the text, values must be between 0.0 and 1.0. Defaults to 0.0

  • rotation (float, optional) -- angle to rotate object. Defaults to 0

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[Trapezoid]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[width:]{.pre} [float]{.pre}]{.n}, [[height:]{.pre} [float]{.pre}]{.n}, [[left_side_angle:]{.pre} [float]{.pre}]{.n}, [[right_side_angle:]{.pre} [float]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[rotation:]{.pre} [float]{.pre} [=]{.pre} [0]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [(<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>)]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Sketch Object: Trapezoid

Create a trapezoid defined by major width, height, and interior angle(s).

Parameters[:]{.colon}
  • width (float) -- trapezoid major width

  • height (float) -- trapezoid height

  • left_side_angle (float) -- bottom left interior angle

  • right_side_angle (float, optional) -- bottom right interior angle. If not provided, the trapezoid will be symmetric. Defaults to None

  • rotation (float, optional) -- angle to rotate object. Defaults to 0

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- align MIN, CENTER, or MAX of object. Defaults to (Align.CENTER, Align.CENTER)

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

Raises[:]{.colon}

ValueError -- Give angles result in an invalid trapezoid

<!-- -->
[class]{.pre}[ ]{.w}[[Triangle]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.n}, [[a:]{.pre} [float]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[b:]{.pre} [float]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[c:]{.pre} [float]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[A:]{.pre} [float]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[B:]{.pre} [float]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[C:]{.pre} [float]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[rotation:]{.pre} [float]{.pre} [=]{.pre} [0]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Sketch Object: Triangle

Create a triangle defined by one side length and any of two other side lengths or interior angles. The interior angles are opposite the side with the same designation (i.e. side 'a' is opposite angle 'A'). Side 'a' is the bottom side, followed by 'b' on the right, going counter-clockwise.

Parameters[:]{.colon}
  • a (float, optional) -- side 'a' length. Defaults to None

  • b (float, optional) -- side 'b' length. Defaults to None

  • c (float, optional) -- side 'c' length. Defaults to None

  • A (float, optional) -- interior angle 'A'. Defaults to None

  • B (float, optional) -- interior angle 'B'. Defaults to None

  • C (float, optional) -- interior angle 'C'. Defaults to None

  • rotation (float, optional) -- angle to rotate object. Defaults to 0

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- align MIN, CENTER, or MAX of object. Defaults to None

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

Raises[:]{.colon}

ValueError -- One length and two other values were not provided

[[A]{.pre}]{.sig-name .descname}

interior angle 'A' in degrees

[[B]{.pre}]{.sig-name .descname}

interior angle 'B' in degrees

[[C]{.pre}]{.sig-name .descname}

interior angle 'C' in degrees

[[a]{.pre}]{.sig-name .descname}

length of side 'a'

[[b]{.pre}]{.sig-name .descname}

length of side 'b'

[[c]{.pre}]{.sig-name .descname}

length of side 'c'

[[edge_a]{.pre}]{.sig-name .descname}

edge 'a'

[[edge_b]{.pre}]{.sig-name .descname}

edge 'b'

[[edge_c]{.pre}]{.sig-name .descname}

edge 'c'

[[vertex_A]{.pre}]{.sig-name .descname}

vertex 'A'

[[vertex_B]{.pre}]{.sig-name .descname}

vertex 'B'

[[vertex_C]{.pre}]{.sig-name .descname}

vertex 'C' ::: :::

::: {#objects.xhtml#id3 .section}

3D Objects

::: {.sd-container-fluid .sd-sphinx-override .sd-mb-4 .docutils} ::: {.sd-row .sd-row-cols-3 .sd-row-cols-xs-3 .sd-row-cols-sm-3 .sd-row-cols-md-3 .sd-row-cols-lg-3 .docutils} ::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Box{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Box defined by length, width, height ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Cone{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Cone defined by radii and height ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} CounterBoreHole{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Counter bore hole defined by radii and depths ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} CounterSinkHole{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Counter sink hole defined by radii and depth and angle ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Cylinder{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Cylinder defined by radius and height ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Hole{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Hole defined by radius and depth ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Sphere{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Sphere defined by radius and arc angles ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Torus{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Torus defined major and minor radii ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Wedge{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

:::

::: {.sd-card-footer .docutils} Wedge defined by lengths along multiple Axes ::: ::: ::: ::: :::

::: {#objects.xhtml#id4 .section}

Reference

[class]{.pre}[ ]{.w}[[BasePartObject]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[part:]{.pre} [~build123d.topology.composite.Part]{.pre} [|]{.pre} [~build123d.topology.three_d.Solid]{.pre}]{.n}, [[rotation:]{.pre} [~build123d.geometry.Rotation]{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, [[float]{.pre}]{.n}, float{.pre} [=]{.pre} [(0]{.pre}]{.n}, [[0]{.pre}]{.n}, [[0)]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, [[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Base class for all BuildPart objects & operations

Parameters[:]{.colon}
  • solid (Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- object to create

  • rotation (RotationLike, optional) -- angles to rotate about axes. Defaults to (0, 0, 0)

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}] | None, optional) -- align MIN, CENTER, or MAX of object. Defaults to None

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[Box]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[length:]{.pre} [float]{.pre}]{.n}, [[width:]{.pre} [float]{.pre}]{.n}, [[height:]{.pre} [float]{.pre}]{.n}, [[rotation:]{.pre} [~build123d.geometry.Rotation]{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, [[float]{.pre}]{.n}, float{.pre} [=]{.pre} [(0]{.pre}]{.n}, [[0]{.pre}]{.n}, [[0)]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, [[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [=]{.pre} [(<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>)]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Part Object: Box

Create a box defined by length, width, and height.

Parameters[:]{.colon}
  • length (float) -- box length

  • width (float) -- box width

  • height (float) -- box height

  • rotation (RotationLike, optional) -- angles to rotate about axes. Defaults to (0, 0, 0)

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}] | None, optional) -- align MIN, CENTER, or MAX of object. Defaults to (Align.CENTER, Align.CENTER, Align.CENTER)

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combine mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[Cone]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[bottom_radius:]{.pre} [float]{.pre}]{.n}, [[top_radius:]{.pre} [float]{.pre}]{.n}, [[height:]{.pre} [float]{.pre}]{.n}, [[arc_size:]{.pre} [float]{.pre} [=]{.pre} [360]{.pre}]{.n}, [[rotation:]{.pre} [~build123d.geometry.Rotation]{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, [[float]{.pre}]{.n}, float{.pre} [=]{.pre} [(0]{.pre}]{.n}, [[0]{.pre}]{.n}, [[0)]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, [[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [=]{.pre} [(<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>)]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Part Object: Cone

Create a cone defined by bottom radius, top radius, and height.

Parameters[:]{.colon}
  • bottom_radius (float) -- bottom radius

  • top_radius (float) -- top radius, may be zero

  • height (float) -- cone height

  • arc_size (float, optional) -- angular size of cone. Defaults to 360

  • rotation (RotationLike, optional) -- angles to rotate about axes. Defaults to (0, 0, 0)

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}] | None, optional) -- align MIN, CENTER, or MAX of object. Defaults to (Align.CENTER, Align.CENTER, Align.CENTER)

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combine mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[CounterBoreHole]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[radius:]{.pre} [float]{.pre}]{.n}, [[counter_bore_radius:]{.pre} [float]{.pre}]{.n}, [[counter_bore_depth:]{.pre} [float]{.pre}]{.n}, [[depth:]{.pre} [float]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.SUBTRACT>]{.pre}]{.n}[)]{.sig-paren}

Part Operation: Counter Bore Hole

Create a counter bore hole defined by radius, counter bore radius, counter bore and depth.

Parameters[:]{.colon}
  • radius (float) -- hole radius

  • counter_bore_radius (float) -- counter bore radius

  • counter_bore_depth (float) -- counter bore depth

  • depth (float, optional) -- hole depth, through part if None. Defaults to None

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.SUBTRACT

<!-- -->
[class]{.pre}[ ]{.w}[[CounterSinkHole]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[radius:]{.pre} [float]{.pre}]{.n}, [[counter_sink_radius:]{.pre} [float]{.pre}]{.n}, [[depth:]{.pre} [float]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[counter_sink_angle:]{.pre} [float]{.pre} [=]{.pre} [82]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.SUBTRACT>]{.pre}]{.n}[)]{.sig-paren}

Part Operation: Counter Sink Hole

Create a countersink hole defined by radius, countersink radius, countersink angle, and depth.

Parameters[:]{.colon}
  • radius (float) -- hole radius

  • counter_sink_radius (float) -- countersink radius

  • depth (float, optional) -- hole depth, through part if None. Defaults to None

  • counter_sink_angle (float, optional) -- cone angle. Defaults to 82

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.SUBTRACT

<!-- -->
[class]{.pre}[ ]{.w}[[Cylinder]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[radius:]{.pre} [float]{.pre}]{.n}, [[height:]{.pre} [float]{.pre}]{.n}, [[arc_size:]{.pre} [float]{.pre} [=]{.pre} [360]{.pre}]{.n}, [[rotation:]{.pre} [~build123d.geometry.Rotation]{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, [[float]{.pre}]{.n}, float{.pre} [=]{.pre} [(0]{.pre}]{.n}, [[0]{.pre}]{.n}, [[0)]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, [[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [=]{.pre} [(<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>)]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Part Object: Cylinder

Create a cylinder defined by radius and height.

Parameters[:]{.colon}
  • radius (float) -- cylinder radius

  • height (float) -- cylinder height

  • arc_size (float, optional) -- angular size of cone. Defaults to 360.

  • rotation (RotationLike, optional) -- angles to rotate about axes. Defaults to (0, 0, 0)

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}] | None, optional) -- align MIN, CENTER, or MAX of object. Defaults to (Align.CENTER, Align.CENTER, Align.CENTER)

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combine mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[Hole]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[radius:]{.pre} [float]{.pre}]{.n}, [[depth:]{.pre} [float]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.SUBTRACT>]{.pre}]{.n}[)]{.sig-paren}

Part Operation: Hole

Create a hole defined by radius and depth.

Parameters[:]{.colon}
  • radius (float) -- hole radius

  • depth (float, optional) -- hole depth, through part if None. Defaults to None

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.SUBTRACT

<!-- -->
[class]{.pre}[ ]{.w}[[Sphere]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[radius:]{.pre} [float]{.pre}]{.n}, [[arc_size1:]{.pre} [float]{.pre} [=]{.pre} [-90]{.pre}]{.n}, [[arc_size2:]{.pre} [float]{.pre} [=]{.pre} [90]{.pre}]{.n}, [[arc_size3:]{.pre} [float]{.pre} [=]{.pre} [360]{.pre}]{.n}, [[rotation:]{.pre} [~build123d.geometry.Rotation]{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, [[float]{.pre}]{.n}, float{.pre} [=]{.pre} [(0]{.pre}]{.n}, [[0]{.pre}]{.n}, [[0)]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, [[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [=]{.pre} [(<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>)]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Part Object: Sphere

Create a sphere defined by a radius.

Parameters[:]{.colon}
  • radius (float) -- sphere radius

  • arc_size1 (float, optional) -- angular size of bottom hemisphere. Defaults to -90.

  • arc_size2 (float, optional) -- angular size of top hemisphere. Defaults to 90.

  • arc_size3 (float, optional) -- angular revolution about pole. Defaults to 360.

  • rotation (RotationLike, optional) -- angles to rotate about axes. Defaults to (0, 0, 0)

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}] | None, optional) -- align MIN, CENTER, or MAX of object. Defaults to (Align.CENTER, Align.CENTER, Align.CENTER)

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combine mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[Torus]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[major_radius:]{.pre} [float]{.pre}]{.n}, [[minor_radius:]{.pre} [float]{.pre}]{.n}, [[minor_start_angle:]{.pre} [float]{.pre} [=]{.pre} [0]{.pre}]{.n}, [[minor_end_angle:]{.pre} [float]{.pre} [=]{.pre} [360]{.pre}]{.n}, [[major_angle:]{.pre} [float]{.pre} [=]{.pre} [360]{.pre}]{.n}, [[rotation:]{.pre} [~build123d.geometry.Rotation]{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, [[float]{.pre}]{.n}, float{.pre} [=]{.pre} [(0]{.pre}]{.n}, [[0]{.pre}]{.n}, [[0)]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, [[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [=]{.pre} [(<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>)]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Part Object: Torus

Create a torus defined by major and minor radii.

Parameters[:]{.colon}
  • major_radius (float) -- major torus radius

  • minor_radius (float) -- minor torus radius

  • minor_start_angle (float, optional) -- angle to start minor arc. Defaults to 0

  • minor_end_angle (float, optional) -- angle to end minor arc. Defaults to 360

  • major_angle (float, optional) -- angle to revolve minor arc. Defaults to 360

  • rotation (RotationLike, optional) -- angles to rotate about axes. Defaults to (0, 0, 0)

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}] | None, optional) -- align MIN, CENTER, or MAX of object. Defaults to (Align.CENTER, Align.CENTER, Align.CENTER)

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combine mode. Defaults to Mode.ADD

<!-- -->
[class]{.pre}[ ]{.w}[[Wedge]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[xsize:]{.pre} [float]{.pre}]{.n}, [[ysize:]{.pre} [float]{.pre}]{.n}, [[zsize:]{.pre} [float]{.pre}]{.n}, [[xmin:]{.pre} [float]{.pre}]{.n}, [[zmin:]{.pre} [float]{.pre}]{.n}, [[xmax:]{.pre} [float]{.pre}]{.n}, [[zmax:]{.pre} [float]{.pre}]{.n}, [[rotation:]{.pre} [~build123d.geometry.Rotation]{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, [[float]{.pre}]{.n}, float{.pre} [=]{.pre} [(0]{.pre}]{.n}, [[0]{.pre}]{.n}, [[0)]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, [[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [=]{.pre} [(<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>)]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

Part Object: Wedge

Create a wedge with a near face defined by xsize and z size, a far face defined by xmin to xmax and zmin to zmax, and a depth of ysize.

Parameters[:]{.colon}
  • xsize (float) -- length of near face along x-axis

  • ysize (float) -- length of part along y-axis

  • zsize (float) -- length of near face z-axis

  • xmin (float) -- minimum position far face along x-axis

  • zmin (float) -- minimum position far face along z-axis

  • xmax (float) -- maximum position far face along x-axis

  • zmax (float) -- maximum position far face along z-axis

  • rotation (RotationLike, optional) -- angles to rotate about axes. Defaults to (0, 0, 0)

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}] | None, optional) -- align MIN, CENTER, or MAX of object. Defaults to (Align.CENTER, Align.CENTER, Align.CENTER)

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combine mode. Defaults to Mode.ADD ::: :::

::: {#objects.xhtml#custom-objects .section}

Custom Objects

All of the objects presented above were created using one of three base object classes: BaseLineObject{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} , BaseSketchObject{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} , and BasePartObject{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} . Users can use these base object classes to easily create custom objects that have all the functionality of the core objects.

{.align-center}

Here is an example of a custom sketch object specially created as part of the design of this playing card storage box (see the playing_cards.py example{.xref .download .docutils .literal .notranslate}):

::: {.highlight-build123d .notranslate} ::: highlight class Club(BaseSketchObject): def init( self, height: float, rotation: float = 0, align: tuple[Align, Align] = (Align.CENTER, Align.CENTER), mode: Mode = Mode.ADD, ): with BuildSketch() as club: with BuildLine(): l0 = Line((0, -188), (76, -188)) b0 = Bezier(l0 @ 1, (61, -185), (33, -173), (17, -81)) b1 = Bezier(b0 @ 1, (49, -128), (146, -145), (167, -67)) b2 = Bezier(b1 @ 1, (187, 9), (94, 52), (32, 18)) b3 = Bezier(b2 @ 1, (92, 57), (113, 188), (0, 188)) mirror(about=Plane.YZ) make_face() scale(by=height / club.sketch.bounding_box().size.Y) super().init(obj=club.sketch, rotation=rotation, align=align, mode=mode) ::: :::

Here the new custom object class is called Club{.docutils .literal .notranslate} and it's a sub-class of BaseSketchObject{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} . The __init__{.docutils .literal .notranslate} method contains all of the parameters used to instantiate the custom object, specially a height{.docutils .literal .notranslate}, rotation{.docutils .literal .notranslate}, align{.docutils .literal .notranslate}, and mode{.docutils .literal .notranslate} - your objects may contain a sub or super set of these parameters but should always contain a mode{.docutils .literal .notranslate} parameter such that it can be combined with a builder's object.

Next is the creation of the object itself, in this case a sketch of the club suit.

The final line calls the __init__{.docutils .literal .notranslate} method of the super class - i.e. BaseSketchObject{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} with its parameters.

That's it, now the Club{.docutils .literal .notranslate} object can be used anywhere a Circle{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} would be used - with either the Algebra or Builder API.

{.align-center} ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#operations.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#operations.xhtml#operations .section}

Operations

Operations are functions that take objects as inputs and transform them into new objects. For example, a 2D Sketch can be extruded to create a 3D Part. All operations are Python functions which can be applied using both the Algebra and Builder APIs. It's important to note that objects created by operations are not affected by Locations{.docutils .literal .notranslate}, meaning their position is determined solely by the input objects used in the operation.

Here are a couple ways to use extrude(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, in Builder and Algebra mode:

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as cylinder: with BuildSketch(): Circle(radius) extrude(amount=height) ::: :::

::: {.highlight-build123d .notranslate} ::: highlight cylinder = extrude(Circle(radius), amount=height) ::: :::

The following table summarizes all of the available operations. Operations marked as 1D are applicable to BuildLine and Algebra Curve, 2D to BuildSketch and Algebra Sketch, 3D to BuildPart and Algebra Part.

Operation Description 0D 1D 2D 3D Example


add(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Add object to builder ✓ ✓ ✓ [16]{.std .std-ref}{.reference .internal} bounding_box(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Add bounding box as Shape ✓ ✓ ✓
chamfer(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Bevel Vertex or Edge ✓ ✓ [9]{.std .std-ref}{.reference .internal} draft(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Add a draft taper to a part ✓ [Cast Bearing Unit]{.std .std-ref}{.reference .internal} extrude(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Draw 2D Shape into 3D ✓ [3]{.std .std-ref}{.reference .internal} fillet(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Radius Vertex or Edge ✓ ✓ [9]{.std .std-ref}{.reference .internal} full_round(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Round-off Face along given Edge ✓ [24-SPO-06 Buffer Stand]{.std .std-ref}{.reference .internal} loft(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Create 3D Shape from sections ✓ [24]{.std .std-ref}{.reference .internal} make_brake_formed(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Create sheet metal parts ✓
make_face(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Create a Face from Edges ✓ [4]{.std .std-ref}{.reference .internal} make_hull(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Create Convex Hull from Edges ✓
mirror(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Mirror about Plane ✓ ✓ ✓ [15]{.std .std-ref}{.reference .internal} offset(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Inset or outset Shape ✓ ✓ ✓ [25]{.std .std-ref}{.reference .internal} project(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Project points, lines or Faces ✓ ✓ ✓
project_workplane(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Create workplane for projection
revolve(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Swing 2D Shape about Axis ✓ [23]{.std .std-ref}{.reference .internal} scale(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Change size of Shape ✓ ✓ ✓
section(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Generate 2D slices from 3D Shape ✓
split(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Divide object by Plane ✓ ✓ ✓ [27]{.std .std-ref}{.reference .internal} sweep(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Extrude 1/2D section(s) along path ✓ ✓ [14]{.std .std-ref}{.reference .internal} thicken(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Expand 2D section(s) ✓
trace(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Convert lines to faces ✓

The following table summarizes all of the selectors that can be used within the scope of a Builder. Note that they will extract objects from the builder that is currently within scope without it being explicitly referenced.

                                                                                                                                                                                                                             Builder            

Selector Description Line Sketch Part edge(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Select edge from current builder ✓ ✓ ✓ edges(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Select edges from current builder ✓ ✓ ✓ face(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Select face from current builder ✓ ✓ faces(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Select faces from current builder ✓ ✓ solid(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Select solid from current builder ✓ solids(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Select solids from current builder ✓ vertex(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Select vertex from current builder ✓ ✓ ✓ vertices(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Select vertices from current builder ✓ ✓ ✓ wire(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Select wire from current builder ✓ ✓ ✓ wires(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Select wires from current builder ✓ ✓ ✓

::: {#operations.xhtml#reference .section}

Reference

[[add]{.pre}]{.sig-name .descname}[(]{.sig-paren}[objects:]{.pre} [~build123d.topology.one_d.Edge]{.pre} [|]{.pre} [~build123d.topology.one_d.Wire]{.pre} [|]{.pre} [~build123d.topology.two_d.Face]{.pre} [|]{.pre} [~build123d.topology.three_d.Solid]{.pre} [|]{.pre} [~build123d.topology.composite.Compound]{.pre} [|]{.pre} [~build123d.build_common.Builder]{.pre} [|]{.pre} [~collections.abc.Iterable[~build123d.topology.one_d.Edge]{.pre} [|]{.pre} [~build123d.topology.one_d.Wire]{.pre} [|]{.pre} [~build123d.topology.two_d.Face]{.pre} [|]{.pre} [~build123d.topology.three_d.Solid]{.pre} [|]{.pre} [~build123d.topology.composite.Compound]{.pre} [|]{.pre} [~build123d.build_common.Builder],]{.pre} [rotation:]{.pre} [float]{.pre} [|]{.pre} [~build123d.geometry.Rotation]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [clean:]{.pre} [bool]{.pre} [=]{.pre} [True,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren} [[→]{.sig-return-icon} [[Compound]{.pre}]{.sig-return-typehint}]{.sig-return}

Generic Object: Add Object to Part or Sketch

Add an object to a builder.

BuildPart:

Edges and Wires are added to pending_edges. Compounds of Face are added to pending_faces. Solids or Compounds of Solid are combined into the part.

BuildSketch:

Edges and Wires are added to pending_edges. Compounds of Face are added to sketch.

BuildLine:

Edges and Wires are added to line.

Parameters[:]{.colon}
  • objects (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal} | Face{.hxr-hoverxref .hxr-tooltip .reference .internal} | Solid{.hxr-hoverxref .hxr-tooltip .reference .internal} | Compound{.hxr-hoverxref .hxr-tooltip .reference .internal} or Iterable of) -- objects to add

  • rotation (float | RotationLike, optional) -- rotation angle for sketch, rotation about each axis for part. Defaults to None.

  • clean -- Remove extraneous internal structure. Defaults to True.

<!-- -->
[[bounding_box]{.pre}]{.sig-name .descname}[(]{.sig-paren}objects:]{.pre} [~build123d.topology.shape_core.Shape]{.pre} [{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.PRIVATE>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Sketch]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Part]{.pre}]{.sig-return-typehint}]{.sig-return}

Generic Operation: Add Bounding Box

Applies to: BuildSketch and BuildPart

Add the 2D or 3D bounding boxes of the object sequence

Parameters[:]{.colon}
  • objects (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal} or Iterable of) -- objects to create bbox for

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

<!-- -->
[[chamfer]{.pre}]{.sig-name .descname}[(]{.sig-paren}objects]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}[ ]{.w}[[{.pre}]{.p}]{.n}, [[length]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[length2]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[reference]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Face]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Sketch]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Part]{.pre}]{.sig-return-typehint}]{.sig-return}

Generic Operation: chamfer

Applies to 2 and 3 dimensional objects.

Chamfer the given sequence of edges or vertices.

Parameters[:]{.colon}
  • objects (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal} or Iterable of) -- edges or vertices to chamfer

  • length (float) -- chamfer size

  • length2 (float, optional) -- asymmetric chamfer size. Defaults to None.

  • angle (float, optional) -- chamfer angle in degrees. Defaults to None.

  • reference (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Face{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- identifies the side where length is measured. Edge(s) must be part of the face. Vertex/Vertices must be part of edge

Raises[:]{.colon}
  • ValueError -- no objects provided

  • ValueError -- objects must be Edges

  • ValueError -- objects must be Vertices

  • ValueError -- Only one of length2 or angle should be provided

  • ValueError -- reference can only be used in conjunction with length2 or angle

<!-- -->
[[draft]{.pre}]{.sig-name .descname}[(]{.sig-paren}faces]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Face]{.pre}[ ]{.w}[[{.pre}]{.p}]{.n}, [[neutral_plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}]{.n}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Part]{.pre}]{.sig-return-typehint}]{.sig-return}

Part Operation: draft

Apply a draft angle to the given faces of the part

Parameters[:]{.colon}
  • faces -- Faces to which the draft should be applied.

  • neutral_plane -- Plane defining the neutral direction and position.

  • angle -- Draft angle in degrees.

<!-- -->
[[extrude]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[to_extrude:]{.pre} [~build123d.topology.two_d.Face]{.pre} [|]{.pre} [~build123d.topology.composite.Sketch]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[amount:]{.pre} [float]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[dir:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, float{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, [[float]{.pre}]{.n}, float{.pre} [|]{.pre} [~collections.abc.Sequence[float]]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[until:]{.pre} [~build123d.build_enums.Until]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[target:]{.pre} [~build123d.topology.three_d.Solid]{.pre} [|]{.pre} [~build123d.topology.composite.Compound]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[both:]{.pre} [bool]{.pre} [=]{.pre} [False]{.pre}]{.n}, [[taper:]{.pre} [float]{.pre} [=]{.pre} [0.0]{.pre}]{.n}, [[clean:]{.pre} [bool]{.pre} [=]{.pre} [True]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Part]{.pre}]{.sig-return-typehint}]{.sig-return}

Part Operation: extrude

Extrude a sketch or face by an amount or until another object.

Parameters[:]{.colon}
  • to_extrude (Union[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}, Sketch{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- object to extrude. Defaults to None.

  • amount (float, optional) -- distance to extrude, sign controls direction. Defaults to None.

  • dir (VectorLike, optional) -- direction. Defaults to None.

  • until (Until{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- extrude limit. Defaults to None.

  • target (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- extrude until target. Defaults to None.

  • both (bool, optional) -- extrude in both directions. Defaults to False.

  • taper (float, optional) -- taper angle. Defaults to 0.0.

  • clean (bool, optional) -- Remove extraneous internal structure. Defaults to True.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

Raises[:]{.colon}
  • ValueError -- No object to extrude

  • ValueError -- No target object

Returns[:]{.colon}

extruded object

Return type[:]{.colon}

Part{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[[fillet]{.pre}]{.sig-name .descname}[(]{.sig-paren}objects]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}[ ]{.w}[[{.pre}]{.p}]{.n}, [[radius]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Sketch]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Part]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Curve]{.pre}]{.sig-return-typehint}]{.sig-return}

Generic Operation: fillet

Applies to 2 and 3 dimensional objects.

Fillet the given sequence of edges or vertices. Note that vertices on either end of an open line will be automatically skipped.

Parameters[:]{.colon}
  • objects (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal} or Iterable of) -- edges or vertices to fillet

  • radius (float) -- fillet size - must be less than 1/2 local width

Raises[:]{.colon}
  • ValueError -- no objects provided

  • ValueError -- objects must be Edges

  • ValueError -- objects must be Vertices

  • ValueError -- nothing to fillet

<!-- -->
[[full_round]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[edge:]{.pre} [~build123d.topology.one_d.Edge]{.pre}]{.n}, [[invert:]{.pre} [bool]{.pre} [=]{.pre} [False]{.pre}]{.n}, [[voronoi_point_count:]{.pre} [int]{.pre} [=]{.pre} [100]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.REPLACE>]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[Sketch]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Sketch Operation: full_round

Given an edge from a Face/Sketch, modify the face by replacing the given edge with the arc of the Voronoi largest empty circle that will fit within the Face. This "rounds off" the end of the object.

Parameters[:]{.colon}
  • edge (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- target Edge to remove

  • invert (bool, optional) -- make the arc concave instead of convex. Defaults to False.

  • voronoi_point_count (int, optional) -- number of points along each edge used to create the voronoi vertices as potential locations for the center of the largest empty circle. Defaults to 100.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.REPLACE.

Raises[:]{.colon}

ValueError -- Invalid geometry

Returns[:]{.colon}

the modified shape

Return type[:]{.colon}

Sketch{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[[loft]{.pre}]{.sig-name .descname}[(]{.sig-paren}sections:]{.pre} [~build123d.topology.two_d.Face]{.pre} [{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[ruled:]{.pre} [bool]{.pre} [=]{.pre} [False]{.pre}]{.n}, [[clean:]{.pre} [bool]{.pre} [=]{.pre} [True]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Part]{.pre}]{.sig-return-typehint}]{.sig-return}

Part Operation: loft

Loft the pending sketches/faces, across all workplanes, into a solid.

Parameters[:]{.colon}
  • sections (Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal}, Face{.hxr-hoverxref .hxr-tooltip .reference .internal}, Sketch{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- slices to loft into object. If not provided, pending_faces will be used. If vertices are to be used, a vertex can be the first, last, or first and last elements.

  • ruled (bool, optional) -- discontiguous layer tangents. Defaults to False.

  • clean (bool, optional) -- Remove extraneous internal structure. Defaults to True.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

<!-- -->
[[make_brake_formed]{.pre}]{.sig-name .descname}[(]{.sig-paren}[thickness:]{.pre} [float,]{.pre} [station_widths:]{.pre} [float]{.pre} [|]{.pre} [~collections.abc.Iterable[float],]{.pre} [line:]{.pre} [~build123d.topology.one_d.Edge]{.pre} [|]{.pre} [~build123d.topology.one_d.Wire]{.pre} [|]{.pre} [~build123d.topology.composite.Curve]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [side:]{.pre} [~build123d.build_enums.Side]{.pre} [=]{.pre} [<Side.LEFT>,]{.pre} [kind:]{.pre} [~build123d.build_enums.Kind]{.pre} [=]{.pre} [<Kind.ARC>,]{.pre} [clean:]{.pre} [bool]{.pre} [=]{.pre} [True,]{.pre} [mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}[)]{.sig-paren} [[→]{.sig-return-icon} [[Part]{.pre}]{.sig-return-typehint}]{.sig-return}

Create a part typically formed with a sheet metal brake from a single outline. The line parameter describes how the material is to be bent. Either a single width value or a width value at each vertex or station is provided to control the width of the end part. Note that if multiple values are provided there must be one for each vertex and that the resulting part is composed of linear segments.

Parameters[:]{.colon}
  • thickness (float) -- sheet metal thickness

  • station_widths (Union[float, Iterable[float]]) -- width of part at each vertex or a single value. Note that this width is perpendicular to the provided line/plane.

  • line (Union[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}, Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}, Curve{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- outline of part. Defaults to None.

  • side (Side, optional) -- offset direction. Defaults to Side.LEFT.

  • kind (Kind{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- offset intersection type. Defaults to Kind.ARC.

  • clean (bool, optional) -- clean the resulting solid. Defaults to True.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

Raises[:]{.colon}
  • ValueError -- invalid line type

  • ValueError -- not line provided

  • ValueError -- line not suitable

  • ValueError -- incorrect # of width values

Returns[:]{.colon}

sheet metal part

Return type[:]{.colon}

Part{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[[make_face]{.pre}]{.sig-name .descname}[(]{.sig-paren}edges:]{.pre} [~build123d.topology.one_d.Edge]{.pre} [{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Sketch]{.pre}]{.sig-return-typehint}]{.sig-return}

Sketch Operation: make_face

Create a face from the given perimeter edges.

Parameters[:]{.colon}
  • edges (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- sequence of perimeter edges. Defaults to all sketch pending edges.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

<!-- -->
[[make_hull]{.pre}]{.sig-name .descname}[(]{.sig-paren}edges:]{.pre} [~build123d.topology.one_d.Edge]{.pre} [{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Sketch]{.pre}]{.sig-return-typehint}]{.sig-return}

Sketch Operation: make_hull

Create a face from the convex hull of the given edges

Parameters[:]{.colon}
  • edges (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- sequence of edges to hull. Defaults to all sketch pending edges.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

<!-- -->
[[mirror]{.pre}]{.sig-name .descname}[(]{.sig-paren}objects:]{.pre} [~build123d.topology.one_d.Edge]{.pre} [{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[about:]{.pre} [~build123d.geometry.Plane]{.pre} [=]{.pre} [Plane(o=(0.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[x=(1.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[z=(0.00]{.pre}]{.n}, [[-1.00]{.pre}]{.n}, [[0.00))]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Curve]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Sketch]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Part]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Compound]{.pre}]{.sig-return-typehint}]{.sig-return}

Generic Operation: mirror

Applies to 1, 2, and 3 dimensional objects.

Mirror a sequence of objects over the given plane.

Parameters[:]{.colon}
  • objects (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Face{.hxr-hoverxref .hxr-tooltip .reference .internal} | Compound{.hxr-hoverxref .hxr-tooltip .reference .internal} or Iterable of) -- objects to mirror

  • about (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- reference plane. Defaults to "XZ".

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

Raises[:]{.colon}

ValueError -- missing objects

<!-- -->
[[offset]{.pre}]{.sig-name .descname}[(]{.sig-paren}objects:]{.pre} [~build123d.topology.one_d.Edge]{.pre} [{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[amount:]{.pre} [float]{.pre} [=]{.pre} [0]{.pre}]{.n}, openings:]{.pre} [~build123d.topology.two_d.Face]{.pre} [{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[kind:]{.pre} [~build123d.build_enums.Kind]{.pre} [=]{.pre} [<Kind.ARC>]{.pre}]{.n}, [[side:]{.pre} [~build123d.build_enums.Side]{.pre} [=]{.pre} [<Side.BOTH>]{.pre}]{.n}, [[closed:]{.pre} [bool]{.pre} [=]{.pre} [True]{.pre}]{.n}, [[min_edge_length:]{.pre} [float]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.REPLACE>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Curve]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Sketch]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Part]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Compound]{.pre}]{.sig-return-typehint}]{.sig-return}

Generic Operation: offset

Applies to 1, 2, and 3 dimensional objects.

Offset the given sequence of Edges, Faces, Compound of Faces, or Solids. The kind parameter controls the shape of the transitions. For Solid objects, the openings parameter allows selected faces to be open, like a hollow box with no lid.

Parameters[:]{.colon}
  • objects (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Face{.hxr-hoverxref .hxr-tooltip .reference .internal} | Solid{.hxr-hoverxref .hxr-tooltip .reference .internal} | Compound{.hxr-hoverxref .hxr-tooltip .reference .internal} or Iterable of) -- objects to offset

  • amount (float) -- positive values external, negative internal

  • openings (list[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- Defaults to None.

  • kind (Kind{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- transition shape. Defaults to Kind.ARC.

  • side (Side, optional) -- side to place offset. Defaults to Side.BOTH.

  • closed (bool, optional) -- if Side!=BOTH, close the LEFT or RIGHT offset. Defaults to True.

  • min_edge_length (float, optional) -- repair degenerate edges generated by offset by eliminating edges of minimum length in offset wire. Defaults to None.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.REPLACE.

Raises[:]{.colon}
  • ValueError -- missing objects

  • ValueError -- Invalid object type

<!-- -->
[[project]{.pre}]{.sig-name .descname}[(]{.sig-paren}objects:]{.pre} [~build123d.topology.one_d.Edge]{.pre} [{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[workplane:]{.pre} [~build123d.geometry.Plane]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[target:]{.pre} [~build123d.topology.three_d.Solid]{.pre} [|]{.pre} [~build123d.topology.composite.Compound]{.pre} [|]{.pre} [~build123d.topology.composite.Part]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[Curve]{.pre}[ ]{.w}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Generic Operation: project

Applies to 0, 1, and 2 dimensional objects.

Project the given objects or points onto a BuildLine or BuildSketch workplane in the direction of the normal of that workplane. When projecting onto a sketch a Face(s) are generated while Edges are generated for BuildLine. Will only use the first if BuildSketch has multiple active workplanes. In algebra mode a workplane must be provided and the output is either a Face, Curve, Sketch, Compound, or ShapeList[Vector].

Note that only if mode is not Mode.PRIVATE only Faces can be projected into BuildSketch and Edge/Wires into BuildLine.

Parameters[:]{.colon}
  • objects (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Face{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal} | VectorLike | Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal} or Iterable of) -- objects or points to project

  • workplane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- screen workplane

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

Raises[:]{.colon}
  • ValueError -- project doesn't accept group_by

  • ValueError -- Either a workplane must be provided or a builder must be active

  • ValueError -- Points and faces can only be projected in PRIVATE mode

  • ValueError -- Edges, wires and points can only be projected in PRIVATE mode

  • RuntimeError -- BuildPart doesn't have a project operation

<!-- -->
[[project_workplane]{.pre}]{.sig-name .descname}[(]{.sig-paren}origin]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vertex]{.pre}]{.n}, x_dir]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vertex]{.pre}]{.n}, projection_dir]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, [[distance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Plane]{.pre}]{.sig-return-typehint}]{.sig-return}

Part Operation: project_workplane

Return a plane to be used as a BuildSketch or BuildLine workplane with a known origin and x direction. The plane's origin will be the projection of the provided origin (in 3D space). The plane's x direction will be the projection of the provided x_dir (in 3D space).

Parameters[:]{.colon}
  • origin (Union[VectorLike, Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- origin in 3D space

  • x_dir (Union[VectorLike, Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- x direction in 3D space

  • projection_dir (VectorLike) -- projection direction

  • distance (float) -- distance from origin to workplane

Raises[:]{.colon}
  • RuntimeError -- Not suitable for BuildLine or BuildSketch

  • ValueError -- x_dir perpendicular to projection_dir

Returns[:]{.colon}

workplane aligned for projection

Return type[:]{.colon}

Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[[revolve]{.pre}]{.sig-name .descname}[(]{.sig-paren}profiles:]{.pre} [~build123d.topology.two_d.Face]{.pre} [{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[axis:]{.pre} [~build123d.geometry.Axis]{.pre} [=]{.pre} [((0.0]{.pre}]{.n}, [[0.0]{.pre}]{.n}, [[0.0)]{.pre}]{.n}, [[(0.0]{.pre}]{.n}, [[0.0]{.pre}]{.n}, [[1.0))]{.pre}]{.n}, [[revolution_arc:]{.pre} [float]{.pre} [=]{.pre} [360.0]{.pre}]{.n}, [[clean:]{.pre} [bool]{.pre} [=]{.pre} [True]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Part]{.pre}]{.sig-return-typehint}]{.sig-return}

Part Operation: Revolve

Revolve the profile or pending sketches/face about the given axis. Note that the most common use case is when the axis is in the same plane as the face to be revolved but this isn't required.

Parameters[:]{.colon}
  • profiles (Face{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- 2D profile(s) to revolve.

  • axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- axis of rotation. Defaults to Axis.Z.

  • revolution_arc (float, optional) -- angular size of revolution. Defaults to 360.0.

  • clean (bool, optional) -- Remove extraneous internal structure. Defaults to True.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

Raises[:]{.colon}

ValueError -- Invalid axis of revolution

<!-- -->
[[scale]{.pre}]{.sig-name .descname}[(]{.sig-paren}objects:]{.pre} [~build123d.topology.shape_core.Shape]{.pre} [{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[by:]{.pre} [float]{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, [[float]{.pre}]{.n}, float{.pre} [=]{.pre} [1]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.REPLACE>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Curve]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Sketch]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Part]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Compound]{.pre}]{.sig-return-typehint}]{.sig-return}

Generic Operation: scale

Applies to 1, 2, and 3 dimensional objects.

Scale a sequence of objects. Note that when scaling non-uniformly across the three axes, the type of the underlying object may change to bspline from line, circle, etc.

Parameters[:]{.colon}
  • objects (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Face{.hxr-hoverxref .hxr-tooltip .reference .internal} | Compound{.hxr-hoverxref .hxr-tooltip .reference .internal} | Solid{.hxr-hoverxref .hxr-tooltip .reference .internal} or Iterable of) -- objects to scale

  • by (float | tuple[float, float, float]) -- scale factor

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.REPLACE.

Raises[:]{.colon}

ValueError -- missing objects

<!-- -->
[[section]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj:]{.pre} [~build123d.topology.composite.Part]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, section_by:]{.pre} [~build123d.geometry.Plane]{.pre} [{.pre} [=]{.pre} [Plane(o=(0.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[x=(1.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[z=(0.00]{.pre}]{.n}, [[-1.00]{.pre}]{.n}, [[0.00))]{.pre}]{.n}, [[height:]{.pre} [float]{.pre} [=]{.pre} [0.0]{.pre}]{.n}, [[clean:]{.pre} [bool]{.pre} [=]{.pre} [True]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.PRIVATE>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Sketch]{.pre}]{.sig-return-typehint}]{.sig-return}

Part Operation: section

Slices current part at the given height by section_by or current workplane(s).

Parameters[:]{.colon}
  • obj (Part{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- object to section. Defaults to None.

  • section_by (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- plane(s) to section object. Defaults to None.

  • height (float, optional) -- workplane offset. Defaults to 0.0.

  • clean (bool, optional) -- Remove extraneous internal structure. Defaults to True.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.INTERSECT.

<!-- -->
[[split]{.pre}]{.sig-name .descname}[(]{.sig-paren}objects:]{.pre} [~build123d.topology.one_d.Edge]{.pre} [{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[bisect_by:]{.pre} [~build123d.geometry.Plane]{.pre} [|]{.pre} [~build123d.topology.two_d.Face]{.pre} [|]{.pre} [~build123d.topology.two_d.Shell]{.pre} [=]{.pre} [Plane(o=(0.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[x=(1.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[z=(0.00]{.pre}]{.n}, [[-1.00]{.pre}]{.n}, [[0.00))]{.pre}]{.n}, [[keep:]{.pre} [~build123d.build_enums.Keep]{.pre} [=]{.pre} [<Keep.TOP>]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.REPLACE>]{.pre}]{.n}[)]{.sig-paren}

Generic Operation: split

Applies to 1, 2, and 3 dimensional objects.

Bisect object with plane and keep either top, bottom or both.

Parameters[:]{.colon}
  • objects (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal} | Face{.hxr-hoverxref .hxr-tooltip .reference .internal} | Solid{.hxr-hoverxref .hxr-tooltip .reference .internal} or Iterable of)

  • bisect_by (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal} | Face{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- plane to segment part. Defaults to Plane.XZ.

  • keep (Keep{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- selector for which segment to keep. Defaults to Keep.TOP.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.REPLACE.

Raises[:]{.colon}

ValueError -- missing objects

<!-- -->
[[sweep]{.pre}]{.sig-name .descname}[(]{.sig-paren}sections:]{.pre} [~build123d.topology.composite.Compound]{.pre} [{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, path:]{.pre} [~build123d.topology.composite.Curve]{.pre} [{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[multisection:]{.pre} [bool]{.pre} [=]{.pre} [False]{.pre}]{.n}, [[is_frenet:]{.pre} [bool]{.pre} [=]{.pre} [False]{.pre}]{.n}, [[transition:]{.pre} [~build123d.build_enums.Transition]{.pre} [=]{.pre} [<Transition.TRANSFORMED>]{.pre}]{.n}, [[normal:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, float{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, [[float]{.pre}]{.n}, float{.pre} [|]{.pre} [~collections.abc.Sequence[float]]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[binormal:]{.pre} [~build123d.topology.one_d.Edge]{.pre} [|]{.pre} [~build123d.topology.one_d.Wire]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[clean:]{.pre} [bool]{.pre} [=]{.pre} [True]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Part]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Sketch]{.pre}]{.sig-return-typehint}]{.sig-return}

Generic Operation: sweep

Sweep pending 1D or 2D objects along path.

Parameters[:]{.colon}
  • sections (Compound{.hxr-hoverxref .hxr-tooltip .reference .internal} | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal} | Face{.hxr-hoverxref .hxr-tooltip .reference .internal} | Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- cross sections to sweep into object

  • path (Curve{.hxr-hoverxref .hxr-tooltip .reference .internal} | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- path to follow. Defaults to context pending_edges.

  • multisection (bool, optional) -- sweep multiple on path. Defaults to False.

  • is_frenet (bool, optional) -- use frenet algorithm. Defaults to False.

  • transition (Transition{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- discontinuity handling option. Defaults to Transition.TRANSFORMED.

  • normal (VectorLike, optional) -- fixed normal. Defaults to None.

  • binormal (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- guide rotation along path. Defaults to None.

  • clean (bool, optional) -- Remove extraneous internal structure. Defaults to True.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination. Defaults to Mode.ADD.

<!-- -->
[[thicken]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[to_thicken:]{.pre} [~build123d.topology.two_d.Face]{.pre} [|]{.pre} [~build123d.topology.composite.Sketch]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[amount:]{.pre} [float]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[normal_override:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, float{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, [[float]{.pre}]{.n}, float{.pre} [|]{.pre} [~collections.abc.Sequence[float]]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[both:]{.pre} [bool]{.pre} [=]{.pre} [False]{.pre}]{.n}, [[clean:]{.pre} [bool]{.pre} [=]{.pre} [True]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Part]{.pre}]{.sig-return-typehint}]{.sig-return}

Part Operation: thicken

Create a solid(s) from a potentially non planar face(s) by thickening along the normals.

Parameters[:]{.colon}
  • to_thicken (Union[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}, Sketch{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- object to thicken. Defaults to None.

  • amount (float) -- distance to extrude, sign controls direction.

  • normal_override (Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- The normal_override vector can be used to indicate which way is 'up', potentially flipping the face normal direction such that many faces with different normals all go in the same direction (direction need only be +/- 90 degrees from the face normal). Defaults to None.

  • both (bool, optional) -- thicken in both directions. Defaults to False.

  • clean (bool, optional) -- Remove extraneous internal structure. Defaults to True.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

Raises[:]{.colon}
  • ValueError -- No object to extrude

  • ValueError -- No target object

Returns[:]{.colon}

extruded object

Return type[:]{.colon}

Part{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[[trace]{.pre}]{.sig-name .descname}[(]{.sig-paren}lines:]{.pre} [~build123d.topology.composite.Curve]{.pre} [{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[line_width:]{.pre} [float]{.pre} [=]{.pre} [1]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Sketch]{.pre}]{.sig-return-typehint}]{.sig-return}

Sketch Operation: trace

Convert edges, wires or pending edges into faces by sweeping a perpendicular line along them.

Parameters[:]{.colon}
  • lines (Curve{.hxr-hoverxref .hxr-tooltip .reference .internal} | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal} | Iterable[Curve{.hxr-hoverxref .hxr-tooltip .reference .internal} | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]], optional) -- lines to trace. Defaults to sketch pending edges.

  • line_width (float, optional) -- Defaults to 1.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

Raises[:]{.colon}

ValueError -- No objects to trace

Returns[:]{.colon}

Traced lines

Return type[:]{.colon}

Sketch{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[[edge]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[self]{.pre}]{.n}, [[select:]{.pre} [~build123d.build_enums.Select]{.pre} [=]{.pre} [<Select.ALL>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}]{.sig-return-typehint}]{.sig-return}

Return Edge

Return an edge.

Parameters[:]{.colon}

select (Select{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Edge selector. Defaults to Select.ALL.

Returns[:]{.colon}

Edge extracted

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[[edges]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[self]{.pre}]{.n}, [[select:]{.pre} [~build123d.build_enums.Select]{.pre} [=]{.pre} [<Select.ALL>]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[ShapeList]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Return Edges

Return either all or the edges created during the last operation.

Parameters[:]{.colon}

select (Select{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Edge selector. Defaults to Select.ALL.

Returns[:]{.colon}

Edges extracted

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}]

<!-- -->
[[face]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[self]{.pre}]{.n}, [[select:]{.pre} [~build123d.build_enums.Select]{.pre} [=]{.pre} [<Select.ALL>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}]{.sig-return-typehint}]{.sig-return}

Return Face

Return a face.

Parameters[:]{.colon}

select (Select{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Face selector. Defaults to Select.ALL.

Returns[:]{.colon}

Face extracted

Return type[:]{.colon}

Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[[faces]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[self]{.pre}]{.n}, [[select:]{.pre} [~build123d.build_enums.Select]{.pre} [=]{.pre} [<Select.ALL>]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[ShapeList]{.pre}[[[]{.pre}]{.p}[Face]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Return Faces

Return either all or the faces created during the last operation.

Parameters[:]{.colon}

select (Select{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Face selector. Defaults to Select.ALL.

Returns[:]{.colon}

Faces extracted

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}]

<!-- -->
[[solid]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[self]{.pre}]{.n}, [[select:]{.pre} [~build123d.build_enums.Select]{.pre} [=]{.pre} [<Select.ALL>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}]{.sig-return-typehint}]{.sig-return}

Return Solid

Return a solid.

Parameters[:]{.colon}

select (Select{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Solid selector. Defaults to Select.ALL.

Returns[:]{.colon}

Solid extracted

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[[solids]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[self]{.pre}]{.n}, [[select:]{.pre} [~build123d.build_enums.Select]{.pre} [=]{.pre} [<Select.ALL>]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[ShapeList]{.pre}[[[]{.pre}]{.p}[Solid]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Return Solids

Return either all or the solids created during the last operation.

Parameters[:]{.colon}

select (Select{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Solid selector. Defaults to Select.ALL.

Returns[:]{.colon}

Solids extracted

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}]

<!-- -->
[[vertex]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[self]{.pre}]{.n}, [[select:]{.pre} [~build123d.build_enums.Select]{.pre} [=]{.pre} [<Select.ALL>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vertex]{.pre}]{.sig-return-typehint}]{.sig-return}

Return Vertex

Return a vertex.

Parameters[:]{.colon}

select (Select{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Vertex selector. Defaults to Select.ALL.

Returns[:]{.colon}

Vertex extracted

Return type[:]{.colon}

Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[[vertices]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[self]{.pre}]{.n}, [[select:]{.pre} [~build123d.build_enums.Select]{.pre} [=]{.pre} [<Select.ALL>]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[ShapeList]{.pre}[[[]{.pre}]{.p}[Vertex]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Return Vertices

Return either all or the vertices created during the last operation.

Parameters[:]{.colon}

select (Select{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Vertex selector. Defaults to Select.ALL.

Returns[:]{.colon}

Vertices extracted

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal}]

<!-- -->
[[wire]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[self]{.pre}]{.n}, [[select:]{.pre} [~build123d.build_enums.Select]{.pre} [=]{.pre} [<Select.ALL>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}]{.sig-return-typehint}]{.sig-return}

Return Wire

Return a wire.

Parameters[:]{.colon}

select (Select{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Wire selector. Defaults to Select.ALL.

Returns[:]{.colon}

Wire extracted

Return type[:]{.colon}

Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[[wires]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[self]{.pre}]{.n}, [[select:]{.pre} [~build123d.build_enums.Select]{.pre} [=]{.pre} [<Select.ALL>]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[ShapeList]{.pre}[[[]{.pre}]{.p}[Wire]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Return Wires

Return either all or the wires created during the last operation.

Parameters[:]{.colon}

select (Select{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Wire selector. Defaults to Select.ALL.

Returns[:]{.colon}

Wires extracted

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}] ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#topology_selection.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#topology_selection.xhtml#topology-selection-and-exploration .section}

Topology Selection and Exploration

[Topology]{.std .std-ref}{.reference .internal} is the structure of build123d geometric features and traversing the topology of a part is often required to specify objects for an operation or to locate a CAD feature. [Selectors]{.std .std-ref}{.reference .internal} allow selection of topology objects into a ShapeList{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}. [Operators]{.std .std-ref}{.reference .internal} are powerful methods further explore and refine a ShapeList{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} for subsequent operations.

::: {#topology_selection.xhtml#selectors .section} []{#topology_selection.xhtml#id1}

Selectors

Selectors provide methods to extract all or a subset of a feature type in the referenced object. These methods select Edges, Faces, Solids, Vertices, or Wires in Builder objects or from Shape objects themselves. All of these methods return a ShapeList{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, which is a subclass of list{.docutils .literal .notranslate} and may be sorted, grouped, or filtered by [Operators]{.std .std-ref}{.reference .internal}.

::: {#topology_selection.xhtml#overview .section}

Overview

Selector Criteria Applicability Description


vertices(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ALL, LAST BuildLine{.docutils .literal .notranslate}, BuildSketch{.docutils .literal .notranslate}, BuildPart{.docutils .literal .notranslate} Vertex{.docutils .literal .notranslate} extraction edges(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ALL, LAST, NEW BuildLine{.docutils .literal .notranslate}, BuildSketch{.docutils .literal .notranslate}, BuildPart{.docutils .literal .notranslate} Edge{.docutils .literal .notranslate} extraction wires(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ALL, LAST BuildLine{.docutils .literal .notranslate}, BuildSketch{.docutils .literal .notranslate}, BuildPart{.docutils .literal .notranslate} Wire{.docutils .literal .notranslate} extraction faces(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ALL, LAST BuildSketch{.docutils .literal .notranslate}, BuildPart{.docutils .literal .notranslate} Face{.docutils .literal .notranslate} extraction solids(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ALL, LAST BuildPart{.docutils .literal .notranslate} Solid{.docutils .literal .notranslate} extraction

Both shape objects and builder objects have access to selector methods to select all of a feature as long as they can contain the feature being selected.

::: {.highlight-build123d .notranslate} ::: highlight # In context with BuildSketch() as context: Rectangle(1, 1) context.edges()

    # Build context implicitly has access to the selector
    edges()

# Taking the sketch out of context
context.sketch.edges()

# Create sketch out of context
Rectangle(1, 1).edges()

::: ::: :::

::: {#topology_selection.xhtml#select-in-build-context .section}

Select In Build Context

Build contexts track the last operation and their selector methods can take Select{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} as criteria to specify a subset of features to extract. By default, a selector will select ALL{.docutils .literal .notranslate} of a feature, while LAST{.docutils .literal .notranslate} selects features created or altered by the most recent operation. edges(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} can uniquely specify NEW{.docutils .literal .notranslate} to only select edges created in the last operation which neither existed in the referenced object before the last operation, nor the modifying object.

::: {.admonition .important} Important

Select{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} as selector criteria is only valid for builder objects!

::: {.highlight-build123d .notranslate} ::: highlight # In context with BuildPart() as context: Box(2, 2, 1) Cylinder(1, 2) context.edges(Select.LAST)

# Does not work out of context!
context.part.edges(Select.LAST)
(Box(2, 2, 1) + Cylinder(1, 2)).edges(Select.LAST)

::: ::: :::

Create a simple part to demonstrate selectors. Select using the default criteria Select.ALL{.docutils .literal .notranslate}. Specifying Select.ALL{.docutils .literal .notranslate} for the selector is not required.

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as part: Box(5, 5, 1) Cylinder(1, 5)

    part.vertices()
    part.edges()
    part.faces()

    # Is the same as
    part.vertices(Select.ALL)
    part.edges(Select.ALL)
    part.faces(Select.ALL)

::: :::

[The default Select.ALL{.docutils .literal .notranslate} features]{.caption-text}

Select features changed in the last operation with criteria Select.LAST{.docutils .literal .notranslate}.

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as part: Box(5, 5, 1) Cylinder(1, 5)

    part.vertices(Select.LAST)
    part.edges(Select.LAST)
    part.faces(Select.LAST)

::: :::

[Select.LAST{.docutils .literal .notranslate} features]{.caption-text}

Select only new edges from the last operation with Select.NEW{.docutils .literal .notranslate}. This option is only available for a ShapeList{.docutils .literal .notranslate} of edges!

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as part: Box(5, 5, 1) Cylinder(1, 5)

    part.edges(Select.NEW)

::: :::

[Select.NEW{.docutils .literal .notranslate} edges where box and cylinder intersect]{.caption-text}

This only returns new edges which are not reused from Box or Cylinder, in this case where the objects <cite>{=html}intersect</cite>{=html}. But what happens if the objects don't intersect and all the edges are reused?

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as part: Box(5, 5, 1, align=(Align.CENTER, Align.CENTER, Align.MAX)) Cylinder(2, 2, align=(Align.CENTER, Align.CENTER, Align.MIN))

    part.edges(Select.NEW)

::: :::

[Select.NEW{.docutils .literal .notranslate} edges when box and cylinder don't intersect]{.caption-text}

No edges are selected! Unlike the previous example, the Edge between the Box and Cylinder objects is an edge reused from the Cylinder. Think of Select.NEW{.docutils .literal .notranslate} as a way to select only completely new edges created by the operation.

::: {.admonition .note} Note

Chamfer and fillet modify the current object, but do not have new edges via Select.NEW{.docutils .literal .notranslate}.

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as part: Box(5, 5, 1) Cylinder(1, 5) edges = part.edges().filter_by(lambda a: a.length == 1) fillet(edges, 1)

    part.edges(Select.NEW)

::: :::

[Left, Select.NEW{.docutils .literal .notranslate} returns no edges after fillet. Right, Select.LAST{.docutils .literal .notranslate}]{.caption-text} ::: :::

::: {#topology_selection.xhtml#select-new-edges-in-algebra-mode .section}

Select New Edges In Algebra Mode

The utility method new_edges{.docutils .literal .notranslate} compares one or more shape objects to a another "combined" shape object and returns the edges new to the combined shape. new_edges{.docutils .literal .notranslate} is available both Algebra mode or Builder mode, but is necessary in Algebra Mode where Select.NEW{.docutils .literal .notranslate} is unavailable

::: {.highlight-build123d .notranslate} ::: highlight box = Box(5, 5, 1) circle = Cylinder(2, 5) part = box + circle edges = new_edges(box, circle, combined=part) ::: :::

new_edges{.docutils .literal .notranslate} can also find edges created during a chamfer or fillet operation by comparing the object before the operation to the "combined" object.

::: {.highlight-build123d .notranslate} ::: highlight box = Box(5, 5, 1) circle = Cylinder(2, 5) part_before = box + circle edges = part_before.edges().filter_by(lambda a: a.length == 1) part = fillet(edges, 1) edges = new_edges(part_before, combined=part) ::: :::

::: :::

::: {#topology_selection.xhtml#operators .section} []{#topology_selection.xhtml#id2}

Operators

Operators provide methods refine a ShapeList{.docutils .literal .notranslate} of features isolated by a selector to further specify feature(s). These methods can sort, group, or filter ShapeList{.docutils .literal .notranslate} objects and return a modified ShapeList{.docutils .literal .notranslate}, or in the case of group_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, GroupBy{.docutils .literal .notranslate}, a list of ShapeList{.docutils .literal .notranslate} objects accessible by index or key.

::: {#topology_selection.xhtml#id3 .section}

Overview

Method Criteria Description


sort_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Axis{.docutils .literal .notranslate}, Edge{.docutils .literal .notranslate}, Wire{.docutils .literal .notranslate}, SortBy{.docutils .literal .notranslate}, callable, property Sort ShapeList{.docutils .literal .notranslate} by criteria sort_by_distance(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Shape{.docutils .literal .notranslate}, VectorLike{.docutils .literal .notranslate} Sort ShapeList{.docutils .literal .notranslate} by distance from criteria group_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Axis{.docutils .literal .notranslate}, Edge{.docutils .literal .notranslate}, Wire{.docutils .literal .notranslate}, SortBy{.docutils .literal .notranslate}, callable, property Group ShapeList{.docutils .literal .notranslate} by criteria filter_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Axis{.docutils .literal .notranslate}, Plane{.docutils .literal .notranslate}, GeomType{.docutils .literal .notranslate}, ShapePredicate{.docutils .literal .notranslate}, property Filter ShapeList{.docutils .literal .notranslate} by criteria filter_by_position(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Axis{.docutils .literal .notranslate} Filter ShapeList{.docutils .literal .notranslate} by Axis{.docutils .literal .notranslate} & mix / max values

Operator methods take criteria to refine ShapeList{.docutils .literal .notranslate}. Broadly speaking, the criteria fall into the following categories, though not all operators take all criteria:

  • Geometric objects: Axis{.docutils .literal .notranslate}, Plane{.docutils .literal .notranslate}

  • Topological objects: Edge{.docutils .literal .notranslate}, Wire{.docutils .literal .notranslate}

  • Enums: SortBy{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, GeomType{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}

  • Properties, eg: Face.area{.docutils .literal .notranslate}, Edge.length{.docutils .literal .notranslate}

  • ShapePredicate{.docutils .literal .notranslate}, eg: lambda e: e.is_interior == 1{.docutils .literal .notranslate}, lambda f: lf.edges() >= 3{.docutils .literal .notranslate}

  • Callable eg: Vertex().distance{.docutils .literal .notranslate} :::

::: {#topology_selection.xhtml#sort .section}

Sort

A ShapeList{.docutils .literal .notranslate} can be sorted with the sort_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and sort_by_distance(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} methods based on a sorting criteria. Sorting is a critical step when isolating individual features as a ShapeList{.docutils .literal .notranslate} from a selector is typically unordered.

Here we want to capture some vertices from the object furthest along X{.docutils .literal .notranslate}: All the vertices are first captured with the vertices(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} selector, then sort by Axis.X{.docutils .literal .notranslate}. Finally, the vertices can be captured with a list slice for the last 4 list items, as the items are sorted from least to greatest X{.docutils .literal .notranslate} position. Remember, ShapeList{.docutils .literal .notranslate} is a subclass of list{.docutils .literal .notranslate}, so any list slice can be used.

::: {.highlight-build123d .notranslate} ::: highlight part.vertices().sort_by(Axis.X)[-4:] ::: :::

::: line-block ::: line
::: :::

::: {#topology_selection.xhtml#examples .section}

Examples

::: {.toctree-wrapper .compound} :::

::: {.sd-container-fluid .sd-sphinx-override .sd-mb-4 .docutils} ::: {.sd-row .sd-row-cols-3 .sd-row-cols-xs-3 .sd-row-cols-sm-3 .sd-row-cols-md-3 .sd-row-cols-lg-3 .sd-g-3 .sd-g-xs-3 .sd-g-sm-3 .sd-g-md-3 .sd-g-lg-3 .docutils} ::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} SortBy ::: :::

[SortBy]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Along Wire ::: :::

[Along Wire]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Axis ::: :::

[Axis]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Distance From ::: :::

[Distance From]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: ::: ::: ::: ::: :::

::: {#topology_selection.xhtml#group .section}

Group

A ShapeList can be grouped and sorted with the group_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} method based on a grouping criteria. Grouping can be a great way to organize features without knowing the values of specific feature properties. Rather than returning a ShapeList{.docutils .literal .notranslate}, group_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} returns a GroupBy{.docutils .literal .notranslate}, a list of ShapeList{.docutils .literal .notranslate} objects sorted by the grouping criteria. GroupBy{.docutils .literal .notranslate} can be printed to view the members of each group, indexed like a list to retrieve a ShapeList{.docutils .literal .notranslate}, and be accessed using a key with the group{.docutils .literal .notranslate} method. If the group keys are unknown they can be discovered with key_to_group_index{.docutils .literal .notranslate}.

If we want only the edges from the smallest faces by area we can get the faces, then group by SortBy.AREA{.docutils .literal .notranslate}. The ShapeList{.docutils .literal .notranslate} of smallest faces is available from the first list index. Finally, a ShapeList{.docutils .literal .notranslate} has access to selectors, so calling edges(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} will return a new list of all edges in the previous list.

::: {.highlight-build123d .notranslate} ::: highlight part.faces().group_by(SortBy.AREA)[0].edges()) ::: :::

::: line-block ::: line
::: :::

::: {#topology_selection.xhtml#id4 .section}

Examples

::: {.toctree-wrapper .compound} :::

::: {.sd-container-fluid .sd-sphinx-override .sd-mb-4 .docutils} ::: {.sd-row .sd-row-cols-3 .sd-row-cols-xs-3 .sd-row-cols-sm-3 .sd-row-cols-md-3 .sd-row-cols-lg-3 .sd-g-3 .sd-g-xs-3 .sd-g-sm-3 .sd-g-md-3 .sd-g-lg-3 .docutils} ::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Axis and Length ::: :::

[Axis and Length]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Hole Area ::: :::

[Hole Area]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Properties with Keys ::: :::

[Properties with Keys]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: ::: ::: ::: ::: :::

::: {#topology_selection.xhtml#filter .section}

Filter

A ShapeList{.docutils .literal .notranslate} can be filtered with the filter_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and filter_by_position(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} methods based on a filtering criteria. Filters are flexible way to isolate (or exclude) features based on known criteria.

Lets say we need all the faces with a normal in the +Z{.docutils .literal .notranslate} direction. One way to do this might be with a list comprehension, however filter_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} has the capability to take a lambda function as a filter condition on the entire list. In this case, the normal of each face can be checked against a vector direction and filtered accordingly.

::: {.highlight-build123d .notranslate} ::: highlight part.faces().filter_by(lambda f: f.normal_at() == Vector(0, 0, 1)) ::: :::

::: line-block ::: line
::: :::

::: {#topology_selection.xhtml#id5 .section}

Examples

::: {.toctree-wrapper .compound} :::

::: {.sd-container-fluid .sd-sphinx-override .sd-mb-4 .docutils} ::: {.sd-row .sd-row-cols-3 .sd-row-cols-xs-3 .sd-row-cols-sm-3 .sd-row-cols-md-3 .sd-row-cols-lg-3 .sd-g-3 .sd-g-xs-3 .sd-g-sm-3 .sd-g-md-3 .sd-g-lg-3 .docutils} ::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} GeomType ::: :::

[GeomType]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} All Edges Circle ::: :::

[All Edges Circle]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Axis and Plane ::: :::

[Axis and Plane]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Inner Wire Count ::: :::

[Inner Wire Count]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Nested Filters ::: :::

[Nested Filters]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .sd-card-hover .docutils} {.sd-card-img-top}

::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Shape Properties ::: :::

[Shape Properties]{.std .std-ref}{.sd-stretched-link .sd-hide-link-text .reference .internal} ::: ::: ::: ::: ::: ::: ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#sort_examples.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#sort_examples.xhtml#sort-examples .section}

Sort Examples

::: {#sort_examples.xhtml#sortby .section} []{#sort_examples.xhtml#sort-sortby}

SortBy

SortBy{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} enums are shape property shorthands which work across Shape{.docutils .literal .notranslate} multiple object types. SortBy{.docutils .literal .notranslate} is a criteria for both sort_by{.docutils .literal .notranslate} and group_by{.docutils .literal .notranslate}.

  • SortBy.LENGTH{.docutils .literal .notranslate} works with Edge{.docutils .literal .notranslate}, Wire{.docutils .literal .notranslate}

  • SortBy.AREA{.docutils .literal .notranslate} works with Face{.docutils .literal .notranslate}, Solid{.docutils .literal .notranslate}

  • SortBy.VOLUME{.docutils .literal .notranslate} works with Solid{.docutils .literal .notranslate}

  • SortBy.RADIUS{.docutils .literal .notranslate} works with Edge{.docutils .literal .notranslate}, Face{.docutils .literal .notranslate} with GeomType{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} CIRCLE{.docutils .literal .notranslate}, CYLINDER{.docutils .literal .notranslate}, SPHERE{.docutils .literal .notranslate}

  • SortBy.DISTANCE{.docutils .literal .notranslate} works Vertex{.docutils .literal .notranslate}, Edge{.docutils .literal .notranslate}, Wire{.docutils .literal .notranslate}, Face{.docutils .literal .notranslate}, Solid{.docutils .literal .notranslate}

SortBy{.docutils .literal .notranslate} is often interchangeable with specific shape properties and can alternatively be used with``group_by``.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Setup]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import *

with BuildPart() as part:
    Box(5, 5, 1)
    Cylinder(2, 5)
    edges = part.edges().filter_by(lambda a: a.length == 1)
    fillet(edges, 1)

::: ::: :::

</details>

::: {.highlight-build123d .notranslate} ::: highlight part.wires().sort_by(SortBy.LENGTH)[:4]

part.wires().sort_by(Wire.length)[:4]
part.wires().group_by(SortBy.LENGTH)[0]

::: :::

::: line-block ::: line
::: :::

::: {.highlight-build123d .notranslate} ::: highlight part.vertices().sort_by(SortBy.DISTANCE)[-2:]

part.vertices().sort_by_distance(Vertex())[-2:]
part.vertices().group_by(Vertex().distance)[-1]

::: :::

::: line-block ::: line
::: ::: :::

::: {#sort_examples.xhtml#along-wire .section} []{#sort_examples.xhtml#sort-along-wire}

Along Wire

Vertices selected from an edge or wire might have a useful ordering when created from a single object, but when created from multiple objects, the ordering not useful. For example, when applying incrementing fillet radii to a list of vertices from the face, the order is random.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Setup]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import *

with BuildSketch() as along_wire:
    Rectangle(48, 16, align=Align.MIN)
    Rectangle(16, 48, align=Align.MIN)
    Rectangle(32, 32, align=Align.MIN)

::: ::: :::

</details>

::: {.highlight-build123d .notranslate} ::: highlight for i, v in enumerate(along_wire.vertices()): fillet(v, i + 1) ::: :::

::: line-block ::: line
::: :::

Vertices may be sorted along the wire they fall on to create order. Notice the fillet radii now increase in order.

::: {.highlight-build123d .notranslate} ::: highlight sorted_verts = along_wire.vertices().sort_by(along_wire.wire()) for i, v in enumerate(sorted_verts): fillet(v, i + 1) ::: :::

::: line-block ::: line
::: ::: :::

::: {#sort_examples.xhtml#axis .section} []{#sort_examples.xhtml#sort-axis}

Axis

Sorting by axis is often the most straightforward way to optimize selections. In this part we want to revolve the face at the end around an inside edge of the completed extrusion. First, the face to extrude can be found by sorting along x-axis and the revolution edge can be found sorting along y-axis.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Setup]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import *

with BuildPart() as part:
    with BuildSketch(Plane.YZ) as profile:
        with BuildLine():
            l1 = FilletPolyline((16, 0), (32, 0), (32, 25), radius=12)
            l2 = FilletPolyline((16, 4), (28, 4), (28, 15), radius=8)
            Line(l1 @ 0, l2 @ 0)
            Polyline(l1 @ 1, l1 @ 1 - Vector(2, 0), l2 @ 1 + Vector(2, 0), l2 @ 1)
        make_face()
    extrude(amount=34)

::: ::: :::

</details>

::: {.highlight-build123d .notranslate} ::: highlight face = part.faces().sort_by(Axis.X)[-1] edge = face.edges().sort_by(Axis.Y)[0] revolve(face, -Axis(edge), 90) ::: :::

::: line-block ::: line
::: ::: :::

::: {#sort_examples.xhtml#distance-from .section} []{#sort_examples.xhtml#sort-distance-from}

Distance From

A sort_by_distance{.docutils .literal .notranslate} can be used to sort objects by their distance from another object. Here we are sorting the boxes by distance from the origin, using an empty Vertex{.docutils .literal .notranslate} (at the origin) as the reference shape to find distance to.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Setup]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from itertools import product

from build123d import *
from ocp_vscode import *

boxes = ShapeList(
    Box(1, 1, 1).scale(0.75 if (i, j) == (1, 2) else 0.25).translate((i, j, 0))
    for i, j in product(range(-3, 4), repeat=2)
)

::: ::: :::

</details>

::: {.highlight-build123d .notranslate} ::: highlight boxes = boxes.sort_by_distance(Vertex()) show(*boxes, colors=ColorMap.listed(len(boxes))) ::: :::

::: line-block ::: line
::: :::

The example can be extended by first sorting the boxes by volume using the Solid{.docutils .literal .notranslate} property volume{.docutils .literal .notranslate}, and getting the last (largest) box. Then, the boxes sorted by their distance from the largest box.

::: {.highlight-build123d .notranslate} ::: highlight boxes = boxes.sort_by_distance(boxes.sort_by(Solid.volume).last) show(*boxes, colors=ColorMap.listed(len(boxes))) ::: :::

::: line-block ::: line
::: ::: ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#group_examples.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#group_examples.xhtml#group-examples .section}

Group Examples

::: {#group_examples.xhtml#axis-and-length .section} []{#group_examples.xhtml#group-axis}

Axis and Length

This heatsink component could use fillets on the ends of the fins on the long ends. One way to accomplish this is to filter by length, sort by axis, and slice the result knowing how many edges to expect.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Setup]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import *

with BuildPart() as fins:
    with GridLocations(4, 6, 4, 4):
        Box(2, 3, 10, align=(Align.CENTER, Align.CENTER, Align.MIN))

with BuildPart() as part:
    Box(34, 48, 5, align=(Align.CENTER, Align.CENTER, Align.MAX))
    with GridLocations(20, 27, 2, 2):
        add(fins)

::: ::: :::

</details>

::: line-block ::: line
::: :::

However, group_by{.docutils .literal .notranslate} can be used to first group all the edges by z-axis position and then group again by length. In both cases, you can select the desired edges from the last group.

::: {.highlight-build123d .notranslate} ::: highlight target = part.edges().group_by(Axis.Z)[-1].group_by(Edge.length)[-1] fillet(target, .75) ::: :::

::: line-block ::: line
::: ::: :::

::: {#group_examples.xhtml#hole-area .section} []{#group_examples.xhtml#group-hole-area}

Hole Area

Callables are available to group_by{.docutils .literal .notranslate}, like sort_by{.docutils .literal .notranslate}. Here, the first inner wire is converted to a face and then that area is the grouping criteria to find the faces with the largest hole.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Setup]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import *

with BuildPart() as part:
    Cylinder(10, 30, rotation=(90, 0, 0))
    Cylinder(8, 40, rotation=(90, 0, 0), align=(Align.CENTER, Align.CENTER, Align.MAX))
    Cylinder(8, 23, rotation=(90, 0, 0), align=(Align.CENTER, Align.CENTER, Align.MIN))
    Cylinder(5, 40, rotation=(90, 0, 0), align=(Align.CENTER, Align.CENTER, Align.MIN))
    with BuildSketch(Plane.XY.offset(8)) as s:
        SlotCenterPoint((0, 38), (0, 48), 5)
    extrude(amount=2.5, both=True, mode=Mode.SUBTRACT)

::: ::: :::

</details>

::: {.highlight-build123d .notranslate} ::: highlight faces = part.faces().group_by( lambda f: Face(f.inner_wires()[0]).area if f.inner_wires() else 0 ) chamfer([f.outer_wire().edges() for f in faces[-1]], 0.5) ::: :::

::: line-block ::: line
::: ::: :::

::: {#group_examples.xhtml#properties-with-keys .section} []{#group_examples.xhtml#group-properties-with-keys}

Properties with Keys

Groups are usually selected by list slice, often smallest [0]{.docutils .literal .notranslate} or largest [-1]{.docutils .literal .notranslate}, but they can also be selected by key with the group{.docutils .literal .notranslate} method if the keys are known. Starting with an incomplete bearing block we are looking to add fillets to the ribs and corners. We know the edge lengths so the edges can be grouped by Edge.Length{.docutils .literal .notranslate} and then the desired groups are selected with the group{.docutils .literal .notranslate} method using the lengths as keys.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Setup]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import *

with BuildPart() as part:
    with BuildSketch(Plane.XZ) as sketch:
        with BuildLine():
            CenterArc((-6, 12), 10, 0, 360)
            Line((-16, 0), (16, 0))
        make_hull()
        Rectangle(50, 5, align=(Align.CENTER, Align.MAX))

    extrude(amount=12)

    Box(38, 6, 22, align=(Align.CENTER, Align.MAX, Align.MIN), mode=Mode.SUBTRACT)

    circle = part.edges().filter_by(GeomType.CIRCLE).sort_by(Axis.Y)[0]
    with Locations(Plane(circle.arc_center, z_dir=circle.normal())):
        CounterBoreHole(13 / 2, 16 / 2, 4)

    mirror(about=Plane.XZ)

::: ::: :::

</details>

::: {.highlight-build123d .notranslate} ::: highlight length_groups = part.edges().group_by(Edge.length) fillet(length_groups.group(6) + length_groups.group(5), 4) ::: :::

::: line-block ::: line
::: :::

Next, we add alignment pin and counterbore holes after the fillets to make sure screw heads sit flush where they overlap the fillet. Once that is done, it's time to finalize the tight-tolerance bearing and pin holes with chamfers to make installation easier. We can filter by GeomType.CIRCLE{.docutils .literal .notranslate} and group by Edge.radius{.docutils .literal .notranslate} to group the circular edges. Again, the radii are known, so we can retrieve those groups directly and then further specify only the edges the bearings and pins are installed from.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Adding holes]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight with BuildSketch() as pins: with Locations((-21, 0)): Circle(3 / 2) with Locations((21, 0)): SlotCenterToCenter(1, 3) extrude(amount=-12, mode=Mode.SUBTRACT)

    with GridLocations(42, 16, 2, 2):
        CounterBoreHole(3.5 / 2, 3.5, 0)

::: ::: :::

</details>

::: {.highlight-build123d .notranslate} ::: highlight radius_groups = part.edges().filter_by(GeomType.CIRCLE).group_by(Edge.radius) bearing_edges = radius_groups.group(8).group_by(SortBy.DISTANCE)[-1] pin_edges = radius_groups.group(1.5).filter_by_position(Axis.Z, -5, -5) chamfer([pin_edges, bearing_edges], .5) ::: :::

::: line-block ::: line
::: :::

Note that group_by{.docutils .literal .notranslate} is not the only way to capture edges with a known property value! filter_by{.docutils .literal .notranslate} with a lambda expression can be used as well:

::: {.highlight-build123d .notranslate} ::: highlight radius_groups = part.edges().filter_by(GeomType.CIRCLE) bearing_edges = radius_groups.filter_by(lambda e: e.radius == 8) pin_edges = radius_groups.filter_by(lambda e: e.radius == 1.5) ::: ::: ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#filter_examples.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#filter_examples.xhtml#filter-examples .section}

Filter Examples

::: {#filter_examples.xhtml#geomtype .section} []{#filter_examples.xhtml#filter-geomtype}

GeomType

GeomType{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} enums are shape type shorthands for Edge{.docutils .literal .notranslate} and Face{.docutils .literal .notranslate} objects. They are most helpful for filtering objects of that specific type for further operations, and are sometimes necessary e.g. before sorting or filtering by radius. Edge{.docutils .literal .notranslate} and Face{.docutils .literal .notranslate} each support a subset of GeomType{.docutils .literal .notranslate}:

  • Edge{.docutils .literal .notranslate} can be type LINE{.docutils .literal .notranslate}, CIRCLE{.docutils .literal .notranslate}, ELLIPSE{.docutils .literal .notranslate}, HYPERBOLA{.docutils .literal .notranslate}, PARABOLA{.docutils .literal .notranslate}, BEZIER{.docutils .literal .notranslate}, BSPLINE{.docutils .literal .notranslate}, OFFSET{.docutils .literal .notranslate}, OTHER{.docutils .literal .notranslate}

  • Face{.docutils .literal .notranslate} can be type PLANE{.docutils .literal .notranslate}, CYLINDER{.docutils .literal .notranslate}, CONE{.docutils .literal .notranslate}, SPHERE{.docutils .literal .notranslate}, TORUS{.docutils .literal .notranslate}, BEZIER{.docutils .literal .notranslate}, BSPLINE{.docutils .literal .notranslate}, REVOLUTION{.docutils .literal .notranslate}, EXTRUSION{.docutils .literal .notranslate}, OFFSET{.docutils .literal .notranslate}, OTHER{.docutils .literal .notranslate}

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Setup]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import *

with BuildPart() as part:
    Box(5, 5, 1)
    Cylinder(2, 5)
    edges = part.edges().filter_by(lambda a: a.length == 1)
    fillet(edges, 1)

::: ::: :::

</details>

::: {.highlight-build123d .notranslate} ::: highlight part.edges().filter_by(GeomType.LINE) ::: :::

::: line-block ::: line
::: :::

::: {.highlight-build123d .notranslate} ::: highlight part.faces().filter_by(GeomType.CYLINDER) ::: :::

::: line-block ::: line
::: ::: :::

::: {#filter_examples.xhtml#all-edges-circle .section} []{#filter_examples.xhtml#filter-all-edges-circle}

All Edges Circle

In this complete bearing block, we want to add joints for the bearings. These should be located in the counterbore recess. One way to locate the joints is by finding faces with centers located where the joints need to be located. Filtering for faces with only circular edges selects the counterbore faces that meet the joint criteria.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Setup]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import *

with BuildPart() as part:
    with BuildSketch() as s:
        Rectangle(115, 50)
        with Locations((5 / 2, 0)):
            SlotOverall(90, 12, mode=Mode.SUBTRACT)
    extrude(amount=15)

    with BuildSketch(Plane.XZ.offset(50 / 2)) as s3:
        with Locations((-115 / 2 + 26, 15)):
            SlotOverall(42 + 2 * 26 + 12, 2 * 26, rotation=90)
    zz = extrude(amount=-12)
    split(bisect_by=Plane.XY)
    edgs = part.part.edges().filter_by(Axis.Y).group_by(Axis.X)[-2]
    fillet(edgs, 9)

    with Locations(zz.faces().sort_by(Axis.Y)[0]):
        with Locations((42 / 2 + 6, 0)):
            CounterBoreHole(24 / 2, 34 / 2, 4)
    mirror(about=Plane.XZ)

    with BuildSketch() as s4:
        RectangleRounded(115, 50, 6)
    extrude(amount=80, mode=Mode.INTERSECT)
    # fillet does not work right, mode intersect is safer

    with BuildSketch(Plane.YZ) as s4:
        with BuildLine() as bl:
            l1 = Line((0, 0), (18 / 2, 0))
            l2 = PolarLine(l1 @ 1, 8, 60, length_mode=LengthMode.VERTICAL)
            l3 = Line(l2 @ 1, (0, 8))
            mirror(about=Plane.YZ)
        make_face()
    extrude(amount=115 / 2, both=True, mode=Mode.SUBTRACT)

::: ::: :::

</details>

::: {.highlight-build123d .notranslate} ::: highlight faces = part.faces().filter_by( lambda f: all(e.geom_type == GeomType.CIRCLE for e in f.edges()) ) for i, f in enumerate(faces): RigidJoint(f"bearing_bore_{i}", joint_location=f.center_location) ::: :::

::: line-block ::: line
::: ::: :::

::: {#filter_examples.xhtml#axis-and-plane .section} []{#filter_examples.xhtml#filter-axis-plane}

Axis and Plane

Filtering by an Axis will select faces perpendicular to the axis. Likewise filtering by Plane will select faces parallel to the plane.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Setup]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import *

with BuildPart() as part:
    Box(1, 1, 1)

::: ::: :::

</details>

::: {.highlight-build123d .notranslate} ::: highlight part.faces().filter_by(Axis.Z) part.faces().filter_by(Plane.XY) ::: :::

::: line-block ::: line
::: :::

It might be useful to filter by an Axis or Plane in other ways. A lambda can be used to accomplish this with feature properties or methods. Here, we are looking for faces where the dot product of face normal and either the axis direction or the plane normal is about to 0. The result is faces parallel to the axis or perpendicular to the plane.

::: {.highlight-build123d .notranslate} ::: highlight part.faces().filter_by(lambda f: abs(f.normal_at().dot(Axis.Z.direction) < 1e-6) part.faces().filter_by(lambda f: abs(f.normal_at().dot(Plane.XY.z_dir)) < 1e-6) ::: :::

::: line-block ::: line
::: ::: :::

::: {#filter_examples.xhtml#inner-wire-count .section} []{#filter_examples.xhtml#filter-inner-wire-count}

Inner Wire Count

This motor bracket imported from a step file needs joints for adding to an assembly. Joints for the M3 clearance holes were already found by using the cylindrical face's axis of rotation, but the motor bore and slots need specific placement. The motor bore can be found by filtering for faces with 5 inner wires, sorting for the desired face, and then filtering for the specific inner wire by radius.

  • bracket STEP model: nema-17-bracket.step{.xref .download .docutils .literal .notranslate}
<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Setup]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import *

bracket = import_step(os.path.join(working_path, "nema-17-bracket.step"))
faces = bracket.faces()

motor_mounts = faces.filter_by(GeomType.CYLINDER).filter_by(lambda f: f.radius == 3.3/2)
for i, f in enumerate(motor_mounts):
    location = f.axis_of_rotation.location
    RigidJoint(f"motor_m3_{i}", bracket, joint_location=location)

::: ::: :::

</details>

::: {.highlight-build123d .notranslate} ::: highlight motor_face = faces.filter_by(lambda f: len(f.inner_wires()) == 5).sort_by(Axis.X)[-1] motor_bore = motor_face.inner_wires().edges().filter_by(lambda e: e.radius == 16).edge() location = Location(motor_bore.arc_center, motor_bore.normal() * 90, Intrinsic.YXZ) RigidJoint(f"motor", bracket, joint_location=location) ::: :::

::: line-block ::: line
::: :::

Linear joints for the slots are appropriate for mating flexibility, but require more than a single location. The slot arc centers can be used for creating a linear joint axis and range. To do that we can filter for faces with 6 inner wires, sort for and select the top face, and then filter for the circular edges of the inner wires.

::: {.highlight-build123d .notranslate} ::: highlight mount_face = faces.filter_by(lambda f: len(f.inner_wires()) == 6).sort_by(Axis.Z)[-1] mount_slots = mount_face.inner_wires().edges().filter_by(GeomType.CIRCLE) joint_edges = [ Line(mount_slots[i].arc_center, mount_slots[i + 1].arc_center) for i in range(0, len(mount_slots), 2) ] for i, e in enumerate(joint_edges): LinearJoint(f"mount_m4_{i}", bracket, axis=Axis(e), linear_range=(0, e.length / 2)) ::: :::

::: line-block ::: line
::: ::: :::

::: {#filter_examples.xhtml#nested-filters .section} []{#filter_examples.xhtml#filter-nested}

Nested Filters

Filters can be nested to specify features by characteristics other than their own, like child properties. Here we want to chamfer the mating edges of the D bore and square shaft. A way to do this is first looking for faces with only 2 line edges among the inner wires. The nested filter captures the straight edges, while the parent filter selects faces based on the count. Then, from those faces, we filter for the wires with any line edges.

<details class="sd-sphinx-override sd-dropdown sd-card sd-mb-3">
<summary class="sd-summary-title sd-card-header">

[Setup]{.sd-summary-text}

<span class="sd-summary-state-marker sd-summary-chevron-right">
<svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewbox="0 0 24 24" aria-hidden="true">

<path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z">{=html}</path>{=html}

</svg>

</span>{=html}

</summary>

::: {.sd-summary-content .sd-card-body .docutils} ::: {.highlight-build123d .notranslate} ::: highlight from build123d import *

with BuildPart() as part:
    Cylinder(15, 2, align=(Align.CENTER, Align.CENTER, Align.MIN))
    with BuildSketch():
        RectangleRounded(10, 10, 2.5)
    extrude(amount=15)

    with BuildSketch():
        Circle(2.5)
        Rectangle(4, 5, mode=Mode.INTERSECT)
    extrude(amount=15, mode=Mode.SUBTRACT)

    with GridLocations(20, 0, 2, 1):
        Hole(3.5 / 2)

::: ::: :::

</details>

::: {.highlight-build123d .notranslate} ::: highlight faces = part.faces().filter_by( lambda f: len(f.inner_wires().edges().filter_by(GeomType.LINE)) == 2 ) wires = faces.wires().filter_by( lambda w: any(e.geom_type == GeomType.LINE for e in w.edges()) ) chamfer(wires.edges(), 0.5) ::: :::

::: line-block ::: line
::: ::: :::

::: {#filter_examples.xhtml#shape-properties .section} []{#filter_examples.xhtml#filter-shape-properties}

Shape Properties

Selected features can be quickly filtered by feature properties. First, we filter by interior and exterior edges using the Edge{.docutils .literal .notranslate} is interior{.docutils .literal .notranslate} property to apply different fillets accordingly. Then the Face{.docutils .literal .notranslate} is_circular_*{.docutils .literal .notranslate} properties are used to highlight the resulting fillets.

::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import *

with BuildPart() as open_box_builder:
    Box(20, 20, 5)
    offset(amount=-2, openings=open_box_builder.faces().sort_by(Axis.Z)[-1])
    inside_edges = open_box_builder.edges().filter_by(Edge.is_interior)
    fillet(inside_edges, 1.5)
    outside_edges = open_box_builder.edges().filter_by(Edge.is_interior, reverse=True)
    fillet(outside_edges, 0.5)

open_box = open_box_builder.part
open_box.color = Color(0xEDAE49)
outside_fillets = Compound(open_box.faces().filter_by(Face.is_circular_convex))
outside_fillets.color = Color(0xD1495B)
inside_fillets = Compound(open_box.faces().filter_by(Face.is_circular_concave))
inside_fillets.color = Color(0x00798C)

::: :::

::: line-block ::: line
::: ::: ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#builders.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#builders.xhtml#builders .section}

Builders

The following sections describe each of the build123d stateful context builders.

::: {.toctree-wrapper .compound}

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#build_line.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#build_line.xhtml#buildline .section}

BuildLine

BuildLine is a python context manager that is used to create one dimensional objects - objects with the property of length but not area - that are typically used as part of a BuildSketch sketch or a BuildPart path.

The complete API for BuildLine is located at the end of this section.

::: {#build_line.xhtml#basic-functionality .section}

Basic Functionality

The following is a simple BuildLine example:

::: {.highlight-build123d .notranslate} ::: highlight with BuildLine() as example_1: Line((0, 0), (2, 0)) ThreePointArc((0, 0), (1, 1), (2, 0)) ::: :::

The with{.docutils .literal .notranslate} statement creates the BuildLine{.docutils .literal .notranslate} context manager with the identifier example_1{.docutils .literal .notranslate}. The objects and operations that are within the scope (i.e. indented) of this context will contribute towards the object being created by the context manager. For BuildLine{.docutils .literal .notranslate}, this object is line{.docutils .literal .notranslate} and it's referenced as example_1.line{.docutils .literal .notranslate}.

The first object in this example is a Line{.docutils .literal .notranslate} object which is used to create a straight line from coordinates (0,0) to (2,0) on the default XY plane. The second object is a ThreePointArc{.docutils .literal .notranslate} that starts and ends at the two ends of the line.

{.align-center} :::

::: {#build_line.xhtml#constraints .section}

Constraints

Building with constraints enables the designer to capture design intent and add a high degree of robustness to their designs. The following sections describe creating positional and tangential constraints as well as using object attributes to enable this type of design.

::: {#build_line.xhtml#position-at-operator .section}

@ position_at{.docutils .literal .notranslate} Operator

In the previous example, the ThreePointArc{.docutils .literal .notranslate} started and ended at the two ends of the Line{.docutils .literal .notranslate} but this was done by referring to the same point (0,0){.docutils .literal .notranslate} and (2,0){.docutils .literal .notranslate}. This can be improved upon by specifying constraints that lock the arc to those two end points, as follows:

::: {.highlight-build123d .notranslate} ::: highlight with BuildLine() as example_2: l1 = Line((0, 0), (2, 0)) l2 = ThreePointArc(l1 @ 0, (1, 1), l1 @ 1) ::: :::

Here instance variables l1{.docutils .literal .notranslate} and l2{.docutils .literal .notranslate} are assigned to the two BuildLine objects and the ThreePointArc{.docutils .literal .notranslate} references the beginning of the straight line with l1 @ 0{.docutils .literal .notranslate} and the end with l1 @ 1{.docutils .literal .notranslate}. The @{.docutils .literal .notranslate} operator takes a float (or integer) parameter between 0 and 1 and determines a position at this fractional position along the line's length.

This example can be improved on further by calculating the mid-point of the arc as follows:

::: {.highlight-build123d .notranslate} ::: highlight with BuildLine() as example_3: l1 = Line((0, 0), (2, 0)) l2 = ThreePointArc(l1 @ 0, l1 @ 0.5 + (0, 1), l1 @ 1) ::: :::

Here l1 @ 0.5{.docutils .literal .notranslate} finds the center of l1{.docutils .literal .notranslate} while l1 @ 0.5 + (0, 1){.docutils .literal .notranslate} does a vector addition to generate the point (1,1){.docutils .literal .notranslate}.

To make the design even more parametric, the height of the arc can be calculated from l1{.docutils .literal .notranslate} as follows:

::: {.highlight-build123d .notranslate} ::: highlight with BuildLine() as example_4: l1 = Line((0, 0), (2, 0)) l2 = ThreePointArc(l1 @ 0, l1 @ 0.5 + (0, l1.length / 2), l1 @ 1) ::: :::

The arc height is now calculated as (0, l1.length / 2){.docutils .literal .notranslate} by using the length{.docutils .literal .notranslate} property of Edge{.docutils .literal .notranslate} and Wire{.docutils .literal .notranslate} shapes. At this point the ThreePointArc{.docutils .literal .notranslate} is fully parametric and able to generate the same shape for any horizontal line. :::

::: {#build_line.xhtml#tangent-at-operator .section}

% tangent_at{.docutils .literal .notranslate} Operator

The other operator that is commonly used within BuildLine is %{.docutils .literal .notranslate} the tangent at operator. Here is another example:

::: {.highlight-build123d .notranslate} ::: highlight with BuildLine() as example_5: l1 = Line((0, 0), (5, 0)) l2 = Line(l1 @ 1, l1 @ 1 + (0, l1.length - 1)) l3 = JernArc(start=l2 @ 1, tangent=l2 % 1, radius=0.5, arc_size=90) l4 = Line(l3 @ 1, (0, l2.length + l3.radius)) ::: :::

which generates (note that the circles show line junctions):

{.align-center}

The JernArc{.docutils .literal .notranslate} has the following parameters:

  • start=l2 @ 1{.docutils .literal .notranslate} - start the arc at the end of line l2{.docutils .literal .notranslate},

  • tangent=l2 % 1{.docutils .literal .notranslate} - the tangent of the arc at the start point is equal to the l2{.docutils .literal .notranslate}'s, tangent at its end (shown as a dashed line)

  • radius=0.5{.docutils .literal .notranslate} - the radius of the arc, and

  • arc_size=90{.docutils .literal .notranslate} the angular size of the arc.

The final line starts at the end of l3{.docutils .literal .notranslate} and ends at a point calculated from the length of l2{.docutils .literal .notranslate} and the radius of arc l3{.docutils .literal .notranslate}.

Building with constraints as shown here will ensure that your designs both fully represent design intent and are robust to design changes. ::: :::

::: {#build_line.xhtml#buildline-to-buildsketch .section}

BuildLine to BuildSketch

As mentioned previously, one of the two primary reasons to create BuildLine objects is to use them in BuildSketch. When a BuildLine context manager exits and is within the scope of a BuildSketch context manager it will transfer the generated line to BuildSketch. The BuildSketch make_face(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} or make_hull(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} operations are then used to transform the line (specifically a list of Edges) into a Face - the native BuildSketch objects.

Here is an example of using BuildLine to create an object that otherwise might be difficult to create:

::: {.highlight-build123d .notranslate} ::: highlight with BuildSketch() as example_6: with BuildLine() as club_outline: l0 = Line((0, -188), (76, -188)) b0 = Bezier(l0 @ 1, (61, -185), (33, -173), (17, -81)) b1 = Bezier(b0 @ 1, (49, -128), (146, -145), (167, -67)) b2 = Bezier(b1 @ 1, (187, 9), (94, 52), (32, 18)) b3 = Bezier(b2 @ 1, (92, 57), (113, 188), (0, 188)) mirror(about=Plane.YZ) make_face() ::: :::

which generates:

{.align-center}

::: {.admonition .note} Note

SVG import to BuildLine

The BuildLine code used in this example was generated by translating a SVG file into BuildLine source code with the import_svg_as_buildline_code(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} function. For example:

::: {.highlight-default .notranslate} ::: highlight svg_code, builder_name = import_svg_as_buildline_code("club.svg") ::: :::

would translate the "club.svg" image file's paths into BuildLine code much like that shown above. From there it's easy for a user to add constraints or otherwise enhance the original image and use it in their design. ::: :::

::: {#build_line.xhtml#buildline-to-buildpart .section}

BuildLine to BuildPart

The other primary reasons to use BuildLine is to create paths for BuildPart sweep(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} operations. Here some curved and straight segments define a path:

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as example_7: with BuildLine() as example_7_path: l1 = RadiusArc((0, 0), (1, 1), 2) l2 = Spline(l1 @ 1, (2, 3), (3, 3), tangents=(l1 % 1, (0, -1))) l3 = Line(l2 @ 1, (3, 0)) with BuildSketch(Plane(origin=l1 @ 0, z_dir=l1 % 0)) as example_7_section: Circle(0.1) sweep() ::: :::

which generates:

{.align-center}

There are few things to note from this example:

  • The @ and % operators are used to create a plane normal to the beginning of the path with which to create the circular section used by the sweep operation (this plane is not one of the ordinal planes).

  • Both the path generated by BuildLine and the section generated by BuildSketch have been transferred to BuildPart when each of them exit.

  • The BuildPart Sweep{.docutils .literal .notranslate} operation is using the path and section previously transferred to it (as "pending" objects) as parameters of the sweep. The Sweep{.docutils .literal .notranslate} operation "consumes" these pending objects as to not interfere with subsequence operations. :::

::: {#build_line.xhtml#working-on-other-planes .section}

Working on other Planes

So far all of the examples were created on Plane.XY{.docutils .literal .notranslate} - the default plane - which is equivalent to global coordinates. Sometimes it's convenient to work on another plane, especially when creating paths for BuildPart Sweep{.docutils .literal .notranslate} operations.

::: {.highlight-build123d .notranslate} ::: highlight with BuildLine(Plane.YZ) as example_8: l1 = Line((0, 0), (5, 0)) l2 = Line(l1 @ 1, l1 @ 1 + (0, l1.length - 1)) l3 = JernArc(start=l2 @ 1, tangent=l2 % 1, radius=0.5, arc_size=90) l4 = Line(l3 @ 1, (0, l2.length + l3.radius)) ::: :::

which generates:

{.align-center}

Here the BuildLine object is created on Plane.YZ{.docutils .literal .notranslate} just by specifying the working plane during BuildLine initialization.

There are three rules to keep in mind when working with alternate planes in BuildLine:

  1. BuildLine{.docutils .literal .notranslate} accepts a single Plane{.docutils .literal .notranslate} to work with as opposed to other Builders that accept more than one workplane.

  2. Values entered as tuples such as (1, 2){.docutils .literal .notranslate} or (1, 2, 3){.docutils .literal .notranslate} will be localized to the current workplane. This rule applies to points and to the use of tuples to modify locations calculated with the @{.docutils .literal .notranslate} and %{.docutils .literal .notranslate} operators such as l1 @ 1 + (1, 1){.docutils .literal .notranslate}. For example, if the workplane is Plane.YZ{.docutils .literal .notranslate} the local value of (1, 2){.docutils .literal .notranslate} would be converted to (0, 1, 2){.docutils .literal .notranslate} in global coordinates. Three tuples are converted as well - (1, 2, 3){.docutils .literal .notranslate} on Plane.YZ{.docutils .literal .notranslate} would be (3, 1, 2){.docutils .literal .notranslate} in global coordinates. Providing values in local coordinates allows the designer to automate such conversions.

  3. Values entered using the Vector{.docutils .literal .notranslate} class or those generated by the @{.docutils .literal .notranslate} operator are considered global values and are not localized. For example: Line(Vector(1, 2, 3), Vector(4, 5, 6)){.docutils .literal .notranslate} will generate the same line independent of the current workplane. It's unlikely that users will need to use Vector{.docutils .literal .notranslate} values but the option is there.

Finally, BuildLine's workplane need not be one of the predefined ordinal planes, it could be one created from a surface of a BuildPart part that is currently under construction. :::

::: {#build_line.xhtml#module-build_line .section} []{#build_line.xhtml#reference}

Reference

[class]{.pre}[ ]{.w}[[BuildLine]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[workplane:]{.pre} [~build123d.topology.two_d.Face]{.pre} [|]{.pre} [~build123d.geometry.Plane]{.pre} [|]{.pre} [~build123d.geometry.Location]{.pre} [=]{.pre} [Plane(o=(0.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[x=(1.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[z=(0.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[1.00))]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

The BuildLine class is a subclass of Builder for building lines (objects with length but not area or volume). It has an _obj property that returns the current line being built. The class overrides the faces and solids methods of Builder since they don't apply to lines.

BuildLine only works with a single workplane which is used to convert tuples as inputs to global coordinates. For example:

::: {.highlight-default .notranslate} ::: highlight with BuildLine(Plane.YZ) as radius_arc: RadiusArc((1, 2), (2, 1), 1) ::: :::

creates an arc from global points (0, 1, 2) to (0, 2, 1). Note that points entered as Vector(x, y, z) are considered global and are not localized.

The workplane is also used to define planes parallel to the workplane that arcs are created on.

Parameters[:]{.colon}
  • workplane (Union[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}, Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, Location{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- plane used when local coordinates are used and when creating arcs. Defaults to Plane.XY.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

[[face]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}[)]{.sig-paren}

face() not implemented

[[faces]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}[)]{.sig-paren}

faces() not implemented

[property]{.pre}[ ]{.w}[[line]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Curve]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}

Get the current line

[[solid]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}[)]{.sig-paren}

solid() not implemented

[[solids]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}[)]{.sig-paren}

solids() not implemented ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#build_sketch.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#build_sketch.xhtml#buildsketch .section}

BuildSketch

BuildSketch is a python context manager that is used to create planar two dimensional objects - objects with the property of area but not volume - that are typically used as profiles for BuildPart operations like extrude(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} or revolve(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}.

The complete API for BuildSketch is located at the end of this section.

::: {#build_sketch.xhtml#basic-functionality .section}

Basic Functionality

The following is a simple BuildSketch example:

::: {.highlight-build123d .notranslate} ::: highlight length, radius = 40.0, 60.0

with BuildSketch() as circle_with_hole:
    Circle(radius=radius)
    Rectangle(width=length, height=length, mode=Mode.SUBTRACT)

::: :::

The with{.docutils .literal .notranslate} statement creates the BuildSketch{.docutils .literal .notranslate} context manager with the identifier circle_with_hole{.docutils .literal .notranslate}. The objects and operations that are within the scope (i.e. indented) of this context will contribute towards the object being created by the context manager. For BuildSketch{.docutils .literal .notranslate}, this object is sketch{.docutils .literal .notranslate} and it's referenced as circle_with_hole.sketch{.docutils .literal .notranslate}.

The first object in this example is a Circle{.docutils .literal .notranslate} object which is used to create a filled circular shape on the default XY plane. The second object is a Rectangle{.docutils .literal .notranslate} that is subtracted from the circle as directed by the mode=Mode.SUBTRACT{.docutils .literal .notranslate} parameter. A key aspect of sketch objects is that they are all filled shapes and not just a shape perimeter which enables combining subsequent shapes with different modes (the valid values of Mode are ADD{.docutils .literal .notranslate}, SUBTRACT{.docutils .literal .notranslate}, INTERSECT{.docutils .literal .notranslate}, REPLACE{.docutils .literal .notranslate}, and PRIVATE{.docutils .literal .notranslate}).

{.align-center} :::

::: {#build_sketch.xhtml#sketching-on-other-planes .section} []{#build_sketch.xhtml#id1}

Sketching on other Planes

Often when designing parts one needs to build on top of other features. To facilitate doing this BuildSketch{.docutils .literal .notranslate} allows one to create sketches on any Plane while allowing the designer to work in a local X, Y coordinate system. It might be helpful to think of what is happening with this metaphor:

  1. When instantiating BuildSketch{.docutils .literal .notranslate} one or more workplanes can be passed as parameters. These are the placement targets for the completed sketch.

  2. The designer draws on a flat "drafting table" which is Plane.XY{.docutils .literal .notranslate}.

  3. Once the sketch is complete, it's applied like a sticker to all of the workplanes passed in step 1.

As an example, let's build the following simple control box with a display on an angled plane:

{.align-center}

Here is the code:

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as controller: # Create the side view of the controller with BuildSketch(Plane.YZ) as profile: with BuildLine(): Polyline((0, 0), (0, 40), (20, 80), (40, 80), (40, 0), (0, 0)) # Create a filled face from the perimeter drawing make_face() # Extrude to create the basis controller shape extrude(amount=30, both=True) # Round off all the edges fillet(controller.edges(), radius=3) # Hollow out the controller offset(amount=-1, mode=Mode.SUBTRACT) # Extract the face that will house the display display_face = ( controller.faces() .filter_by(GeomType.PLANE) .filter_by_position(Axis.Z, 50, 70)[0] ) # Create a workplane from the face display_workplane = Plane( origin=display_face.center(), x_dir=(1, 0, 0), z_dir=display_face.normal_at() ) # Place the sketch directly on the controller with BuildSketch(display_workplane) as display: RectangleRounded(40, 30, 2) with GridLocations(45, 35, 2, 2): Circle(1) # Cut the display sketch through the controller extrude(amount=-1, mode=Mode.SUBTRACT) ::: :::

The highlighted part of the code shows how a face is extracted from the design, a workplane is constructed from this face and finally this workplane is passed to BuildSketch{.docutils .literal .notranslate} as the target for the complete sketch. Notice how the display{.docutils .literal .notranslate} sketch uses local coordinates for its features thus avoiding having the user to determine how to move and rotate the sketch to get it where it should go.

Note that BuildSketch{.docutils .literal .notranslate} accepts a sequence planes, faces and locations for workplanes so creation of an explicit workplane is often not required. Being able to work on multiple workplanes at once allows for features to be created on multiple side of an object - say both the top and bottom - which is convenient for symmetric parts. :::

::: {#build_sketch.xhtml#local-vs-global-sketches .section}

Local vs. Global Sketches

In the above example the target for the sketch was not Plane.XY{.docutils .literal .notranslate} but a workplane passed by the user. Internally BuildSketch{.docutils .literal .notranslate} is always creating the sketch on Plane.XY{.docutils .literal .notranslate} which one can see by looking at the sketch_local{.docutils .literal .notranslate} property of your sketch. For example, to display the local version of the display{.docutils .literal .notranslate} sketch from above, one would use:

::: {.highlight-build123d .notranslate} ::: highlight show_object(display.sketch_local, name="sketch on Plane.XY") ::: :::

while the sketches as applied to their target workplanes is accessible through the sketch{.docutils .literal .notranslate} property, as follows:

::: {.highlight-build123d .notranslate} ::: highlight show_object(display.sketch, name="sketch on target workplane(s)") ::: :::

When using the add(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} operation to add an external Face to a sketch the face will automatically be reoriented to Plane.XY{.docutils .literal .notranslate} before being combined with the sketch. As Faces don't provide an x-direction it's possible that the new Face may not be oriented as expected. To reorient the Face manually to Plane.XY{.docutils .literal .notranslate} one can use the to_local_coords(){.xref .py .py-meth .docutils .literal .notranslate} method as follows:

::: {.highlight-build123d .notranslate} ::: highlight reoriented_face = plane.to_local_coords(face) ::: :::

where plane{.docutils .literal .notranslate} is the plane that face{.docutils .literal .notranslate} was constructed on. :::

::: {#build_sketch.xhtml#locating-features .section}

Locating Features

Within a sketch features are positioned with Locations{.docutils .literal .notranslate} contexts (see [Location Context]{.std .std-ref}{.reference .internal}) on the current workplane(s). The following location contexts are available within a sketch:

Generally one would specify tuples of (X, Y) values when defining locations but there are many options available to the user. :::

::: {#build_sketch.xhtml#module-build_sketch .section} []{#build_sketch.xhtml#reference}

Reference

[class]{.pre}[ ]{.w}[[BuildSketch]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*workplanes:]{.pre} [~build123d.topology.two_d.Face]{.pre} [|]{.pre} [~build123d.geometry.Plane]{.pre} [|]{.pre} [~build123d.geometry.Location]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

The BuildSketch class is a subclass of Builder for building planar 2D sketches (objects with area but not volume) from faces or lines. It has an _obj property that returns the current sketch being built. The sketch property consists of the sketch(es) applied to the input workplanes while the sketch_local attribute is the sketch constructed on Plane.XY. The class overrides the solids method of Builder since they don't apply to lines.

Note that all sketch construction is done within sketch_local on Plane.XY. When objects are added to the sketch they must be coplanar to Plane.XY, usually handled automatically but may need user input for Edges and Wires since their construction plane isn't always able to be determined.

Parameters[:]{.colon}
  • workplanes (Union[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}, Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, Location{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- objects converted to plane(s) to place the sketch on. Defaults to Plane.XY.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

consolidate_edges]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}[ ]{.w}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Unify pending edges into one or more Wires

[property]{.pre}[ ]{.w}[[sketch]{.pre}]{.sig-name .descname}

The global version of the sketch - may contain multiple sketches

[property]{.pre}[ ]{.w}[[sketch_local]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Sketch]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}

Get the builder's object

[[solid]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}[)]{.sig-paren}

solid() not implemented

[[solids]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}[)]{.sig-paren}

solids() not implemented ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#build_part.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#build_part.xhtml#buildpart .section}

BuildPart

BuildPart is a python context manager that is used to create three dimensional objects - objects with the property of volume - that are typically finished parts.

The complete API for BuildPart is located at the end of this section.

::: {#build_part.xhtml#basic-functionality .section}

Basic Functionality

The following is a simple BuildPart example:

::: {.highlight-build123d .notranslate} ::: highlight length, width, thickness = 80.0, 60.0, 10.0 center_hole_dia = 22.0

with BuildPart() as ex2:
    Box(length, width, thickness)
    Cylinder(radius=center_hole_dia / 2, height=thickness, mode=Mode.SUBTRACT)

::: :::

The with{.docutils .literal .notranslate} statement creates the BuildPart{.docutils .literal .notranslate} context manager with the identifier ex2{.docutils .literal .notranslate} (this code is the second of the introductory examples). The objects and operations that are within the scope (i.e. indented) of this context will contribute towards the object being created by the context manager. For BuildPart{.docutils .literal .notranslate}, this object is part{.docutils .literal .notranslate} and it's referenced as ex2.part{.docutils .literal .notranslate}.

The first object in this example is a Box{.docutils .literal .notranslate} object which is used to create a polyhedron with rectangular faces centered on the default Plane.XY{.docutils .literal .notranslate}. The second object is a Cylinder{.docutils .literal .notranslate} that is subtracted from the box as directed by the mode=Mode.SUBTRACT{.docutils .literal .notranslate} parameter thus creating a hole.

{.align-center} :::

::: {#build_part.xhtml#implicit-parameters .section}

Implicit Parameters

The BuildPart context keeps track of pending objects such that they can be used implicitly - there are a couple things to consider when deciding how to proceed:

  • For sketches, the planes that they were constructed on is maintained in internal data structures such that operations like extrude(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} will have a good reference for the extrude direction. One can pass a Face to extrude but it will then be forced to use the normal direction at the center of the Face as the extrude direction which unfortunately can be reversed in some circumstances.

  • Implicit parameters save some typing but hide some functionality - users have to decide what works best for them.

This tea cup example uses implicit parameters - note the sweep(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} operation on the last line:

::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import show

wall_thickness = 3 * MM
fillet_radius = wall_thickness * 0.49

with BuildPart() as tea_cup:
    # Create the bowl of the cup as a revolved cross section
    with BuildSketch(Plane.XZ) as bowl_section:
        with BuildLine():
            # Start & end points with control tangents
            s = Spline(
                (30 * MM, 10 * MM),
                (69 * MM, 105 * MM),
                tangents=((1, 0.5), (0.7, 1)),
                tangent_scalars=(1.75, 1),
            )
            # Lines to finish creating ½ the bowl shape
            Polyline(s @ 0, s @ 0 + (10 * MM, -10 * MM), (0, 0), (0, (s @ 1).Y), s @ 1)
        make_face()  # Create a filled 2D shape
    revolve(axis=Axis.Z)
    # Hollow out the bowl with openings on the top and bottom
    offset(amount=-wall_thickness, openings=tea_cup.faces().filter_by(GeomType.PLANE))
    # Add a bottom to the bowl
    with Locations((0, 0, (s @ 0).Y)):
        Cylinder(radius=(s @ 0).X, height=wall_thickness)
    # Smooth out all the edges
    fillet(tea_cup.edges(), radius=fillet_radius)

    # Determine where the handle contacts the bowl
    handle_intersections = [
        tea_cup.part.find_intersection_points(
            Axis(origin=(0, 0, vertical_offset), direction=(1, 0, 0))
        )[-1][0]
        for vertical_offset in [35 * MM, 80 * MM]
    ]
    # Create a path for handle creation
    with BuildLine(Plane.XZ) as handle_path:
        Spline(
            handle_intersections[0] - (wall_thickness / 2, 0),
            handle_intersections[0] + (35 * MM, 30 * MM),
            handle_intersections[0] + (40 * MM, 60 * MM),
            handle_intersections[1] - (wall_thickness / 2, 0),
            tangents=((1, 1.25), (-0.2, -1)),
        )
    # Align the cross section to the beginning of the path
    with BuildSketch(handle_path.line ^ 0) as handle_cross_section:
        RectangleRounded(wall_thickness, 8 * MM, fillet_radius)
    sweep()  # Sweep handle cross section along path

assert abs(tea_cup.part.volume - 130326) < 1

show(tea_cup, names=["tea cup"])

::: :::

sweep(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} requires a 2D cross section - handle_cross_section{.docutils .literal .notranslate} - and a path - handle_path{.docutils .literal .notranslate} - which are both passed implicitly.

{.align-center} :::

::: {#build_part.xhtml#units .section}

Units

Parts created with build123d have no inherent units associated with them. However, when exporting parts to external formats like STL{.docutils .literal .notranslate} or STEP{.docutils .literal .notranslate} the units are assumed to be millimeters (mm). To be more explicit with units one can use the technique shown in the above tea cup example where linear dimensions are followed by * MM{.docutils .literal .notranslate} which multiplies the dimension by the MM{.docutils .literal .notranslate} scaling factor - in this case 1{.docutils .literal .notranslate}.

The following dimensional constants are pre-defined:

::: {.highlight-python .notranslate} ::: highlight MM = 1 CM = 10 * MM M = 1000 * MM IN = 25.4 * MM FT = 12 * IN THOU = IN / 1000 ::: :::

Some export formats like DXF have the ability to explicitly set the units used. :::

::: {#build_part.xhtml#module-build_part .section} []{#build_part.xhtml#reference}

Reference

[class]{.pre}[ ]{.w}[[BuildPart]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*workplanes:]{.pre} [~build123d.topology.two_d.Face]{.pre} [|]{.pre} [~build123d.geometry.Plane]{.pre} [|]{.pre} [~build123d.geometry.Location]{.pre}]{.n}, [[mode:]{.pre} [~build123d.build_enums.Mode]{.pre} [=]{.pre} [<Mode.ADD>]{.pre}]{.n}[)]{.sig-paren}

The BuildPart class is another subclass of Builder for building parts (objects with the property of volume) from sketches or 3D objects. It has an _obj property that returns the current part being built, and several pending lists for storing faces, edges, and planes that will be integrated into the final part later. The class overrides the _add_to_pending method of Builder.

Parameters[:]{.colon}
  • workplanes (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- initial plane to work on. Defaults to Plane.XY.

  • mode (Mode{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- combination mode. Defaults to Mode.ADD.

[property]{.pre}[ ]{.w}[[location]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Location]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}

Builder's location

[property]{.pre}[ ]{.w}[[part]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Part]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}

Get the current part

[property]{.pre}[ ]{.w}[[pending_edges_as_wire]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Wire]{.pre}

Return a wire representation of the pending edges ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#joints.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#joints.xhtml#joints .section} []{#joints.xhtml#id1}

Joints

Joint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}'s enable Solid and Compound objects to be arranged relative to each other in an intuitive manner - with the same degree of motion that is found with the equivalent physical joints. Joint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}'s always work in pairs - a Joint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} can only be connected to another Joint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} as follows:

Joint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} connect_to Example


BallJoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} RigidJoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Gimbal CylindricalJoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} RigidJoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Screw LinearJoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} RigidJoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, RevoluteJoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Slider or Pin Slot RevoluteJoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} RigidJoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Hinge RigidJoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} RigidJoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Fixed

Objects may have many joints bound to them each with an identifying label. All Joint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} objects have a symbol{.docutils .literal .notranslate} property that can be displayed to help visualize their position and orientation (the ocp-vscode{.reference .external}[ [https://github.com/bernhard-42/vscode-ocp-cad-viewer]]{.link-target} viewer has built-in support for displaying joints).

::: {.admonition .note} Note

If joints are created within the scope of a BuildPart{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} builder, the to_part{.docutils .literal .notranslate} parameter need not be specified as the builder will, on exit, automatically transfer the joints created in its scope to the part created. :::

The following sections provide more detail on the available joints and describes how they are used.

::: {#joints.xhtml#rigid-joint .section} []{#joints.xhtml#module-joints}

Rigid Joint

A rigid joint positions two components relative to each another with no freedom of movement. When a RigidJoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} is instantiated it's assigned a label{.docutils .literal .notranslate}, a part to bind to (to_part{.docutils .literal .notranslate}), and a joint_location{.docutils .literal .notranslate} which defines both the position and orientation of the joint (see Location{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}) - as follows:

::: {.highlight-build123d .notranslate} ::: highlight RigidJoint(label="outlet", to_part=pipe, joint_location=path.location_at(1)) ::: :::

Once a joint is bound to a part this way, the connect_to(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} method can be used to repositioning another part relative to self{.docutils .literal .notranslate} which stay fixed - as follows:

::: {.highlight-build123d .notranslate} ::: highlight pipe.joints["outlet"].connect_to(flange_outlet.joints["pipe"]) ::: :::

::: {.admonition .note} Note

Within a part all of the joint labels must be unique. :::

The connect_to(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} method only does a one time re-position of a part and does not bind them in any way; however, putting them into an [Assemblies]{.std .std-ref}{.reference .internal} will maintain there relative locations as will combining parts with boolean operations or within a BuildPart{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} context.

As a example of creating parts with joints and connecting them together, consider the following code where flanges are attached to the ends of a curved pipe:

::: {.highlight-build123d .notranslate} ::: highlight import copy from build123d import * from bd_warehouse.flange import WeldNeckFlange from bd_warehouse.pipe import PipeSection from ocp_vscode import *

flange_inlet = WeldNeckFlange(nps="10", flange_class=300)
flange_outlet = copy.copy(flange_inlet)

with BuildPart() as pipe_builder:
    # Create the pipe
    with BuildLine():
        path = TangentArc((0, 0, 0), (2 * FT, 0, 1 * FT), tangent=(1, 0, 0))
    with BuildSketch(Plane(origin=path @ 0, z_dir=path % 0)):
        PipeSection("10", material="stainless", identifier="40S")
    sweep()

    # Add the joints
    RigidJoint(label="inlet", joint_location=-path.location_at(0))
    RigidJoint(label="outlet", joint_location=path.location_at(1))

# Place the flanges at the ends of the pipe
pipe_builder.part.joints["inlet"].connect_to(flange_inlet.joints["pipe"])
pipe_builder.part.joints["outlet"].connect_to(flange_outlet.joints["pipe"])

show(pipe_builder, flange_inlet, flange_outlet, render_joints=True)

::: :::

Note how the locations of the joints are determined by the location_at(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} method and how the -{.docutils .literal .notranslate} negate operator is used to reverse the direction of the location without changing its position. Also note that the WeldNeckFlange{.docutils .literal .notranslate} class predefines two joints, one at the pipe end and one at the face end - both of which are shown in the above image (generated by ocp-vscode with the render_joints=True{.docutils .literal .notranslate} flag set in the show{.docutils .literal .notranslate} function).

[class]{.pre}[ ]{.w}[[RigidJoint]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}, [[to_part]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Solid]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Compound]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[joint_location]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Location]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

A rigid joint fixes two components to one another.

Parameters[:]{.colon}
  • label (str) -- joint label

  • to_part (Union[Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}, Compound{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- object to attach joint to

  • joint_location (Location{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- global location of joint

Variables[:]{.colon}

relative_location (Location{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- joint location relative to bound object

[[connect_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[BallJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, angles]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Rotation]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[**]{.pre}]{.o}[[kwargs]{.pre}]{.n}[)]{.sig-paren}\
[[connect_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[CylindricalJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, [[position]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}\
[[connect_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[LinearJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, [[position]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}\
[[connect_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[RevoluteJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}\
[[connect_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[RigidJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren}

Connect the RigidJoint to another Joint

Parameters[:]{.colon}
  • other (Joint{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- joint to connect to

  • angle (float, optional) -- angle in degrees. Defaults to range min.

  • angles (RotationLike, optional) -- angles about axes in degrees. Defaults to range minimums.

  • position (float, optional) -- linear position. Defaults to linear range min.

[property]{.pre}[ ]{.w}[[location]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Location]{.pre}

Location of joint

[[relative_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[BallJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, angles]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Rotation]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}\
[[relative_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[CylindricalJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, [[position]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}\
[[relative_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[LinearJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, [[position]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}\
[[relative_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[RevoluteJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}\
[[relative_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[RigidJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren}

Relative location of RigidJoint to another Joint

Parameters[:]{.colon}
  • other (RigidJoint{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- relative to joint

  • angle (float, optional) -- angle in degrees. Defaults to range min.

  • angles (RotationLike, optional) -- angles about axes in degrees. Defaults to range minimums.

  • position (float, optional) -- linear position. Defaults to linear range min.

Raises[:]{.colon}

TypeError -- other must be of a type in: BallJoint, CylindricalJoint, LinearJoint, RevoluteJoint, RigidJoint.

[property]{.pre}[ ]{.w}[[symbol]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Compound]{.pre}

A CAD symbol (XYZ indicator) as bound to part :::

::: {#joints.xhtml#revolute-joint .section}

Revolute Joint

Component rotates around axis like a hinge. The [Joint Tutorial]{.std .std-ref}{.reference .internal} covers Revolute Joints in detail.

During instantiation of a RevoluteJoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} there are three parameters not present with Rigid Joints: axis{.docutils .literal .notranslate}, angle_reference{.docutils .literal .notranslate}, and range{.docutils .literal .notranslate} that allow the circular motion to be fully defined.

When connect_to(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} with a Revolute Joint, an extra angle{.docutils .literal .notranslate} parameter is present which allows one to change the relative position of joined parts by changing a single value.

[class]{.pre}[ ]{.w}[[RevoluteJoint]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}, [[to_part]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Solid]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Compound]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[axis]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[((0.0,]{.pre} [0.0,]{.pre} [0.0),]{.pre} [(0.0,]{.pre} [0.0,]{.pre} [1.0))]{.pre}]{.default_value}, angle_reference]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, angular_range]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[(0,]{.pre} [360)]{.pre}]{.default_value}[)]{.sig-paren}

Component rotates around axis like a hinge.

Parameters[:]{.colon}
  • label (str) -- joint label

  • to_part (Union[Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}, Compound{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- object to attach joint to

  • axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- axis of rotation

  • angle_reference (VectorLike, optional) -- direction normal to axis defining where angles will be measured from. Defaults to None.

  • range (tuple[float, float], optional) -- (min,max) angle of joint. Defaults to (0, 360).

Variables[:]{.colon}
  • angle (float) -- angle of joint

  • angle_reference (Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- reference for angular positions

  • angular_range (tuple[float,float]) -- min and max angular position of joint

  • relative_axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- joint axis relative to bound part

Raises[:]{.colon}

ValueError -- angle_reference must be normal to axis

[[connect_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[RigidJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

Connect RevoluteJoint and RigidJoint

Parameters[:]{.colon}
  • other (RigidJoint{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- relative to joint

  • angle (float, optional) -- angle in degrees. Defaults to range min.

Returns[:]{.colon}

other must of type RigidJoint ValueError: angle out of range

Return type[:]{.colon}

TypeError

[property]{.pre}[ ]{.w}[[location]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Location]{.pre}

Location of joint

[[relative_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[RigidJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

Relative location of RevoluteJoint to RigidJoint

Parameters[:]{.colon}
  • other (RigidJoint{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- relative to joint

  • angle (float, optional) -- angle in degrees. Defaults to range min.

Raises[:]{.colon}
  • TypeError -- other must of type RigidJoint

  • ValueError -- angle out of range

[property]{.pre}[ ]{.w}[[symbol]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Compound]{.pre}

A CAD symbol representing the axis of rotation as bound to part :::

::: {#joints.xhtml#linear-joint .section}

Linear Joint

Component moves along a single axis as with a sliding latch shown here:

The code to generate these components follows:

::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from ocp_vscode import *

with BuildPart() as latch:
    # Basic box shape to start with filleted corners
    Box(70, 30, 14)
    end = latch.faces().sort_by(Axis.X)[-1]  # save the end with the hole
    fillet(latch.edges().filter_by(Axis.Z), 2)
    fillet(latch.edges().sort_by(Axis.Z)[-1], 1)
    # Make screw tabs
    with BuildSketch(latch.faces().sort_by(Axis.Z)[0]) as l4:
        with Locations((-30, 0), (30, 0)):
            SlotOverall(50, 10, rotation=90)
        Rectangle(50, 30)
        fillet(l4.vertices(Select.LAST), radius=2)
    extrude(amount=-2)
    with GridLocations(60, 40, 2, 2):
        Hole(2)
    # Create the hole from the end saved previously
    with BuildSketch(end) as slide_hole:
        add(end)
        offset(amount=-2)
        fillet(slide_hole.vertices(), 1)
    extrude(amount=-68, mode=Mode.SUBTRACT)
    # Slot for the handle to slide in
    with BuildSketch(latch.faces().sort_by(Axis.Z)[-1]):
        SlotOverall(32, 8)
    extrude(amount=-2, mode=Mode.SUBTRACT)
    # The slider will move align the x axis 12mm in each direction
    LinearJoint("latch", axis=Axis.X, linear_range=(-12, 12))

with BuildPart() as slide:
    # The slide will be a little smaller than the hole
    with BuildSketch() as s1:
        add(slide_hole.sketch)
        offset(amount=-0.25)
    # The extrusions aren't symmetric
    extrude(amount=46)
    extrude(slide.faces().sort_by(Axis.Z)[0], amount=20)
    # Round off the ends
    fillet(slide.edges().group_by(Axis.Z)[0], 1)
    fillet(slide.edges().group_by(Axis.Z)[-1], 1)
    # Create the knob
    with BuildSketch() as s2:
        with Locations((12, 0)):
            SlotOverall(15, 4, rotation=90)
        Rectangle(12, 7, align=(Align.MIN, Align.CENTER))
        fillet(s2.vertices(Select.LAST), 1)
        split(bisect_by=Plane.XZ)
    revolve(axis=Axis.X)
    # Align the joint to Plane.ZY flipped
    RigidJoint("slide", joint_location=Location(-Plane.ZY))

# Position the slide in the latch: -12 >= position <= 12
latch.part.joints["latch"].connect_to(slide.part.joints["slide"], position=12)

# show(latch.part, render_joints=True)
# show(slide.part, render_joints=True)
show(latch.part, slide.part, render_joints=True)

::: :::

{style="width: 65%;"} {style="width: 27.5%;"}

Note how the slide is constructed in a different orientation than the direction of motion. The three highlighted lines of code show how the joints are created and connected together:

The slider can be moved back and forth by just changing the position{.docutils .literal .notranslate} value. Values outside of the limits will raise an exception.

[class]{.pre}[ ]{.w}[[LinearJoint]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}, [[to_part]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Solid]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Compound]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[axis]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[((0.0,]{.pre} [0.0,]{.pre} [0.0),]{.pre} [(0.0,]{.pre} [0.0,]{.pre} [1.0))]{.pre}]{.default_value}, linear_range]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[(0,]{.pre} [inf)]{.pre}]{.default_value}[)]{.sig-paren}

Component moves along a single axis.

Parameters[:]{.colon}
  • label (str) -- joint label

  • to_part (Union[Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}, Compound{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- object to attach joint to

  • axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- axis of linear motion

  • range (tuple[float, float], optional) -- (min,max) position of joint. Defaults to (0, inf).

Variables[:]{.colon}
  • axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- joint axis

  • angle (float) -- angle of joint

  • linear_range (tuple[float,float]) -- min and max positional values

  • position (float) -- joint position

  • relative_axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- joint axis relative to bound part

[[connect_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[RevoluteJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, [[position]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}\
[[connect_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[RigidJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, [[position]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

Connect LinearJoint to another Joint

Parameters[:]{.colon}
  • other (Joint{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- joint to connect to

  • angle (float, optional) -- angle in degrees. Defaults to range min.

  • position (float, optional) -- linear position. Defaults to linear range min.

Raises[:]{.colon}
  • TypeError -- other must be of type RevoluteJoint or RigidJoint

  • ValueError -- position out of range

  • ValueError -- angle out of range

[property]{.pre}[ ]{.w}[[location]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Location]{.pre}

Location of joint

[[relative_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[RigidJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, [[position]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}\
[[relative_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[RevoluteJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, [[position]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

Relative location of LinearJoint to RevoluteJoint or RigidJoint

Parameters[:]{.colon}
  • other (Joint{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- joint to connect to

  • angle (float, optional) -- angle in degrees. Defaults to range min.

  • position (float, optional) -- linear position. Defaults to linear range min.

Raises[:]{.colon}
  • TypeError -- other must be of type RevoluteJoint or RigidJoint

  • ValueError -- position out of range

  • ValueError -- angle out of range

[property]{.pre}[ ]{.w}[[symbol]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Compound]{.pre}

A CAD symbol of the linear axis positioned relative to_part :::

::: {#joints.xhtml#cylindrical-joint .section}

Cylindrical Joint

A CylindricalJoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} allows a component to rotate around and moves along a single axis like a screw combining the functionality of a LinearJoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and a RevoluteJoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} joint. The connect_to{.docutils .literal .notranslate} for these joints have both position{.docutils .literal .notranslate} and angle{.docutils .literal .notranslate} parameters as shown below extracted from the joint tutorial.

[class]{.pre}[ ]{.w}[[CylindricalJoint]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}, [[to_part]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Solid]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Compound]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[axis]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[((0.0,]{.pre} [0.0,]{.pre} [0.0),]{.pre} [(0.0,]{.pre} [0.0,]{.pre} [1.0))]{.pre}]{.default_value}, angle_reference]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, linear_range]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[(0,]{.pre} [inf)]{.pre}]{.default_value}, angular_range]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[(0,]{.pre} [360)]{.pre}]{.default_value}[)]{.sig-paren}

Component rotates around and moves along a single axis like a screw.

Parameters[:]{.colon}
  • label (str) -- joint label

  • to_part (Union[Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}, Compound{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- object to attach joint to

  • axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- axis of rotation and linear motion

  • angle_reference (VectorLike, optional) -- direction normal to axis defining where angles will be measured from. Defaults to None.

  • linear_range (tuple[float, float], optional) -- (min,max) position of joint. Defaults to (0, inf).

  • angular_range (tuple[float, float], optional) -- (min,max) angle of joint. Defaults to (0, 360).

Variables[:]{.colon}
  • axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- joint axis

  • linear_position (float) -- linear joint position

  • rotational_position (float) -- revolute joint angle in degrees

  • angle_reference (Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- reference for angular positions

  • angular_range (tuple[float,float]) -- min and max angular position of joint

  • linear_range (tuple[float,float]) -- min and max positional values

  • relative_axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- joint axis relative to bound part

  • position (float) -- joint position

  • angle (float) -- angle of joint

Raises[:]{.colon}

ValueError -- angle_reference must be normal to axis

[[connect_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[RigidJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, [[position]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

Connect CylindricalJoint and RigidJoint"

Parameters[:]{.colon}
  • other (Joint{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- joint to connect to

  • position (float, optional) -- linear position. Defaults to linear range min.

  • angle (float, optional) -- angle in degrees. Defaults to range min.

Raises[:]{.colon}
  • TypeError -- other must be of type RigidJoint

  • ValueError -- position out of range

  • ValueError -- angle out of range

[property]{.pre}[ ]{.w}[[location]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Location]{.pre}

Location of joint

[[relative_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[RigidJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, [[position]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

Relative location of CylindricalJoint to RigidJoint

Parameters[:]{.colon}
  • other (Joint{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- joint to connect to

  • position (float, optional) -- linear position. Defaults to linear range min.

  • angle (float, optional) -- angle in degrees. Defaults to range min.

Raises[:]{.colon}
  • TypeError -- other must be of type RigidJoint

  • ValueError -- position out of range

  • ValueError -- angle out of range

[property]{.pre}[ ]{.w}[[symbol]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Compound]{.pre}

A CAD symbol representing the cylindrical axis as bound to part :::

::: {#joints.xhtml#ball-joint .section}

Ball Joint

A component rotates around all 3 axes using a gimbal system (3 nested rotations). A BallJoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} is found within a rod end as shown here:

::: {.highlight-build123d .notranslate} ::: highlight from build123d import * from bd_warehouse.thread import IsoThread from ocp_vscode import *

# Create the thread so the min radius is available below
thread = IsoThread(major_diameter=6, pitch=1, length=20, end_finishes=("fade", "raw"))
inner_radius = 15.89 / 2
inner_gap = 0.2

with BuildPart() as rod_end:
    # Create the outer shape
    with BuildSketch():
        Circle(22.25 / 2)
        with Locations((0, -12)):
            Rectangle(8, 1)
        make_hull()
        split(bisect_by=Plane.YZ)
    revolve(axis=Axis.Y)
    # Refine the shape
    with BuildSketch(Plane.YZ) as s2:
        Rectangle(25, 8, align=(Align.MIN, Align.CENTER))
        Rectangle(9, 10, align=(Align.MIN, Align.CENTER))
        chamfer(s2.vertices(), 0.5)
    revolve(axis=Axis.Z, mode=Mode.INTERSECT)
    # Add the screw shaft
    Cylinder(
        thread.min_radius,
        30,
        rotation=(90, 0, 0),
        align=(Align.CENTER, Align.CENTER, Align.MIN),
    )
    # Cutout the ball socket
    Sphere(inner_radius, mode=Mode.SUBTRACT)
    # Add thread
    with Locations((0, -30, 0)):
        add(thread, rotation=(-90, 0, 0))
    # Create the ball joint
    BallJoint(
        "socket",
        joint_location=Location(),
        angular_range=((-14, 14), (-14, 14), (0, 360)),
    )

with BuildPart() as ball:
    Sphere(inner_radius - inner_gap)
    Box(50, 50, 13, mode=Mode.INTERSECT)
    Hole(4)
    ball.part.color = Color("aliceblue")
    RigidJoint("ball", joint_location=Location())

rod_end.part.joints["socket"].connect_to(ball.part.joints["ball"], angles=(5, 10, 0))

show(rod_end.part, ball.part, s2)

::: :::

Note how limits are defined during the instantiation of the ball joint when ensures that the pin or bolt within the rod end does not interfere with the rod end itself. The connect_to{.docutils .literal .notranslate} sets the three angles (only two are significant in this example).

[class]{.pre}[ ]{.w}[[BallJoint]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}, [[to_part]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Solid]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Compound]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[joint_location]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Location]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, angular_range]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p},]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p},]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}{.pre}]{.p}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[((0,]{.pre} [360),]{.pre} [(0,]{.pre} [360),]{.pre} [(0,]{.pre} [360))]{.pre}]{.default_value}, [[angle_reference]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[Plane(o=(0.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [x=(1.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [z=(0.00,]{.pre} [0.00,]{.pre} [1.00))]{.pre}]{.default_value}[)]{.sig-paren}

A component rotates around all 3 axes using a gimbal system (3 nested rotations).

Parameters[:]{.colon}
  • label (str) -- joint label

  • to_part (Union[Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}, Compound{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- object to attach joint to

  • joint_location (Location{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- global location of joint

  • angular_range -- (tuple[ tuple[float, float], tuple[float, float], tuple[float, float] ], optional): X, Y, Z angle (min, max) pairs. Defaults to ((0, 360), (0, 360), (0, 360)).

  • angle_reference (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- plane relative to part defining zero degrees of rotation. Defaults to Plane.XY.

Variables[:]{.colon}
  • relative_location (Location{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- joint location relative to bound part

  • angular_range -- (tuple[ tuple[float, float], tuple[float, float], tuple[float, float] ]): X, Y, Z angle (min, max) pairs.

  • angle_reference (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- plane relative to part defining zero degrees of

[[connect_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[RigidJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, angles]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Rotation]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

Connect BallJoint and RigidJoint

Parameters[:]{.colon}
  • other (RigidJoint{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- joint to connect to

  • angles (RotationLike, optional) -- angles about axes in degrees. Defaults to range minimums.

Raises[:]{.colon}
  • TypeError -- invalid other joint type

  • ValueError -- angles out of range

[property]{.pre}[ ]{.w}[[location]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Location]{.pre}

Location of joint

[[relative_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[RigidJoint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[*]{.pre}]{.o}, angles]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Rotation]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

relative_to - BallJoint

Return the relative location from this joint to the RigidJoint of another object

Parameters[:]{.colon}
  • other (RigidJoint{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- joint to connect to

  • angles (RotationLike, optional) -- angles about axes in degrees. Defaults to range minimums.

Raises[:]{.colon}
  • TypeError -- invalid other joint type

  • ValueError -- angles out of range

[property]{.pre}[ ]{.w}[[symbol]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Compound]{.pre}

A CAD symbol representing joint as bound to part ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#assemblies.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#assemblies.xhtml#assemblies .section} []{#assemblies.xhtml#assembly}

Assemblies

Most CAD designs consist of more than one part which are naturally arranged in some type of assembly. Once parts have been assembled in a Compound{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} object they can be treated as a unit - i.e. moved(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} or exported.

To create an assembly in build123d, one needs to create a tree of parts by simply assigning either a Compound{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} object's parent{.docutils .literal .notranslate} or children{.docutils .literal .notranslate} attributes. To illustrate the process, we'll extend the [Joint Tutorial]{.std .std-ref}{.reference .internal}.

::: {#assemblies.xhtml#assigning-labels .section}

Assigning Labels

In order keep track of objects one can assign a label{.docutils .literal .notranslate} to all Shape{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} objects. Here we'll assign labels to all of the components that will be part of the box assembly:

::: {.highlight-build123d .notranslate} ::: highlight box.label = "box" lid.label = "lid" hinge_outer.label = "outer hinge" hinge_inner.label = "inner hinge" m6_screw.label = "M6 screw" ::: :::

The labels are just strings with no further limitations (they don't have to be unique within the assembly). :::

::: {#assemblies.xhtml#create-the-assembly-compound .section}

Create the Assembly Compound

Creation of the assembly is done by simply creating a Compound{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} object and assigning appropriate parent{.docutils .literal .notranslate} and children{.docutils .literal .notranslate} attributes as shown here:

::: {.highlight-build123d .notranslate} ::: highlight box_assembly = Compound(label="assembly", children=[box, lid, hinge_inner, hinge_outer]) ::: :::

To display the topology of an assembly Compound{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, the show_topology(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} method can be used as follows:

::: {.highlight-build123d .notranslate} ::: highlight print(box_assembly.show_topology()) ::: :::

which results in:

::: {.highlight-default .notranslate} ::: highlight assembly Compound at 0x7fc8ee235760, Location(p=(0, 0, 0), o=(-0, 0, -0)) ├── box Compound at 0x7fc8ee2188b0, Location(p=(0, 0, 50), o=(-0, 0, -0)) ├── lid Compound at 0x7fc8ee228460, Location(p=(-26, 0, 181), o=(-180, 30, -0)) ├── inner hinge Hinge at 0x7fc9292c3f70, Location(p=(-119, 60, 122), o=(90, 0, -150)) └── outer hinge Hinge at 0x7fc9292c3f40, Location(p=(-150, 60, 50), o=(90, 0, 90)) ::: :::

To add to an assembly Compound{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} one can change either children{.docutils .literal .notranslate} or parent{.docutils .literal .notranslate} attributes.

::: {.highlight-build123d .notranslate} ::: highlight m6_screw.parent = box_assembly print(box_assembly.show_topology()) ::: :::

and now the screw is part of the assembly.

::: {.highlight-default .notranslate} ::: highlight assembly Compound at 0x7fc8ee235760, Location(p=(0, 0, 0), o=(-0, 0, -0)) ├── box Compound at 0x7fc8ee2188b0, Location(p=(0, 0, 50), o=(-0, 0, -0)) ├── lid Compound at 0x7fc8ee228460, Location(p=(-26, 0, 181), o=(-180, 30, -0)) ├── inner hinge Hinge at 0x7fc9292c3f70, Location(p=(-119, 60, 122), o=(90, 0, -150)) ├── outer hinge Hinge at 0x7fc9292c3f40, Location(p=(-150, 60, 50), o=(90, 0, 90)) └── M6 screw Compound at 0x7fc8ee235310, Location(p=(-157, -40, 70), o=(-0, -90, -60)) ::: ::: :::

::: {#assemblies.xhtml#shallow-vs-deep-copies-of-shapes .section} []{#assemblies.xhtml#shallow-copy}

Shallow vs. Deep Copies of Shapes

Build123d supports the standard python copy{.docutils .literal .notranslate} module which provides two different types of copy operations copy.copy(){.docutils .literal .notranslate} and copy.deepcopy(){.docutils .literal .notranslate}.

Build123d's implementation of deepcopy(){.docutils .literal .notranslate} for the Shape{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} class (e.g. Solid{.docutils .literal .notranslate}, Face{.docutils .literal .notranslate}, etc.) does just that, creates a complete copy of the original all the way down to the CAD object. deepcopy{.docutils .literal .notranslate} is therefore suited to the case where the copy will be subsequently modified to become its own unique item.

However, when building an assembly a common use case is to include many instances of an object, each one identical but in a different location. This is where copy.copy(){.docutils .literal .notranslate} is very useful as it copies all of the Shape{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} except for the actual CAD object which instead is a reference to the original (OpenCascade refers this as a TShape{.docutils .literal .notranslate}). As it's a reference any changes to the original will be seen in all of the shallow copies.

Consider this example where 100 screws are added to an assembly:

{.align-center}

::: {.highlight-default .notranslate} ::: highlight screw = import_step("M6-1x12-countersunk-screw.step") locs = HexLocations(6, 10, 10).local_locations

screw_copies = [copy.deepcopy(screw).locate(loc) for loc in locs]
copy_assembly = Compound(children=screw_copies)
export_step(copy_assembly, "copy_assembly.step")

::: :::

which takes about 5 seconds to run (on an older computer) and produces a file of size 51938 KB. However, if a shallow copy is used instead:

::: {.highlight-default .notranslate} ::: highlight screw = import_step("M6-1x12-countersunk-screw.step") locs = HexLocations(6, 10, 10).local_locations

screw_references = [copy.copy(screw).locate(loc) for loc in locs]
reference_assembly = Compound(children=screw_references)
export_step(reference_assembly, "reference_assembly.step")

::: :::

this takes about ¼ second and produces a file of size 550 KB - just over 1% of the size of the deepcopy(){.docutils .literal .notranslate} version and only 12% larger than the screw's step file.

Using copy.copy(){.docutils .literal .notranslate} to create references to the original CAD object for assemblies can substantially reduce the time and resources used to create and store that assembly. :::

::: {#assemblies.xhtml#shapes-are-anytree-nodes .section}

Shapes are Anytree Nodes

The build123d assembly constructs are built using the python anytree{.reference .external}[ [https://anytree.readthedocs.io/en/latest/]]{.link-target} package by making the build123d Shape{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} class a sub-class of anytree's NodeMixin{.docutils .literal .notranslate} class. Doing so adds the following attributes to Shape{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}:

  • parent{.docutils .literal .notranslate} - Parent Node. On set, the node is detached from any previous parent node and attached to the new node.

  • children{.docutils .literal .notranslate} - Tuple of all child nodes.

  • path{.docutils .literal .notranslate} - Path of this Node{.docutils .literal .notranslate}.

  • iter_path_reverse{.docutils .literal .notranslate} - Iterate up the tree from the current node.

  • ancestors{.docutils .literal .notranslate} - All parent nodes and their parent nodes.

  • descendants{.docutils .literal .notranslate} - All child nodes and all their child nodes.

  • root{.docutils .literal .notranslate} - Tree Root Node.

  • siblings{.docutils .literal .notranslate} - Tuple of nodes with the same parent.

  • leaves{.docutils .literal .notranslate} - Tuple of all leaf nodes.

  • is_leaf{.docutils .literal .notranslate} - Node{.docutils .literal .notranslate} has no children (External Node).

  • is_root{.docutils .literal .notranslate} - Node{.docutils .literal .notranslate} is tree root.

  • height{.docutils .literal .notranslate} - Number of edges on the longest path to a leaf Node{.docutils .literal .notranslate}.

  • depth{.docutils .literal .notranslate} - Number of edges to the root Node{.docutils .literal .notranslate}.

::: {.admonition .note} Note

Changing the children{.docutils .literal .notranslate} attribute

Any iterator can be assigned to the children{.docutils .literal .notranslate} attribute but subsequently the children are stored as immutable tuple{.docutils .literal .notranslate} objects. To add a child to an existing Compound{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} object, the children{.docutils .literal .notranslate} attribute will have to be reassigned. ::: :::

::: {#assemblies.xhtml#iterating-over-compounds .section} []{#assemblies.xhtml#pack}

Iterating Over Compounds

As Compounds are containers for shapes, build123d can iterate over these as required. Complex nested assemblies (compounds within compounds) do not need to be looped over with recursive functions. In the example below, the variable total_volume holds the sum of all the volumes in each solid in an assembly. Compare this to assembly3_volume which only results in the volume of the top level part.

::: {.highlight-python .notranslate} ::: highlight # [import] from build123d import * from ocp_vscode import *

# Each assembly has a box and the previous assembly.
assembly1 = Compound(label='Assembly1', children=[Box(1, 1, 1),])
assembly2 = Compound(label='Assembly2', children=[assembly1, Box(1, 1, 1)])
assembly3 = Compound(label='Assembly3', children=[assembly2, Box(1, 1, 1)])
total_volume = sum(part.volume for part in assembly3.solids()) # 3
assembly3_volume = assembly3.volume # 1

::: ::: :::

::: {#assemblies.xhtml#id1 .section}

pack

The pack.pack(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} function arranges objects in a compact, non-overlapping layout within a square(ish) 2D area. It is designed to minimize the space between objects while ensuring that no two objects overlap.

[[pack]{.pre}]{.sig-name .descname}[(]{.sig-paren}objects]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Collection]{.pre}[[[]{.pre}]{.p}[Shape]{.pre}[[{.pre}]{.p}]{.n}, [[padding]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[align_z]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}[)]{.sig-paren} →]{.sig-return-icon} [[Collection]{.pre}[[[]{.pre}]{.p}[Shape]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Pack objects in a squarish area in Plane.XY.

Parameters[:]{.colon}
  • objects (Collection[Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- objects to arrange

  • padding (float) -- space between objects

  • align_z (bool, optional) -- align shape bottoms to Plane.XY. Defaults to False.

Returns[:]{.colon}

rearranged objects

Return type[:]{.colon}

Collection[Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}]

::: {#assemblies.xhtml#detailed-description .section}

Detailed Description

The pack{.docutils .literal .notranslate} function uses a bin-packing algorithm to efficiently place objects within a 2D plane, ensuring that there is no overlap and that the space between objects is minimized. This is particularly useful in scenarios where spatial efficiency is crucial, such as layout design and object arrangement in constrained spaces.

The function begins by calculating the bounding boxes for each object, including the specified padding. It then uses a helper function _pack2d{.docutils .literal .notranslate} to determine the optimal positions for each object within the 2D plane. The positions are then translated back to the original objects, ensuring that they are arranged without overlapping. :::

::: {#assemblies.xhtml#usage-note .section}

Usage Note

The align_z{.docutils .literal .notranslate} parameter is especially useful when creating print-plates for 3D printing. By aligning the bottoms of the shapes to the same XY plane, you ensure that the objects are perfectly positioned for slicing software, which will no longer need to perform this alignment for you. This can streamline the process and improve the accuracy of the print setup. :::

::: {#assemblies.xhtml#example-usage .section}

Example Usage

::: {.highlight-python .notranslate} ::: highlight # [import] from build123d import * from ocp_vscode import *

# [initial space]
b1 = Box(100, 100, 100, align=(Align.CENTER, Align.CENTER, Align.MIN))
b2 = Box(54, 54, 54, align=(Align.CENTER, Align.CENTER, Align.MAX), mode=Mode.SUBTRACT)
b3 = Box(34, 34, 34, align=(Align.MIN, Align.MIN, Align.CENTER), mode=Mode.SUBTRACT)
b4 = Box(24, 24, 24, align=(Align.MAX, Align.MAX, Align.CENTER), mode=Mode.SUBTRACT)

::: :::

{.align-center}

::: {.highlight-python .notranslate} ::: highlight # [pack 2D]

xy_pack = pack(
    [b1, b2, b3, b4],
    padding=5,
    align_z=False
)

::: :::

{.align-center}

::: {.highlight-python .notranslate} ::: highlight # [Pack and align_z]

z_pack = pack(
    [b1, b2, b3, b4],
    padding=5,
    align_z=True
)

::: :::

{.align-center} :::

::: {#assemblies.xhtml#tip .section}

Tip

If you place the arranged objects into a Compound{.docutils .literal .notranslate}, you can easily determine their bounding box and check whether the objects fit on your print bed.

::: {.highlight-python .notranslate} ::: highlight # [bounding box] print(Compound(xy_pack).bounding_box()) # bbox: 0.0 <= x <= 159.0, 0.0 <= y <= 129.0, -54.0 <= z <= 100.0

print(Compound(z_pack).bounding_box())
# bbox: 0.0 <= x <= 159.0, 0.0 <= y <= 129.0, 0.0 <= z <= 100.0

::: ::: ::: ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#tips.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#tips.xhtml#tips-best-practices-and-faq .section}

Tips, Best Practices and FAQ

Although there are countless ways to create objects with build123d, experience has proven that certain techniques can assist designers in achieving their goals with the greatest efficiency. The following is a description of these techniques.

::: {#tips.xhtml#can-t-get-there-from-here .section}

Can't Get There from Here

Unfortunately, it's a reality that not all parts described using build123d can be successfully constructed by the underlying CAD core. Designers may have to explore different design approaches to get the OpenCascade CAD core to successfully build the target object. For instance, if a multi-section sweep(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} operation fails, a loft(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} operation may be a viable alternative in certain situations. It's crucial to remember that CAD is a complex field and patience may be required to achieve the desired results. :::

::: {#tips.xhtml#d-before-3d .section}

2D before 3D

When creating complex 3D objects, it is generally best to start with 2D work before moving on to 3D. This is because 3D structures are much more intricate, and 3D operations can be slower and more prone to failure. For designers who come from a Constructive Solid Geometry (CSG) background, such as OpenSCAD, this approach may seem counterintuitive. On the other hand, designers from a GUI BREP CAD background, like Fusion 360 or SolidWorks, may find this approach more natural.

In practice, this means that 3D objects are often created by applying operations like extrude(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} or revolve(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} to 2D sketches, as shown below:

::: {.highlight-python .notranslate} ::: highlight with BuildPart() as my_part: with BuildSketch() as part_profile: ... extrude(amount=some_distance) ... ::: :::

With this structure part_profile{.docutils .literal .notranslate} may have many objects that are combined and modified by operations like fillet(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} before being extruded to a 3D shape. :::

::: {#tips.xhtml#delay-chamfers-and-fillets .section}

Delay Chamfers and Fillets

Chamfers and fillets can add complexity to a design by transforming simple vertices or edges into arcs or non-planar faces. This can significantly increase the complexity of the design. To avoid unnecessary processing costs and potential errors caused by a needlessly complicated design, it's recommended to perform these operations towards the end of the object's design. This is especially true for 3D shapes, as it is sometimes necessary to fillet or chamfer in the 2D design phase. Luckily, these 2D fillets and chamfers are less likely to fail than their 3D counterparts. :::

::: {#tips.xhtml#parameterize .section}

Parameterize

One of the most powerful features of build123d is the ability to design fully parameterized parts. While it may be faster to use a GUI CAD package for the initial iteration of a part, subsequent iterations can prove frustratingly difficult. By using variables for critical dimensions and deriving other dimensions from these key variables, not only can a single part be created, but a whole set of parts can be readily available. When inevitable change requests arise, a simple parameter adjustment may be all that's required to make necessary modifications. :::

::: {#tips.xhtml#use-shallow-copies .section}

Use Shallow Copies

As discussed in the Assembly section, a [shallow copy]{.std .std-ref}{.reference .internal} of parts that are repeated in your design can make a huge difference in performance and usability of your end design. Objects like fasteners, bearings, chain links, etc. could be duplicated tens or even hundreds of times otherwise. Use shallow copies where possible but keep in mind that if one instance of the object changes all will change. :::

::: {#tips.xhtml#object-selection .section}

Object Selection

When selecting features in a design it's sometimes easier to select an object from higher up in the topology first, then select the object from there. For example let's consider a plate with four chamfered holes like this:

{.align-center}

When selecting edges to be chamfered one might first select the face that these edges belong to then select the edges as shown here:

::: {.highlight-build123d .notranslate} ::: highlight from build123d import *

svg_opts = {"pixel_scale": 5, "show_axes": False, "show_hidden": True}

length, width, thickness = 80.0, 60.0, 10.0
hole_dia = 6.0

with BuildPart() as plate:
    Box(length, width, thickness)
    with GridLocations(length - 20, width - 20, 2, 2):
        Hole(radius=hole_dia / 2)
    top_face: Face = plate.faces().sort_by(Axis.Z)[-1]
    hole_edges = top_face.edges().filter_by(GeomType.CIRCLE)
    chamfer(hole_edges, length=1)

::: ::: :::

::: {#tips.xhtml#build123d-cadquery-integration .section}

Build123d - CadQuery Integration

As both CadQuery{.reference .external}[ [https://cadquery.readthedocs.io/en/latest/index.html]]{.link-target} and build123d use a common OpenCascade Python wrapper (OCP{.reference .external}[ [https://github.com/CadQuery/OCP]]{.link-target}) it's possible to interchange objects both from CadQuery to build123d and vice-versa by transferring the wrapped{.docutils .literal .notranslate} objects as follows (first from CadQuery to build123d):

::: {.highlight-build123d .notranslate} ::: highlight import build123d as b3d b3d_solid = b3d.Solid.make_box(1,1,1)

... some cadquery stuff ...

b3d_solid.wrapped = cq_solid.wrapped

::: :::

Secondly, from build123d to CadQuery as follows:

::: {.highlight-build123d .notranslate} ::: highlight import build123d as b3d import cadquery as cq

with b3d.BuildPart() as b123d_box:
    b3d.Box(1,2,3)

cq_solid = cq.Solid.makeBox(1,1,1)
cq_solid.wrapped = b123d_box.part.solid().wrapped

::: ::: :::

::: {#tips.xhtml#self-intersection .section}

Self Intersection

Avoid creating objects that intersect themselves - even if at a single vertex - as these topologies will almost certainly be invalid (even if is_valid(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} reports a True{.docutils .literal .notranslate} value). An example of where this may arise is with the thread of a screw (or any helical shape) where after one complete revolution the part may contact itself. One is likely be more successful if the part is split into multiple sections - say 180° of a helix - which are then stored in an assembly. :::

::: {#tips.xhtml#packing-objects-on-a-plane .section .clearfix}

Packing Objects on a Plane

When designing independent shapes it's common to place each at or near the global origin, which can make it tricky to visualize many shapes at once. pack.pack(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} will translate the Shape{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}'s passed to it so that they don't overlap, with an optional padding/spacing. Here's the result of packing a bunch of overlapping boxes (left) using some padding (right):

{.align-left style="width: 200px;"} {.align-right}

By default, the original Z value of all objects packed using the pack.pack(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} function is preserved. If you want to align all objects so that they are "placed" on the zero Z coordinate, the pack(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} function has an <cite>{=html}align_z</cite>{=html} argument. When set to <cite>{=html}True</cite>{=html}, this will align all objects.

This can be useful, for example, when preparing print setups for 3D printing, giving you full control over this alignment so you don't have to leave it to the slicer. :::

::: {#tips.xhtml#isnt-from-build123d-import-bad-practice .section} []{#tips.xhtml#are-glob-imports-bad-practice}

Isn't from build123d import *{.docutils .literal .notranslate} bad practice?

Glob imports like from build123d import *{.docutils .literal .notranslate} are generally frowned upon when writing software, and for good reason. They pollute the global namespace, cause confusing collisions, and are not future-proof, as future changes to the library being imported could collide with other names. It would be much safer to do something like import build123d as bd{.docutils .literal .notranslate} and then reference every item with, for example, bd.BuildPart(){.docutils .literal .notranslate}. If your goal is to integrate build123d into a larger piece of software, which many people work on, or where long-term maintainability is a priority, using this approach is definitely a good idea! Why then, are glob imports so often used in build123d code and official examples?

build123d is most commonly used not as a library within a larger application, but as a Domain-Specific Language{.reference .external}[ [https://en.wikipedia.org/wiki/Domain-specific_language]]{.link-target} which, together with something like the OCP CAD Viewer, acts as the user interface for a CAD application. Writing build123d often involves live coding in a REPL or typing in editors with limited space due to the rest of the CAD GUI taking up screen space. Scripts are usually centred around build123d usage, with usage of other libraries being limited enough that naming conflicts are easily avoided. In this context, it's entirely reasonable to prioritise developer ergonomics over "correctness" by making build123d's primitives available in the global namespace. :::

::: {#tips.xhtml#why-doesn-t-buildsketch-plane-xz-work .section}

Why doesn't BuildSketch(Plane.XZ) work?

When creating a sketch not on the default Plane.XY{.docutils .literal .notranslate} users may expect that they are drawing directly on the workplane / coordinate system provided. For example:

::: {.highlight-build123d .notranslate} ::: highlight with BuildSketch(Plane.XZ) as vertical_sketch: Rectangle(1, 1) with Locations(vertices().group_by(Axis.X)[-1].sort_by(Axis.Z)[-1]): Circle(0.2) ::: :::

In this case the circle is not positioned in the top right as one would expect; in-fact, the position of the circle randomly switches between the bottom and top corner.

This is because all sketches are created on a local Plane.XY{.docutils .literal .notranslate} independent of where they will be ultimately placed; therefore, the sort_by(Axis.Z){.docutils .literal .notranslate} is sorting two points that have a Z value of zero as they are located on Plane.XY{.docutils .literal .notranslate} and effectively return a random point.

Why does BuildSketch{.docutils .literal .notranslate} work this way? Consider an example where the user wants to work on a plane not aligned with any Axis, as follows (this is often done when creating a sketch on a Face{.docutils .literal .notranslate} of a 3D part but is simulated here by rotating a Plane{.docutils .literal .notranslate}):

::: {.highlight-build123d .notranslate} ::: highlight with BuildSketch(Plane.YZ.rotated((123, 45, 6))) as custom_plane: Rectangle(1, 1, align=Align.MIN) with Locations(vertices().group_by(Axis.X)[-1].sort_by(Axis.Y)[-1]): Circle(0.2) ::: :::

Here one can see both sketch_local{.docutils .literal .notranslate} (with the light fill on Plane.XY{.docutils .literal .notranslate}) and the sketch{.docutils .literal .notranslate} (with the darker fill) placed on the user provided workplane. As the selectors work off global coordinates, selection of the "top right" of this sketch would be quite challenging and would likely change if the sketch was ever moved as could happen if the 3D part changed. For an example of sketching on a 3D part, see [Sketching on other Planes]{.std .std-ref}{.reference .internal}. :::

::: {#tips.xhtml#why-is-buildline-not-working-as-expected-within-the-scope-of-buildsketch .section}

Why is BuildLine not working as expected within the scope of BuildSketch?

As described above, all sketching is done on a local Plane.XY{.docutils .literal .notranslate}; however, the following is a common issue:

::: {.highlight-build123d .notranslate} ::: highlight with BuildSketch() as sketch: with BuildLine(Plane.XZ): Polyline(...) make_face() ::: :::

Here BuildLine{.docutils .literal .notranslate} is within the scope of BuildSketch{.docutils .literal .notranslate}; therefore, all of the drawing should be done on Plane.XY{.docutils .literal .notranslate}; however, the user has specified Plane.XZ{.docutils .literal .notranslate} when creating the BuildLine{.docutils .literal .notranslate} instance. Although this isn't absolutely incorrect it's almost certainly not what the user intended. Here the face created by make_face{.docutils .literal .notranslate} will be reoriented to Plane.XY{.docutils .literal .notranslate} as all sketching must be done on that plane. This reorienting of objects to Plane.XY{.docutils .literal .notranslate} allows a user to add{.docutils .literal .notranslate} content from other sources to the sketch without having to manually re-orient the object.

Unless there is a good reason and the user understands how the BuildLine{.docutils .literal .notranslate} object will be reoriented, all BuildLine{.docutils .literal .notranslate} instances within the scope of BuildSketch{.docutils .literal .notranslate} should be done on the default Plane.XY{.docutils .literal .notranslate}. :::

::: {#tips.xhtml#don-t-builders-inherit-workplane-coordinate-systems-when-nested .section}

Don't Builders inherit workplane/coordinate systems when nested

Some users expect that nested Builders will inherit the workplane or coordinate system from their parent Builder - this is not true. When a Builder is instantiated, a workplane is either provided by the user or it defaults to Plane.XY{.docutils .literal .notranslate}. Having Builders inherent coordinate systems from their parents could result in confusion when they are nested as well as change their behaviour depending on which scope they are in. Inheriting coordinate systems isn't necessarily incorrect, it was considered for build123d but ultimately the simple static approach was taken. ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#import_export.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#import_export.xhtml#import-export .section}

Import/Export

Methods and functions specific to exporting and importing build123d objects are defined below.

For example:

::: {.highlight-build123d .notranslate} ::: highlight with BuildPart() as box_builder: Box(1, 1, 1) export_step(box_builder.part, "box.step") ::: :::

::: {#import_export.xhtml#file-formats .section}

File Formats

::: {#import_export.xhtml#mf .section}

3MF

The 3MF (3D Manufacturing Format) file format is a versatile and modern standard for representing 3D models used in additive manufacturing, 3D printing, and other applications. Developed by the 3MF Consortium, it aims to overcome the limitations of traditional 3D file formats by providing a more efficient and feature-rich solution. The 3MF format supports various advanced features like color information, texture mapping, multi-material definitions, and precise geometry representation, enabling seamless communication between design software, 3D printers, and other manufacturing devices. Its open and extensible nature makes it an ideal choice for exchanging complex 3D data in a compact and interoperable manner. :::

::: {#import_export.xhtml#brep .section}

BREP

The BREP (Boundary Representation) file format is a widely used data format in computer-aided design (CAD) and computer-aided engineering (CAE) applications. BREP represents 3D geometry using topological entities like vertices, edges, and faces, along with their connectivity information. It provides a precise and comprehensive representation of complex 3D models, making it suitable for advanced modeling and analysis tasks. BREP files are widely supported by various CAD software, enabling seamless data exchange between different systems. Its ability to represent both geometric shapes and their topological relationships makes it a fundamental format for storing and sharing detailed 3D models. :::

::: {#import_export.xhtml#dxf .section}

DXF

The DXF (Drawing Exchange Format) file format is a widely used standard for representing 2D and 3D drawings, primarily used in computer-aided design (CAD) applications. Developed by Autodesk, DXF files store graphical and geometric data, such as lines, arcs, circles, and text, as well as information about layers, colors, and line weights. Due to its popularity, DXF files can be easily exchanged and shared between different CAD software. The format's simplicity and human-readable structure make it a versatile choice for sharing designs, drawings, and models across various CAD platforms, facilitating seamless collaboration in engineering and architectural projects. :::

::: {#import_export.xhtml#gltf .section}

glTF

The glTF (GL Transmission Format) is a royalty-free specification for the efficient transmission and loading of 3D models and scenes by applications. Developed by the Khronos Group, glTF is designed as a compact, interoperable format that enables the quick display of assets across various platforms and devices. glTF supports a rich feature set, including detailed meshes, materials, textures, skeletal animations, and more, facilitating complex 3D visualizations. It streamlines the process of sharing and deploying 3D content in web applications, game engines, and other visualization tools, making it the "JPEG of 3D." glTF's versatility and efficiency have led to its widespread adoption in the 3D content industry. :::

::: {#import_export.xhtml#stl .section}

STL

The STL (STereoLithography) file format is a widely used file format in 3D printing and computer-aided design (CAD) applications. It represents 3D geometry using triangular facets to approximate the surface of a 3D model. STL files are widely supported and can store both the geometry and color information of the model. They are used for rapid prototyping and 3D printing, as they provide a simple and efficient way to represent complex 3D objects. The format's popularity stems from its ease of use, platform independence, and ability to accurately describe the surface of intricate 3D models with a minimal file size. :::

::: {#import_export.xhtml#step .section}

STEP

The STEP (Standard for the Exchange of Product model data) file format is a widely used standard for representing 3D product and manufacturing data in computer-aided design (CAD) and computer-aided engineering (CAE) applications. It is an ISO standard (ISO 10303) and supports the representation of complex 3D geometry, product structure, and metadata. STEP files store information in a neutral and standardized format, making them highly interoperable across different CAD/CAM software systems. They enable seamless data exchange between various engineering disciplines, facilitating collaboration and data integration throughout the entire product development and manufacturing process. :::

::: {#import_export.xhtml#svg .section}

SVG

The SVG (Scalable Vector Graphics) file format is an XML-based standard used for describing 2D vector graphics. It is widely supported and can be displayed in modern web browsers, making it suitable for web-based graphics and interactive applications. SVG files define shapes, paths, text, and images using mathematical equations, allowing for smooth scalability without loss of quality. The format is ideal for logos, icons, illustrations, and other graphics that require resolution independence. SVG files are also easily editable in text editors or vector graphic software, making them a popular choice for designers and developers seeking flexible and versatile graphic representation. ::: :::

::: {#import_export.xhtml#d-exporters .section}

2D Exporters

Exports to DXF (Drawing Exchange Format) and SVG (Scalable Vector Graphics) are provided by the 2D Exporters: ExportDXF and ExportSVG classes.

DXF is a widely used file format for exchanging CAD (Computer-Aided Design) data between different software applications. SVG is a widely used vector graphics format that is supported by web browsers and various graphic editors.

The core concept to these classes is the creation of a DXF/SVG document with specific properties followed by the addition of layers and shapes to the documents. Once all of the layers and shapes have been added, the document can be written to a file.

::: {#import_export.xhtml#d-to-2d-projection .section}

3D to 2D Projection

There are a couple ways to generate a 2D drawing of a 3D part:

  • Generate a section: The section(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} operation can be used to create a 2D cross section of a 3D part at a given plane.

  • Generate a projection: The project_to_viewport(){.xref .py .py-meth .docutils .literal .notranslate} method can be used to create a 2D projection of a 3D scene. Similar to a camera, the viewport_origin{.docutils .literal .notranslate} defines the location of camera, the viewport_up{.docutils .literal .notranslate} defines the orientation of the camera, and the look_at{.docutils .literal .notranslate} parameter defined where the camera is pointed. By default, viewport_up{.docutils .literal .notranslate} is the positive z axis and look_up{.docutils .literal .notranslate} is the center of the shape. The return value is a tuple of lists of edges, the first the visible edges and the second the hidden edges.

Each of these Edges and Faces can be assigned different line color/types and fill colors as described below (as project_to_viewport{.docutils .literal .notranslate} only generates Edges, fill doesn't apply). The shapes generated from the above steps are to be added as shapes in one of the exporters described below and written as either a DXF or SVG file as shown in this example:

::: {.highlight-build123d .notranslate} ::: highlight view_port_origin=(-100, -50, 30) visible, hidden = part.project_to_viewport(view_port_origin) max_dimension = max(*Compound(children=visible + hidden).bounding_box().size) exporter = ExportSVG(scale=100 / max_dimension) 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("part_projection.svg") ::: ::: :::

::: {#import_export.xhtml#linetype .section}

LineType

ANSI (American National Standards Institute) and ISO (International Organization for Standardization) standards both define line types in drawings used in DXF and SVG exported drawings:

ANSI Standards:

:   -   ANSI/ASME Y14.2 - "Line Conventions and Lettering" is the standard that defines line types, line weights, and line usage in engineering drawings in the United States.
ISO Standards:

:   -   ISO 128 - "Technical drawings -- General principles of presentation" is the ISO standard that covers the general principles of technical drawing presentation, including line types and line conventions.

    -   ISO 13567 - "Technical product documentation (TPD) -- Organization and naming of layers for CAD" provides guidelines for the organization and naming of layers in Computer-Aided Design (CAD) systems, which may include line type information.

These standards help ensure consistency and clarity in technical drawings, making it easier for engineers, designers, and manufacturers to communicate and interpret the information presented in the drawings.

The line types used by the 2D Exporters are defined by the LineType{.xref .py .py-class .docutils .literal .notranslate} Enum and are shown in the following diagram:

{.align-center} :::

::: {#import_export.xhtml#exportdxf .section}

ExportDXF

[class]{.pre}[ ]{.w}[[ExportDXF]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[version:]{.pre} [str]{.pre} [=]{.pre} ['AC1027']{.pre}]{.n}, [[unit:]{.pre} [~build123d.build_enums.Unit]{.pre} [=]{.pre} [<Unit.MM>]{.pre}]{.n}, [[color:]{.pre} [~exporters.ColorIndex]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[line_weight:]{.pre} [float]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[line_type:]{.pre} [~exporters.LineType]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}[)]{.sig-paren}

The ExportDXF class provides functionality for exporting 2D shapes to DXF (Drawing Exchange Format) format. DXF is a widely used file format for exchanging CAD (Computer-Aided Design) data between different software applications.

Parameters[:]{.colon}
  • version (str, optional) -- The DXF version to use for the output file. Defaults to ezdxf.DXF2013.

  • unit (Unit, optional) -- The unit used for the exported DXF. It should be one of the Unit enums: Unit.MC, Unit.MM, Unit.CM, Unit.M, Unit.IN, or Unit.FT. Defaults to Unit.MM.

  • color (Optional[ColorIndex], optional) -- The default color index for shapes. It can be specified as a ColorIndex enum or None.. Defaults to None.

  • line_weight (Optional[float], optional) -- The default line weight (stroke width) for shapes, in millimeters. . Defaults to None.

  • line_type (Optional[LineType], optional) -- e default line type for shapes. It should be a LineType enum or None.. Defaults to None.

Example

::: {.highlight-python .notranslate} ::: highlight exporter = ExportDXF(unit=Unit.MM, line_weight=0.5) exporter.add_layer("Layer 1", color=ColorIndex.RED, line_type=LineType.DASHED) exporter.add_shape(shape_object, layer="Layer 1") exporter.write("output.dxf") ::: :::

Raises[:]{.colon}

ValueError -- unit not supported

[[METRIC_UNITS]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[{<Unit.CM>,]{.pre} [<Unit.M>,]{.pre} [<Unit.MM>}]{.pre}
[[add_layer]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[name]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}, [[*]{.pre}]{.o}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[ColorIndex]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[line_weight]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[line_type]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[LineType]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Adds a new layer to the DXF export with the given properties.

Parameters[:]{.colon}
  • name (str) -- The name of the layer definition. Must be unique among all layers.

  • color (Optional[ColorIndex], optional) -- The color index for shapes on this layer. It can be specified as a ColorIndex enum or None. Defaults to None.

  • line_weight (Optional[float], optional) -- The line weight (stroke width) for shapes on this layer, in millimeters. Defaults to None.

  • line_type (Optional[LineType], optional) -- The line type for shapes on this layer. It should be a LineType enum or None. Defaults to None.

Returns[:]{.colon}

DXF document with additional layer

Return type[:]{.colon}

Self

[[add_shape]{.pre}]{.sig-name .descname}[(]{.sig-paren}shape]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}[ ]{.w}[[{.pre}]{.p}]{.n}, [[layer]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Adds a shape to the specified layer.

Parameters[:]{.colon}
  • shape (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal} | Iterable[Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- The shape or collection of shapes to be added. It can be a single Shape object or an iterable of Shape objects.

  • layer (str, optional) -- The name of the layer where the shape will be added. If not specified, the default layer will be used. Defaults to "".

Returns[:]{.colon}

Document with additional shape

Return type[:]{.colon}

Self

[[write]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[file_name]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[PathLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[str]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[bytes]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[BytesIO]{.pre}]{.n}[)]{.sig-paren}

Writes the DXF data to the specified file name.

Parameters[:]{.colon}

file_name (PathLike | str | bytes | BytesIO) -- The file name (including path) where the DXF data will be written. :::

::: {#import_export.xhtml#exportsvg .section}

ExportSVG

[class]{.pre}[ ]{.w}[[ExportSVG]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[unit:]{.pre} [~build123d.build_enums.Unit]{.pre} [=]{.pre} [<Unit.MM>]{.pre}]{.n}, [[scale:]{.pre} [float]{.pre} [=]{.pre} [1]{.pre}]{.n}, [[margin:]{.pre} [float]{.pre} [=]{.pre} [0]{.pre}]{.n}, [[fit_to_stroke:]{.pre} [bool]{.pre} [=]{.pre} [True]{.pre}]{.n}, [[precision:]{.pre} [int]{.pre} [=]{.pre} [6]{.pre}]{.n}, [[fill_color:]{.pre} [~exporters.ColorIndex]{.pre} [|]{.pre} [~ezdxf.colors.RGB]{.pre} [|]{.pre} [~build123d.geometry.Color]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[line_color:]{.pre} [~exporters.ColorIndex]{.pre} [|]{.pre} [~ezdxf.colors.RGB]{.pre} [|]{.pre} [~build123d.geometry.Color]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [ColorIndex.BLACK]{.pre}]{.n}, [[line_weight:]{.pre} [float]{.pre} [=]{.pre} [0.09]{.pre}]{.n}, [[line_type:]{.pre} [~exporters.LineType]{.pre} [=]{.pre} [LineType.CONTINUOUS]{.pre}]{.n}, [[dot_length:]{.pre} [~exporters.DotLength]{.pre} [|]{.pre} [float]{.pre} [=]{.pre} [DotLength.INKSCAPE_COMPAT]{.pre}]{.n}[)]{.sig-paren}

SVG file export functionality.

The ExportSVG class provides functionality for exporting 2D shapes to SVG (Scalable Vector Graphics) format. SVG is a widely used vector graphics format that is supported by web browsers and various graphic editors.

Parameters[:]{.colon}
  • unit (Unit, optional) -- The unit used for the exported SVG. It should be one of the Unit enums: Unit.MM, Unit.CM, or Unit.IN. Defaults to Unit.MM.

  • scale (float, optional) -- The scaling factor applied to the exported SVG. Defaults to 1.

  • margin (float, optional) -- The margin added around the exported shapes. Defaults to 0.

  • fit_to_stroke (bool, optional) -- A boolean indicating whether the SVG view box should fit the strokes of the shapes. Defaults to True.

  • precision (int, optional) -- The number of decimal places used for rounding coordinates in the SVG. Defaults to 6.

  • fill_color (ColorIndex | RGB | None, optional) -- The default fill color for shapes. It can be specified as a ColorIndex, an RGB tuple, or None. Defaults to None.

  • line_color (ColorIndex | RGB | None, optional) -- The default line color for shapes. It can be specified as a ColorIndex or an RGB tuple, or None. Defaults to Export2D.DEFAULT_COLOR_INDEX.

  • line_weight (float, optional) -- The default line weight (stroke width) for shapes, in millimeters. Defaults to Export2D.DEFAULT_LINE_WEIGHT.

  • line_type (LineType, optional) -- The default line type for shapes. It should be a LineType enum. Defaults to Export2D.DEFAULT_LINE_TYPE.

  • dot_length (DotLength | float, optional) -- The width of rendered dots in a Can be either a DotLength enum or a float value in tenths of an inch. Defaults to DotLength.INKSCAPE_COMPAT.

Example

::: {.highlight-python .notranslate} ::: highlight exporter = ExportSVG(unit=Unit.MM, line_weight=0.5) exporter.add_layer("Layer 1", fill_color=(255, 0, 0), line_color=(0, 0, 255)) exporter.add_shape(shape_object, layer="Layer 1") exporter.write("output.svg") ::: :::

Raises[:]{.colon}

ValueError -- Invalid unit.

[[add_layer]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[name]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}, [[*]{.pre}]{.o}, [[fill_color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[ColorIndex]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[RGB]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Color]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[line_color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[ColorIndex]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[RGB]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Color]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[ColorIndex.BLACK]{.pre}]{.default_value}, [[line_weight]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.09]{.pre}]{.default_value}, [[line_type]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[LineType]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[LineType.CONTINUOUS]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Adds a new layer to the SVG export with the given properties.

Parameters[:]{.colon}
  • name (str) -- The name of the layer. Must be unique among all layers.

  • fill_color (ColorIndex | RGB | Color{.hxr-hoverxref .hxr-tooltip .reference .internal} | None, optional) -- The fill color for shapes on this layer. It can be specified as a ColorIndex, an RGB tuple, a Color, or None. Defaults to None.

  • line_color (ColorIndex | RGB | Color{.hxr-hoverxref .hxr-tooltip .reference .internal} | None, optional) -- The line color for shapes on this layer. It can be specified as a ColorIndex or an RGB tuple, a Color, or None. Defaults to Export2D.DEFAULT_COLOR_INDEX.

  • line_weight (float, optional) -- The line weight (stroke width) for shapes on this layer, in millimeters. Defaults to Export2D.DEFAULT_LINE_WEIGHT.

  • line_type (LineType, optional) -- The line type for shapes on this layer. It should be a LineType enum. Defaults to Export2D.DEFAULT_LINE_TYPE.

Raises[:]{.colon}
  • ValueError -- Duplicate layer name

  • ValueError -- Unknown linetype

Returns[:]{.colon}

Drawing with an additional layer

Return type[:]{.colon}

Self

[[add_shape]{.pre}]{.sig-name .descname}[(]{.sig-paren}shape]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}[ ]{.w}[[{.pre}]{.p}]{.n}, [[layer]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[reverse_wires]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}[)]{.sig-paren}

Adds a shape or a collection of shapes to the specified layer.

Parameters[:]{.colon}
  • shape (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal} | Iterable[Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- The shape or collection of shapes to be added. It can be a single Shape object or an iterable of Shape objects.

  • layer (str, optional) -- The name of the layer where the shape(s) will be added. Defaults to "".

  • reverse_wires (bool, optional) -- A boolean indicating whether the wires of the shape(s) should be in reversed direction. Defaults to False.

Raises[:]{.colon}

ValueError -- Undefined layer

[[write]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[path]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[PathLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[str]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[bytes]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[BytesIO]{.pre}]{.n}[)]{.sig-paren}

Writes the SVG data to the specified file path.

Parameters[:]{.colon}

path (PathLike | str | bytes | BytesIO) -- The file path where the SVG data will be written. ::: :::

::: {#import_export.xhtml#module-exporters3d .section} []{#import_export.xhtml#id1}

3D Exporters

[[export_brep]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[to_export]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}]{.n}, [[file_path]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[PathLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[str]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[bytes]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[BytesIO]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

Export this shape to a BREP file

Parameters[:]{.colon}
  • to_export (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- object or assembly

  • file_path -- Union[PathLike, str, bytes, BytesIO]: brep file path or memory buffer

Returns[:]{.colon}

write status

Return type[:]{.colon}

bool

<!-- -->
[[export_gltf]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[to_export:]{.pre} [~build123d.topology.shape_core.Shape]{.pre}]{.n}, [[file_path:]{.pre} [~os.PathLike]{.pre} [|]{.pre} [str]{.pre} [|]{.pre} [bytes]{.pre}]{.n}, [[unit:]{.pre} [~build123d.build_enums.Unit]{.pre} [=]{.pre} [<Unit.MM>]{.pre}]{.n}, [[binary:]{.pre} [bool]{.pre} [=]{.pre} [False]{.pre}]{.n}, [[linear_deflection:]{.pre} [float]{.pre} [=]{.pre} [0.001]{.pre}]{.n}, [[angular_deflection:]{.pre} [float]{.pre} [=]{.pre} [0.1]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

The glTF (GL Transmission Format) specification primarily focuses on the efficient transmission and loading of 3D models as a compact, binary format that is directly renderable by graphics APIs like WebGL, OpenGL, and Vulkan. It's designed to store detailed 3D model data, including meshes (vertices, normals, textures, etc.), animations, materials, and scene hierarchy, among other aspects.

Parameters[:]{.colon}
  • to_export (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- object or assembly

  • file_path (Union[PathLike, str, bytes]) -- glTF file path

  • unit (Unit, optional) -- shape units. Defaults to Unit.MM.

  • binary (bool, optional) -- output format. Defaults to False.

  • linear_deflection (float, optional) -- A linear deflection setting which limits the distance between a curve and its tessellation. Setting this value too low will result in large meshes that can consume computing resources. Setting the value too high can result in meshes with a level of detail that is too low. The default is a good starting point for a range of cases. Defaults to 1e-3.

  • angular_deflection (float, optional) -- Angular deflection setting which limits the angle between subsequent segments in a polyline. Defaults to 0.1.

Raises[:]{.colon}

RuntimeError -- Failed to write glTF file

Returns[:]{.colon}

write status

Return type[:]{.colon}

bool

<!-- -->
[[export_step]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[to_export:]{.pre} [~build123d.topology.shape_core.Shape]{.pre}]{.n}, [[file_path:]{.pre} [~os.PathLike]{.pre} [|]{.pre} [str]{.pre} [|]{.pre} [bytes]{.pre} [|]{.pre} [~_io.BytesIO]{.pre}]{.n}, [[unit:]{.pre} [~build123d.build_enums.Unit]{.pre} [=]{.pre} [<Unit.MM>]{.pre}]{.n}, [[write_pcurves:]{.pre} [bool]{.pre} [=]{.pre} [True]{.pre}]{.n}, [[precision_mode:]{.pre} [~build123d.build_enums.PrecisionMode]{.pre} [=]{.pre} [<PrecisionMode.AVERAGE>]{.pre}]{.n}, [[*]{.pre}]{.n}, [[timestamp:]{.pre} [str]{.pre} [|]{.pre} [~datetime.datetime]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

Export a build123d Shape or assembly with color and label attributes. Note that if the color of a node in an assembly isn't set, it will be assigned the color of its nearest ancestor.

Parameters[:]{.colon}
  • to_export (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- object or assembly

  • file_path (Union[PathLike, str, bytes, BytesIO]) -- step file path

  • unit (Unit, optional) -- shape units. Defaults to Unit.MM.

  • write_pcurves (bool, optional) -- write parametric curves to the STEP file. Defaults to True.

  • precision_mode (PrecisionMode, optional) -- geometric data precision. Defaults to PrecisionMode.AVERAGE.

Raises[:]{.colon}

RuntimeError -- Unknown Compound type

Returns[:]{.colon}

success

Return type[:]{.colon}

bool

<!-- -->
[[export_stl]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[to_export]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}]{.n}, [[file_path]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[PathLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[str]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[bytes]{.pre}]{.n}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.001]{.pre}]{.default_value}, [[angular_tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.1]{.pre}]{.default_value}, [[ascii_format]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

Export STL

Exports a shape to a specified STL file.

Parameters[:]{.colon}
  • to_export (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- object or assembly

  • file_path (Union[PathLike, str, bytes]) -- The path and file name to write the STL output to.

  • tolerance (float, optional) -- A linear deflection setting which limits the distance between a curve and its tessellation. Setting this value too low will result in large meshes that can consume computing resources. Setting the value too high can result in meshes with a level of detail that is too low. The default is a good starting point for a range of cases. Defaults to 1e-3.

  • angular_tolerance (float, optional) -- Angular deflection setting which limits the angle between subsequent segments in a polyline. Defaults to 0.1.

  • ascii_format (bool, optional) -- Export the file as ASCII (True) or binary (False) STL format. Defaults to False (binary).

Returns[:]{.colon}

Success

Return type[:]{.colon}

bool

::: {#import_export.xhtml#d-mesh-export .section}

3D Mesh Export

Both 3MF and STL export (and import) are provided with the Mesher{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} class. As mentioned above, the 3MF format it provides is feature-rich and therefore has a slightly more complex API than the simple Shape exporters.

For example:

::: {.highlight-build123d .notranslate} ::: highlight # Create the shapes and assign attributes blue_shape = Solid.make_cone(20, 0, 50) blue_shape.color = Color("blue") blue_shape.label = "blue" blue_uuid = uuid.uuid1() red_shape = Solid.make_cylinder(5, 50).move(Location((0, -30, 0))) red_shape.color = Color("red") red_shape.label = "red"

# Create a Mesher instance as an exporter, add shapes and write
exporter = Mesher()
exporter.add_shape(blue_shape, part_number="blue-1234-5", uuid_value=blue_uuid)
exporter.add_shape(red_shape)
exporter.add_meta_data(
    name_space="custom",
    name="test_meta_data",
    value="hello world",
    metadata_type="str",
    must_preserve=False,
)
exporter.add_code_to_metadata()
exporter.write("example.3mf")
exporter.write("example.stl")

::: :::

[class]{.pre}[ ]{.w}[[Mesher]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[unit:]{.pre} [~build123d.build_enums.Unit]{.pre} [=]{.pre} [<Unit.MM>]{.pre}]{.n}[)]{.sig-paren}

Tool for exporting and importing meshed objects stored in 3MF or STL files.

Parameters[:]{.colon}

unit (Unit, optional) -- model units. Defaults to Unit.MM.

[[add_code_to_metadata]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren}

Add the code calling this method to the 3MF metadata with the custom name space <cite>{=html}build123d</cite>{=html}, name equal to the base file name and the type as <cite>{=html}python</cite>{=html}

[[add_meta_data]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[name_space]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}, [[name]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}, [[value]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}, [[metadata_type]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}, [[must_preserve]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[)]{.sig-paren}

Add meta data to the models

Parameters[:]{.colon}
  • name_space (str) -- categorizer of different metadata entries

  • name (str) -- metadata label

  • value (str) -- metadata content

  • metadata_type (str) -- metadata type

  • must_preserve (bool) -- metadata must not be removed if unused

[[add_shape]{.pre}]{.sig-name .descname}[(]{.sig-paren}[shape:]{.pre} [~build123d.topology.shape_core.Shape]{.pre} [|]{.pre} [~collections.abc.Iterable[~build123d.topology.shape_core.Shape],]{.pre} [linear_deflection:]{.pre} [float]{.pre} [=]{.pre} [0.001,]{.pre} [angular_deflection:]{.pre} [float]{.pre} [=]{.pre} [0.1,]{.pre} [mesh_type:]{.pre} [~build123d.build_enums.MeshType]{.pre} [=]{.pre} [<MeshType.MODEL>,]{.pre} [part_number:]{.pre} [str]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [uuid_value:]{.pre} [~uuid.UUID]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}[)]{.sig-paren}

Add a shape to the 3MF/STL file.

Parameters[:]{.colon}
  • shape (Union[Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}, Iterable[Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}]]) -- build123d object

  • linear_deflection (float, optional) -- mesh control for edges. Defaults to 0.001.

  • angular_deflection (float, optional) -- mesh control for non-planar surfaces. Defaults to 0.1.

  • mesh_type (MeshType, optional) -- 3D printing use of mesh. Defaults to MeshType.MODEL.

  • part_number (str, optional) -- part #. Defaults to None.

  • uuid_value (uuid, optional) -- value from uuid package. Defaults to None.

Raises[:]{.colon}
  • RuntimeError -- 3mf mesh is invalid

  • Warning -- Degenerate shape skipped

  • Warning -- 3mf mesh is not manifold

get_mesh_properties]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[list]{.pre}[[[]{.pre}]{.p}[dict]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Retrieve the properties from all the meshes

get_meta_data]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[list]{.pre}[[[]{.pre}]{.p}[dict]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Retrieve all of the metadata

[[get_meta_data_by_key]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[name_space]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}, [[name]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[dict]{.pre}]{.sig-return-typehint}]{.sig-return}

Retrieve the metadata value and type for the provided name space and name

[property]{.pre}[ ]{.w}[[library_version]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[str]{.pre}

3MF Consortium Lib#MF version

[property]{.pre}[ ]{.w}[[mesh_count]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[int]{.pre}

Number of meshes in the model

[property]{.pre}[ ]{.w}[[model_unit]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Unit]{.pre}

Unit used in the model

[[read]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[file_name]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[PathLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[str]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[bytes]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[list]{.pre}[[[]{.pre}]{.p}[Shape]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}
Parameters[:]{.colon}
  • Union[PathLike (file_name) -- file path

  • str -- file path

  • bytes] -- file path

Raises[:]{.colon}

ValueError -- Unknown file format - must be 3mf or stl

Returns[:]{.colon}

build123d shapes extracted from mesh file

Return type[:]{.colon}

list[Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}]

[property]{.pre}[ ]{.w}[[triangle_counts]{.pre}]{.sig-name .descname}:]{.pre}]{.p}[ ]{.w}[list]{.pre}[[[]{.pre}]{.p}[int]{.pre}[[{.pre}]{.p}

Number of triangles in each of the model's meshes

[property]{.pre}[ ]{.w}[[vertex_counts]{.pre}]{.sig-name .descname}:]{.pre}]{.p}[ ]{.w}[list]{.pre}[[[]{.pre}]{.p}[int]{.pre}[[{.pre}]{.p}

Number of vertices in each of the models's meshes

[[write]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[file_name]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[PathLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[str]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[bytes]{.pre}]{.n}[)]{.sig-paren}
Parameters[:]{.colon}
  • Union[Pathlike (file_name) -- file path

  • str -- file path

  • bytes] -- file path

Raises[:]{.colon}

ValueError -- Unknown file format - must be 3mf or stl

[[write_stream]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[stream]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[BytesIO]{.pre}]{.n}, [[file_type]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[)]{.sig-paren}

::: {.admonition .note} Note

If you need to align multiple components for 3D printing, you can use the [pack()]{.std .std-ref}{.reference .internal} function to arrange the objects side by side and align them on the same plane. This ensures that your components are well-organized and ready for the printing process. ::: ::: :::

::: {#import_export.xhtml#module-importers .section} []{#import_export.xhtml#d-importers}

2D Importers

[[import_svg]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[svg_file:]{.pre} [str]{.pre} [|]{.pre} [~pathlib.Path]{.pre} [|]{.pre} [~typing.TextIO]{.pre}]{.n}, [[*]{.pre}]{.n}, [[flip_y:]{.pre} [bool]{.pre} [=]{.pre} [True]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [<Align.MIN>]{.pre}]{.n}, [[ignore_visibility:]{.pre} [bool]{.pre} [=]{.pre} [False]{.pre}]{.n}, [[label_by:]{.pre} [~typing.Literal['id']{.pre}]{.n}, [['class']{.pre}]{.n}, 'inkscape:label'{.pre} [|]{.pre} [str]{.pre} [=]{.pre} ['id']{.pre}]{.n}, [[is_inkscape_label:]{.pre} [bool]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[ShapeList]{.pre}[[[]{.pre}]{.p}[Wire]{.pre}[ ]{.w}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}
Parameters[:]{.colon}
  • svg_file (Union[str, Path, TextIO]) -- svg file

  • flip_y (bool, optional) -- flip objects to compensate for svg orientation. Defaults to True.

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}] | None, optional) -- alignment of the SVG's viewbox, if None, the viewbox's origin will be at <cite>{=html}(0,0,0)</cite>{=html}. Defaults to Align.MIN.

  • ignore_visibility (bool, optional) -- Defaults to False.

  • label_by (str, optional) -- XML attribute to use for imported shapes' <cite>{=html}label</cite>{=html} property. Defaults to "id". Use <cite>{=html}inkscape:label</cite>{=html} to read labels set from Inkscape's "Layers and Objects" panel.

Raises[:]{.colon}

ValueError -- unexpected shape type

Returns[:]{.colon}

objects contained in svg

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Union[Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}, Face{.hxr-hoverxref .hxr-tooltip .reference .internal}]]

<!-- -->
[[import_svg_as_buildline_code]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[file_name]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[PathLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[str]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[bytes]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[str]{.pre}[[,]{.pre}]{.p}[ ]{.w}[str]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

translate_to_buildline_code

Translate the contents of the given svg file into executable build123d/BuildLine code.

Parameters[:]{.colon}

file_name (Union[PathLike, str, bytes]) -- svg file name

Returns[:]{.colon}

code, builder instance name

Return type[:]{.colon}

tuple[str, str] :::

::: {#import_export.xhtml#id2 .section}

3D Importers

[[import_brep]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[file_name]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[PathLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[str]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[bytes]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Shape]{.pre}]{.sig-return-typehint}]{.sig-return}

Import shape from a BREP file

Parameters[:]{.colon}

file_name (Union[PathLike, str, bytes]) -- brep file

Raises[:]{.colon}

ValueError -- file not found

Returns[:]{.colon}

build123d object

Return type[:]{.colon}

Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[[import_step]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[filename]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[PathLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[str]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[bytes]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Compound]{.pre}]{.sig-return-typehint}]{.sig-return}

Extract shapes from a STEP file and return them as a Compound object.

Parameters[:]{.colon}

file_name (Union[PathLike, str, bytes]) -- file path of STEP file to import

Raises[:]{.colon}

ValueError -- can't open file

Returns[:]{.colon}

contents of STEP file

Return type[:]{.colon}

Compound{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[[import_stl]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[file_name]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[PathLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[str]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[bytes]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}]{.sig-return-typehint}]{.sig-return}

Extract shape from an STL file and return it as a Face reference object.

Note that importing with this method and creating a reference is very fast while creating an editable model (with Mesher) may take minutes depending on the size of the STL file.

Parameters[:]{.colon}

file_name (Union[PathLike, str, bytes]) -- file path of STL file to import

Raises[:]{.colon}

ValueError -- Could not import file

Returns[:]{.colon}

STL model

Return type[:]{.colon}

Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

::: {#import_export.xhtml#d-mesh-import .section}

3D Mesh Import

Both 3MF and STL import (and export) are provided with the Mesher{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} class.

For example:

::: {.highlight-build123d .notranslate} ::: highlight importer = Mesher() cone, cyl = importer.read("example.3mf") print( f"{importer.mesh_count=}, {importer.vertex_counts=}, {importer.triangle_counts=}" ) print(f"Imported model unit: {importer.model_unit}") print(f"{cone.label=}") print(f"{cone.color.to_tuple()=}") print(f"{cyl.label=}") print(f"{cyl.color.to_tuple()=}") ::: :::

::: {.highlight-none .notranslate} ::: highlight importer.mesh_count=2, importer.vertex_counts=[66, 52], importer.triangle_counts=[128, 100] Imported model unit: Unit.MM cone.label='blue' cone.color.to_tuple()=(0.0, 0.0, 1.0, 1.0) cyl.label='red' cyl.color.to_tuple()=(1.0, 0.0, 0.0, 1.0) ::: ::: ::: ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#advanced.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#advanced.xhtml#advanced-topics .section}

Advanced Topics

::: {.toctree-wrapper .compound}

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#algebra_performance.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#algebra_performance.xhtml#performance-considerations-in-algebra-mode .section} []{#algebra_performance.xhtml#algebra-performance}

Performance considerations in algebra mode

Creating lots of Shapes in a loop means for every step fuse{.docutils .literal .notranslate} and clean{.docutils .literal .notranslate} will be called. In an example like the below, both functions get slower and slower the more objects are already fused. Overall it takes on an M1 Mac 4.76 sec.

::: {.highlight-build123d .notranslate} ::: highlight diam = 80 holes = Sketch() r = Rectangle(2, 2) for loc in GridLocations(4, 4, 20, 20): if loc.position.X2 + loc.position.Y2 < (diam / 2 - 1.8) ** 2: holes += loc * r

c = Circle(diam / 2) - holes

::: :::

One way to avoid it is to use lazy evaluation for the algebra operations. Just collect all objects and then call fuse{.docutils .literal .notranslate} (+{.docutils .literal .notranslate}) once with all objects and clean{.docutils .literal .notranslate} once. Overall it takes 0.19 sec.

::: {.highlight-build123d .notranslate} ::: highlight r = Rectangle(2, 2) holes = [ loc * r for loc in GridLocations(4, 4, 20, 20).locations if loc.position.X2 + loc.position.Y2 < (diam / 2 - 1.8) ** 2 ]

c = Circle(diam / 2) - holes

::: :::

Another way to leverage the vectorized algebra operations is to add a list comprehension of objects to an empty Part{.docutils .literal .notranslate}, Sketch{.docutils .literal .notranslate} or Curve{.docutils .literal .notranslate}:

::: {.highlight-build123d .notranslate} ::: highlight polygons = Sketch() + [ loc * RegularPolygon(radius=5, side_count=5) for loc in GridLocations(40, 30, 2, 2) ] ::: :::

This again ensures one single fuse{.docutils .literal .notranslate} and clean{.docutils .literal .notranslate} call. :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#location_arithmetic.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#location_arithmetic.xhtml#location-arithmetic-for-algebra-mode .section} []{#location_arithmetic.xhtml#location-arithmetics}

Location arithmetic for algebra mode

::: {#location_arithmetic.xhtml#position-a-shape-relative-to-the-xy-plane .section}

Position a shape relative to the XY plane

For the following use the helper function:

::: {.highlight-build123d .notranslate} ::: highlight def location_symbol(location: Location, scale: float = 1) -> Compound: return Compound.make_triad(axes_scale=scale).locate(location)

def plane_symbol(plane: Plane, scale: float = 1) -> Compound:
    triad = Compound.make_triad(axes_scale=scale)
    circle = Circle(scale * .8).edge()
    return (triad + circle).locate(plane.location)

::: :::

  1. Positioning at a location

    ::: {.highlight-build123d .notranslate} ::: highlight ::: :::

    loc = Location((0.1, 0.2, 0.3), (10, 20, 30))

    face = loc * Rectangle(1, 2)

    show_object(face, name="face") show_object(location_symbol(loc), name="location")

  1. Positioning on a plane

    ::: {.highlight-build123d .notranslate} ::: highlight ::: :::

    plane = Plane.XZ

    face = plane * Rectangle(1, 2)

    show_object(face, name="face") show_object(plane_symbol(plane), name="plane")

Note: The x{.docutils .literal .notranslate}-axis and the y{.docutils .literal .notranslate}-axis of the plane are on the x{.docutils .literal .notranslate}-axis and the z{.docutils .literal .notranslate}-axis of the world coordinate system (red and blue axis). :::

::: {#location_arithmetic.xhtml#relative-positioning-to-a-plane .section}

Relative positioning to a plane

  1. Position an object on a plane relative to the plane

    ::: {.highlight-build123d .notranslate} ::: highlight ::: :::

    loc = Location((0.1, 0.2, 0.3), (10, 20, 30))

    face = loc * Rectangle(1,2)

    box = Plane(loc) * Pos(0.2, 0.4, 0.1) * Box(0.2, 0.2, 0.2) # box = Plane(face.location) * Pos(0.2, 0.4, 0.1) * Box(0.2, 0.2, 0.2) # box = loc * Pos(0.2, 0.4, 0.1) * Box(0.2, 0.2, 0.2)

    show_object(face, name="face") show_object(location_symbol(loc), name="location") show_object(box, name="box")

The X{.docutils .literal .notranslate}, Y{.docutils .literal .notranslate}, Z{.docutils .literal .notranslate} components of Pos(0.2, 0.4, 0.1){.docutils .literal .notranslate} are relative to the x{.docutils .literal .notranslate}-axis, y{.docutils .literal .notranslate}-axis or z{.docutils .literal .notranslate}-axis of the underlying location loc{.docutils .literal .notranslate}.

Note: Plane(loc) *{.docutils .literal .notranslate}, Plane(face.location) *{.docutils .literal .notranslate} and loc *{.docutils .literal .notranslate} are equivalent in this example.

  1. Rotate an object on a plane relative to the plane

    ::: {.highlight-build123d .notranslate} ::: highlight ::: :::

    loc = Location((0.1, 0.2, 0.3), (10, 20, 30))

    face = loc * Rectangle(1,2)

    box = Plane(loc) * Rot(Z=80) * Box(0.2, 0.2, 0.2)

    show_object(face, name="face") show_object(location_symbol(loc), name="location") show_object(box, name="box")

The box is rotated via Rot(Z=80){.docutils .literal .notranslate} around the z{.docutils .literal .notranslate}-axis of the underlying location (and not of the z-axis of the world).

More general:

::: {.highlight-build123d .notranslate} ::: highlight ::: :::

loc = Location((0.1, 0.2, 0.3), (10, 20, 30))

face = loc * Rectangle(1,2)

box = loc * Rot(20, 40, 80) * Box(0.2, 0.2, 0.2)

show_object(face, name="face") show_object(location_symbol(loc), name="location") show_object(box, name="box")

The box is rotated via Rot(20, 40, 80){.docutils .literal .notranslate} around all three axes relative to the plane.

  1. Rotate and position an object relative to a location

    ::: {.highlight-build123d .notranslate} ::: highlight ::: :::

    loc = Location((0.1, 0.2, 0.3), (10, 20, 30))

    face = loc * Rectangle(1,2)

    box = loc * Rot(20, 40, 80) * Pos(0.2, 0.4, 0.1) * Box(0.2, 0.2, 0.2)

    show_object(face, name="face") show_object(location_symbol(loc), name="location") show_object(box, name="box") show_object(location_symbol(loc * Rot(20, 40, 80), 0.5), options={"color":(0, 255, 255)}, name="local_location")

The box is positioned via Pos(0.2, 0.4, 0.1){.docutils .literal .notranslate} relative to the location loc * Rot(20, 40, 80){.docutils .literal .notranslate}

  1. Position and rotate an object relative to a location

    ::: {.highlight-build123d .notranslate} ::: highlight ::: :::

    loc = Location((0.1, 0.2, 0.3), (10, 20, 30))

    face = loc * Rectangle(1,2)

    box = loc * Pos(0.2, 0.4, 0.1) * Rot(20, 40, 80) * Box(0.2, 0.2, 0.2)

    show_object(face, name="face") show_object(location_symbol(loc), name="location") show_object(box, name="box") show_object(location_symbol(loc * Pos(0.2, 0.4, 0.1), 0.5), options={"color":(0, 255, 255)}, name="local_location")

Note: This is the same as box = loc * Location((0.2, 0.4, 0.1), (20, 40, 80)) * Box(0.2, 0.2, 0.2){.docutils .literal .notranslate} ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#algebra_definition.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#algebra_definition.xhtml#algebraic-definition .section} []{#algebra_definition.xhtml#algebra-definition}

Algebraic definition

::: {#algebra_definition.xhtml#objects-and-arithmetic .section}

Objects and arithmetic

Set definitions:

[\(C^3\)]{.math .notranslate .nohighlight} is the set of all Part{.docutils .literal .notranslate} objects p{.docutils .literal .notranslate} with p._dim = 3{.docutils .literal .notranslate}

[\(C^2\)]{.math .notranslate .nohighlight} is the set of all Sketch{.docutils .literal .notranslate} objects s{.docutils .literal .notranslate} with s._dim = 2{.docutils .literal .notranslate}

[\(C^1\)]{.math .notranslate .nohighlight} is the set of all Curve{.docutils .literal .notranslate} objects c{.docutils .literal .notranslate} with c._dim = 1{.docutils .literal .notranslate}

Neutral elements:

[\(c^3_0\)]{.math .notranslate .nohighlight} is the empty Part{.docutils .literal .notranslate} object p0 = Part(){.docutils .literal .notranslate} with p0._dim = 3{.docutils .literal .notranslate} and p0.wrapped = None{.docutils .literal .notranslate}

[\(c^2_0\)]{.math .notranslate .nohighlight} is the empty Sketch{.docutils .literal .notranslate} object s0 = Sketch(){.docutils .literal .notranslate} with s0._dim = 2{.docutils .literal .notranslate} and s0.wrapped = None{.docutils .literal .notranslate}

[\(c^1_0\)]{.math .notranslate .nohighlight} is the empty Curve{.docutils .literal .notranslate} object c0 = Curve(){.docutils .literal .notranslate} with c0._dim = 1{.docutils .literal .notranslate} and c0.wrapped = None{.docutils .literal .notranslate}

Sets of predefined basic shapes:

[\(B^3 := \lbrace\)]{.math .notranslate .nohighlight} Part{.docutils .literal .notranslate}, Box{.docutils .literal .notranslate}, Cylinder{.docutils .literal .notranslate}, Cone{.docutils .literal .notranslate}, Sphere{.docutils .literal .notranslate}, Torus{.docutils .literal .notranslate}, Wedge{.docutils .literal .notranslate}, Hole{.docutils .literal .notranslate}, CounterBoreHole{.docutils .literal .notranslate}, CounterSinkHole{.docutils .literal .notranslate} [\(\rbrace\)]{.math .notranslate .nohighlight}

[\(B^2 := \lbrace\)]{.math .notranslate .nohighlight} Sketch{.docutils .literal .notranslate}, Rectangle{.docutils .literal .notranslate}, Circle{.docutils .literal .notranslate}, Ellipse{.docutils .literal .notranslate}, Rectangle{.docutils .literal .notranslate}, Polygon{.docutils .literal .notranslate}, RegularPolygon{.docutils .literal .notranslate}, Text{.docutils .literal .notranslate}, Trapezoid{.docutils .literal .notranslate}, SlotArc{.docutils .literal .notranslate}, SlotCenterPoint{.docutils .literal .notranslate}, SlotCenterToCenter{.docutils .literal .notranslate}, SlotOverall{.docutils .literal .notranslate} [\(\rbrace\)]{.math .notranslate .nohighlight}

[\(B^1 := \lbrace\)]{.math .notranslate .nohighlight} Curve{.docutils .literal .notranslate}, Bezier{.docutils .literal .notranslate}, FilletPolyline{.docutils .literal .notranslate}, PolarLine{.docutils .literal .notranslate}, Polyline{.docutils .literal .notranslate}, Spline{.docutils .literal .notranslate}, Helix{.docutils .literal .notranslate}, CenterArc{.docutils .literal .notranslate}, EllipticalCenterArc{.docutils .literal .notranslate}, ParabolicCenterArc{.docutils .literal .notranslate}, HyperbolicCenterArc{.docutils .literal .notranslate}, RadiusArc{.docutils .literal .notranslate}, SagittaArc{.docutils .literal .notranslate}, TangentArc{.docutils .literal .notranslate}, ThreePointArc{.docutils .literal .notranslate}, JernArc{.docutils .literal .notranslate} [\(\rbrace\)]{.math .notranslate .nohighlight}

with [\(B^3 \subset C^3, B^2 \subset C^2\)]{.math .notranslate .nohighlight} and [\(B^1 \subset C^1\)]{.math .notranslate .nohighlight}

Operations:

[\(+: C^n \times C^n \rightarrow C^n\)]{.math .notranslate .nohighlight} with [\((a,b) \mapsto a + b\)]{.math .notranslate .nohighlight}, [\(\;\)]{.math .notranslate .nohighlight} for [\(n=1,2,3\)]{.math .notranslate .nohighlight}

[\(\; a + b :=\)]{.math .notranslate .nohighlight} a.fuse(b){.docutils .literal .notranslate} for each operation

[\(-: C^n \rightarrow C^n\)]{.math .notranslate .nohighlight} with [\(a \mapsto -a\)]{.math .notranslate .nohighlight}, [\(\;\)]{.math .notranslate .nohighlight} for [\(n=1,2,3\)]{.math .notranslate .nohighlight}

[\(\; b + (-a) :=\)]{.math .notranslate .nohighlight} b.cut(a){.docutils .literal .notranslate} for each operation (implicit definition)

[\(\&: C^n \times C^n \rightarrow C^n\)]{.math .notranslate .nohighlight} with [\((a,b) \mapsto a \; \& \; b\)]{.math .notranslate .nohighlight}, [\(\;\)]{.math .notranslate .nohighlight} for [\(n=2,3\)]{.math .notranslate .nohighlight}

[\(\; a \; \& \; b :=\)]{.math .notranslate .nohighlight} a.intersect(b){.docutils .literal .notranslate} for each operation

  • [\(\&\)]{.math .notranslate .nohighlight} is not defined for [\(n=1\)]{.math .notranslate .nohighlight} in build123d

  • The following relationship holds: [\(a \; \& \; b = (a + b) + -(a + (-b)) + -(b + (-a))\)]{.math .notranslate .nohighlight}

Abelian groups

[\(( C^n, \; c^n_0, \; +, \; -)\)]{.math .notranslate .nohighlight} [\(\;\)]{.math .notranslate .nohighlight} are abelian groups for [\(n=1,2,3\)]{.math .notranslate .nohighlight}.

  • The implementation a - b = a.cut(b){.docutils .literal .notranslate} needs to be read as [\(a + (-b)\)]{.math .notranslate .nohighlight} since the group does not have a binary -{.docutils .literal .notranslate} operation. As such, [\(a - (b - c) = a + -(b + -c)) \ne a - b + c\)]{.math .notranslate .nohighlight}

  • This definition also includes that neither -{.docutils .literal .notranslate} nor &{.docutils .literal .notranslate} are commutative. :::

::: {#algebra_definition.xhtml#locations-planes-and-location-arithmetic .section}

Locations, planes and location arithmetic

Set definitions:

[\(L := \lbrace\)]{.math .notranslate .nohighlight} Location((x, y, z), (a, b, c)){.docutils .literal .notranslate} [\(: x,y,z \in R \land a,b,c \in R \rbrace\;\)]{.math .notranslate .nohighlight}

with [\(a,b,c\)]{.math .notranslate .nohighlight} being angles in degrees.

[\(P := \lbrace\)]{.math .notranslate .nohighlight} Plane(o, x, z){.docutils .literal .notranslate} [\(: o,x,z ∈ R^3 \land \|x\| = \|z\| = 1\rbrace\)]{.math .notranslate .nohighlight}

with o{.docutils .literal .notranslate} being the origin and x{.docutils .literal .notranslate}, z{.docutils .literal .notranslate} the x- and z-direction of the plane.

Neutral element: [\(\; l_0 \in L\)]{.math .notranslate .nohighlight}: Location(){.docutils .literal .notranslate}

Operations:

[\(*: L \times L \rightarrow L\)]{.math .notranslate .nohighlight} with [\((l_1,l_2) \mapsto l_1 * l_2\)]{.math .notranslate .nohighlight}

[\(\; l_1 * l_2 :=\)]{.math .notranslate .nohighlight} l1 * l2{.docutils .literal .notranslate} (multiply two locations)

[\(*: P \times L \rightarrow P\)]{.math .notranslate .nohighlight} with [\((p,l) \mapsto p * l\)]{.math .notranslate .nohighlight}

[\(\; p * l :=\)]{.math .notranslate .nohighlight} Plane(p.location * l){.docutils .literal .notranslate} (move plane [\(p \in P\)]{.math .notranslate .nohighlight} to location [\(l \in L\)]{.math .notranslate .nohighlight})

Inverse element: [\(\; l^{-1} \in L\)]{.math .notranslate .nohighlight}: l.inverse(){.docutils .literal .notranslate}

Placing objects onto planes

[\(*: P \times C^n \rightarrow C^n \;\)]{.math .notranslate .nohighlight} with [\((p,c) \mapsto p * c\)]{.math .notranslate .nohighlight}, [\(\;\)]{.math .notranslate .nohighlight} for [\(n=1,2,3\)]{.math .notranslate .nohighlight}

Locate an object [\(c \in C^n\)]{.math .notranslate .nohighlight} onto plane [\(p \in P\)]{.math .notranslate .nohighlight}, i.e. c.moved(p.location){.docutils .literal .notranslate}

Placing objects at locations

[\(*: L \times C^n \rightarrow C^n \;\)]{.math .notranslate .nohighlight} with [\((l,c) \mapsto l * c\)]{.math .notranslate .nohighlight}, [\(\;\)]{.math .notranslate .nohighlight} for [\(n=1,2,3\)]{.math .notranslate .nohighlight}

Locate an object [\(c \in C^n\)]{.math .notranslate .nohighlight} at location [\(l \in L\)]{.math .notranslate .nohighlight}, i.e. c.moved(l){.docutils .literal .notranslate}

::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#center.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#center.xhtml#cad-object-centers .section}

CAD Object Centers

Finding the center of a CAD object is a surprisingly complex operation. To illustrate let's consider two examples: a simple isosceles triangle and a curved line (their bounding boxes are shown with dashed lines):

{style="width: 49%;"} {style="width: 49%;"}

One can see that there is are significant differences between the different types of centers. To allow the designer to choose the center that makes the most sense for the given shape there are three possible values for the CenterOf{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Enum:

CenterOf{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Symbol 1D 2D 3D Compound


CenterOf.BOUNDING_BOX □ ✓ ✓ ✓ ✓ CenterOf.GEOMETRY △ ✓ ✓
CenterOf.MASS ○ ✓ ✓ ✓ ✓ :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#debugging_logging.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#debugging_logging.xhtml#debugging-logging .section}

Debugging & Logging

Debugging problems with your build123d design involves the same techniques one would use to debug any Python source code; however, there are some specific techniques that might be of assistance. The following sections describe these techniques.

::: {#debugging_logging.xhtml#python-debugger .section}

Python Debugger

Many Python IDEs have step by step debugging systems that can be used to walk through your code monitoring its operation with full visibility of all Python objects. Here is a screenshot of the Visual Studio Code debugger in action:

{.align-center}

This shows that a break-point has been encountered and the code operation has been stopped. From here all of the Python variables are visible and the system is waiting on input from the user on how to proceed. One can enter the code that assigns top_face{.docutils .literal .notranslate} by pressing the down arrow button on the top right. Following code execution like this is a very powerful debug technique. :::

::: {#debugging_logging.xhtml#logging .section}

Logging

Build123d support standard python logging and generates its own log stream. If one is using cq-editor as a display system there is a built in Log viewer{.docutils .literal .notranslate} tab that shows the current log stream - here is an example of a log stream:

::: {.highlight-bash .notranslate} ::: highlight [18:43:44.678646] INFO: Entering BuildPart with mode=Mode.ADD which is in different scope as parent [18:43:44.679233] INFO: WorkplaneList is pushing 1 workplanes: [Plane(o=(0.00, 0.00, 0.00), x=(1.00, 0.00, 0.00), z=(0.00, 0.00, 1.00))] [18:43:44.679888] INFO: LocationList is pushing 1 points: [(p=(0.00, 0.00, 0.00), o=(-0.00, 0.00, -0.00))] [18:43:44.681751] INFO: BuildPart context requested by Box [18:43:44.685950] INFO: Completed integrating 1 object(s) into part with Mode=Mode.ADD [18:43:44.690072] INFO: GridLocations is pushing 4 points: [(p=(-30.00, -20.00, 0.00), o=(-0.00, 0.00, -0.00)), (p=(-30.00, 20.00, 0.00), o=(-0.00, 0.00, -0.00)), (p=(30.00, -20.00, 0.00), o=(-0.00, 0.00, -0.00)), (p=(30.00, 20.00, 0.00), o=(-0.00, 0.00, -0.00))] [18:43:44.691604] INFO: BuildPart context requested by Hole [18:43:44.724628] INFO: Completed integrating 4 object(s) into part with Mode=Mode.SUBTRACT [18:43:44.728681] INFO: GridLocations is popping 4 points [18:43:44.747358] INFO: BuildPart context requested by chamfer [18:43:44.762429] INFO: Completed integrating 1 object(s) into part with Mode=Mode.REPLACE [18:43:44.765380] INFO: LocationList is popping 1 points [18:43:44.766106] INFO: WorkplaneList is popping 1 workplanes [18:43:44.766729] INFO: Exiting BuildPart ::: :::

The build123d logger is defined by:

::: {.highlight-python .notranslate} ::: highlight logging.getLogger("build123d").addHandler(logging.NullHandler()) logger = logging.getLogger("build123d") ::: :::

To export logs to a file, the following configuration is recommended:

::: {.highlight-python .notranslate} ::: highlight logging.basicConfig( filename="myapp.log", level=logging.INFO, format="%(name)s-%(levelname)s %(asctime)s - [%(filename)s:%(lineno)s -
%(funcName)20s() ] - %(message)s", ) ::: :::

Logs can be easily placed in your code - here is an example:

::: {.highlight-python .notranslate} ::: highlight logger.info("Exiting %s", type(self).name) ::: ::: :::

::: {#debugging_logging.xhtml#printing .section}

Printing

Sometimes the best debugging aid is just placing a print statement in your code. Many of the build123d classes are setup to provide useful information beyond their class and location in memory, as follows:

::: {.highlight-build123d .notranslate} ::: highlight plane = Plane.XY.offset(1) print(f"{plane=}") ::: :::

::: {.highlight-bash .notranslate} ::: highlight plane=Plane(o=(0.00, 0.00, 1.00), x=(1.00, 0.00, 0.00), z=(0.00, 0.00, 1.00)) ::: :::

which shows the origin, x direction, and z direction of the plane. ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#cheat_sheet.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#cheat_sheet.xhtml#cheat-sheet .section} []{#cheat_sheet.xhtml#id1}

Cheat Sheet

::: {.sd-card .sd-sphinx-override .sd-mb-3 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Stateful Contexts :::

::: line-block ::: line BuildLine{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} BuildPart{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} BuildSketch{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line GridLocations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} HexLocations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Locations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} PolarLocations{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ::: ::: ::: :::

::: {.sd-card .sd-sphinx-override .sd-mb-3 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Objects :::

::: {.sd-container-fluid .sd-sphinx-override .sd-mb-4 .docutils} ::: {.sd-row .sd-row-cols-3 .sd-row-cols-xs-3 .sd-row-cols-sm-3 .sd-row-cols-md-3 .sd-row-cols-lg-3 .docutils} ::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} 1D - BuildLine :::

::: line-block ::: line Airfoil{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line ArcArcTangentArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line ArcArcTangentLine{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Bezier{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line BlendCurve{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line CenterArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line DoubleTangentArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line EllipticalCenterArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line ParabolicCenterArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line HyperbolicCenterArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line FilletPolyline{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Helix{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line IntersectingLine{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line JernArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Line{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line PointArcTangentArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line PointArcTangentLine{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line PolarLine{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Polyline{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line RadiusArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line SagittaArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Spline{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line TangentArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line ThreePointArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ::: ::: ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} 2D - BuildSketch :::

::: line-block ::: line Arrow{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line ArrowHead{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Circle{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line DimensionLine{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Ellipse{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line ExtensionLine{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Polygon{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Rectangle{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line RectangleRounded{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line RegularPolygon{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line SlotArc{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line SlotCenterPoint{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line SlotCenterToCenter{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line SlotOverall{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Text{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line TechnicalDrawing{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Trapezoid{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Triangle{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ::: ::: ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} 3D - BuildPart :::

::: line-block ::: line Box{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Cone{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line CounterBoreHole{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line CounterSinkHole{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Cylinder{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Hole{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Sphere{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Torus{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line Wedge{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ::: ::: ::: ::: ::: ::: ::: ::: :::

::: {.sd-card .sd-sphinx-override .sd-mb-3 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Operations :::

::: {.sd-container-fluid .sd-sphinx-override .sd-mb-4 .docutils} ::: {.sd-row .sd-row-cols-3 .sd-row-cols-xs-3 .sd-row-cols-sm-3 .sd-row-cols-md-3 .sd-row-cols-lg-3 .docutils} ::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} 1D - BuildLine :::

::: line-block ::: line add(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line bounding_box(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line mirror(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line offset(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line project(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line scale(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line split(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ::: ::: ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} 2D - BuildSketch :::

::: line-block ::: line add(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line chamfer(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line fillet(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line full_round(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line make_face(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line make_hull(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line mirror(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line offset(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line project(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line scale(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line split(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line sweep(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line trace(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ::: ::: ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} 3D - BuildPart :::

::: line-block ::: line add(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line chamfer(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line draft(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line extrude(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line fillet(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line loft(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line make_brake_formed(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line mirror(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line offset(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line project(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line revolve(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line scale(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line section(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line split(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line sweep(){.xref .py .py-func .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ::: ::: ::: ::: ::: ::: ::: ::: :::

::: {.sd-card .sd-sphinx-override .sd-mb-3 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Selectors :::

::: {.sd-container-fluid .sd-sphinx-override .sd-mb-4 .docutils} ::: {.sd-row .sd-row-cols-3 .sd-row-cols-xs-3 .sd-row-cols-sm-3 .sd-row-cols-md-3 .sd-row-cols-lg-3 .docutils} ::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} 1D - BuildLine :::

::: line-block ::: line vertices(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line edges(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line wires(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ::: ::: ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} 2D - BuildSketch :::

::: line-block ::: line vertices(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line edges(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line wires(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line faces(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ::: ::: ::: ::: :::

::: {.sd-col .sd-d-flex-row .docutils} ::: {.sd-card .sd-sphinx-override .sd-w-100 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} 3D - BuildPart :::

::: line-block ::: line vertices(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line edges(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line wires(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line faces(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} :::

::: line solids(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ::: ::: ::: ::: ::: ::: ::: ::: :::

::: {.sd-card .sd-sphinx-override .sd-mb-3 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Selector Operators :::

Operator Operand Method


> Axis{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, Edge{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, Wire{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, SortBy{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} sort_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} < Axis{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, Edge{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, Wire{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, SortBy{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} sort_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} >> Axis{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, Edge{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, Wire{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, SortBy{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} group_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}[-1] << Axis{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, Edge{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, Wire{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, SortBy{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} group_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}[0] | Axis{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, Plane{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, GeomType{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} filter_by(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}

         [`Axis`{.xref .py .py-class .docutils .literal .notranslate}](#direct_api_reference.xhtml#geometry.Axis "geometry.Axis"){.hxr-hoverxref .hxr-tooltip .reference .internal}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    [`filter_by_position()`{.xref .py .py-meth .docutils .literal .notranslate}](#direct_api_reference.xhtml#topology.ShapeList.filter_by_position "topology.ShapeList.filter_by_position"){.hxr-hoverxref .hxr-tooltip .reference .internal}

::: :::

::: {.sd-card .sd-sphinx-override .sd-mb-3 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Edge and Wire Operators :::

Operator Operand Method Description


@ 0.0 <= float <= 1.0 position_at(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Position as Vector along object % 0.0 <= float <= 1.0 tangent_at(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Tangent as Vector along object ^ 0.0 <= float <= 1.0 location_at(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Location along object ::: :::

::: {.sd-card .sd-sphinx-override .sd-mb-3 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Shape Operators :::

Operator Operand Method Description


== Any is_same(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Compare CAD objects not including meta data ::: :::

::: {.sd-card .sd-sphinx-override .sd-mb-3 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Plane Operators :::

Operator Operand Description


== Plane{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Check for equality != Plane{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Check for inequality - Plane{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Reverse direction of normal * Plane{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} Relocate by Location ::: :::

::: {.sd-card .sd-sphinx-override .sd-mb-3 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Vector Operators :::

Operator Operand Method Description


+ Vector{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} add(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} add - Vector{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} sub(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} subtract * float{.docutils .literal .notranslate} multiply(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} multiply by scalar / float{.docutils .literal .notranslate} multiply(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} divide by scalar ::: :::

::: {.sd-card .sd-sphinx-override .sd-mb-3 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Vertex Operators :::

Operator Operand Method


+ Vertex{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} add(){.xref .py .py-meth .docutils .literal .notranslate} - Vertex{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} sub(){.xref .py .py-meth .docutils .literal .notranslate} ::: :::

::: {.sd-card .sd-sphinx-override .sd-mb-3 .sd-shadow-sm .docutils} ::: {.sd-card-body .docutils} ::: {.sd-card-title .sd-font-weight-bold .docutils} Enums :::


Align{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} MIN, CENTER, MAX ApproxOption{.xref .py .py-class .docutils .literal .notranslate} ARC, NONE, SPLINE AngularDirection{.xref .py .py-class .docutils .literal .notranslate} CLOCKWISE, COUNTER_CLOCKWISE CenterOf{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} GEOMETRY, MASS, BOUNDING_BOX Extrinsic{.xref .py .py-class .docutils .literal .notranslate} XYZ, XZY, YZX, YXZ, ZXY, ZYX, XYX, XZX, YZY, YXY, ZXZ, ZYZ FontStyle{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} REGULAR, BOLD, BOLDITALIC, ITALIC FrameMethod{.xref .py .py-class .docutils .literal .notranslate} CORRECTED, FRENET GeomType{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} BEZIER, BSPLINE, CIRCLE, CONE, CYLINDER, ELLIPSE, EXTRUSION, HYPERBOLA, LINE, OFFSET, OTHER, PARABOLA, PLANE, REVOLUTION, SPHERE, TORUS Intrinsic{.xref .py .py-class .docutils .literal .notranslate} XYZ, XZY, YZX, YXZ, ZXY, ZYX, XYX, XZX, YZY, YXY, ZXZ, ZYZ HeadType{.xref .py .py-class .docutils .literal .notranslate} CURVED, FILLETED, STRAIGHT Keep{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ALL, TOP, BOTTOM, BOTH, INSIDE, OUTSIDE Kind{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ARC, INTERSECTION, TANGENT LengthMode{.xref .py .py-class .docutils .literal .notranslate} DIAGONAL, HORIZONTAL, VERTICAL MeshType{.xref .py .py-class .docutils .literal .notranslate} OTHER, MODEL, SUPPORT, SOLIDSUPPORT Mode{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ADD, SUBTRACT, INTERSECT, REPLACE, PRIVATE NumberDisplay{.xref .py .py-class .docutils .literal .notranslate} DECIMAL, FRACTION PageSize{.xref .py .py-class .docutils .literal .notranslate} A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, LEDGER, LEGAL, LETTER PositionMode{.xref .py .py-class .docutils .literal .notranslate} LENGTH, PARAMETER PrecisionMode{.xref .py .py-class .docutils .literal .notranslate} LEAST, AVERAGE, GREATEST, SESSION Select{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} ALL, LAST, NEW Side{.xref .py .py-class .docutils .literal .notranslate} BOTH, LEFT, RIGHT SortBy{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} LENGTH, RADIUS, AREA, VOLUME, DISTANCE TextAlign{.xref .py .py-class .docutils .literal .notranslate} BOTTOM, CENTER, LEFT, RIGHT, TOP, TOPFIRSTLINE Transition{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} RIGHT, ROUND, TRANSFORMED Unit{.xref .py .py-class .docutils .literal .notranslate} MC, MM, CM, M, IN, FT Until{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} FIRST, LAST, NEXT, PREVIOUS


::: ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#external.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#external.xhtml#external-tools-and-libraries .section} []{#external.xhtml#external}

External Tools and Libraries

The following sections describe tools and libraries external to build123d that extend its functionality.

::: {#external.xhtml#editors-viewers .section}

Editors & Viewers

::: {#external.xhtml#ocp-vscode .section}

ocp-vscode

A viewer for OCP based Code-CAD (CadQuery, build123d) integrated into VS Code.

See: ocp-vscode{.reference .external}[ [https://github.com/bernhard-42/vscode-ocp-cad-viewer]]{.link-target} (formerly known as cq_vscode)

Watch Jern create three build123d designs in realtime with Visual Studio Code and the ocp-vscode viewer extension in a timed event from the TooTallToby 2024 Spring Open Tournament: build123d entry video{.reference .external}[ [https://www.youtube.com/watch?v=UhUmMInlJic]]{.link-target} :::

::: {#external.xhtml#cq-editor-fork .section}

cq-editor fork

GUI editor based on PyQT. This fork has changes from jdegenstein to allow easier use with build123d.

See: jdegenstein's fork of cq-editor{.reference .external}[ [https://github.com/jdegenstein/jmwright-CQ-Editor]]{.link-target} :::

::: {#external.xhtml#yet-another-cad-viewer .section}

Yet Another CAD Viewer

A web-based CAD viewer for OCP models (CadQuery/build123d) that runs in any modern browser and supports static site deployment. Features include interactive inspection of faces, edges, and vertices, measurement tools, per-model clipping planes, transparency control, and hot reloading via yacv-server{.docutils .literal .notranslate}. It also has a build123d playground for editing and sharing models directly in the browser (demo{.reference .external}[ [https://yeicor-3d.github.io/yet-another-cad-viewer/#pg_code_url=https://raw.githubusercontent.com/gumyr/build123d/refs/heads/dev/examples/toy_truck.py]]{.link-target}).

See: Yet Another CAD Viewer{.reference .external}[ [https://github.com/yeicor-3d/yet-another-cad-viewer]]{.link-target} :::

::: {#external.xhtml#partcad-vs-code-extension .section}

PartCAD VS Code extension

A wrapper around ocp-vscode{.docutils .literal .notranslate} (see above) which requires build123d scripts to be packaged using PartCAD{.docutils .literal .notranslate} (see below). While it requires the overhead of maintaining the package, it provides some convenience features (such as UI controls to export models) as well as functional features (such as UI controls to pass parameters into build123d scripts and AI-based generative design tools).

It's also the most convenient tool to create new packages and parts. More PDM and PLM features are expected to arrive soon. ::: :::

::: {#external.xhtml#part-libraries .section}

Part Libraries

::: {#external.xhtml#bd-warehouse .section}

bd_warehouse

On-demand generation of parametric parts that seamlessly integrate into build123d projects.

Parts available include:

  • fastener - Nuts, Screws, Washers and custom holes

  • flange - Standardized parametric flanges

  • pipe - Standardized parametric pipes

  • thread - Parametric helical threads (Iso, Acme, Plastic, etc.)

See: bd_warehouse{.reference .external}[ [https://bd-warehouse.readthedocs.io/en/latest/index.html]]{.link-target} :::

::: {#external.xhtml#bd-beams-and-bars .section}

bd_beams_and_bars

2D sections and 3D beams generation (UPN, IPN, UPE, flat bars, ...)

See: bd_beams_and_bars{.reference .external}[ [https://bd-beams-and-bars.3d.experimentslabs.com/]]{.link-target} :::

::: {#external.xhtml#superellipses-superellipsoids .section}

Superellipses & Superellipsoids

Superellipses are a more sophisticated alternative to rounded rectangles, with smoothly changing curvature. They are flexible shapes that can be adjusted by changing the "exponent" to get a result that varies between rectangular and elliptical, or from square, through squircle, to circle, and beyond...

Superellipses can be found:

  • in typefaces such as Melior, Eurostyle, and Computer Modern

  • as the shape of airliner windows, tables, plates

  • clipping the outline of iOS app icons

They were named and popularized in the 1950s-1960s by the Danish mathematician and poet Piet Hein, who used them in the winning design for the Sergels Torg roundabout in Stockholm.

See: Superellipses & Superellipsoids{.reference .external}[ [https://github.com/fanf2/kbd/blob/model-b/keybird42/superellipse.py]]{.link-target} :::

::: {#external.xhtml#public-partcad-repository .section}

Public PartCAD repository

See partcad.org{.reference .external}[ [https://partcad.org/repository]]{.link-target} for all the models packaged and published using PartCAD{.docutils .literal .notranslate} (see below). This repository contains individual parts, as well as large assemblies created using those parts. See the OpenVMP robot{.reference .external}[ [https://partcad.org/repository/package/robotics/multimodal/openvmp/robots/don1]]{.link-target} as an example of an assembly :::

::: {#external.xhtml#gggears-generator .section}

gggears generator

A gear generation framework that allows easy creation of a wide range of gears and drives.

See gggears{.reference .external}[ [https://github.com/GarryBGoode/gggears]]{.link-target} ::: :::

::: {#external.xhtml#tools .section}

Tools

::: {#external.xhtml#blendquery .section}

blendquery

CadQuery and build123d integration for Blender.

See: blendquery{.reference .external}[ [https://github.com/uki-dev/blendquery]]{.link-target} :::

::: {#external.xhtml#nething .section}

nething

3D generative AI for CAD modeling. Now everyone is an engineer. Make your ideas real.

See: nething{.reference .external}[ [https://nething.xyz/]]{.link-target}

Listen to the following podcast which discusses nething in detail: The Next Byte Podcast{.reference .external}[ [https://pod.link/wevolver/episode/74b11c1ff2bfc977adc96e5c7b4cd162]]{.link-target} :::

::: {#external.xhtml#ocp-freecad-cam .section}

ocp-freecad-cam

CAM for CadQuery and Build123d by leveraging FreeCAD library. Visualizes in CQ-Editor and ocp-cad-viewer. Spiritual successor of cq-cam{.reference .external}[ [https://github.com/voneiden/cq-cam]]{.link-target}

See: ocp-freecad-cam{.reference .external}[ [https://github.com/voneiden/ocp-freecad-cam]]{.link-target} :::

::: {#external.xhtml#partcad .section}

PartCAD

A package manager for CAD models. Build123d is the most supported Code-CAD framework, but CadQuery and OpenSCAD are also supported. It can be used by build123d designs to import parts{.reference .external}[ [https://partcad.readthedocs.io/en/latest/use_cases.html#python-build123d]]{.link-target} from PartCAD repositories, and to publish build123d designs{.reference .external}[ [https://partcad.readthedocs.io/en/latest/use_cases.html#publish-packages]]{.link-target} to be consumed by others. :::

::: {#external.xhtml#dl4to4ocp .section}

dl4to4ocp

Library that helps perform topology optimization{.reference .external}[ [https://en.wikipedia.org/wiki/Topology_optimization]]{.link-target} on your OCP{.reference .external}[ [https://github.com/CadQuery/OCP]]{.link-target}-based CAD models (CadQuery{.reference .external}[ [https://github.com/CadQuery/cadquery]]{.link-target}/Build123d{.reference .external}[ [https://github.com/gumyr/build123d]]{.link-target}/...) using the dl4to{.reference .external}[ [https://github.com/dl4to/dl4to]]{.link-target} library.

See: dl4to4ocp{.reference .external}[ [https://github.com/yeicor-3d/dl4to4ocp/]]{.link-target} :::

::: {#external.xhtml#ocp-wasm .section}

OCP.wasm

This project ports the low-level dependencies required for build123d to run in a browser. For a fully featured frontend, check out Yet Another CAD Viewer{.docutils .literal .notranslate} (see above).

See: OCP.wasm{.reference .external}[ [https://github.com/yeicor/OCP.wasm]]{.link-target} ::: ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#builder_api_reference.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#builder_api_reference.xhtml#builder-common-api-reference .section} []{#builder_api_reference.xhtml#builder-api-reference}

Builder Common API Reference

The following are common to all the builders.

::: {#builder_api_reference.xhtml#selector-methods .section}

Selector Methods

[[Builder.]{.pre}]{.sig-prename .descclassname}[[vertices]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[select:]{.pre} [~build123d.build_enums.Select]{.pre} [=]{.pre} [<Select.ALL>]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[ShapeList]{.pre}[[[]{.pre}]{.p}[Vertex]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Return Vertices

Return either all or the vertices created during the last operation.

Parameters[:]{.colon}

select (Select{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Vertex selector. Defaults to Select.ALL.

Returns[:]{.colon}

Vertices extracted

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal}]

<!-- -->
[[Builder.]{.pre}]{.sig-prename .descclassname}[[faces]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[select:]{.pre} [~build123d.build_enums.Select]{.pre} [=]{.pre} [<Select.ALL>]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[ShapeList]{.pre}[[[]{.pre}]{.p}[Face]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Return Faces

Return either all or the faces created during the last operation.

Parameters[:]{.colon}

select (Select{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Face selector. Defaults to Select.ALL.

Returns[:]{.colon}

Faces extracted

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}]

<!-- -->
[[Builder.]{.pre}]{.sig-prename .descclassname}[[edges]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[select:]{.pre} [~build123d.build_enums.Select]{.pre} [=]{.pre} [<Select.ALL>]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[ShapeList]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Return Edges

Return either all or the edges created during the last operation.

Parameters[:]{.colon}

select (Select{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Edge selector. Defaults to Select.ALL.

Returns[:]{.colon}

Edges extracted

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}]

<!-- -->
[[Builder.]{.pre}]{.sig-prename .descclassname}[[wires]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[select:]{.pre} [~build123d.build_enums.Select]{.pre} [=]{.pre} [<Select.ALL>]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[ShapeList]{.pre}[[[]{.pre}]{.p}[Wire]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Return Wires

Return either all or the wires created during the last operation.

Parameters[:]{.colon}

select (Select{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Wire selector. Defaults to Select.ALL.

Returns[:]{.colon}

Wires extracted

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]

<!-- -->
[[Builder.]{.pre}]{.sig-prename .descclassname}[[solids]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[select:]{.pre} [~build123d.build_enums.Select]{.pre} [=]{.pre} [<Select.ALL>]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[ShapeList]{.pre}[[[]{.pre}]{.p}[Solid]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Return Solids

Return either all or the solids created during the last operation.

Parameters[:]{.colon}

select (Select{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Solid selector. Defaults to Select.ALL.

Returns[:]{.colon}

Solids extracted

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}] :::

::: {#builder_api_reference.xhtml#module-build_enums .section} []{#builder_api_reference.xhtml#enums}

Enums

[class]{.pre}[ ]{.w}[[Align]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[value]{.pre}]{.n}[)]{.sig-paren}

Align object about Axis

[[CENTER]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[2]{.pre}
[[MAX]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[3]{.pre}
[[MIN]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[1]{.pre}
[[NONE]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[None]{.pre}
<!-- -->
[class]{.pre}[ ]{.w}[[CenterOf]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[value]{.pre}]{.n}[)]{.sig-paren}

Center Options

[[BOUNDING_BOX]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[3]{.pre}
[[GEOMETRY]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[1]{.pre}
[[MASS]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[2]{.pre}
<!-- -->
[class]{.pre}[ ]{.w}[[FontStyle]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[value]{.pre}]{.n}[)]{.sig-paren}

Text Font Styles

[[BOLD]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[2]{.pre}
[[BOLDITALIC]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[4]{.pre}
[[ITALIC]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[3]{.pre}
[[REGULAR]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[1]{.pre}
<!-- -->
[class]{.pre}[ ]{.w}[[GeomType]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[value]{.pre}]{.n}[)]{.sig-paren}

CAD geometry object type

[[BEZIER]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[6]{.pre}
[[BSPLINE]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[7]{.pre}
[[CIRCLE]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[12]{.pre}
[[CONE]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[3]{.pre}
[[CYLINDER]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[2]{.pre}
[[ELLIPSE]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[13]{.pre}
[[EXTRUSION]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[9]{.pre}
[[HYPERBOLA]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[14]{.pre}
[[LINE]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[11]{.pre}
[[OFFSET]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[10]{.pre}
[[OTHER]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[16]{.pre}
[[PARABOLA]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[15]{.pre}
[[PLANE]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[1]{.pre}
[[REVOLUTION]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[8]{.pre}
[[SPHERE]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[4]{.pre}
[[TORUS]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[5]{.pre}
<!-- -->
[class]{.pre}[ ]{.w}[[Keep]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[value]{.pre}]{.n}[)]{.sig-paren}

Split options

[[ALL]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[1]{.pre}
[[BOTH]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[3]{.pre}
[[BOTTOM]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[2]{.pre}
[[INSIDE]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[4]{.pre}
[[OUTSIDE]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[5]{.pre}
[[TOP]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[6]{.pre}
<!-- -->
[class]{.pre}[ ]{.w}[[Kind]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[value]{.pre}]{.n}[)]{.sig-paren}

Offset corner transition

[[ARC]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[1]{.pre}
[[INTERSECTION]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[2]{.pre}
[[TANGENT]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[3]{.pre}
<!-- -->
[class]{.pre}[ ]{.w}[[Mode]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[value]{.pre}]{.n}[)]{.sig-paren}

Combination Mode

[[ADD]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[1]{.pre}
[[INTERSECT]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[3]{.pre}
[[PRIVATE]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[5]{.pre}
[[REPLACE]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[4]{.pre}
[[SUBTRACT]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[2]{.pre}
<!-- -->
[class]{.pre}[ ]{.w}[[Select]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[value]{.pre}]{.n}[)]{.sig-paren}

Selector scope - all, last operation or new objects

[[ALL]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[1]{.pre}
[[LAST]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[2]{.pre}
[[NEW]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[3]{.pre}
<!-- -->
[class]{.pre}[ ]{.w}[[SortBy]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[value]{.pre}]{.n}[)]{.sig-paren}

Sorting criteria

[[AREA]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[3]{.pre}
[[DISTANCE]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[5]{.pre}
[[LENGTH]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[1]{.pre}
[[RADIUS]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[2]{.pre}
[[VOLUME]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[4]{.pre}
<!-- -->
[class]{.pre}[ ]{.w}[[Transition]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[value]{.pre}]{.n}[)]{.sig-paren}

Sweep discontinuity handling option

[[RIGHT]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[1]{.pre}
[[ROUND]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[2]{.pre}
[[TRANSFORMED]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[3]{.pre}
<!-- -->
[class]{.pre}[ ]{.w}[[Until]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[value]{.pre}]{.n}[)]{.sig-paren}

Extrude limit

[[FIRST]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[4]{.pre}
[[LAST]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[2]{.pre}
[[NEXT]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[1]{.pre}
[[PREVIOUS]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[3]{.pre}

:::

::: {#builder_api_reference.xhtml#locations .section}

Locations

[class]{.pre}[ ]{.w}[[Locations]{.pre}]{.sig-name .descname}[(]{.sig-paren}*]{.pre}]{.o}[[pts]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Vertex]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Vertex]{.pre}[ ]{.w}[[{.pre}]{.p}]{.n}[)]{.sig-paren}

Location Context: Push Points

Creates a context of locations for Part or Sketch

Parameters[:]{.colon}

pts (Union[VectorLike, Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal}, Location{.hxr-hoverxref .hxr-tooltip .reference .internal}, Face{.hxr-hoverxref .hxr-tooltip .reference .internal}, Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}] or iterable of same) -- sequence of points to push

Variables[:]{.colon}

local_locations (list{Location}) -- locations relative to workplane

[[local_locations]{.pre}]{.sig-name .descname}

values independent of workplanes

<!-- -->
[class]{.pre}[ ]{.w}[[GridLocations]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[x_spacing:]{.pre} [float]{.pre}]{.n}, [[y_spacing:]{.pre} [float]{.pre}]{.n}, [[x_count:]{.pre} [int]{.pre}]{.n}, [[y_count:]{.pre} [int]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [=]{.pre} [(<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>)]{.pre}]{.n}[)]{.sig-paren}

Location Context: Rectangular Array

Creates a context of rectangular array of locations for Part or Sketch

Parameters[:]{.colon}
  • x_spacing (float) -- horizontal spacing

  • y_spacing (float) -- vertical spacing

  • x_count (int) -- number of horizontal points

  • y_count (int) -- number of vertical points

  • align (Union[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}]], optional) -- align min, center, or max of object. Defaults to (Align.CENTER, Align.CENTER).

Variables[:]{.colon}
  • x_spacing (float) -- horizontal spacing

  • y_spacing (float) -- vertical spacing

  • x_count (int) -- number of horizontal points

  • y_count (int) -- number of vertical points

  • align (Union[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}]]) -- align min, center, or max of object.

  • local_locations (list{Location}) -- locations relative to workplane

Raises[:]{.colon}

ValueError -- Either x or y count must be greater than or equal to one.

[[local_locations]{.pre}]{.sig-name .descname}

values independent of workplanes

[[max]{.pre}]{.sig-name .descname}

top right corner

[[min]{.pre}]{.sig-name .descname}

bottom left corner

[[size]{.pre}]{.sig-name .descname}

size of the grid

<!-- -->
[class]{.pre}[ ]{.w}[[HexLocations]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[radius:]{.pre} [float]{.pre}]{.n}, [[x_count:]{.pre} [int]{.pre}]{.n}, [[y_count:]{.pre} [int]{.pre}]{.n}, [[major_radius:]{.pre} [bool]{.pre} [=]{.pre} [False]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [=]{.pre} [(<Align.CENTER>]{.pre}]{.n}, [[<Align.CENTER>)]{.pre}]{.n}[)]{.sig-paren}

Location Context: Hex Array

Creates a context of hexagon array of locations for Part or Sketch. When creating hex locations for an array of circles, set <cite>{=html}radius</cite>{=html} to the radius of the circle plus one half the spacing between the circles.

Parameters[:]{.colon}
  • radius (float) -- distance from origin to vertices (major), or optionally from the origin to side (minor or apothem) with major_radius = False

  • x_count (int) -- number of points ( > 0 )

  • y_count (int) -- number of points ( > 0 )

  • major_radius (bool) -- If True the radius is the major radius, else the radius is the minor radius (also known as inscribed radius). Defaults to False.

  • align (Union[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}]], optional) -- align min, center, or max of object. Defaults to (Align.CENTER, Align.CENTER).

Variables[:]{.colon}
  • radius (float) -- distance from origin to vertices (major), or optionally from the origin to side (minor or apothem) with major_radius = False

  • apothem (float) -- radius of the inscribed circle, also known as minor radius

  • x_count (int) -- number of points ( > 0 )

  • y_count (int) -- number of points ( > 0 )

  • major_radius (bool) -- If True the radius is the major radius, else the radius is the minor radius (also known as inscribed radius).

  • align (Union[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}]]) -- align min, center, or max of object.

  • diagonal (float) -- major radius

  • local_locations (list{Location}) -- locations relative to workplane

Raises[:]{.colon}

ValueError -- Spacing and count must be > 0

[[local_locations]{.pre}]{.sig-name .descname}

values independent of workplanes

<!-- -->
[class]{.pre}[ ]{.w}[[PolarLocations]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[radius]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[count]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[int]{.pre}]{.n}, [[start_angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.0]{.pre}]{.default_value}, [[angular_range]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[360.0]{.pre}]{.default_value}, [[rotate]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[True]{.pre}]{.default_value}, [[endpoint]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}[)]{.sig-paren}

Location Context: Polar Array

Creates a context of polar array of locations for Part or Sketch

Parameters[:]{.colon}
  • radius (float) -- array radius

  • count (int) -- Number of points to push

  • start_angle (float, optional) -- angle to first point from +ve X axis. Defaults to 0.0.

  • angular_range (float, optional) -- magnitude of array from start angle. Defaults to 360.0.

  • rotate (bool, optional) -- Align locations with arc tangents. Defaults to True.

  • endpoint (bool, optional) -- If True, <cite>{=html}start_angle</cite>{=html} + <cite>{=html}angular_range</cite>{=html} is the last sample. Otherwise, it is not included. Defaults to False.

Variables[:]{.colon}

local_locations (list{Location}) -- locations relative to workplane

Raises[:]{.colon}

ValueError -- Count must be greater than or equal to 1

[[local_locations]{.pre}]{.sig-name .descname}

values independent of workplanes ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#direct_api_reference.xhtml}

::: document ::: documentwrapper ::: {.body role="main"} ::: {#direct_api_reference.xhtml#direct-api-reference .section}

Direct API Reference

The Direct API is an interface layer between the primary user interface API (the Builders) and the OpenCascade (OCCT) API. This API is based on the CadQuery Direct API (thank you to all of the CadQuery contributors that made this possible) with the following major changes:

  • PEP8 compliance

  • New Axis class

  • New ShapeList class enabling sorting and filtering of shape objects

  • Literal strings replaced with Enums

::: {#direct_api_reference.xhtml#geometric-objects .section}

Geometric Objects

The geometric classes defined by build123d are defined below. This parameters to the CAD objects described in the following section are frequently of these types.

::: graphviz Inheritance diagram of geometry{.inheritance .graphviz usemap="#inheritance6a9b0cc043"} :::

<map id="inheritance6a9b0cc043" name="inheritance6a9b0cc043">
<area shape="rect" id="node1" href="#geometry.Axis" target="_top" title="Axis" alt coords="41,523,113,548">
</area>
<area shape="rect" id="node3" href="#geometry.BoundBox" target="_top" title="A BoundingBox for a Shape" alt coords="33,424,121,449">
</area>
<area shape="rect" id="node4" href="#geometry.Color" target="_top" title="Color object based on OCCT Quantity_ColorRGBA." alt coords="41,375,113,400">
</area>
<area shape="rect" id="node8" href="#geometry.LocationEncoder" target="_top" title="Custom JSON Encoder for Location values" alt coords="197,375,327,400">
</area>
<area shape="rect" id="node7" href="#geometry.Location" target="_top" title="Location in 3D space. Depending on usage can be absolute or relative." alt coords="39,252,116,277">
</area>
<area shape="rect" id="node13" href="#geometry.Pos" target="_top" title="A position only sub-class of Location" alt coords="226,227,298,252">
</area>
<area shape="rect" id="node14" href="#geometry.Rotation" target="_top" title="Subclass of Location used only for object rotation" alt coords="223,276,301,301">
</area>
<area shape="rect" id="node9" href="#geometry.Matrix" target="_top" title="A 3d , 4x4 transformation matrix." alt coords="41,203,113,228">
</area>
<area shape="rect" id="node11" href="#geometry.Plane" target="_top" title="Plane" alt coords="41,104,113,129">
</area>
<area shape="rect" id="node15" href="#geometry.Vector" target="_top" title="Create a 3-dimensional vector" alt coords="41,5,113,31">
</area>
</map>
[class]{.pre}[ ]{.w}[[Axis]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}, [[**]{.pre}]{.o}[[kwargs]{.pre}]{.n}[)]{.sig-paren}

Axis defined by point and direction

Parameters[:]{.colon}
  • origin (VectorLike) -- start point

  • direction (VectorLike) -- direction

  • edge (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- origin & direction defined by start of edge

  • location (Location{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- location to convert to axis

Variables[:]{.colon}
  • position (Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- the global position of the axis origin

  • direction (Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- the normalized direction vector

  • wrapped (gp_Ax1) -- the OCP axis object

[[__copy__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return copy of self

[[__deepcopy__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[_memo]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return deepcopy of self

[[__neg__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Flip direction operator -

[[angle_between]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[float]{.pre}]{.sig-return-typehint}]{.sig-return}

calculate angle between axes

Computes the angular value, in degrees, between the direction of self and other between 0° and 360°.

Parameters[:]{.colon}

other (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- axis to compare to

Returns[:]{.colon}

angle between axes

Return type[:]{.colon}

float

[property]{.pre}[ ]{.w}[[direction]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}

The normalized direction of the Axis

[[intersect]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}, [[**]{.pre}]{.o}[[kwargs]{.pre}]{.n}[)]{.sig-paren}

Find intersection of axis and geometric object or shape

[[is_coaxial]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[angular_tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1e-05]{.pre}]{.default_value}, [[linear_tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1e-05]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

are axes coaxial

True if the angle between self and other is lower or equal to angular_tolerance and the distance between self and other is lower or equal to linear_tolerance.

Parameters[:]{.colon}
  • other (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- axis to compare to

  • angular_tolerance (float, optional) -- max angular deviation. Defaults to 1e-5.

  • linear_tolerance (float, optional) -- max linear deviation. Defaults to 1e-5.

Returns[:]{.colon}

axes are coaxial

Return type[:]{.colon}

bool

[[is_normal]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[angular_tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1e-05]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

are axes normal

Returns True if the direction of this and another axis are normal to each other. That is, if the angle between the two axes is equal to 90° within the angular_tolerance.

Parameters[:]{.colon}
  • other (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- axis to compare to

  • angular_tolerance (float, optional) -- max angular deviation. Defaults to 1e-5.

Returns[:]{.colon}

axes are normal

Return type[:]{.colon}

bool

[[is_opposite]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[angular_tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1e-05]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

are axes opposite

Returns True if the direction of this and another axis are parallel with opposite orientation. That is, if the angle between the two axes is equal to 180° within the angular_tolerance.

Parameters[:]{.colon}
  • other (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- axis to compare to

  • angular_tolerance (float, optional) -- max angular deviation. Defaults to 1e-5.

Returns[:]{.colon}

axes are opposite

Return type[:]{.colon}

bool

[[is_parallel]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[angular_tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1e-05]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

are axes parallel

Returns True if the direction of this and another axis are parallel with same orientation or opposite orientation. That is, if the angle between the two axes is equal to 0° or 180° within the angular_tolerance.

Parameters[:]{.colon}
  • other (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- axis to compare to

  • angular_tolerance (float, optional) -- max angular deviation. Defaults to 1e-5.

Returns[:]{.colon}

axes are parallel

Return type[:]{.colon}

bool

[[is_skew]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1e-05]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

are axes skew

Returns True if this axis and another axis are skew, meaning they are neither parallel nor coplanar. Two axes are skew if they do not lie in the same plane and never intersect.

Mathematically, this means:

  • The axes are not parallel (the cross product of their direction vectors is nonzero).

  • The axes are not coplanar (the vector between their positions is not aligned with the plane spanned by their directions).

If either condition is false (i.e., the axes are parallel or coplanar), they are not skew.

Parameters[:]{.colon}
  • other (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- axis to compare to

  • tolerance (float, optional) -- max deviation. Defaults to 1e-5.

Returns[:]{.colon}

axes are skew

Return type[:]{.colon}

bool

[[located]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[new_location]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Location]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren}

relocates self to a new location possibly changing position and direction

[property]{.pre}[ ]{.w}[[location]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Location]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}

Return self as Location

[property]{.pre}[ ]{.w}[[position]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}

The position or origin of the Axis

[[reverse]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return a copy of self with the direction reversed

[[to_plane]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Plane]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return self as Plane

<!-- -->
[class]{.pre}[ ]{.w}[[BoundBox]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[bounding_box]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Bnd_Box]{.pre}]{.n}[)]{.sig-paren}

A BoundingBox for a Shape

[[add]{.pre}]{.sig-name .descname}[(]{.sig-paren}obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[BoundBox]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[tol]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[BoundBox]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Returns a modified (expanded) bounding box

obj can be one of several things:
  1. a 3-tuple corresponding to x,y, and z amounts to add

  2. a vector, containing the x,y,z values to add

  3. another bounding box, where a new box will be created that encloses both.

This bounding box is not changed.

Parameters[:]{.colon}
  • obj -- tuple[float, float, float] | Vector | BoundBox]:

  • tol -- float: (Default value = None)

Returns:

[[center]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return center of the bounding box

[property]{.pre}[ ]{.w}[[diagonal]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

body diagonal length (i.e. object maximum size)

[static]{.pre}[ ]{.w}[[find_outside_box_2d]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[bb1]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[BoundBox]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[bb2]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[BoundBox]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[BoundBox]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.sig-return-typehint}]{.sig-return}

Compares bounding boxes

Compares bounding boxes. Returns none if neither is inside the other. Returns the outer one if either is outside the other.

BoundBox.is_inside works in 3d, but this is a 2d bounding box, so it doesn't work correctly plus, there was all kinds of rounding error in the built-in implementation i do not understand.

Parameters[:]{.colon}
  • bb1 -- BoundBox:

  • bb2 -- BoundBox:

Returns:

[classmethod]{.pre}[ ]{.w}[[from_topo_ds]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[shape]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Shape]{.pre}]{.n}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[optimal]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[True]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[BoundBox]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Constructs a bounding box from a TopoDS_Shape

Parameters[:]{.colon}
  • shape -- TopoDS_Shape:

  • tolerance -- float: (Default value = None)

  • optimal -- bool: This algorithm builds precise bounding box (Default value = True)

Returns:

[[is_inside]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[second_box]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[BoundBox]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

Is the provided bounding box inside this one?

Parameters[:]{.colon}

b2 -- BoundBox:

Returns:

[property]{.pre}[ ]{.w}[[measure]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

Return the overall Lebesgue measure of the bounding box.

  • For 1D objects: length

  • For 2D objects: area

  • For 3D objects: volume

[[to_align_offset]{.pre}]{.sig-name .descname}[(]{.sig-paren}align]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Align]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[Align]{.pre}[ ]{.w}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Amount to move object to achieve the desired alignment

<!-- -->
[class]{.pre}[ ]{.w}[[Color]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}, [[**]{.pre}]{.o}[[kwargs]{.pre}]{.n}[)]{.sig-paren}

Color object based on OCCT Quantity_ColorRGBA.

Variables[:]{.colon}

wrapped (Quantity_ColorRGBA) -- the OCP color object

[[__copy__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Color]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return copy of self

[[__deepcopy__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[_memo]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Color]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return deepcopy of self

[classmethod]{.pre}[ ]{.w}[[categorical_set]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[color_count]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[int]{.pre}]{.n}, starting_hue]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[int]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Color]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Quantity_ColorRGBA]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.0]{.pre}]{.default_value}, alpha]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[{.pre}]{.p}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1.0]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[list]{.pre}[[[]{.pre}]{.p}[Color]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Generate a palette of evenly spaced colors.

Creates a list of visually distinct colors suitable for representing discrete categories (such as different parts, assemblies, or data series). Colors are evenly spaced around the hue circle and share consistent lightness and saturation levels, resulting in balanced perceptual contrast across all hues.

Produces palettes similar in appearance to the Tableau 10 and D3 Category10 color sets---both widely recognized standards in data visualization for their clarity and accessibility. These values have been empirically chosen to maintain consistent perceived brightness across hues while avoiding overly vivid or dark colors.

Parameters[:]{.colon}
  • color_count (int) -- Number of colors to generate.

  • starting_hue (ColorLike | float) -- Either a Color-like object or a hue value in the range [0.0, 1.0] that defines the starting color.

  • alpha (float | Iterable[float]) -- Alpha value(s) for the colors. Can be a single float or an iterable of length <cite>{=html}color_count</cite>{=html}.

Returns[:]{.colon}

List of generated colors.

Return type[:]{.colon}

list[Color{.hxr-hoverxref .hxr-tooltip .reference .internal}]

Raises[:]{.colon}

ValueError -- If starting_hue is out of range or alpha length mismatch.

<!-- -->
[class]{.pre}[ ]{.w}[[Location]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}, [[**]{.pre}]{.o}[[kwargs]{.pre}]{.n}[)]{.sig-paren}

Location in 3D space. Depending on usage can be absolute or relative.

This class wraps the TopLoc_Location class from OCCT. It can be used to move Shape objects in both relative and absolute manner. It is the preferred type to locate objects in build123d.

Variables[:]{.colon}

wrapped (TopLoc_Location) -- the OCP location object

[[__copy__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Location]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Lib/copy.py shallow copy

[[__deepcopy__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[_memo]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Location]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Lib/copy.py deep copy

[[__eq__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[object]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

Compare Locations

[[__mul__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Location]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Iterable]{.pre}[[[]{.pre}]{.p}[Location]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Location]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[list]{.pre}[[[]{.pre}]{.p}[Location]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Combine locations

[[__neg__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Location]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Flip the orientation without changing the position operator -

[[__pow__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[exponent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[int]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Location]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}
[[center]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return center of the location - useful for sorting

[[intersect]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}, [[**]{.pre}]{.o}[[kwargs]{.pre}]{.n}[)]{.sig-paren}

Find intersection of location and geometric object or shape

[[inverse]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Location]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Inverted location

[[mirror]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[mirror_plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Location]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return a new Location mirrored across the given plane.

This method reflects both the position and orientation of the current Location across the specified mirror_plane using affine vector mathematics.

Due to the mathematical properties of reflection:
  • The true mirror of a right-handed coordinate system is a left-handed one.

However, <cite>{=html}build123d</cite>{=html} requires all coordinate systems to be right-handed. Therefore, this implementation: - Reflects the X and Z directions across the mirror plane - Recomputes the Y direction as: <cite>{=html}Y = X × Z</cite>{=html}

This ensures the resulting Location maintains a valid right-handed frame, while remaining as close as possible to the geometric mirror.

Parameters[:]{.colon}

mirror_plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- The plane to mirror across.

Returns[:]{.colon}

A new mirrored Location that preserves right-handedness.

Return type[:]{.colon}

Location{.hxr-hoverxref .hxr-tooltip .reference .internal}

[property]{.pre}[ ]{.w}[[orientation]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}

Extract orientation/rotation component of self

Returns[:]{.colon}

orientation part of Location

Return type[:]{.colon}

Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}

[property]{.pre}[ ]{.w}[[position]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}

Extract Position component of self

Returns[:]{.colon}

Position part of Location

Return type[:]{.colon}

Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[to_axis]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Convert the location into an Axis

to_tuple]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p},]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Convert the location to a translation, rotation tuple.

[property]{.pre}[ ]{.w}[[x_axis]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}

Default X axis when used as a plane

[property]{.pre}[ ]{.w}[[y_axis]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}

Default Y axis when used as a plane

[property]{.pre}[ ]{.w}[[z_axis]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}

Default Z axis when used as a plane

<!-- -->
[class]{.pre}[ ]{.w}[[LocationEncoder]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}, [[skipkeys]{.pre}]{.n}[[=]{.pre}]{.o}[[False]{.pre}]{.default_value}, [[ensure_ascii]{.pre}]{.n}[[=]{.pre}]{.o}[[True]{.pre}]{.default_value}, [[check_circular]{.pre}]{.n}[[=]{.pre}]{.o}[[True]{.pre}]{.default_value}, [[allow_nan]{.pre}]{.n}[[=]{.pre}]{.o}[[True]{.pre}]{.default_value}, [[sort_keys]{.pre}]{.n}[[=]{.pre}]{.o}[[False]{.pre}]{.default_value}, [[indent]{.pre}]{.n}[[=]{.pre}]{.o}[[None]{.pre}]{.default_value}, [[separators]{.pre}]{.n}[[=]{.pre}]{.o}[[None]{.pre}]{.default_value}, [[default]{.pre}]{.n}[[=]{.pre}]{.o}[[None]{.pre}]{.default_value}[)]{.sig-paren}

Custom JSON Encoder for Location values

Example:

::: {.highlight-default .notranslate} ::: highlight data_dict = { "part1": { "joint_one": Location((1, 2, 3), (4, 5, 6)), "joint_two": Location((7, 8, 9), (10, 11, 12)), }, "part2": { "joint_one": Location((13, 14, 15), (16, 17, 18)), "joint_two": Location((19, 20, 21), (22, 23, 24)), }, } json_object = json.dumps(data_dict, indent=4, cls=LocationEncoder) with open("sample.json", "w") as outfile: outfile.write(json_object) with open("sample.json", "r") as infile: copy_data_dict = json.load(infile, object_hook=LocationEncoder.location_hook) ::: :::

[[default]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[o]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Location]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[dict]{.pre}]{.sig-return-typehint}]{.sig-return}

Return a serializable object

[static]{.pre}[ ]{.w}[[location_hook]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[dict]{.pre}]{.sig-return-typehint}]{.sig-return}

Convert Locations loaded from json to Location objects

Example

read_json = json.load(infile, object_hook=LocationEncoder.location_hook)

<!-- -->
[class]{.pre}[ ]{.w}[[Pos]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}, [[**]{.pre}]{.o}[[kwargs]{.pre}]{.n}[)]{.sig-paren}

A position only sub-class of Location

<!-- -->
[[Rot]{.pre}]{.sig-name .descname}

alias of Rotation{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[class]{.pre}[ ]{.w}[[Matrix]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}, [[**]{.pre}]{.o}[[kwargs]{.pre}]{.n}[)]{.sig-paren}

A 3d , 4x4 transformation matrix.

Used to move geometry in space.

The provided "matrix" parameter may be None, a gp_GTrsf, or a nested list of values.

If given a nested list, it is expected to be of the form:

\[m11, m12, m13, m14

: [m21, m22, m23, m24], [m31, m32, m33, m34]]

A fourth row may be given, but it is expected to be: [0.0, 0.0, 0.0, 1.0] since this is a transform matrix.

Variables[:]{.colon}

wrapped (gp_GTrsf) -- the OCP transformation function

[[__copy__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Matrix]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return copy of self

[[__deepcopy__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[_memo]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Matrix]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return deepcopy of self

[[inverse]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Matrix]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Invert Matrix

[[multiply]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[)]{.sig-paren}

Matrix multiplication

[[rotate]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[axis]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren}

General rotate about axis

transposed_list]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Needed by the cqparts gltf exporter

<!-- -->
[class]{.pre}[ ]{.w}[[Plane]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}, [[**]{.pre}]{.o}[[kwargs]{.pre}]{.n}[)]{.sig-paren}

A plane is positioned in space with a coordinate system such that the plane is defined by the origin, x_dir (X direction), y_dir (Y direction), and z_dir (Z direction) of this coordinate system, which is the "local coordinate system" of the plane. The z_dir is a vector normal to the plane. The coordinate system is right-handed.

A plane allows the use of local 2D coordinates, which are later converted to global, 3d coordinates when the operations are complete.

Planes can be created from faces as workplanes for feature creation on objects.

Name x_dir y_dir z_dir


XY +x +y +z YZ +y +z +x ZX +z +x +y XZ +x +z -y YX +y +x -z ZY +z +y -x front +x +z -y back -x +z +y left -y +z -x right +y +z +x top +x +y +z bottom +x -y -z isometric +x+y -x+y+z +x+y-z

Parameters[:]{.colon}
  • gp_pln (gp_Pln) -- an OCCT plane object

  • origin (tuple[float, float, float] | Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- the origin in global coordinates

  • x_dir (tuple[float, float, float] | Vector{.hxr-hoverxref .hxr-tooltip .reference .internal} | None) -- an optional vector representing the X Direction. Defaults to None.

  • z_dir (tuple[float, float, float] | Vector{.hxr-hoverxref .hxr-tooltip .reference .internal} | None) -- the normal direction for the plane. Defaults to (0, 0, 1).

Variables[:]{.colon}
  • origin (Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- global position of local (0,0,0) point

  • x_dir (Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- x direction

  • y_dir (Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- y direction

  • z_dir (Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- z direction

  • local_coord_system (gp_Ax3) -- OCP coordinate system

  • forward_transform (Matrix{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- forward location transformation matrix

  • reverse_transform (Matrix{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- reverse location transformation matrix

  • wrapped (gp_Pln) -- the OCP plane object

Raises[:]{.colon}
  • ValueError -- z_dir must be non null

  • ValueError -- x_dir must be non null

  • ValueError -- the specified x_dir is not orthogonal to the provided normal

Returns[:]{.colon}

A plane

Return type[:]{.colon}

Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[__copy__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Plane]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return copy of self

[[__deepcopy__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[_memo]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Plane]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return deepcopy of self

[[__eq__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[object]{.pre}]{.n}[)]{.sig-paren}

Are planes equal operator ==

[[__mul__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Location]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Plane]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[list]{.pre}[[[]{.pre}]{.p}[Plane]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}
[[__neg__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Plane]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Reverse z direction of plane operator -

[[contains]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1e-06]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

Is this point or Axis fully contained in this plane?

Parameters[:]{.colon}
  • obj (VectorLike | Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- point or Axis to evaluate

  • tolerance (float, optional) -- comparison tolerance. Defaults to TOLERANCE.

Returns[:]{.colon}

self contains point or Axis

Return type[:]{.colon}

bool

[[from_local_coords]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Any]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[BoundBox]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren}

Reposition the object relative from this plane

Parameters[:]{.colon}
  • obj -- VectorLike | Shape | BoundBox an object to reposition. Note that

  • classes. (type Any refers to all topological)

Returns[:]{.colon}

an object of the same type, but repositioned to world coordinates

[static]{.pre}[ ]{.w}[[get_topods_face_normal]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[face]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Face]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Find the normal at the center of a TopoDS_Face

[[intersect]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}, [[**]{.pre}]{.o}[[kwargs]{.pre}]{.n}[)]{.sig-paren}

Find intersection of plane and geometric object or shape

[property]{.pre}[ ]{.w}[[location]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Location]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}

Return Location representing the origin and z direction

[[location_between]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Location]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return a location representing the translation from self to other

[[move]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[loc]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Location]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Plane]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Change the position & orientation of self by applying a relative location

Parameters[:]{.colon}

loc (Location{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- relative change

Returns[:]{.colon}

relocated plane

Return type[:]{.colon}

Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[offset]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[amount]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Plane]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Move the Plane by amount in the direction of z_dir

[property]{.pre}[ ]{.w}[[origin]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}

Get the Plane origin

[[reverse]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Plane]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Reverse z direction of plane

[[rotated]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[rotation]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[(0,]{.pre} [0,]{.pre} [0)]{.pre}]{.default_value}, [[ordering]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Extrinsic]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Intrinsic]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Plane]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Returns a copy of this plane, rotated about the specified axes

The origin of the workplane is unaffected by the rotation.

Rotations are done in order x, y, z. If you need a different order, specify ordering. e.g. Intrinsic.ZYX changes rotation to (z angle, y angle, x angle) and rotates in that order.

Parameters[:]{.colon}
  • rotation (VectorLike, optional) -- (x angle, y angle, z angle). Defaults to (0, 0, 0)

  • ordering (Intrinsic | Extrinsic, optional) -- order of rotations in Intrinsic or Extrinsic rotation mode. Defaults to Intrinsic.XYZ

Returns[:]{.colon}

a copy of this plane rotated as requested.

Return type[:]{.colon}

Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[shift_origin]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[locator]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[VectorLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Plane]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

shift plane origin

Creates a new plane with the origin moved within the plane to the point of intersection of the axis or at the given Vertex. The plane's x_dir and z_dir are unchanged.

Parameters[:]{.colon}

locator (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal} | VectorLike | Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- Either Axis that intersects the new plane origin or Vertex within Plane.

Raises[:]{.colon}
  • ValueError -- Vertex isn't within plane

  • ValueError -- Point isn't within plane

  • ValueError -- Axis doesn't intersect plane

Returns[:]{.colon}

plane with new origin

Return type[:]{.colon}

Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[to_gp_ax2]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[gp_Ax2]{.pre}]{.sig-return-typehint}]{.sig-return}

Return gp_Ax2 version of the plane

[[to_local_coords]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Any]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[BoundBox]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren}

Reposition the object relative to this plane

Parameters[:]{.colon}
  • obj -- VectorLike | Shape | BoundBox an object to reposition. Note that

  • classes. (type Any refers to all topological)

Returns[:]{.colon}

an object of the same type, but repositioned to local coordinates

<!-- -->
[class]{.pre}[ ]{.w}[[Rotation]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}, [[**]{.pre}]{.o}[[kwargs]{.pre}]{.n}[)]{.sig-paren}

Subclass of Location used only for object rotation

Variables[:]{.colon}
  • X (float) -- rotation in degrees about X axis

  • Y (float) -- rotation in degrees about Y axis

  • Z (float) -- rotation in degrees about Z axis

  • enums, (optionally specify rotation ordering with Intrinsic or Extrinsic) -- defaults to Intrinsic.XYZ

<!-- -->
[class]{.pre}[ ]{.w}[[Vector]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}, [[**]{.pre}]{.o}[[kwargs]{.pre}]{.n}[)]{.sig-paren}

Create a 3-dimensional vector

Parameters[:]{.colon}
  • x (float) -- x component

  • y (float) -- y component

  • z (float) -- z component

  • vec (Vector{.hxr-hoverxref .hxr-tooltip .reference .internal} | Sequence(float) | gp_Vec | gp_Pnt | gp_Dir | gp_XYZ) -- vector representations

Note that if no z value is provided it's assumed to be zero. If no values are provided the returned Vector has the value of 0, 0, 0.

Variables[:]{.colon}

wrapped (gp_Vec) -- the OCP vector object

[property]{.pre}[ ]{.w}[[X]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

Get x value

[property]{.pre}[ ]{.w}[[Y]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

Get y value

[property]{.pre}[ ]{.w}[[Z]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

Get z value

[[__abs__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[float]{.pre}]{.sig-return-typehint}]{.sig-return}

Vector length operator abs()

[[__add__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[vec]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Mathematical addition operator +

[[__copy__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return copy of self

[[__deepcopy__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[_memo]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return deepcopy of self

[[__eq__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[object]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

Vectors equal operator ==

[[__mul__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[scale]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Mathematical multiply operator *

[[__neg__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Flip direction of vector operator -

[[__rmul__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[scale]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Mathematical multiply operator *

[[__sub__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[vec]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Mathematical subtraction operator -

[[__truediv__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[denom]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Mathematical division operator /

[[add]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[vec]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Mathematical addition function

[[center]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}
Returns[:]{.colon}

The center of myself is myself. Provided so that vectors, vertices, and other shapes all support a common interface, when center() is requested for all objects on the stack.

[[cross]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[vec]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Mathematical cross function

[[distance_to_plane]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[float]{.pre}]{.sig-return-typehint}]{.sig-return}

Minimum unsigned distance between vector and plane

[[dot]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[vec]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[float]{.pre}]{.sig-return-typehint}]{.sig-return}

Mathematical dot function

[[get_angle]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[vec]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[float]{.pre}]{.sig-return-typehint}]{.sig-return}

Unsigned angle between vectors

[[get_signed_angle]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[vec]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[normal]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[float]{.pre}]{.sig-return-typehint}]{.sig-return}

Signed Angle Between Vectors

Return the signed angle in degrees between two vectors with the given normal based on this math: angle = atan2((Va × Vb) ⋅ Vn, Va ⋅ Vb)

Parameters[:]{.colon}
  • v (Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- Second Vector

  • normal (Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- normal direction. Defaults to None.

Returns[:]{.colon}

Angle between vectors

Return type[:]{.colon}

float

[[intersect]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}, [[**]{.pre}]{.o}[[kwargs]{.pre}]{.n}[)]{.sig-paren}

Find intersection of vector and geometric object or shape

[property]{.pre}[ ]{.w}[[length]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

Vector length

[[multiply]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[scale]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Mathematical multiply function

[[normalized]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Scale to length of 1

[[project_to_line]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[line]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Returns a new vector equal to the projection of this Vector onto the line represented by Vector <line>

Parameters[:]{.colon}

line (Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- project to this line

Returns[:]{.colon}

Returns the projected vector.

Return type[:]{.colon}

Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[project_to_plane]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Vector is projected onto the plane provided as input.

Parameters[:]{.colon}

args -- Plane object

Returns the projected vector.

plane: Plane:

Returns:

[[reverse]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return a vector with the same magnitude but pointing in the opposite direction

[[rotate]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[axis]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Rotate about axis

Rotate about the given Axis by an angle in degrees

Parameters[:]{.colon}
  • axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- Axis of rotation

  • angle (float) -- angle in degrees

Returns[:]{.colon}

rotated vector

Return type[:]{.colon}

Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[signed_distance_from_plane]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[float]{.pre}]{.sig-return-typehint}]{.sig-return}

Signed distance from plane to point vector.

[[sub]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[vec]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Mathematical subtraction function

[[to_dir]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[gp_Dir]{.pre}]{.sig-return-typehint}]{.sig-return}

Convert to OCCT gp_Dir object

[[to_pnt]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[gp_Pnt]{.pre}]{.sig-return-typehint}]{.sig-return}

Convert to OCCT gp_Pnt object

to_tuple]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Return tuple equivalent

[[transform]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[affine_transform]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Matrix]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[is_direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Apply affine transformation

Parameters[:]{.colon}
  • affine_transform (Matrix{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- affine transformation matrix

  • is_direction (bool, optional) -- Should self be transformed as a vector or direction? Defaults to False (vector)

Returns[:]{.colon}

transformed vector

Return type[:]{.colon}

Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}

[property]{.pre}[ ]{.w}[[wrapped]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[gp_Vec]{.pre}

OCCT object :::

::: {#direct_api_reference.xhtml#topological-objects .section}

Topological Objects

The topological object classes defined by build123d are defined below.

Note that the Mixin1D{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and Mixin3D{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} classes add supplementary functionality specific to 1D (Edge{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and Wire{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}) and 3D (Compound{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} and <cite>{=html}~topology.Solid</cite>{=html}) objects respectively. Note that a Compound{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal} may be contain only 1D, 2D (Face{.xref .py .py-class .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}) or 3D objects.

::: graphviz Inheritance diagram of topology.shape_core, topology.zero_d, topology.one_d, topology.two_d, topology.three_d, topology.composite, topology.utils{.inheritance .graphviz usemap="#inheritance97dd5a8489"} :::

<map id="inheritance97dd5a8489" name="inheritance97dd5a8489">
<area shape="rect" id="node10" href="#topology.Mixin2D" target="_top" title="Additional methods to add to Face and Shell class" alt coords="335,104,411,129">
</area>
<area shape="rect" id="node13" href="#topology.Joint" target="_top" title="Joint" alt coords="337,55,409,80">
</area>
<area shape="rect" id="node3" href="#topology.Compound" target="_top" title="A Compound in build123d is a topological entity representing a collection of" alt coords="491,153,583,179">
</area>
<area shape="rect" id="node5" href="#topology.Curve" target="_top" title="A Compound containing 1D objects - aka Edges" alt coords="631,104,703,129">
</area>
<area shape="rect" id="node16" href="#topology.Part" target="_top" title="A Compound containing 3D objects - aka Solids" alt coords="631,153,703,179">
</area>
<area shape="rect" id="node21" href="#topology.Sketch" target="_top" title="A Compound containing 2D objects - aka Faces" alt coords="631,203,703,228">
</area>
<area shape="rect" id="node4" href="#topology.Mixin3D" target="_top" title="Additional methods to add to 3D Shape classes" alt coords="335,203,411,228">
</area>
<area shape="rect" id="node23" href="#topology.Solid" target="_top" title="A Solid in build123d represents a three-dimensional solid geometry" alt coords="501,203,573,228">
</area>
<area shape="rect" id="node7" href="#topology.Edge" target="_top" title="An Edge in build123d is a fundamental element in the topological data structure" alt coords="501,252,573,277">
</area>
<area shape="rect" id="node8" href="#topology.Mixin1D" target="_top" title="Methods to add to the Edge and Wire classes" alt coords="335,252,411,277">
</area>
<area shape="rect" id="node26" href="#topology.Wire" target="_top" title="A Wire in build123d is a topological entity representing a connected sequence" alt coords="501,301,573,327">
</area>
<area shape="rect" id="node9" href="#topology.Face" target="_top" title="A Face in build123d represents a 3D bounded surface within the topological data" alt coords="501,55,573,80">
</area>
<area shape="rect" id="node20" href="#topology.Shell" target="_top" title="A Shell is a fundamental component in build123d&#39;s topological data structure" alt coords="501,104,573,129">
</area>
<area shape="rect" id="node14" href="#topology.Shape" target="_top" title="Shape" alt coords="179,252,251,277">
</area>
<area shape="rect" id="node25" href="#topology.Vertex" target="_top" title="A Vertex in build123d represents a zero-dimensional point in the topological" alt coords="337,301,409,327">
</area>
<area shape="rect" id="node18" href="#topology.ShapeList" target="_top" title="Subclass of list with custom filter and sort methods appropriate to CAD" alt coords="24,153,109,179">
</area>
</map>
[class]{.pre}[ ]{.w}[[Compound]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Compound]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Iterable]{.pre}[[[]{.pre}]{.p}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Color]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[material]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[joints]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[dict]{.pre}[[[]{.pre}]{.p}[str]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Joint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[children]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Sequence]{.pre}[[[]{.pre}]{.p}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

A Compound in build123d is a topological entity representing a collection of geometric shapes grouped together within a single structure. It serves as a container for organizing diverse shapes like edges, faces, or solids. This hierarchical arrangement facilitates the construction of complex models by combining simpler shapes. Compound plays a pivotal role in managing the composition and structure of intricate 3D models in computer-aided design (CAD) applications, allowing engineers and designers to work with assemblies of shapes as unified entities for efficient modeling and analysis.

[classmethod]{.pre}[ ]{.w}[[cast]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Shape]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Returns the right type of wrapper, given a OCCT object

[[center]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[center_of:]{.pre} [~build123d.build_enums.CenterOf]{.pre} [=]{.pre} [<CenterOf.MASS>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

Return center of object

Find center of object

Parameters[:]{.colon}

center_of (CenterOf{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- center option. Defaults to CenterOf.MASS.

Raises[:]{.colon}
  • ValueError -- Center of GEOMETRY is not supported for this object

  • NotImplementedError -- Unable to calculate center of mass of this object

Returns[:]{.colon}

center

Return type[:]{.colon}

Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[compound]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.sig-return-typehint}]{.sig-return}

Return the Compound

[[compounds]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

compounds - all the compounds in this Shape

[[do_children_intersect]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[include_parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1e-05]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[bool]{.pre}[[,]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[None]{.pre}[[{.pre}]{.p},]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Do Children Intersect

Determine if any of the child objects within a Compound/assembly intersect by intersecting each of the shapes with each other and checking for a common volume.

Parameters[:]{.colon}
  • include_parent (bool, optional) -- check parent for intersections. Defaults to False.

  • tolerance (float, optional) -- maximum allowable volume difference. Defaults to 1e-5.

Returns[:]{.colon}

do the object intersect, intersecting objects, volume of intersection

Return type[:]{.colon}

tuple[bool, tuple[Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}, Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}], float]

[classmethod]{.pre}[ ]{.w}[[extrude]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Extrude a Shell into a Compound.

Parameters[:]{.colon}

direction (VectorLike) -- direction and magnitude of extrusion

Raises[:]{.colon}
  • ValueError -- Unsupported class

  • RuntimeError -- Generated invalid result

Returns[:]{.colon}

extruded shape

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[get_type]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj_type]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[type]{.pre}[[[]{.pre}]{.p}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[type]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[type]{.pre}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[type]{.pre}[[[]{.pre}]{.p}[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[type]{.pre}[[[]{.pre}]{.p}[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[type]{.pre}[[[]{.pre}]{.p}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[list]{.pre}[[[]{.pre}]{.p}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Extract the objects of the given type from a Compound. Note that this isn't the same as Faces() etc. which will extract Faces from Solids.

Parameters[:]{.colon}

obj_type (Union[Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal}, Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}, Face{.hxr-hoverxref .hxr-tooltip .reference .internal}, Shell{.hxr-hoverxref .hxr-tooltip .reference .internal}, Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}, Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- Object types to extract

Returns[:]{.colon}

Extracted objects

Return type[:]{.colon}

list[Union[Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal}, Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}, Face{.hxr-hoverxref .hxr-tooltip .reference .internal}, Shell{.hxr-hoverxref .hxr-tooltip .reference .internal}, Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}, Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]]

[[intersect]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[to_intersect]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Location]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Plane]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[None]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Intersect Compound with Shape or geometry object

Parameters[:]{.colon}

to_intersect (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal} | Vector{.hxr-hoverxref .hxr-tooltip .reference .internal} | Location{.hxr-hoverxref .hxr-tooltip .reference .internal} | Axis{.hxr-hoverxref .hxr-tooltip .reference .internal} | Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- objects to intersect

Returns[:]{.colon}
ShapeList of vertices, edges,

faces, and/or solids.

</p>
Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal} | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Face{.hxr-hoverxref .hxr-tooltip .reference .internal} | Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}] | None

[classmethod]{.pre}[ ]{.w}[[make_text]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[txt:]{.pre} [str]{.pre}]{.n}, [[font_size:]{.pre} [float]{.pre}]{.n}, [[font:]{.pre} [str]{.pre} [=]{.pre} ['Arial']{.pre}]{.n}, [[font_path:]{.pre} [str]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[font_style:]{.pre} [~build123d.build_enums.FontStyle]{.pre} [=]{.pre} [<FontStyle.REGULAR>]{.pre}]{.n}, [[text_align:]{.pre} [tuple[~build123d.build_enums.TextAlign]{.pre}]{.n}, ~build123d.build_enums.TextAlign{.pre} [=]{.pre} [(<TextAlign.CENTER>]{.pre}]{.n}, [[<TextAlign.CENTER>)]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[position_on_path:]{.pre} [float]{.pre} [=]{.pre} [0.0]{.pre}]{.n}, [[text_path:]{.pre} [~topology.one_d.Edge]{.pre} [|]{.pre} [~topology.one_d.Wire]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

2D Text that optionally follows a path.

The text that is created can be combined as with other sketch features by specifying a mode or rotated by the given angle. In addition, edges have been previously created with arc or segment, the text will follow the path defined by these edges. The start parameter can be used to shift the text along the path to achieve precise positioning.

Parameters[:]{.colon}
  • txt -- text to be rendered

  • font_size -- size of the font in model units

  • font -- font name

  • font_path -- path to font file

  • font_style -- text style. Defaults to FontStyle.REGULAR

  • text_align (tuple[TextAlign, TextAlign], optional) -- horizontal text align LEFT, CENTER, or RIGHT. Vertical text align BOTTOM, CENTER, TOP, or TOPFIRSTLINE. Defaults to (TextAlign.CENTER, TextAlign.CENTER)

  • align (Union[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}]], optional) -- align min, center, or max of object. Defaults to None

  • position_on_path -- the relative location on path to position the text, between 0.0 and 1.0. Defaults to 0.0

  • text_path -- a path for the text to follows. Defaults to None (linear text)

Returns[:]{.colon}

a Compound object containing multiple Faces representing the text

Examples:

::: {.highlight-default .notranslate} ::: highlight fox = Compound.make_text( txt="The quick brown fox jumped over the lazy dog", font_size=10, position_on_path=0.1, text_path=jump_edge, ) ::: :::

[classmethod]{.pre}[ ]{.w}[[make_triad]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[axes_scale]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

The coordinate system triad (X, Y, Z axes)

[[order]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[4.0]{.pre}
[[project_to_viewport]{.pre}]{.sig-name .descname}[(]{.sig-paren}viewport_origin]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, viewport_up]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[(0,]{.pre} [0,]{.pre} [1)]{.pre}]{.default_value}, look_at]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[focus]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[[,]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Project a shape onto a viewport returning visible and hidden Edges.

Parameters[:]{.colon}
  • viewport_origin (VectorLike) -- location of viewport

  • viewport_up (VectorLike, optional) -- direction of the viewport y axis. Defaults to (0, 0, 1).

  • look_at (VectorLike, optional) -- point to look at. Defaults to None (center of shape).

  • focus (float, optional) -- the focal length for perspective projection Defaults to None (orthographic projection)

Returns[:]{.colon}

visible & hidden Edges

Return type[:]{.colon}

tuple[ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}],ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}]]

[[unwrap]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[fully]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[True]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Strip unnecessary Compound wrappers

Parameters[:]{.colon}

fully (bool, optional) -- return base shape without any Compound wrappers (otherwise one Compound is left). Defaults to True.

Returns[:]{.colon}

base shape

Return type[:]{.colon}

Union[Self, Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}]

[property]{.pre}[ ]{.w}[[volume]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

volume - the volume of this Compound

<!-- -->
[class]{.pre}[ ]{.w}[[Edge]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Edge]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Color]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

An Edge in build123d is a fundamental element in the topological data structure representing a one-dimensional geometric entity within a 3D model. It encapsulates information about a curve, which could be a line, arc, or other parametrically defined shape. Edge is crucial in for precise modeling and manipulation of curves, facilitating operations like filleting, chamfering, and Boolean operations. It serves as a building block for constructing complex structures, such as wires and faces.

[property]{.pre}[ ]{.w}[[arc_center]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Vector]{.pre}

center of an underlying circle or ellipse geometry.

[[close]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Close an Edge

[[distribute_locations]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[count]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[int]{.pre}]{.n}, [[start]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.0]{.pre}]{.default_value}, [[stop]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1.0]{.pre}]{.default_value}, [[positions_only]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}[)]{.sig-paren} →]{.sig-return-icon} [[list]{.pre}[[[]{.pre}]{.p}[Location]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Distribute Locations

Distribute locations along edge or wire.

Parameters[:]{.colon}
  • self -- Wire:Edge:

  • count (int) -- Number of locations to generate

  • start (float) -- position along Edge|Wire to start. Defaults to 0.0.

  • stop (float) -- position along Edge|Wire to end. Defaults to 1.0.

  • positions_only (bool) -- only generate position not orientation. Defaults to False.

Returns[:]{.colon}

locations distributed along Edge|Wire

Return type[:]{.colon}

list[Location{.hxr-hoverxref .hxr-tooltip .reference .internal}]

Raises[:]{.colon}

ValueError -- count must be two or greater

[classmethod]{.pre}[ ]{.w}[[extrude]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Extrude a Vertex into an Edge.

Parameters[:]{.colon}

direction (VectorLike) -- direction and magnitude of extrusion

Raises[:]{.colon}
  • ValueError -- Unsupported class

  • RuntimeError -- Generated invalid result

Returns[:]{.colon}

extruded shape

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[find_intersection_points]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1e-06]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[Vector]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Determine the points where a 2D edge crosses itself or another 2D edge

Parameters[:]{.colon}
  • other (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal} | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- curve to compare with

  • tolerance (float, optional) -- the precision of computing the intersection points. Defaults to TOLERANCE.

Raises[:]{.colon}

ValueError -- empty edge

Returns[:]{.colon}

list of intersection points

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}]

[[find_tangent]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[list]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Find the parameter values of self where the tangent is equal to angle.

Parameters[:]{.colon}

angle (float) -- target angle in degrees

Returns[:]{.colon}

u values between 0.0 and 1.0

Return type[:]{.colon}

list[float]

[[geom_adaptor]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[BRepAdaptor_Curve]{.pre}]{.sig-return-typehint}]{.sig-return}

Return the Geom Curve from this Edge

[classmethod]{.pre}[ ]{.w}[[make_bezier]{.pre}]{.sig-name .descname}[(]{.sig-paren}*]{.pre}]{.o}[[cntl_pnts]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, weights]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[list]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Create a rational (with weights) or non-rational bezier curve. The first and last control points represent the start and end of the curve respectively. If weights are provided, there must be one provided for each control point.

Parameters[:]{.colon}
  • cntl_pnts (sequence[VectorLike]) -- points defining the curve

  • weights (list[float], optional) -- control point weights list. Defaults to None.

Raises[:]{.colon}
  • ValueError -- Too few control points

  • ValueError -- Too many control points

  • ValueError -- A weight is required for each control point

Returns[:]{.colon}

bezier curve

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_circle]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[radius:]{.pre} [float]{.pre}]{.n}, [[plane:]{.pre} [~build123d.geometry.Plane]{.pre} [=]{.pre} [Plane(o=(0.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[x=(1.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[z=(0.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[1.00))]{.pre}]{.n}, [[start_angle:]{.pre} [float]{.pre} [=]{.pre} [360.0]{.pre}]{.n}, [[end_angle:]{.pre} [float]{.pre} [=]{.pre} [360]{.pre}]{.n}, [[angular_direction:]{.pre} [~build123d.build_enums.AngularDirection]{.pre} [=]{.pre} [<AngularDirection.COUNTER_CLOCKWISE>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

make circle

Create a circle centered on the origin of plane

Parameters[:]{.colon}
  • radius (float) -- circle radius

  • plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- base plane. Defaults to Plane.XY.

  • start_angle (float, optional) -- start of arc angle. Defaults to 360.0.

  • end_angle (float, optional) -- end of arc angle. Defaults to 360.

  • angular_direction (AngularDirection, optional) -- arc direction. Defaults to AngularDirection.COUNTER_CLOCKWISE.

Returns[:]{.colon}

full or partial circle

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_constrained_arcs]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tangency_one]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal},]{.pre}]{.p}[ ]{.w}[Tangency]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, [[tangency_two]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal},]{.pre}]{.p}[ ]{.w}[Tangency]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, [[*]{.pre}]{.o}, [[radius]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[sagitta]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Sagitta]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[Sagitta.SHORT]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}\
[classmethod]{.pre}[ ]{.w}[[make_constrained_arcs]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tangency_one]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal},]{.pre}]{.p}[ ]{.w}[Tangency]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, [[tangency_two]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal},]{.pre}]{.p}[ ]{.w}[Tangency]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, [[*]{.pre}]{.o}, [[center_on]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[sagitta]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Sagitta]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[Sagitta.SHORT]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}\
[classmethod]{.pre}[ ]{.w}[[make_constrained_arcs]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tangency_one]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal},]{.pre}]{.p}[ ]{.w}[Tangency]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, [[tangency_two]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal},]{.pre}]{.p}[ ]{.w}[Tangency]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, [[tangency_three]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal},]{.pre}]{.p}[ ]{.w}[Tangency]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, [[*]{.pre}]{.o}, [[sagitta]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Sagitta]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[Sagitta.SHORT]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}\
[classmethod]{.pre}[ ]{.w}[[make_constrained_arcs]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tangency_one]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal},]{.pre}]{.p}[ ]{.w}[Tangency]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, [[*]{.pre}]{.o}, center]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}\
[classmethod]{.pre}[ ]{.w}[[make_constrained_arcs]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tangency_one]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal},]{.pre}]{.p}[ ]{.w}[Tangency]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, [[*]{.pre}]{.o}, [[radius]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[center_on]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}
[classmethod]{.pre}[ ]{.w}[[make_constrained_lines]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tangency_one]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal},]{.pre}]{.p}[ ]{.w}[Tangency]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[tangency_two]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal},]{.pre}]{.p}[ ]{.w}[Tangency]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}\
[classmethod]{.pre}[ ]{.w}[[make_constrained_lines]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tangency_one]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal},]{.pre}]{.p}[ ]{.w}[Tangency]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[tangency_two]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}\
[classmethod]{.pre}[ ]{.w}[[make_constrained_lines]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tangency_one]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal},]{.pre}]{.p}[ ]{.w}[Tangency]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[tangency_two]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}]{.n}, [[*]{.pre}]{.o}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Create planar line(s) on XY subject to tangency/contact constraints.

::: {#direct_api_reference.xhtml#supported-cases .section}

Supported cases

  1. Tangent to two curves

  2. Tangent to one curve and passing through a given point :::

[classmethod]{.pre}[ ]{.w}[[make_ellipse]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[x_radius:]{.pre} [float]{.pre}]{.n}, [[y_radius:]{.pre} [float]{.pre}]{.n}, [[plane:]{.pre} [~build123d.geometry.Plane]{.pre} [=]{.pre} [Plane(o=(0.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[x=(1.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[z=(0.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[1.00))]{.pre}]{.n}, [[start_angle:]{.pre} [float]{.pre} [=]{.pre} [360.0]{.pre}]{.n}, [[end_angle:]{.pre} [float]{.pre} [=]{.pre} [360.0]{.pre}]{.n}, [[angular_direction:]{.pre} [~build123d.build_enums.AngularDirection]{.pre} [=]{.pre} [<AngularDirection.COUNTER_CLOCKWISE>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

make ellipse

Makes an ellipse centered at the origin of plane.

Parameters[:]{.colon}
  • x_radius (float) -- x radius of the ellipse (along the x-axis of plane)

  • y_radius (float) -- y radius of the ellipse (along the y-axis of plane)

  • plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- base plane. Defaults to Plane.XY.

  • start_angle (float, optional) -- Defaults to 360.0.

  • end_angle (float, optional) -- Defaults to 360.0.

  • angular_direction (AngularDirection, optional) -- arc direction. Defaults to AngularDirection.COUNTER_CLOCKWISE.

Returns[:]{.colon}

full or partial ellipse

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_helix]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[pitch]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[height]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[radius]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, center]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[(0,]{.pre} [0,]{.pre} [0)]{.pre}]{.default_value}, normal]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[(0,]{.pre} [0,]{.pre} [1)]{.pre}]{.default_value}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.0]{.pre}]{.default_value}, [[lefthand]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Make a helix with a given pitch, height and radius. By default a cylindrical surface is used to create the helix. If the :angle: is set (the apex given in degree) a conical surface is used instead.

Parameters[:]{.colon}
  • pitch (float) -- distance per revolution along normal

  • height (float) -- total height

  • radius (float)

  • center (VectorLike, optional) -- Defaults to (0, 0, 0).

  • normal (VectorLike, optional) -- Defaults to (0, 0, 1).

  • angle (float, optional) -- conical angle. Defaults to 0.0.

  • lefthand (bool, optional) -- Defaults to False.

Returns[:]{.colon}

helix

Return type[:]{.colon}

Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_hyperbola]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[x_radius:]{.pre} [float]{.pre}]{.n}, [[y_radius:]{.pre} [float]{.pre}]{.n}, [[plane:]{.pre} [~build123d.geometry.Plane]{.pre} [=]{.pre} [Plane(o=(0.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[x=(1.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[z=(0.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[1.00))]{.pre}]{.n}, [[start_angle:]{.pre} [float]{.pre} [=]{.pre} [360.0]{.pre}]{.n}, [[end_angle:]{.pre} [float]{.pre} [=]{.pre} [360.0]{.pre}]{.n}, [[angular_direction:]{.pre} [~build123d.build_enums.AngularDirection]{.pre} [=]{.pre} [<AngularDirection.COUNTER_CLOCKWISE>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

make hyperbola

Makes a hyperbola centered at the origin of plane.

Parameters[:]{.colon}
  • x_radius (float) -- x radius of the hyperbola (along the x-axis of plane)

  • y_radius (float) -- y radius of the hyperbola (along the y-axis of plane)

  • plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- base plane. Defaults to Plane.XY.

  • start_angle (float, optional) -- Defaults to 360.0.

  • end_angle (float, optional) -- Defaults to 360.0.

  • angular_direction (AngularDirection, optional) -- arc direction. Defaults to AngularDirection.COUNTER_CLOCKWISE.

Returns[:]{.colon}

full or partial hyperbola

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_line]{.pre}]{.sig-name .descname}[(]{.sig-paren}point1]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, point2]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Create a line between two points

Parameters[:]{.colon}
  • point1 -- VectorLike: that represents the first point

  • point2 -- VectorLike: that represents the second point

Returns[:]{.colon}

A linear edge between the two provided points

[classmethod]{.pre}[ ]{.w}[[make_mid_way]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[first]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[second]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[middle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.5]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

make line between edges

Create a new linear Edge between the two provided Edges. If the Edges are parallel but in the opposite directions one Edge is flipped such that the mid way Edge isn't truncated.

Parameters[:]{.colon}
  • first (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- first reference Edge

  • second (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- second reference Edge

  • middle (float, optional) -- factional distance between Edges. Defaults to 0.5.

Returns[:]{.colon}

linear Edge between two Edges

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_parabola]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[focal_length:]{.pre} [float]{.pre}]{.n}, [[plane:]{.pre} [~build123d.geometry.Plane]{.pre} [=]{.pre} [Plane(o=(0.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[x=(1.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[z=(0.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[1.00))]{.pre}]{.n}, [[start_angle:]{.pre} [float]{.pre} [=]{.pre} [0.0]{.pre}]{.n}, [[end_angle:]{.pre} [float]{.pre} [=]{.pre} [90.0]{.pre}]{.n}, [[angular_direction:]{.pre} [~build123d.build_enums.AngularDirection]{.pre} [=]{.pre} [<AngularDirection.COUNTER_CLOCKWISE>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

make parabola

Makes an parabola centered at the origin of plane.

Parameters[:]{.colon}
  • focal_length (float) -- focal length the parabola (distance from the vertex to focus along the x-axis of plane)

  • plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- base plane. Defaults to Plane.XY.

  • start_angle (float, optional) -- Defaults to 0.0.

  • end_angle (float, optional) -- Defaults to 90.0.

  • angular_direction (AngularDirection, optional) -- arc direction. Defaults to AngularDirection.COUNTER_CLOCKWISE.

Returns[:]{.colon}

full or partial parabola

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_spline]{.pre}]{.sig-name .descname}[(]{.sig-paren}points]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[list]{.pre}[[[]{.pre}]{.p}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}{.pre}]{.p}]{.n}, tangents]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[list]{.pre}[[[]{.pre}]{.p}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[periodic]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}, parameters]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[list]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[scale]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[True]{.pre}]{.default_value}, [[tol]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1e-06]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Spline

Interpolate a spline through the provided points.

Parameters[:]{.colon}
  • points (list[VectorLike]) -- the points defining the spline

  • tangents (list[VectorLike], optional) -- start and finish tangent. Defaults to None.

  • periodic (bool, optional) -- creation of periodic curves. Defaults to False.

  • parameters (list[float], optional) -- the value of the parameter at each interpolation point. (The interpolated curve is represented as a vector-valued function of a scalar parameter.) If periodic == True, then len(parameters) must be len(interpolation points) + 1, otherwise len(parameters) must be equal to len(interpolation points). Defaults to None.

  • scale (bool, optional) -- whether to scale the specified tangent vectors before interpolating. Each tangent is scaled, so it's length is equal to the derivative of the Lagrange interpolated curve. I.e., set this to True, if you want to use only the direction of the tangent vectors specified by <cite>{=html}tangents</cite>{=html} , but not their magnitude. Defaults to True.

  • tol (float, optional) -- tolerance of the algorithm (consult OCC documentation). Used to check that the specified points are not too close to each other, and that tangent vectors are not too short. (In either case interpolation may fail.). Defaults to 1e-6.

Raises[:]{.colon}
  • ValueError -- Parameter for each interpolation point

  • ValueError -- Tangent for each interpolation point

  • ValueError -- B-spline interpolation failed

Returns[:]{.colon}

the spline

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_spline_approx]{.pre}]{.sig-name .descname}[(]{.sig-paren}points]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[list]{.pre}[[[]{.pre}]{.p}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}{.pre}]{.p}]{.n}, [[tol]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.001]{.pre}]{.default_value}, smoothing]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[min_deg]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[int]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1]{.pre}]{.default_value}, [[max_deg]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[int]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[6]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Approximate a spline through the provided points.

Parameters[:]{.colon}
  • points (list[Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}])

  • tol (float, optional) -- tolerance of the algorithm. Defaults to 1e-3.

  • smoothing (Tuple[float, float, float], optional) -- optional tuple of 3 weights use for variational smoothing. Defaults to None.

  • min_deg (int, optional) -- minimum spline degree. Enforced only when smoothing is None. Defaults to 1.

  • max_deg (int, optional) -- maximum spline degree. Defaults to 6.

Raises[:]{.colon}

ValueError -- B-spline approximation failed

Returns[:]{.colon}

spline

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_tangent_arc]{.pre}]{.sig-name .descname}[(]{.sig-paren}start]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, tangent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, end]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Tangent Arc

Makes a tangent arc from point start, in the direction of tangent and ends at end.

Parameters[:]{.colon}
  • start (VectorLike) -- start point

  • tangent (VectorLike) -- start tangent

  • end (VectorLike) -- end point

Returns[:]{.colon}

circular arc

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_three_point_arc]{.pre}]{.sig-name .descname}[(]{.sig-paren}point1]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, point2]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, point3]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Three Point Arc

Makes a three point arc through the provided points

Parameters[:]{.colon}
  • point1 (VectorLike) -- start point

  • point2 (VectorLike) -- middle point

  • point3 (VectorLike) -- end point

Returns[:]{.colon}

a circular arc through the three points

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[order]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[1.0]{.pre}
[[param_at_point]{.pre}]{.sig-name .descname}[(]{.sig-paren}point]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[float]{.pre}]{.sig-return-typehint}]{.sig-return}

Return the normalized parameter (∈ [0.0, 1.0]) of the location on this edge closest to <cite>{=html}point</cite>{=html}.

This method always returns a normalized parameter across the edge's full OCCT parameter range, even though the underlying OCP/OCCT queries work in native (non-normalized) parameters. It is robust to several OCCT quirks:

1) Vertex snap (fast path) If <cite>{=html}point</cite>{=html} coincides (within tolerance) with one of the edge's vertices, that vertex's OCCT parameter is used and normalized to [0, 1]. Note: for a closed edge, a vertex may represent both start and end; the mapping is therefore ambiguous and either end may be chosen.

2) Projection via GeomAPI_ProjectPointOnCurve The OCCT projector's <cite>{=html}LowerDistanceParameter()</cite>{=html} can legitimately return a value outside the edge's [param_min, param_max] (e.g., periodic curves or implementation behavior). The result is wrapped back into range using a modulo by the parameter span and then normalized to [0, 1]. The projected answer is accepted only if re-evaluating the 3D point at that normalized parameter is within tolerance of the input <cite>{=html}point</cite>{=html}.

3) Fallback numeric search (robust path) If the projector fails the validation, a bounded 1D search is performed over [0, 1] using progressive subdivision and local minimization of the 3D distance ‖edge(u) - point‖. The first minimum found under geometric resolution is returned.

Parameters[:]{.colon}

point (VectorLike) -- A point expected to lie on this edge (within tolerance).

Raises[:]{.colon}
  • ValueError -- If <cite>{=html}point</cite>{=html} is not on the edge within tolerance.

  • ValueError -- Can't find param on empty edge

  • RuntimeError -- If no parameter can be found (e.g., extremely pathological curves or numerical failure).

Returns[:]{.colon}

Normalized parameter in [0.0, 1.0] corresponding to the point's closest location on the edge.

Return type[:]{.colon}

float

[[project_to_shape]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[target_object]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, center]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[list]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Project Edge

Project an Edge onto a Shape generating new wires on the surfaces of the object one and only one of <cite>{=html}direction</cite>{=html} or <cite>{=html}center</cite>{=html} must be provided. Note that one or more wires may be generated depending on the topology of the target object and location/direction of projection.

To avoid flipping the normal of a face built with the projected wire the orientation of the output wires are forced to be the same as self.

Parameters[:]{.colon}
  • target_object -- Object to project onto

  • direction -- Parallel projection direction. Defaults to None.

  • center -- Conical center of projection. Defaults to None.

  • target_object -- Shape:

  • direction -- VectorLike: (Default value = None)

  • center -- VectorLike: (Default value = None)

Returns[:]{.colon}

Projected Edge(s)

Raises[:]{.colon}

ValueError -- Only one of direction or center must be provided

[[reversed]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[reconstruct]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return a copy of self with the opposite orientation.

Parameters[:]{.colon}

reconstruct (bool, optional) -- rebuild edge instead of setting OCCT flag. Defaults to False.

Returns[:]{.colon}

reversed

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[to_axis]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Axis]{.pre}]{.sig-return-typehint}]{.sig-return}

Translate a linear Edge to an Axis

[[to_wire]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Edge as Wire

[[trim]{.pre}]{.sig-name .descname}[(]{.sig-paren}start]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, end]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

_summary_

Parameters[:]{.colon}
  • start (float | VectorLike) -- _description_

  • end (float | VectorLike) -- _description_

Raises[:]{.colon}
  • TypeError -- _description_

  • ValueError -- _description_

Returns[:]{.colon}

_description_

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[trim_to_length]{.pre}]{.sig-name .descname}[(]{.sig-paren}start]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, [[length]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Create a new edge starting at the given normalized parameter of a given length.

Parameters[:]{.colon}
  • start (float | VectorLike) -- 0.0 <= start < 1.0 or point on edge

  • length (float) -- target length

Raises[:]{.colon}

ValueError -- can't trim empty edge

Returns[:]{.colon}

trimmed edge

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[class]{.pre}[ ]{.w}[[Face]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Face]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Plane]{.pre}]{.n}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Color]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}\
[class]{.pre}[ ]{.w}[[Face]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[outer_wire]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[inner_wires]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Color]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

A Face in build123d represents a 3D bounded surface within the topological data structure. It encapsulates geometric information, defining a face of a 3D shape. These faces are integral components of complex structures, such as solids and shells. Face enables precise modeling and manipulation of surfaces, supporting operations like trimming, filleting, and Boolean operations.

[property]{.pre}[ ]{.w}[[area_without_holes]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

Calculate the total surface area of the face, including the areas of any holes.

This property returns the overall area of the face as if the inner boundaries (holes) were filled in.

Returns[:]{.colon}

The total surface area, including the area of holes. Returns 0.0 if the face is empty.

Return type[:]{.colon}

float

[property]{.pre}[ ]{.w}[[axes_of_symmetry]{.pre}]{.sig-name .descname}:]{.pre}]{.p}[ ]{.w}[list]{.pre}[[[]{.pre}]{.p}[Axis]{.pre}[[{.pre}]{.p}

Computes and returns the axes of symmetry for a planar face.

The method determines potential symmetry axes by analyzing the face's geometry:

  • It first validates that the face is non-empty and planar.

  • For faces with inner wires (holes), it computes the centroid of the holes and the face's overall center (COG).

    • If the holes' centroid significantly deviates from the COG (beyond a specified tolerance), the symmetry axis is taken along the line connecting these points; otherwise, each hole's center is used to generate a candidate axis.
  • For faces without holes, candidate directions are derived by sampling midpoints along the outer wire's edges.

    • If curved edges are present, additional candidate directions are obtained from an oriented bounding box (OBB) constructed around the face.

For each candidate direction, the face is split by a plane (defined using the candidate direction and the face's normal). The top half of the face is then mirrored across this plane, and if the area of the intersection between the mirrored half and the bottom half matches the bottom half's area within a small tolerance, the direction is accepted as an axis of symmetry.

Returns[:]{.colon}
A list of Axis objects, each defined by the face's

center and a direction vector, representing the symmetry axes of the face.

</p>
Return type[:]{.colon}

list[Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}]

Raises[:]{.colon}
  • ValueError -- If the face or its underlying representation is empty.

  • ValueError -- If the face is not planar.

[property]{.pre}[ ]{.w}[[axis_of_rotation]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[None]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}

Get the rotational axis of a cylinder or torus

[[center]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[center_of:]{.pre} [~build123d.build_enums.CenterOf]{.pre} [=]{.pre} [<CenterOf.GEOMETRY>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

Center of Face

Return the center based on center_of

Parameters[:]{.colon}

center_of (CenterOf{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- centering option. Defaults to CenterOf.GEOMETRY.

Returns[:]{.colon}

center

Return type[:]{.colon}

Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}

[property]{.pre}[ ]{.w}[[center_location]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Location]{.pre}

Location at the center of face

[[chamfer_2d]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[distance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[distance2]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[vertices]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}, [[edge]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Apply 2D chamfer to a face

Parameters[:]{.colon}
  • distance (float) -- chamfer length

  • distance2 (float) -- chamfer length

  • vertices (Iterable[Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- vertices to chamfer

  • edge (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- identifies the side where length is measured. The vertices must be part of the edge

Raises[:]{.colon}
  • ValueError -- Cannot chamfer at this location

  • ValueError -- One or more vertices are not part of edge

Returns[:]{.colon}

face with a chamfered corner(s)

Return type[:]{.colon}

Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[extrude]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Extrude an Edge into a Face.

Parameters[:]{.colon}

direction (VectorLike) -- direction and magnitude of extrusion

Raises[:]{.colon}
  • ValueError -- Unsupported class

  • RuntimeError -- Generated invalid result

Returns[:]{.colon}

extruded shape

Return type[:]{.colon}

Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[fillet_2d]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[radius]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[vertices]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Apply 2D fillet to a face

Parameters[:]{.colon}
  • radius -- float:

  • vertices -- Iterable[Vertex]:

Returns:

[[geom_adaptor]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Geom_Surface]{.pre}]{.sig-return-typehint}]{.sig-return}

Return the Geom Surface for this Face

[property]{.pre}[ ]{.w}[[geometry]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[None]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[str]{.pre}

geometry of planar face

[[inner_wires]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Extract the inner or hole wires from this Face

[property]{.pre}[ ]{.w}[[is_circular_concave]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[bool]{.pre}

Determine whether a given face is concave relative to its underlying geometry for supported geometries: cylinder, sphere, torus.

Returns[:]{.colon}

True if concave; otherwise, False.

Return type[:]{.colon}

bool

[property]{.pre}[ ]{.w}[[is_circular_convex]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[bool]{.pre}

Determine whether a given face is convex relative to its underlying geometry for supported geometries: cylinder, sphere, torus.

Returns[:]{.colon}

True if convex; otherwise, False.

Return type[:]{.colon}

bool

[[is_coplanar]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

Is this planar face coplanar with the provided plane

[[is_inside]{.pre}]{.sig-name .descname}[(]{.sig-paren}point]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1e-06]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

Point inside Face

Returns whether or not the point is inside a Face within the specified tolerance. Points on the edge of the Face are considered inside.

Parameters[:]{.colon}
  • point (VectorLike) -- tuple or Vector representing 3D point to be tested

  • tolerance (float) -- tolerance for inside determination. Defaults to 1.0e-6.

  • point -- VectorLike:

  • tolerance -- float: (Default value = 1.0e-6)

Returns[:]{.colon}

indicating whether or not point is within Face

Return type[:]{.colon}

bool

[property]{.pre}[ ]{.w}[[is_planar]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[bool]{.pre}

Is the face planar even though its geom_type may not be PLANE

[property]{.pre}[ ]{.w}[[length]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[None]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[float]{.pre}

length of planar face

[[location_at]{.pre}]{.sig-name .descname}[(]{.sig-paren}surface_point]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[*]{.pre}]{.o}, x_dir]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Location]{.pre}]{.sig-return-typehint}]{.sig-return}\
[[location_at]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[u]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[v]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[*]{.pre}]{.o}, x_dir]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Location]{.pre}]{.sig-return-typehint}]{.sig-return}

location_at

Get the location (origin and orientation) on the surface of the face.

This method supports two overloads:

1. <cite>{=html}location_at(u: float, v: float, *, x_dir: VectorLike | None = None) -> Location</cite>{=html} - Specifies the point in normalized UV parameter space of the face. - <cite>{=html}u</cite>{=html} and <cite>{=html}v</cite>{=html} are floats between 0.0 and 1.0. - Optionally override the local X direction using <cite>{=html}x_dir</cite>{=html}.

2. <cite>{=html}location_at(surface_point: VectorLike, *, x_dir: VectorLike | None = None) -> Location</cite>{=html} - Projects the given 3D point onto the face surface. - The point must be reasonably close to the face. - Optionally override the local X direction using <cite>{=html}x_dir</cite>{=html}.

If no arguments are provided, the location at the center of the face (u=0.5, v=0.5) is returned.

Parameters[:]{.colon}
  • u (float) -- Normalized horizontal surface parameter (optional).

  • v (float) -- Normalized vertical surface parameter (optional).

  • surface_point (VectorLike) -- A 3D point near the surface (optional).

  • x_dir (VectorLike, optional) -- Direction for the local X axis. If not given, the tangent in the U direction is used.

Returns[:]{.colon}

A full 3D placement at the specified point on the face surface.

Return type[:]{.colon}

Location{.hxr-hoverxref .hxr-tooltip .reference .internal}

Raises[:]{.colon}

ValueError -- If only one of <cite>{=html}u</cite>{=html} or <cite>{=html}v</cite>{=html} is provided or invalid keyword args are passed.

[classmethod]{.pre}[ ]{.w}[[make_bezier_surface]{.pre}]{.sig-name .descname}[(]{.sig-paren}points]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[list]{.pre}[[[]{.pre}]{.p}[list]{.pre}[[[]{.pre}]{.p}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}{.pre}]{.p}{.pre}]{.p}]{.n}, weights]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[list]{.pre}[[[]{.pre}]{.p}[list]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Construct a Bézier surface from the provided 2d array of points.

Parameters[:]{.colon}
  • points (list[list[VectorLike]]) -- a 2D list of control points

  • weights (list[list[float]], optional) -- control point weights. Defaults to None.

Raises[:]{.colon}
  • ValueError -- Too few control points

  • ValueError -- Too many control points

  • ValueError -- A weight is required for each control point

Returns[:]{.colon}

a potentially non-planar face

Return type[:]{.colon}

Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_gordon_surface]{.pre}]{.sig-name .descname}[(]{.sig-paren}profiles]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}, guides]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.0003]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Constructs a Gordon surface from a network of profile and guide curves.

Requirements: 1. Profiles and guides may be defined as points or curves. 2. Only the first or last profile or guide may be a point. 3. At least one profile and one guide must be a non-point curve. 4. Each profile must intersect with every guide. 5. Both ends of every profile must lie on a guide. 6. Both ends of every guide must lie on a profile.

Parameters[:]{.colon}
  • profiles (Iterable[VectorLike | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- Profiles defined as points or edges.

  • guides (Iterable[VectorLike | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- Guides defined as points or edges.

  • tolerance (float, optional) -- Tolerance used for surface construction and intersection calculations.

Raises[:]{.colon}

ValueError -- input Edge cannot be empty.

Returns[:]{.colon}

the interpolated Gordon surface

Return type[:]{.colon}

Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[make_holes]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[interior_wires]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[list]{.pre}[[[]{.pre}]{.p}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Make Holes in Face

Create holes in the Face 'self' from interior_wires which must be entirely interior. Note that making holes in faces is more efficient than using boolean operations with solid object. Also note that OCCT core may fail unless the orientation of the wire is correct - use <cite>{=html}Wire(forward_wire.wrapped.Reversed())</cite>{=html} to reverse a wire.

Example

For example, make a series of slots on the curved walls of a cylinder.

Parameters[:]{.colon}
  • interior_wires -- a list of hole outline wires

  • interior_wires -- list[Wire]:

Returns[:]{.colon}

'self' with holes

Return type[:]{.colon}

Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

Raises[:]{.colon}
  • RuntimeError -- adding interior hole in non-planar face with provided interior_wires

  • RuntimeError -- resulting face is not valid

[classmethod]{.pre}[ ]{.w}[[make_plane]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[Plane(o=(0.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [x=(1.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [z=(0.00,]{.pre} [0.00,]{.pre} [1.00))]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Create a unlimited size Face aligned with plane

[classmethod]{.pre}[ ]{.w}[[make_rect]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[width]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[height]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[Plane(o=(0.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [x=(1.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [z=(0.00,]{.pre} [0.00,]{.pre} [1.00))]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Make a Rectangle centered on center with the given normal

Parameters[:]{.colon}
  • width (float, optional) -- width (local x).

  • height (float, optional) -- height (local y).

  • plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- base plane. Defaults to Plane.XY.

Returns[:]{.colon}

The centered rectangle

Return type[:]{.colon}

Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_surface]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[exterior]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Iterable]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}, surface_points]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[interior_wires]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Create Non-Planar Face

Create a potentially non-planar face bounded by exterior (wire or edges), optionally refined by surface_points with optional holes defined by interior_wires.

Parameters[:]{.colon}
  • exterior (Union[Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}, list[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}]]) -- Perimeter of face

  • surface_points (list[VectorLike], optional) -- Points on the surface that refine the shape. Defaults to None.

  • interior_wires (list[Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- Hole(s) in the face. Defaults to None.

Raises[:]{.colon}
  • RuntimeError -- Internal error building face

  • RuntimeError -- Error building non-planar face with provided surface_points

  • RuntimeError -- Error adding interior hole

  • RuntimeError -- Generated face is invalid

Returns[:]{.colon}

Potentially non-planar face

Return type[:]{.colon}

Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_surface_from_array_of_points]{.pre}]{.sig-name .descname}[(]{.sig-paren}points]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[list]{.pre}[[[]{.pre}]{.p}[list]{.pre}[[[]{.pre}]{.p}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}{.pre}]{.p}{.pre}]{.p}]{.n}, [[tol]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.01]{.pre}]{.default_value}, smoothing]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[min_deg]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[int]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1]{.pre}]{.default_value}, [[max_deg]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[int]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[3]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Approximate a spline surface through the provided 2d array of points. The first dimension correspond to points on the vertical direction in the parameter space of the face. The second dimension correspond to points on the horizontal direction in the parameter space of the face. The 2 dimensions are U,V dimensions of the parameter space of the face.

Parameters[:]{.colon}
  • points (list[list[VectorLike]]) -- a 2D list of points, first dimension is V parameters second is U parameters.

  • tol (float, optional) -- tolerance of the algorithm. Defaults to 1e-2.

  • smoothing (Tuple[float, float, float], optional) -- optional tuple of 3 weights use for variational smoothing. Defaults to None.

  • min_deg (int, optional) -- minimum spline degree. Enforced only when smoothing is None. Defaults to 1.

  • max_deg (int, optional) -- maximum spline degree. Defaults to 3.

Raises[:]{.colon}

ValueError -- B-spline approximation failed

Returns[:]{.colon}

a potentially non-planar face defined by points

Return type[:]{.colon}

Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_surface_from_curves]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[edge1]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[edge2]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}\
[classmethod]{.pre}[ ]{.w}[[make_surface_from_curves]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[wire1]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[wire2]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

make_surface_from_curves

Create a ruled surface out of two edges or two wires. If wires are used then these must have the same number of edges.

Parameters[:]{.colon}
  • curve1 (Union[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal},Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- side of surface

  • curve2 (Union[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal},Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- opposite side of surface

Returns[:]{.colon}

potentially non planar surface

Return type[:]{.colon}

Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_surface_patch]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[edge_face_constraints]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[tuple]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[,]{.pre}]{.p}[ ]{.w}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal},]{.pre}]{.p}[ ]{.w}[ContinuityLevel]{.pre}[[{.pre}]{.p}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[edge_constraints]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, point_constraints]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Create a potentially non-planar face patch bounded by exterior edges which can be optionally refined using support faces to ensure e.g. tangent surface continuity. Also can optionally refine the surface using surface points.

Parameters[:]{.colon}
  • edge_face_constraints (list[tuple[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}, Face{.hxr-hoverxref .hxr-tooltip .reference .internal}, ContinuityLevel]], optional) -- Edges defining perimeter of face with adjacent support faces subject to ContinuityLevel. Defaults to None.

  • edge_constraints (list[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- Edges defining perimeter of face without adjacent support faces. Defaults to None.

  • point_constraints (list[VectorLike], optional) -- Points on the surface that refine the shape. Defaults to None.

Raises[:]{.colon}
  • RuntimeError -- Error building non-planar face with provided constraints

  • RuntimeError -- Generated face is invalid

Returns[:]{.colon}

Potentially non-planar face

Return type[:]{.colon}

Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[normal_at]{.pre}]{.sig-name .descname}[(]{.sig-paren}surface_point]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}\
[[normal_at]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[u]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[v]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

normal_at

Computes the normal vector at the desired location on the face.

Parameters[:]{.colon}

surface_point (VectorLike, optional) -- a point that lies on the surface where the normal. Defaults to None.

Returns[:]{.colon}

surface normal direction

Return type[:]{.colon}

Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[order]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[2.0]{.pre}
[[outer_wire]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Extract the perimeter wire from this Face

[[position_at]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[u]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[v]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

Computes a point on the Face given u, v coordinates.

Parameters[:]{.colon}
  • u (float) -- the horizontal coordinate in the parameter space of the Face, between 0.0 and 1.0

  • v (float) -- the vertical coordinate in the parameter space of the Face, between 0.0 and 1.0

Returns[:]{.colon}

point on Face

Return type[:]{.colon}

Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[project_to_shape]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[target_object]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Project Face to target Object

Project a Face onto a Shape generating new Face(s) on the surfaces of the object.

A projection with no taper is illustrated below:

flatProjection

Note that an array of faces is returned as the projection might result in faces on the "front" and "back" of the object (or even more if there are intermediate surfaces in the projection path). faces "behind" the projection are not returned.

Parameters[:]{.colon}
  • target_object (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- Object to project onto

  • direction (VectorLike) -- projection direction

Returns[:]{.colon}

Face(s) projected on target object ordered by distance

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}]

[property]{.pre}[ ]{.w}[[radii]{.pre}]{.sig-name .descname}:]{.pre}]{.p}[ ]{.w}[None]{.pre}[ ]{.w}[[{.pre}]{.p}

Return the major and minor radii of a torus otherwise None

[property]{.pre}[ ]{.w}[[radius]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[None]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[float]{.pre}

Return the radius of a cylinder or sphere, otherwise None

[classmethod]{.pre}[ ]{.w}[[revolve]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[profile]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[axis]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

sweep

Revolve an Edge around an axis.

Parameters[:]{.colon}
  • profile (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- the object to sweep

  • angle (float) -- the angle to revolve through

  • axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- rotation Axis

Returns[:]{.colon}

resulting face

Return type[:]{.colon}

Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

[property]{.pre}[ ]{.w}[[semi_angle]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[None]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[float]{.pre}

Return the semi angle of a cone, otherwise None

[classmethod]{.pre}[ ]{.w}[[sew_faces]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[faces]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[list]{.pre}[[[]{.pre}]{.p}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

sew faces

Group contiguous faces and return them in a list of ShapeList

Parameters[:]{.colon}

faces (Iterable[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- Faces to sew together

Raises[:]{.colon}

RuntimeError -- OCCT SewedShape generated unexpected output

Returns[:]{.colon}

grouped contiguous faces

Return type[:]{.colon}

list[ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}]]

[classmethod]{.pre}[ ]{.w}[[sweep]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[profile:]{.pre} [Curve]{.pre} [|]{.pre} [Edge]{.pre} [|]{.pre} [Wire]{.pre}]{.n}, [[path:]{.pre} [Curve]{.pre} [|]{.pre} [Edge]{.pre} [|]{.pre} [Wire]{.pre}]{.n}, [[transition=<Transition.TRANSFORMED>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Sweep a 1D profile along a 1D path. Both the profile and path must be composed of only 1 Edge.

Parameters[:]{.colon}
  • profile (Union[Curve{.hxr-hoverxref .hxr-tooltip .reference .internal},Edge{.hxr-hoverxref .hxr-tooltip .reference .internal},Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- the object to sweep

  • path (Union[Curve{.hxr-hoverxref .hxr-tooltip .reference .internal},Edge{.hxr-hoverxref .hxr-tooltip .reference .internal},Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- the path to follow when sweeping

  • transition (Transition{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- handling of profile orientation at C1 path discontinuities. Defaults to Transition.TRANSFORMED.

Raises[:]{.colon}

ValueError -- Only 1 Edge allowed in profile & path

Returns[:]{.colon}

resulting face, may be non-planar

Return type[:]{.colon}

Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[to_arcs]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.001]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Approximate planar face with arcs and straight line segments.

This is a utility used internally to convert or adapt a face for Boolean operations. Its purpose is not typically for general use, but rather as a helper within the Boolean kernel to ensure input faces are in a compatible and canonical form.

Parameters[:]{.colon}

tolerance (float, optional) -- Approximation tolerance. Defaults to 1e-3.

Returns[:]{.colon}

approximated face

Return type[:]{.colon}

Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

[property]{.pre}[ ]{.w}[[volume]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

volume - the volume of this Face, which is always zero

[property]{.pre}[ ]{.w}[[width]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[None]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[float]{.pre}

width of planar face

[[wire]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return the outerwire, generate a warning if inner_wires present

[[without_holes]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Remove all of the holes from this face.

Returns[:]{.colon}

A new Face instance identical to the original but without any holes.

Return type[:]{.colon}

Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[wrap]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[planar_shape]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[surface_loc]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Location]{.pre}]{.n}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.001]{.pre}]{.default_value}, [[extension_factor]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.1]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}\
[[wrap]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[planar_shape]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[surface_loc]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Location]{.pre}]{.n}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.001]{.pre}]{.default_value}, [[extension_factor]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.1]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}\
[[wrap]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[planar_shape]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[surface_loc]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Location]{.pre}]{.n}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.001]{.pre}]{.default_value}, [[extension_factor]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.1]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

wrap

Wrap a planar 2D shape onto a 3D surface.

This method conforms a 2D shape defined on the XY plane (Edge, Wire, or Face) to the curvature of a non-planar 3D Face (the target surface), starting at a specified surface location. The operation attempts to preserve the original edge lengths and shape as closely as possible while minimizing the geometric distortion that naturally arises when mapping flat geometry onto curved surfaces.

The wrapping process follows the local orientation of the surface and progressively fits each edge along the curvature. To help ensure continuity, the first and last edges are extended and trimmed to close small gaps introduced by distortion. The final shape is tightly aligned to the surface geometry.

This method is useful for applying flat features---such as decorative patterns, cutouts, or boundary outlines---onto curved or freeform surfaces while retaining their original proportions.

Parameters[:]{.colon}
  • planar_shape (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal} | Face{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- flat shape to wrap around surface

  • surface_loc (Location{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- location on surface to wrap

  • tolerance (float, optional) -- maximum allowed error. Defaults to 0.001

  • extension_factor (float, optional) -- amount to extend the wrapped first and last edges to allow them to cross. Defaults to 0.1

Raises[:]{.colon}

ValueError -- Invalid planar shape

Returns[:]{.colon}

wrapped shape

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal} | Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[wrap_faces]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[faces]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}, [[path]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[start]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.0]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Wrap a sequence of 2D faces onto a 3D surface, aligned along a guiding path.

This method places multiple planar <cite>{=html}Face</cite>{=html} objects (defined in the XY plane) onto a curved 3D surface (<cite>{=html}self</cite>{=html}), following a given path (Wire or Edge) that lies on or closely follows the surface. Each face is spaced along the path according to its original horizontal (X-axis) position, preserving the relative layout of the input faces.

The wrapping process attempts to maintain the shape and size of each face while minimizing distortion. Each face is repositioned to the origin, then individually wrapped onto the surface starting at a specific point along the path. The face's new orientation is defined using the path's tangent direction and the surface normal at that point.

This is particularly useful for placing a series of features---such as embossed logos, engraved labels, or patterned tiles---onto a freeform or cylindrical surface, aligned along a reference edge or curve.

Parameters[:]{.colon}
  • faces (Iterable[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- An iterable of 2D planar faces to be wrapped.

  • path (Wire{.hxr-hoverxref .hxr-tooltip .reference .internal} | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- A curve on the target surface that defines the alignment direction. The X-position of each face is mapped to a relative position along this path.

  • start (float, optional) -- The relative starting point on the path (between 0.0 and 1.0) where the first face should be placed. Defaults to 0.0.

Returns[:]{.colon}
A list of wrapped face objects, aligned and conformed to the

surface.

</p>
Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}]

<!-- -->
[class]{.pre}[ ]{.w}[[Mixin1D]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Shape]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[ColorLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

Methods to add to the Edge and Wire classes

[[__matmul__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[position]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

Position on wire operator @

[[__mod__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[position]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

Tangent on wire operator %

[classmethod]{.pre}[ ]{.w}[[cast]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Shape]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Returns the right type of wrapper, given a OCCT object

[[center]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[center_of:]{.pre} [~build123d.build_enums.CenterOf]{.pre} [=]{.pre} [<CenterOf.GEOMETRY>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

Center of object

Return the center based on center_of

Parameters[:]{.colon}

center_of (CenterOf{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- centering option. Defaults to CenterOf.GEOMETRY.

Returns[:]{.colon}

center

Return type[:]{.colon}

Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[common_plane]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[lines]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1e-06]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[None]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Plane]{.pre}]{.sig-return-typehint}]{.sig-return}

Find the plane containing all the edges/wires (including self). If there is no common plane return None. If the edges are coaxial, select one of the infinite number of valid planes.

Parameters[:]{.colon}
  • lines (sequence of Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- edges in common with self

  • tolerance (float) -- amount lines can deviate from plane. Defaults to TOLERANCE.

Returns[:]{.colon}

Either the common plane or None

Return type[:]{.colon}

None | Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[curvature_comb]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[count]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[int]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[100]{.pre}]{.default_value}, [[max_tooth_size]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Build a curvature comb for a planar (XY) 1D curve.

A curvature comb is a set of short line segments ("teeth") erected perpendicular to the curve that visualize the signed curvature κ(u). Tooth length is proportional to [|κ|]{#direct_api_reference.xhtml#id2 .problematic} and the direction encodes the sign (left normal for κ>0, right normal for κ<0). This is useful for inspecting fairness and continuity (C0/C1/C2) of edges and wires.

Parameters[:]{.colon}
  • count (int, optional) -- Number of uniformly spaced samples over the normalized parameter. Increase for a denser comb. Defaults to 100.

  • max_tooth_size (float | None, optional) -- Maximum tooth height in model units. If None, set to 10% maximum curve dimension. Defaults to None.

Raises[:]{.colon}
  • ValueError -- Empty curve.

  • ValueError -- If the curve is not planar on <cite>{=html}Plane.XY</cite>{=html}.

Returns[:]{.colon}

A list of short <cite>{=html}Edge</cite>{=html} objects (lines) anchored on the curve and oriented along the left normal <cite>{=html}n̂ = normalize(t) × +Z</cite>{=html}.

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}]

Notes

  • On circles, κ = 1/R so tooth length is constant.

  • On straight segments, κ = 0 so no teeth are drawn.

  • At inflection points κ→0 and the tooth flips direction.

  • At C0 corners the tangent is discontinuous; nearby teeth may jump. C1 yields continuous direction; C2 yields continuous magnitude as well.

Example

::: {.doctest .highlight-default .notranslate} ::: highlight >>> comb = my_wire.curvature_comb(count=200, max_tooth_size=2.0) >>> show(my_wire, Curve(comb)) ::: :::

[[derivative_at]{.pre}]{.sig-name .descname}[(]{.sig-paren}[position:]{.pre} [float]{.pre} [|]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float],]{.pre} [order:]{.pre} [int]{.pre} [=]{.pre} [2,]{.pre} [position_mode:]{.pre} [~build123d.build_enums.PositionMode]{.pre} [=]{.pre} [<PositionMode.PARAMETER>]{.pre}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

Derivative At

Generate a derivative along the underlying curve.

Parameters[:]{.colon}
  • position (float | VectorLike) -- distance, parameter value or point

  • order (int) -- derivative order. Defaults to 2

  • position_mode (PositionMode, optional) -- position calculation mode. Defaults to PositionMode.PARAMETER.

Raises[:]{.colon}

ValueError -- position must be a float or a point

Returns[:]{.colon}

position on the underlying curve

Return type[:]{.colon}

Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[end_point]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

The end point of this edge.

Note that circles may have identical start and end points.

[classmethod]{.pre}[ ]{.w}[[extrude]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[VectorLike]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Unused - only here because Mixin1D is a subclass of Shape

[[intersect]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[to_intersect]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Location]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Plane]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[None]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Intersect Edge with Shape or geometry object

Parameters[:]{.colon}

to_intersect (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal} | Vector{.hxr-hoverxref .hxr-tooltip .reference .internal} | Location{.hxr-hoverxref .hxr-tooltip .reference .internal} | Axis{.hxr-hoverxref .hxr-tooltip .reference .internal} | Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- objects to intersect

Returns[:]{.colon}

ShapeList of vertices and/or edges

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal} | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}] | None

[property]{.pre}[ ]{.w}[[is_closed]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[bool]{.pre}

Are the start and end points equal?

[property]{.pre}[ ]{.w}[[is_forward]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[bool]{.pre}

Does the Edge/Wire loop forward or reverse

[property]{.pre}[ ]{.w}[[is_interior]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[bool]{.pre}

Check if the edge is an interior edge.

An interior edge lies between surfaces that are part of the body (internal to the geometry) and does not form part of the exterior boundary.

Returns[:]{.colon}

True if the edge is an interior edge, False otherwise.

Return type[:]{.colon}

bool

[property]{.pre}[ ]{.w}[[length]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

Edge or Wire length

[[location_at]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[distance:]{.pre} [float]{.pre}]{.n}, [[position_mode:]{.pre} [~build123d.build_enums.PositionMode]{.pre} [=]{.pre} [<PositionMode.PARAMETER>]{.pre}]{.n}, [[frame_method:]{.pre} [~build123d.build_enums.FrameMethod]{.pre} [=]{.pre} [<FrameMethod.FRENET>]{.pre}]{.n}, [[planar:]{.pre} [bool]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[x_dir:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, float{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, [[float]{.pre}]{.n}, float{.pre} [|]{.pre} [~collections.abc.Sequence[float]]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Location]{.pre}]{.sig-return-typehint}]{.sig-return}

Locations along curve

Generate a location along the underlying curve.

Parameters[:]{.colon}
  • distance (float) -- distance or parameter value

  • position_mode (PositionMode, optional) -- position calculation mode. Defaults to PositionMode.PARAMETER.

  • frame_method (FrameMethod, optional) -- moving frame calculation method. The FRENET frame can "twist" or flip unexpectedly, especially near flat spots. The CORRECTED frame behaves more like a "camera dolly" or sweep profile would --- it's smoother and more stable. Defaults to FrameMethod.FRENET.

  • planar (bool, optional) -- planar mode. Defaults to None.

  • x_dir (VectorLike, optional) -- override the x_dir to help with plane creation along a 1D shape. Must be perpendicalar to shapes tangent. Defaults to None.

::: deprecated [Deprecated since version The: ]{.versionmodified .deprecated}<cite>{=html}planar</cite>{=html} parameter is deprecated and will be removed in a future release. Use <cite>{=html}x_dir</cite>{=html} to specify orientation instead. :::

Returns[:]{.colon}
A Location object representing local coordinate system

at the specified distance.

</p>
Return type[:]{.colon}

Location{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[locations]{.pre}]{.sig-name .descname}[(]{.sig-paren}[distances:]{.pre} [~collections.abc.Iterable[float],]{.pre} [position_mode:]{.pre} [~build123d.build_enums.PositionMode]{.pre} [=]{.pre} [<PositionMode.PARAMETER>,]{.pre} [frame_method:]{.pre} [~build123d.build_enums.FrameMethod]{.pre} [=]{.pre} [<FrameMethod.FRENET>,]{.pre} [planar:]{.pre} [bool]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None,]{.pre} [x_dir:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float,]{.pre} [float]]{.pre} [|]{.pre} [tuple[float,]{.pre} [float,]{.pre} [float]]{.pre} [|]{.pre} [~collections.abc.Sequence[float]]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}[)]{.sig-paren} →]{.sig-return-icon} [[list]{.pre}[[[]{.pre}]{.p}[Location]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Locations along curve

Generate location along the curve

Parameters[:]{.colon}
  • distances (Iterable[float]) -- distance or parameter values

  • position_mode (PositionMode, optional) -- position calculation mode. Defaults to PositionMode.PARAMETER.

  • frame_method (FrameMethod, optional) -- moving frame calculation method. Defaults to FrameMethod.FRENET.

  • planar (bool, optional) -- planar mode. Defaults to False.

  • x_dir (VectorLike, optional) -- override the x_dir to help with plane creation along a 1D shape. Must be perpendicalar to shapes tangent. Defaults to None.

::: deprecated [Deprecated since version The: ]{.versionmodified .deprecated}<cite>{=html}planar</cite>{=html} parameter is deprecated and will be removed in a future release. Use <cite>{=html}x_dir</cite>{=html} to specify orientation instead. :::

Returns[:]{.colon}
A list of Location objects representing local coordinate

systems at the specified distances.

</p>
Return type[:]{.colon}

list[Location{.hxr-hoverxref .hxr-tooltip .reference .internal}]

[[normal]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

Calculate the normal Vector. Only possible for planar curves.

Returns[:]{.colon}

normal vector

Args:

Returns:

[[offset_2d]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[distance:]{.pre} [float]{.pre}]{.n}, [[kind:]{.pre} [~build123d.build_enums.Kind]{.pre} [=]{.pre} [<Kind.ARC>]{.pre}]{.n}, [[side:]{.pre} [~build123d.build_enums.Side]{.pre} [=]{.pre} [<Side.BOTH>]{.pre}]{.n}, [[closed:]{.pre} [bool]{.pre} [=]{.pre} [True]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

2d Offset

Offsets a planar edge/wire

Parameters[:]{.colon}
  • distance (float) -- distance from edge/wire to offset

  • kind (Kind{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- offset corner transition. Defaults to Kind.ARC.

  • side (Side, optional) -- side to place offset. Defaults to Side.BOTH.

  • closed (bool, optional) -- if Side!=BOTH, close the LEFT or RIGHT offset. Defaults to True.

Raises[:]{.colon}
  • RuntimeError -- Multiple Wires generated

  • RuntimeError -- Unexpected result type

Returns[:]{.colon}

offset wire

Return type[:]{.colon}

Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[param_at]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[position]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[float]{.pre}]{.sig-return-typehint}]{.sig-return}

Map a normalized arc-length position to the underlying OCCT parameter.

The meaning of the returned parameter depends on the type of self:

  • Edge: Returns the native OCCT curve parameter corresponding to the given normalized <cite>{=html}position</cite>{=html} (0.0 → start, 1.0 → end). For closed/periodic edges, OCCT may return a value outside the edge's nominal parameter range <cite>{=html}[param_min, param_max]</cite>{=html} (e.g., by adding/subtracting multiples of the period). If you require a value folded into the edge's range, apply a modulo with the parameter span.

  • Wire: Returns a composite parameter encoding both the edge index and the position within that edge: the integer part is the zero-based count of fully traversed edges, and the fractional part is the normalized position in <cite>{=html}[0.0, 1.0]</cite>{=html} along the current edge.

Parameters[:]{.colon}

position (float) -- Normalized arc-length position along the shape, where <cite>{=html}0.0</cite>{=html} is the start and <cite>{=html}1.0</cite>{=html} is the end. Values outside <cite>{=html}[0.0, 1.0]</cite>{=html} are not validated and yield OCCT-dependent results.

Returns[:]{.colon}

OCCT parameter (for edges) or composite "edgeIndex + fraction" parameter (for wires), as described above.

Return type[:]{.colon}

float

[[perpendicular_line]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[length]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[u_value]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[Plane(o=(0.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [x=(1.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [z=(0.00,]{.pre} [0.00,]{.pre} [1.00))]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Create a line on the given plane perpendicular to and centered on beginning of self

Parameters[:]{.colon}
  • length (float) -- line length

  • u_value (float) -- position along line between 0.0 and 1.0

  • plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- plane containing perpendicular line. Defaults to Plane.XY.

Returns[:]{.colon}

perpendicular line

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[position_at]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[position:]{.pre} [float]{.pre}]{.n}, [[position_mode:]{.pre} [~build123d.build_enums.PositionMode]{.pre} [=]{.pre} [<PositionMode.PARAMETER>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

Position At

Generate a position along the underlying Wire.

Parameters[:]{.colon}
  • position (float) -- distance or parameter value

  • position_mode (PositionMode, optional) -- position calculation mode. Defaults to PositionMode.PARAMETER.

Returns[:]{.colon}

position on the underlying curve

Return type[:]{.colon}

Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[positions]{.pre}]{.sig-name .descname}[(]{.sig-paren}distances:]{.pre} [~collections.abc.Iterable[float{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[position_mode:]{.pre} [~build123d.build_enums.PositionMode]{.pre} [=]{.pre} [<PositionMode.PARAMETER>]{.pre}]{.n}, [[deflection:]{.pre} [float]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[list]{.pre}[[[]{.pre}]{.p}[Vector]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Positions along curve

Generate positions along the underlying curve

Parameters[:]{.colon}
  • distances (Iterable[float] | None, optional) -- distance or parameter values. Defaults to None.

  • position_mode (PositionMode, optional) -- position calculation mode only applies when using distances. Defaults to PositionMode.PARAMETER.

  • deflection (float | None, optional) -- maximum deflection between the curve and the polygon that results from the computed points. Defaults to None.

Returns[:]{.colon}

positions along curve

Return type[:]{.colon}

list[Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}]

[[project]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[face]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[VectorLike]{.pre}]{.n}, [[closest]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[True]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Project onto a face along the specified direction

Parameters[:]{.colon}
  • face -- Face:

  • direction -- VectorLike:

  • closest -- bool: (Default value = True)

Returns:

[[project_to_viewport]{.pre}]{.sig-name .descname}[(]{.sig-paren}viewport_origin]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, viewport_up]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[(0,]{.pre} [0,]{.pre} [1)]{.pre}]{.default_value}, look_at]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[focus]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[[,]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Project a shape onto a viewport returning visible and hidden Edges.

Parameters[:]{.colon}
  • viewport_origin (VectorLike) -- location of viewport

  • viewport_up (VectorLike, optional) -- direction of the viewport y axis. Defaults to (0, 0, 1).

  • look_at (VectorLike, optional) -- point to look at. Defaults to None (center of shape).

  • focus (float, optional) -- the focal length for perspective projection Defaults to None (orthographic projection)

Returns[:]{.colon}

visible & hidden Edges

Return type[:]{.colon}

tuple[ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}],ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}]]

[property]{.pre}[ ]{.w}[[radius]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

Calculate the radius.

Note that when applied to a Wire, the radius is simply the radius of the first edge.

Args:

Returns[:]{.colon}

radius

Raises[:]{.colon}

ValueError -- if kernel can not reduce the shape to a circular edge

[[start_point]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

The start point of this edge

Note that circles may have identical start and end points.

[[tangent_angle_at]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[location_param:]{.pre} [float]{.pre} [=]{.pre} [0.5]{.pre}]{.n}, [[position_mode:]{.pre} [~build123d.build_enums.PositionMode]{.pre} [=]{.pre} [<PositionMode.PARAMETER>]{.pre}]{.n}, [[plane:]{.pre} [~build123d.geometry.Plane]{.pre} [=]{.pre} [Plane(o=(0.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[x=(1.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[z=(0.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[1.00))]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[float]{.pre}]{.sig-return-typehint}]{.sig-return}

Compute the tangent angle at the specified location

Parameters[:]{.colon}
  • location_param (float, optional) -- distance or parameter value. Defaults to 0.5.

  • position_mode (PositionMode, optional) -- position calculation mode. Defaults to PositionMode.PARAMETER.

  • plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- plane line was constructed on. Defaults to Plane.XY.

Returns[:]{.colon}

angle in degrees between 0 and 360

Return type[:]{.colon}

float

[[tangent_at]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[position:]{.pre} [float]{.pre} [|]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, float{.pre} [|]{.pre} [tuple[float]{.pre}]{.n}, [[float]{.pre}]{.n}, float{.pre} [|]{.pre} [~collections.abc.Sequence[float]]{.pre} [=]{.pre} [0.5]{.pre}]{.n}, [[position_mode:]{.pre} [~build123d.build_enums.PositionMode]{.pre} [=]{.pre} [<PositionMode.PARAMETER>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

Find the tangent at a given position on the 1D shape where the position is either a float (or int) parameter or a point that lies on the shape.

Parameters[:]{.colon}
  • position (float | VectorLike) -- distance, parameter value, or point on shape. Defaults to 0.5.

  • position_mode (PositionMode, optional) -- position calculation mode. Defaults to PositionMode.PARAMETER.

Returns[:]{.colon}

tangent value

Return type[:]{.colon}

Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}

[property]{.pre}[ ]{.w}[[volume]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

volume - the volume of this Edge or Wire, which is always zero

<!-- -->
[class]{.pre}[ ]{.w}[[Mixin2D]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Shape]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[ColorLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

Additional methods to add to Face and Shell class

[classmethod]{.pre}[ ]{.w}[[cast]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Shape]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Returns the right type of wrapper, given a OCCT object

[classmethod]{.pre}[ ]{.w}[[extrude]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[VectorLike]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Unused - only here because Mixin1D is a subclass of Shape

[[find_intersection_points]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}]{.n}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1e-06]{.pre}]{.default_value}[)]{.sig-paren} →]{.sig-return-icon} [[list]{.pre}[[[]{.pre}]{.p}[tuple]{.pre}[[[]{.pre}]{.p}[Vector]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[[{.pre}]{.p}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Find point and normal at intersection

Return both the point(s) and normal(s) of the intersection of the axis and the shape

Parameters[:]{.colon}

axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- axis defining the intersection line

Returns[:]{.colon}

Point and normal of intersection

Return type[:]{.colon}

list[tuple[Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}, Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}]]

[[intersect]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[to_intersect]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Location]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Plane]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[None]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Intersect Face with Shape or geometry object

Parameters[:]{.colon}

to_intersect (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal} | Vector{.hxr-hoverxref .hxr-tooltip .reference .internal} | Location{.hxr-hoverxref .hxr-tooltip .reference .internal} | Axis{.hxr-hoverxref .hxr-tooltip .reference .internal} | Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- objects to intersect

Returns[:]{.colon}
ShapeList of vertices, edges, and/or

faces.

</p>
Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal} | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Face{.hxr-hoverxref .hxr-tooltip .reference .internal}] | None

[abstract]{.pre}[ ]{.w}[[location_at]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Any]{.pre}]{.n}, [[**]{.pre}]{.o}[[kwargs]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Any]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Location]{.pre}]{.sig-return-typehint}]{.sig-return}

A location from a face or shell

[[offset]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[amount]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Return a copy of self moved along the normal by amount

[[project_to_viewport]{.pre}]{.sig-name .descname}[(]{.sig-paren}viewport_origin]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, viewport_up]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[(0,]{.pre} [0,]{.pre} [1)]{.pre}]{.default_value}, look_at]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[focus]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[[,]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Project a shape onto a viewport returning visible and hidden Edges.

Parameters[:]{.colon}
  • viewport_origin (VectorLike) -- location of viewport

  • viewport_up (VectorLike, optional) -- direction of the viewport y axis. Defaults to (0, 0, 1).

  • look_at (VectorLike, optional) -- point to look at. Defaults to None (center of shape).

  • focus (float, optional) -- the focal length for perspective projection Defaults to None (orthographic projection)

Returns[:]{.colon}

visible & hidden Edges

Return type[:]{.colon}

tuple[ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}],ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}]]

<!-- -->
[class]{.pre}[ ]{.w}[[Mixin3D]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Shape]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[ColorLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

Additional methods to add to 3D Shape classes

[classmethod]{.pre}[ ]{.w}[[cast]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Shape]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Returns the right type of wrapper, given a OCCT object

[[center]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[center_of:]{.pre} [~build123d.build_enums.CenterOf]{.pre} [=]{.pre} [<CenterOf.MASS>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

Return center of object

Find center of object

Parameters[:]{.colon}

center_of (CenterOf{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- center option. Defaults to CenterOf.MASS.

Raises[:]{.colon}
  • ValueError -- Center of GEOMETRY is not supported for this object

  • NotImplementedError -- Unable to calculate center of mass of this object

Returns[:]{.colon}

center

Return type[:]{.colon}

Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[chamfer]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[length]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[length2]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}, [[edge_list]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}, [[face]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Chamfer

Chamfers the specified edges of this solid.

Parameters[:]{.colon}
  • length (float) -- length > 0, the length (length) of the chamfer

  • length2 (Optional[float]) -- length2 > 0, optional parameter for asymmetrical chamfer. Should be <cite>{=html}None</cite>{=html} if not required.

  • edge_list (Iterable[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- a list of Edge objects, which must belong to this solid

  • face (Face{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- identifies the side where length is measured. The edge(s) must be part of the face

Returns[:]{.colon}

Chamfered solid

Return type[:]{.colon}

Self

[[dprism]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[basis]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}, [[bounds]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[list]{.pre}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}, [[depth]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[taper]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0]{.pre}]{.default_value}, [[up_to_face]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[thru_all]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[True]{.pre}]{.default_value}, [[additive]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[True]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Make a prismatic feature (additive or subtractive)

Parameters[:]{.colon}
  • basis (Optional[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- face to perform the operation on

  • bounds (list[Union[Face{.hxr-hoverxref .hxr-tooltip .reference .internal},Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]]) -- list of profiles

  • depth (float, optional) -- depth of the cut or extrusion. Defaults to None.

  • taper (float, optional) -- in degrees. Defaults to 0.

  • up_to_face (Face{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- a face to extrude until. Defaults to None.

  • thru_all (bool, optional) -- cut thru_all. Defaults to True.

  • additive (bool, optional) -- Defaults to True.

Returns[:]{.colon}

prismatic feature

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[extrude]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[VectorLike]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Unused - only here because Mixin1D is a subclass of Shape

[[fillet]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[radius]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[edge_list]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Fillet

Fillets the specified edges of this solid.

Parameters[:]{.colon}
  • radius (float) -- float > 0, the radius of the fillet

  • edge_list (Iterable[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- a list of Edge objects, which must belong to this solid

Returns[:]{.colon}

Filleted solid

Return type[:]{.colon}

Any

[[find_intersection_points]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}]{.n}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1e-06]{.pre}]{.default_value}[)]{.sig-paren} →]{.sig-return-icon} [[list]{.pre}[[[]{.pre}]{.p}[tuple]{.pre}[[[]{.pre}]{.p}[Vector]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[[{.pre}]{.p}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Find point and normal at intersection

Return both the point(s) and normal(s) of the intersection of the axis and the shape

Parameters[:]{.colon}

axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- axis defining the intersection line

Returns[:]{.colon}

Point and normal of intersection

Return type[:]{.colon}

list[tuple[Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}, Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}]]

[[hollow]{.pre}]{.sig-name .descname}[(]{.sig-paren}faces:]{.pre} [~collections.abc.Iterable[~topology.two_d.Face{.pre} [|]{.pre} [None]{.pre}]{.n}, [[thickness:]{.pre} [float]{.pre}]{.n}, [[tolerance:]{.pre} [float]{.pre} [=]{.pre} [0.0001]{.pre}]{.n}, [[kind:]{.pre} [~build123d.build_enums.Kind]{.pre} [=]{.pre} [<Kind.ARC>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Hollow

Return the outer shelled solid of self.

Parameters[:]{.colon}
  • faces (Optional[Iterable[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}]]) -- faces to be removed,

  • list. (which must be part of the solid. Can be an empty)

  • thickness (float) -- shell thickness - positive shells outwards, negative shells inwards.

  • tolerance (float, optional) -- modelling tolerance of the method. Defaults to 0.0001.

  • kind (Kind{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- intersection type. Defaults to Kind.ARC.

Raises[:]{.colon}

ValueError -- Kind.TANGENT not supported

Returns[:]{.colon}

A hollow solid.

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[intersect]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[to_intersect]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Location]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Plane]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[None]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Intersect Solid with Shape or geometry object

Parameters[:]{.colon}

to_intersect (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal} | Vector{.hxr-hoverxref .hxr-tooltip .reference .internal} | Location{.hxr-hoverxref .hxr-tooltip .reference .internal} | Axis{.hxr-hoverxref .hxr-tooltip .reference .internal} | Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- objects to intersect

Returns[:]{.colon}
ShapeList of vertices, edges,

faces, and/or solids.

</p>
Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal} | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Face{.hxr-hoverxref .hxr-tooltip .reference .internal} | Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}] | None

[[is_inside]{.pre}]{.sig-name .descname}[(]{.sig-paren}point]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1e-06]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

Returns whether or not the point is inside a solid or compound object within the specified tolerance.

Parameters[:]{.colon}
  • point -- tuple or Vector representing 3D point to be tested

  • tolerance -- tolerance for inside determination, default=1.0e-6

  • point -- VectorLike:

  • tolerance -- float: (Default value = 1.0e-6)

Returns[:]{.colon}

bool indicating whether or not point is within solid

[[max_fillet]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[edge_list]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}, [[tolerance]{.pre}]{.n}[[=]{.pre}]{.o}[[0.1]{.pre}]{.default_value}, [[max_iterations]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[int]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[10]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[float]{.pre}]{.sig-return-typehint}]{.sig-return}

Find Maximum Fillet Size

Find the largest fillet radius for the given Shape and edges with a recursive binary search.

Example

max_fillet_radius = my_shape.max_fillet(shape_edges) max_fillet_radius = my_shape.max_fillet(shape_edges, tolerance=0.5, max_iterations=8)

Parameters[:]{.colon}
  • edge_list (Iterable[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- a sequence of Edge objects, which must belong to this solid

  • tolerance (float, optional) -- maximum error from actual value. Defaults to 0.1.

  • max_iterations (int, optional) -- maximum number of recursive iterations. Defaults to 10.

Raises[:]{.colon}
  • RuntimeError -- failed to find the max value

  • ValueError -- the provided Shape is invalid

Returns[:]{.colon}

maximum fillet radius

Return type[:]{.colon}

float

[[offset_3d]{.pre}]{.sig-name .descname}[(]{.sig-paren}openings:]{.pre} [~collections.abc.Iterable[~topology.two_d.Face{.pre} [|]{.pre} [None]{.pre}]{.n}, [[thickness:]{.pre} [float]{.pre}]{.n}, [[tolerance:]{.pre} [float]{.pre} [=]{.pre} [0.0001]{.pre}]{.n}, [[kind:]{.pre} [~build123d.build_enums.Kind]{.pre} [=]{.pre} [<Kind.ARC>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Shell

Make an offset solid of self.

Parameters[:]{.colon}
  • openings (Optional[Iterable[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}]]) -- faces to be removed, which must be part of the solid. Can be an empty list.

  • thickness (float) -- offset amount - positive offset outwards, negative inwards

  • tolerance (float, optional) -- modelling tolerance of the method. Defaults to 0.0001.

  • kind (Kind{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- intersection type. Defaults to Kind.ARC.

Raises[:]{.colon}

ValueError -- Kind.TANGENT not supported

Returns[:]{.colon}

A shelled solid.

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[project_to_viewport]{.pre}]{.sig-name .descname}[(]{.sig-paren}viewport_origin]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, viewport_up]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[(0,]{.pre} [0,]{.pre} [1)]{.pre}]{.default_value}, look_at]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[focus]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[[,]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Project a shape onto a viewport returning visible and hidden Edges.

Parameters[:]{.colon}
  • viewport_origin (VectorLike) -- location of viewport

  • viewport_up (VectorLike, optional) -- direction of the viewport y axis. Defaults to (0, 0, 1).

  • look_at (VectorLike, optional) -- point to look at. Defaults to None (center of shape).

  • focus (float, optional) -- the focal length for perspective projection Defaults to None (orthographic projection)

Returns[:]{.colon}

visible & hidden Edges

Return type[:]{.colon}

tuple[ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}],ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}]]

<!-- -->
[class]{.pre}[ ]{.w}[[Shape]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Shape]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[ColorLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

Base class for all CAD objects such as Edge, Face, Solid, etc.

Parameters[:]{.colon}
  • obj (TopoDS_Shape, optional) -- OCCT object. Defaults to None.

  • label (str, optional) -- Defaults to ''.

  • color (ColorLike, optional) -- Defaults to None.

  • parent (Compound{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- assembly parent. Defaults to None.

Variables[:]{.colon}
  • wrapped (TopoDS_Shape) -- the OCP object

  • label (str) -- user assigned label

  • color (Color{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- object color

  • (dict[str (joints) -- Joint]): dictionary of joints bound to this object (Solid only)

  • children (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- list of assembly children of this object (Compound only)

  • topo_parent (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- assembly parent of this object

[[__add__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[None]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Iterable]{.pre}[[[]{.pre}]{.p}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[Self]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

fuse shape to self operator +

[[__and__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Iterable]{.pre}[[[]{.pre}]{.p}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[None]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Self]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[Self]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

intersect shape with self operator &

[[__copy__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Return shallow copy or reference of self

Create an copy of this Shape that shares the underlying TopoDS_TShape.

Used when there is a need for many objects with the same CAD structure but at different Locations, etc. - for examples fasteners in a larger assembly. By sharing the TopoDS_TShape, the memory size of such assemblies can be greatly reduced.

Changes to the CAD structure of the base object will be reflected in all instances.

[[__deepcopy__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[memo]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Return deepcopy of self

[[__eq__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

Check if two shapes are the same.

This method checks if the current shape is the same as the other shape. Two shapes are considered the same if they share the same TShape with the same Locations. Orientations may differ.

Parameters[:]{.colon}

other (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- The shape to compare with.

Returns[:]{.colon}

True if the shapes are the same, False otherwise.

Return type[:]{.colon}

bool

[[__hash__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[int]{.pre}]{.sig-return-typehint}]{.sig-return}

Return hash code

[[__rmul__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[)]{.sig-paren}

right multiply for positioning operator *

[[__sub__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[None]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Iterable]{.pre}[[[]{.pre}]{.p}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[Self]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

cut shape from self operator -

[property]{.pre}[ ]{.w}[[area]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

area -the surface area of all faces in this Shape

[[bounding_box]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[optimal]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[True]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[BoundBox]{.pre}]{.sig-return-typehint}]{.sig-return}

Create a bounding box for this Shape.

Parameters[:]{.colon}

tolerance (float, optional) -- Defaults to None.

Returns[:]{.colon}

A box sized to contain this Shape

Return type[:]{.colon}

BoundBox{.hxr-hoverxref .hxr-tooltip .reference .internal}

[abstract]{.pre}[ ]{.w}[classmethod]{.pre}[ ]{.w}[[cast]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Shape]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Returns the right type of wrapper, given a OCCT object

[[clean]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Remove internal edges

Returns[:]{.colon}

Original object with extraneous internal edges removed

Return type[:]{.colon}

Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[closest_points]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[Vector]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Points on two shapes where the distance between them is minimal

[property]{.pre}[ ]{.w}[[color]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[None]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Color]{.pre}

Get the shape's color. If it's None, get the color of the nearest ancestor, assign it to this Shape and return this value.

[static]{.pre}[ ]{.w}[[combined_center]{.pre}]{.sig-name .descname}[(]{.sig-paren}[objects:]{.pre} [~collections.abc.Iterable[~topology.shape_core.Shape],]{.pre} [center_of:]{.pre} [~build123d.build_enums.CenterOf]{.pre} [=]{.pre} [<CenterOf.MASS>]{.pre}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

combined center

Calculates the center of a multiple objects.

Parameters[:]{.colon}
  • objects (Iterable[Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- list of objects

  • center_of (CenterOf{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- centering option. Defaults to CenterOf.MASS.

Raises[:]{.colon}

ValueError -- CenterOf.GEOMETRY not implemented

Returns[:]{.colon}

center of multiple objects

Return type[:]{.colon}

Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[compound]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.sig-return-typehint}]{.sig-return}

Return the Compound

[[compounds]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

compounds - all the compounds in this Shape

[static]{.pre}[ ]{.w}[[compute_mass]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[float]{.pre}]{.sig-return-typehint}]{.sig-return}

Calculates the 'mass' of an object.

Parameters[:]{.colon}
  • obj -- Compute the mass of this object

  • obj -- Shape:

Returns:

[[copy_attributes_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[target]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, exceptions]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[str]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

Copy common object attributes to target

Note that preset attributes of target will not be overridden.

Parameters[:]{.colon}
  • target (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- object to gain attributes

  • exceptions (Iterable[str], optional) -- attributes not to copy

Raises[:]{.colon}

ValueError -- invalid attribute

[[cut]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[to_cut]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[Self]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Remove the positional arguments from this Shape.

Parameters[:]{.colon}

*to_cut -- Shape:

Returns[:]{.colon}
Resulting object may be of a different class than self

or a ShapeList if multiple non-Compound object created

</p>
Return type[:]{.colon}

Self | ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Self]

[[distance]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[float]{.pre}]{.sig-return-typehint}]{.sig-return}

Minimal distance between two shapes

Parameters[:]{.colon}

other -- Shape:

Returns:

[[distance_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[float]{.pre}]{.sig-return-typehint}]{.sig-return}

Minimal distance between two shapes

[[distance_to_with_closest_points]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Minimal distance between two shapes and the points on each shape

[[distances]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[others]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[Iterator]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Minimal distances to between self and other shapes

Parameters[:]{.colon}

*others -- Shape:

Returns:

[[downcast_LUT]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[{<TopAbs_ShapeEnum.TopAbs_COMPOUND:]{.pre} [0>:]{.pre} [<built-in]{.pre} [method]{.pre} [Compound_s]{.pre} [of]{.pre} [PyCapsule]{.pre} [object>,]{.pre} [<TopAbs_ShapeEnum.TopAbs_COMPSOLID:]{.pre} [1>:]{.pre} [<built-in]{.pre} [method]{.pre} [CompSolid_s]{.pre} [of]{.pre} [PyCapsule]{.pre} [object>,]{.pre} [<TopAbs_ShapeEnum.TopAbs_EDGE:]{.pre} [6>:]{.pre} [<built-in]{.pre} [method]{.pre} [Edge_s]{.pre} [of]{.pre} [PyCapsule]{.pre} [object>,]{.pre} [<TopAbs_ShapeEnum.TopAbs_FACE:]{.pre} [4>:]{.pre} [<built-in]{.pre} [method]{.pre} [Face_s]{.pre} [of]{.pre} [PyCapsule]{.pre} [object>,]{.pre} [<TopAbs_ShapeEnum.TopAbs_SHELL:]{.pre} [3>:]{.pre} [<built-in]{.pre} [method]{.pre} [Shell_s]{.pre} [of]{.pre} [PyCapsule]{.pre} [object>,]{.pre} [<TopAbs_ShapeEnum.TopAbs_SOLID:]{.pre} [2>:]{.pre} [<built-in]{.pre} [method]{.pre} [Solid_s]{.pre} [of]{.pre} [PyCapsule]{.pre} [object>,]{.pre} [<TopAbs_ShapeEnum.TopAbs_VERTEX:]{.pre} [7>:]{.pre} [<built-in]{.pre} [method]{.pre} [Vertex_s]{.pre} [of]{.pre} [PyCapsule]{.pre} [object>,]{.pre} [<TopAbs_ShapeEnum.TopAbs_WIRE:]{.pre} [5>:]{.pre} [<built-in]{.pre} [method]{.pre} [Wire_s]{.pre} [of]{.pre} [PyCapsule]{.pre} [object>}]{.pre}
[[edge]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.sig-return-typehint}]{.sig-return}

Return the Edge

[[edges]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

edges - all the edges in this Shape - subclasses may override

[[entities]{.pre}]{.sig-name .descname}[(]{.sig-paren}topo_type]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Literal]{.pre}[[[]{.pre}]{.p}[['Vertex']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Edge']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Wire']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Face']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Shell']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Solid']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Compound']{.pre}]{.s}[[{.pre}]{.p}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[list]{.pre}[[[]{.pre}]{.p}[TopoDS_Shape]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Return all of the TopoDS sub entities of the given type

[abstract]{.pre}[ ]{.w}[classmethod]{.pre}[ ]{.w}[[extrude]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[VectorLike]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Extrude a Shape in the provided direction. * Vertices generate Edges * Edges generate Faces * Wires generate Shells * Faces generate Solids * Shells generate Compounds

Parameters[:]{.colon}

direction (VectorLike) -- direction and magnitude of extrusion

Raises[:]{.colon}
  • ValueError -- Unsupported class

  • RuntimeError -- Generated invalid result

Returns[:]{.colon}

extruded shape

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Face{.hxr-hoverxref .hxr-tooltip .reference .internal} | Shell{.hxr-hoverxref .hxr-tooltip .reference .internal} | Solid{.hxr-hoverxref .hxr-tooltip .reference .internal} | Compound{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[face]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.sig-return-typehint}]{.sig-return}

Return the Face

[[faces]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

faces - all the faces in this Shape

[[faces_intersected_by_axis]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[axis]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[tol]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.0001]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Line Intersection

Computes the intersections between the provided axis and the faces of this Shape

Parameters[:]{.colon}
  • axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- Axis on which the intersection line rests

  • tol (float, optional) -- Intersection tolerance. Defaults to 1e-4.

Returns[:]{.colon}

A list of intersected faces sorted by distance from axis.position

Return type[:]{.colon}

list[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}]

[[fix]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

fix - try to fix shape if not valid

[[fuse]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[to_fuse]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[glue]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}, [[tol]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[Self]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Fuse a sequence of shapes into a single shape.

Parameters[:]{.colon}
  • to_fuse (sequence Shape) -- shapes to fuse

  • glue (bool, optional) -- performance improvement for some shapes. Defaults to False.

  • tol (float, optional) -- tolerance. Defaults to None.

Returns[:]{.colon}
Resulting object may be of a different class than self

or a ShapeList if multiple non-Compound object created

</p>
Return type[:]{.colon}

Self | ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Self]

[[geom_LUT_EDGE]{.pre}]{.sig-name .descname}:]{.pre}]{.p}[ ]{.w}[dict]{.pre}[[[]{.pre}]{.p}[GeomAbs_CurveType]{.pre}[[,]{.pre}]{.p}[ ]{.w}[GeomType]{.pre}[[{.pre}]{.p}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[{<GeomAbs_CurveType.GeomAbs_BSplineCurve:]{.pre} [6>:]{.pre} [<GeomType.BSPLINE>,]{.pre} [<GeomAbs_CurveType.GeomAbs_BezierCurve:]{.pre} [5>:]{.pre} [<GeomType.BEZIER>,]{.pre} [<GeomAbs_CurveType.GeomAbs_Circle:]{.pre} [1>:]{.pre} [<GeomType.CIRCLE>,]{.pre} [<GeomAbs_CurveType.GeomAbs_Ellipse:]{.pre} [2>:]{.pre} [<GeomType.ELLIPSE>,]{.pre} [<GeomAbs_CurveType.GeomAbs_Hyperbola:]{.pre} [3>:]{.pre} [<GeomType.HYPERBOLA>,]{.pre} [<GeomAbs_CurveType.GeomAbs_Line:]{.pre} [0>:]{.pre} [<GeomType.LINE>,]{.pre} [<GeomAbs_CurveType.GeomAbs_OffsetCurve:]{.pre} [7>:]{.pre} [<GeomType.OFFSET>,]{.pre} [<GeomAbs_CurveType.GeomAbs_OtherCurve:]{.pre} [8>:]{.pre} [<GeomType.OTHER>,]{.pre} [<GeomAbs_CurveType.GeomAbs_Parabola:]{.pre} [4>:]{.pre} [<GeomType.PARABOLA>}]{.pre}
[[geom_LUT_FACE]{.pre}]{.sig-name .descname}:]{.pre}]{.p}[ ]{.w}[dict]{.pre}[[[]{.pre}]{.p}[GeomAbs_SurfaceType]{.pre}[[,]{.pre}]{.p}[ ]{.w}[GeomType]{.pre}[[{.pre}]{.p}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[{<GeomAbs_SurfaceType.GeomAbs_BSplineSurface:]{.pre} [6>:]{.pre} [<GeomType.BSPLINE>,]{.pre} [<GeomAbs_SurfaceType.GeomAbs_BezierSurface:]{.pre} [5>:]{.pre} [<GeomType.BEZIER>,]{.pre} [<GeomAbs_SurfaceType.GeomAbs_Cone:]{.pre} [2>:]{.pre} [<GeomType.CONE>,]{.pre} [<GeomAbs_SurfaceType.GeomAbs_Cylinder:]{.pre} [1>:]{.pre} [<GeomType.CYLINDER>,]{.pre} [<GeomAbs_SurfaceType.GeomAbs_OffsetSurface:]{.pre} [9>:]{.pre} [<GeomType.OFFSET>,]{.pre} [<GeomAbs_SurfaceType.GeomAbs_OtherSurface:]{.pre} [10>:]{.pre} [<GeomType.OTHER>,]{.pre} [<GeomAbs_SurfaceType.GeomAbs_Plane:]{.pre} [0>:]{.pre} [<GeomType.PLANE>,]{.pre} [<GeomAbs_SurfaceType.GeomAbs_Sphere:]{.pre} [3>:]{.pre} [<GeomType.SPHERE>,]{.pre} [<GeomAbs_SurfaceType.GeomAbs_SurfaceOfExtrusion:]{.pre} [8>:]{.pre} [<GeomType.EXTRUSION>,]{.pre} [<GeomAbs_SurfaceType.GeomAbs_SurfaceOfRevolution:]{.pre} [7>:]{.pre} [<GeomType.REVOLUTION>,]{.pre} [<GeomAbs_SurfaceType.GeomAbs_Torus:]{.pre} [4>:]{.pre} [<GeomType.TORUS>}]{.pre}
[property]{.pre}[ ]{.w}[[geom_type]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[GeomType]{.pre}

Gets the underlying geometry type.

Returns[:]{.colon}

The geometry type of the shape

Return type[:]{.colon}

GeomType{.hxr-hoverxref .hxr-tooltip .reference .internal}

[static]{.pre}[ ]{.w}[[get_shape_list]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[shape]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, entity_type]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Literal]{.pre}[[[]{.pre}]{.p}[['Vertex']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Edge']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Wire']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Face']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Shell']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Solid']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Compound']{.pre}]{.s}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Helper to extract entities of a specific type from a shape.

[static]{.pre}[ ]{.w}[[get_single_shape]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[shape]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, entity_type]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Literal]{.pre}[[[]{.pre}]{.p}[['Vertex']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Edge']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Wire']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Face']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Shell']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Solid']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Compound']{.pre}]{.s}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.sig-return-typehint}]{.sig-return}

Helper to extract a single entity of a specific type from a shape, with a warning if count != 1.

[[get_top_level_shapes]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Retrieve the first level of child shapes from the shape.

This method collects all the non-compound shapes directly contained in the current shape. If the wrapped shape is a <cite>{=html}TopoDS_Compound</cite>{=html}, it traverses its immediate children and collects all shapes that are not further nested compounds. Nested compounds are traversed to gather their non-compound elements without returning the nested compound itself.

Returns[:]{.colon}

A list of all first-level non-compound child shapes.

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}]

Example

If the current shape is a compound containing both simple shapes (e.g., edges, vertices) and other compounds, the method returns a list of only the simple shapes directly contained at the top level.

[property]{.pre}[ ]{.w}[[global_location]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Location]{.pre}

The location of this Shape relative to the global coordinate system.

This property computes the composite transformation by traversing the hierarchy from the root of the assembly to this node, combining the location of each ancestor. It reflects the absolute position and orientation of the shape in world space, even when the shape is deeply nested within an assembly.

::: {.admonition .note} Note

This is only meaningful when the Shape is part of an assembly tree where parent-child relationships define relative placements. :::

[[intersect]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[to_intersect]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Location]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Plane]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[None]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[Self]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Intersection of the arguments and this shape

Parameters[:]{.colon}

to_intersect (sequence of Union[Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}, Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}, Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- Shape(s) to intersect with

Returns[:]{.colon}
Resulting ShapeList may contain different class

than self

</p>
Return type[:]{.colon}

None | ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Self]

[[inverse_shape_LUT]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[{'CompSolid':]{.pre} [<TopAbs_ShapeEnum.TopAbs_COMPSOLID:]{.pre} [1>,]{.pre} ['Compound':]{.pre} [<TopAbs_ShapeEnum.TopAbs_COMPOUND:]{.pre} [0>,]{.pre} ['Edge':]{.pre} [<TopAbs_ShapeEnum.TopAbs_EDGE:]{.pre} [6>,]{.pre} ['Face':]{.pre} [<TopAbs_ShapeEnum.TopAbs_FACE:]{.pre} [4>,]{.pre} ['Shell':]{.pre} [<TopAbs_ShapeEnum.TopAbs_SHELL:]{.pre} [3>,]{.pre} ['Solid':]{.pre} [<TopAbs_ShapeEnum.TopAbs_SOLID:]{.pre} [2>,]{.pre} ['Vertex':]{.pre} [<TopAbs_ShapeEnum.TopAbs_VERTEX:]{.pre} [7>,]{.pre} ['Wire':]{.pre} [<TopAbs_ShapeEnum.TopAbs_WIRE:]{.pre} [5>}]{.pre}
[[is_equal]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

Returns True if two shapes are equal, i.e. if they share the same TShape with the same Locations and Orientations. Also see is_same(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}.

Parameters[:]{.colon}

other -- Shape:

Returns:

[property]{.pre}[ ]{.w}[[is_manifold]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[bool]{.pre}

Check if each edge in the given Shape has exactly two faces associated with it (skipping degenerate edges). If so, the shape is manifold.

Returns[:]{.colon}

is the shape manifold or water tight

Return type[:]{.colon}

bool

[property]{.pre}[ ]{.w}[[is_null]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[bool]{.pre}

Returns true if this shape is null. In other words, it references no underlying shape with the potential to be given a location and an orientation.

[property]{.pre}[ ]{.w}[[is_planar_face]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[bool]{.pre}

Is the shape a planar face even though its geom_type may not be PLANE

[[is_same]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[bool]{.pre}]{.sig-return-typehint}]{.sig-return}

Returns True if other and this shape are same, i.e. if they share the same TShape with the same Locations. Orientations may differ. Also see is_equal(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}

Parameters[:]{.colon}

other -- Shape:

Returns:

[property]{.pre}[ ]{.w}[[is_valid]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[bool]{.pre}

Returns True if no defect is detected on the shape S or any of its subshapes. See the OCCT docs on BRepCheck_Analyzer::IsValid for a full description of what is checked.

[[locate]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[loc]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Location]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Apply a location in absolute sense to self

Parameters[:]{.colon}

loc -- Location:

Returns:

[[located]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[loc]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Location]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Apply a location in absolute sense to a copy of self

Parameters[:]{.colon}

loc (Location{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- new absolute location

Returns[:]{.colon}

copy of Shape at location

Return type[:]{.colon}

Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}

[property]{.pre}[ ]{.w}[[location]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Location]{.pre}

Get this Shape's Location

[property]{.pre}[ ]{.w}[[matrix_of_inertia]{.pre}]{.sig-name .descname}:]{.pre}]{.p}[ ]{.w}[list]{.pre}[[[]{.pre}]{.p}[list]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}{.pre}]{.p}

Compute the inertia matrix (moment of inertia tensor) of the shape.

The inertia matrix represents how the mass of the shape is distributed with respect to its reference frame. It is a 3×3 symmetric tensor that describes the resistance of the shape to rotational motion around different axes.

Returns[:]{.colon}

A 3×3 nested list representing the inertia matrix. The elements of the matrix are given as:

::: line-block ::: line Ixx Ixy Ixz | :::

::: line Ixy Iyy Iyz | :::

::: line Ixz Iyz Izz | ::: :::

where: - Ixx, Iyy, Izz are the moments of inertia about the X, Y, and Z axes. - Ixy, Ixz, Iyz are the products of inertia.

</p>
Return type[:]{.colon}

list[list[float]]

Example

::: {.doctest .highlight-default .notranslate} ::: highlight >>> obj = MyShape() >>> obj.matrix_of_inertia [[1000.0, 50.0, 0.0], [50.0, 1200.0, 0.0], [0.0, 0.0, 300.0]] ::: :::

Notes

  • The inertia matrix is computed relative to the shape's center of mass.

  • It is commonly used in structural analysis, mechanical simulations, and physics-based motion calculations.

[[mesh]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[angular_tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.1]{.pre}]{.default_value}[)]{.sig-paren}

Generate triangulation if none exists.

Parameters[:]{.colon}
  • tolerance -- float:

  • angular_tolerance -- float: (Default value = 0.1)

Returns:

[[mirror]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[mirror_plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Applies a mirror transform to this Shape. Does not duplicate objects about the plane.

Parameters[:]{.colon}

mirror_plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- The plane to mirror about. Defaults to Plane.XY

Returns[:]{.colon}

The mirrored shape

[[move]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[loc]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Location]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Apply a location in relative sense (i.e. update current location) to self

Parameters[:]{.colon}

loc -- Location:

Returns:

[[moved]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[loc]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Location]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Apply a location in relative sense (i.e. update current location) to a copy of self

Parameters[:]{.colon}

loc (Location{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- new location relative to current location

Returns[:]{.colon}

copy of Shape moved to relative location

Return type[:]{.colon}

Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}

[property]{.pre}[ ]{.w}[[orientation]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Vector]{.pre}

Get the orientation component of this Shape's Location

[[oriented_bounding_box]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[OrientedBoundBox]{.pre}]{.sig-return-typehint}]{.sig-return}

Create an oriented bounding box for this Shape.

Returns[:]{.colon}

A box oriented and sized to contain this Shape

Return type[:]{.colon}

OrientedBoundBox

[property]{.pre}[ ]{.w}[[position]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Vector]{.pre}

Get the position component of this Shape's Location

[property]{.pre}[ ]{.w}[[principal_properties]{.pre}]{.sig-name .descname}:]{.pre}]{.p}[ ]{.w}[list]{.pre}[[[]{.pre}]{.p}[tuple]{.pre}[[[]{.pre}]{.p}[Vector]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}{.pre}]{.p}

Compute the principal moments of inertia and their corresponding axes.

Returns[:]{.colon}

A list of tuples, where each tuple contains: - A <cite>{=html}Vector</cite>{=html} representing the axis of inertia. - A <cite>{=html}float</cite>{=html} representing the moment of inertia for that axis.

Return type[:]{.colon}

list[tuple[Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}, float]]

Example

::: {.doctest .highlight-default .notranslate} ::: highlight >>> obj = MyShape() >>> obj.principal_properties [(Vector(1, 0, 0), 1200.0), (Vector(0, 1, 0), 1000.0), (Vector(0, 0, 1), 300.0)] ::: :::

[[project_faces]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[faces]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[list]{.pre}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[path]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[start]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Projected Faces following the given path on Shape

Project by positioning each face of to the shape along the path and projecting onto the surface.

Note that projection may result in distortion depending on the shape at a position along the path.

Parameters[:]{.colon}
  • faces (Union[list[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}], Compound{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- faces to project

  • path -- Path on the Shape to follow

  • start -- Relative location on path to start the faces. Defaults to 0.

Returns[:]{.colon}

The projected faces

[[radius_of_gyration]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[axis]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[float]{.pre}]{.sig-return-typehint}]{.sig-return}

Compute the radius of gyration of the shape about a given axis.

The radius of gyration represents the distance from the axis at which the entire mass of the shape could be concentrated without changing its moment of inertia. It provides insight into how mass is distributed relative to the axis and is useful in structural analysis, rotational dynamics, and mechanical simulations.

Parameters[:]{.colon}

axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- The axis about which the radius of gyration is computed. The axis should be defined in the same coordinate system as the shape.

Returns[:]{.colon}

The radius of gyration in the same units as the shape's dimensions.

Return type[:]{.colon}

float

Example

::: {.doctest .highlight-default .notranslate} ::: highlight >>> obj = MyShape() >>> axis = Axis((0, 0, 0), (0, 0, 1)) >>> obj.radius_of_gyration(axis) 5.47 ::: :::

Notes

  • The radius of gyration is computed based on the shape's mass properties.

  • It is useful for evaluating structural stability and rotational behavior.

[[relocate]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[loc]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Location]{.pre}]{.n}[)]{.sig-paren}

Change the location of self while keeping it geometrically similar

Parameters[:]{.colon}

loc (Location{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- new location to set for self

[[rotate]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[axis]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}]{.n}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

rotate a copy

Rotates a shape around an axis.

Parameters[:]{.colon}
  • axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- rotation Axis

  • angle (float) -- angle to rotate, in degrees

Returns[:]{.colon}

a copy of the shape, rotated

[[scale]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[factor]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Scales this shape through a transformation.

Parameters[:]{.colon}

factor -- float:

Returns:

[[shape_LUT]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[{<TopAbs_ShapeEnum.TopAbs_COMPOUND:]{.pre} [0>:]{.pre} ['Compound',]{.pre} [<TopAbs_ShapeEnum.TopAbs_COMPSOLID:]{.pre} [1>:]{.pre} ['CompSolid',]{.pre} [<TopAbs_ShapeEnum.TopAbs_EDGE:]{.pre} [6>:]{.pre} ['Edge',]{.pre} [<TopAbs_ShapeEnum.TopAbs_FACE:]{.pre} [4>:]{.pre} ['Face',]{.pre} [<TopAbs_ShapeEnum.TopAbs_SHELL:]{.pre} [3>:]{.pre} ['Shell',]{.pre} [<TopAbs_ShapeEnum.TopAbs_SOLID:]{.pre} [2>:]{.pre} ['Solid',]{.pre} [<TopAbs_ShapeEnum.TopAbs_VERTEX:]{.pre} [7>:]{.pre} ['Vertex',]{.pre} [<TopAbs_ShapeEnum.TopAbs_WIRE:]{.pre} [5>:]{.pre} ['Wire'}]{.pre}
[[shape_properties_LUT]{.pre}]{.sig-name .descname}:]{.pre}]{.p}[ ]{.w}[dict]{.pre}[[[]{.pre}]{.p}[TopAbs_ShapeEnum]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Callable]{.pre}[[[]{.pre}]{.p}[[[]{.pre}]{.p}[TopoDS_Shape]{.pre}[[,]{.pre}]{.p}[ ]{.w}[GProp_GProps]{.pre}[[{.pre}]{.p},]{.pre}]{.p}[ ]{.w}[None]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[None]{.pre}[[{.pre}]{.p}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[{<TopAbs_ShapeEnum.TopAbs_COMPOUND:]{.pre} [0>:]{.pre} [<built-in]{.pre} [method]{.pre} [VolumeProperties_s]{.pre} [of]{.pre} [PyCapsule]{.pre} [object>,]{.pre} [<TopAbs_ShapeEnum.TopAbs_COMPSOLID:]{.pre} [1>:]{.pre} [<built-in]{.pre} [method]{.pre} [VolumeProperties_s]{.pre} [of]{.pre} [PyCapsule]{.pre} [object>,]{.pre} [<TopAbs_ShapeEnum.TopAbs_EDGE:]{.pre} [6>:]{.pre} [<built-in]{.pre} [method]{.pre} [LinearProperties_s]{.pre} [of]{.pre} [PyCapsule]{.pre} [object>,]{.pre} [<TopAbs_ShapeEnum.TopAbs_FACE:]{.pre} [4>:]{.pre} [<built-in]{.pre} [method]{.pre} [SurfaceProperties_s]{.pre} [of]{.pre} [PyCapsule]{.pre} [object>,]{.pre} [<TopAbs_ShapeEnum.TopAbs_SHELL:]{.pre} [3>:]{.pre} [<built-in]{.pre} [method]{.pre} [SurfaceProperties_s]{.pre} [of]{.pre} [PyCapsule]{.pre} [object>,]{.pre} [<TopAbs_ShapeEnum.TopAbs_SOLID:]{.pre} [2>:]{.pre} [<built-in]{.pre} [method]{.pre} [VolumeProperties_s]{.pre} [of]{.pre} [PyCapsule]{.pre} [object>,]{.pre} [<TopAbs_ShapeEnum.TopAbs_VERTEX:]{.pre} [7>:]{.pre} [None,]{.pre} [<TopAbs_ShapeEnum.TopAbs_WIRE:]{.pre} [5>:]{.pre} [<built-in]{.pre} [method]{.pre} [LinearProperties_s]{.pre} [of]{.pre} [PyCapsule]{.pre} [object>}]{.pre}
[property]{.pre}[ ]{.w}[[shape_type]{.pre}]{.sig-name .descname}:]{.pre}]{.p}[ ]{.w}[Literal]{.pre}[[[]{.pre}]{.p}[['Vertex']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Edge']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Wire']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Face']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Shell']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Solid']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Compound']{.pre}]{.s}[[{.pre}]{.p}

Return the shape type string for this class

[[shell]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.sig-return-typehint}]{.sig-return}

Return the Shell

[[shells]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

shells - all the shells in this Shape

[[show_topology]{.pre}]{.sig-name .descname}[(]{.sig-paren}limit_class]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Literal]{.pre}[[[]{.pre}]{.p}[['Compound']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Edge']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Face']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Shell']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Solid']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Vertex']{.pre}]{.s}[[,]{.pre}]{.p}[ ]{.w}[['Wire']{.pre}]{.s}[[{.pre}]{.p}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['Vertex']{.pre}]{.default_value}, [[show_center]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[str]{.pre}]{.sig-return-typehint}]{.sig-return}

Display internal topology

Display the internal structure of a Compound 'assembly' or Shape. Example:

::: {.highlight-default .notranslate} ::: highlight >>> c1.show_topology()

c1 is the root         Compound at 0x7f4a4cafafa0, Location(...))
├──                    Solid    at 0x7f4a4cafafd0, Location(...))
├── c2 is 1st compound Compound at 0x7f4a4cafaee0, Location(...))
│   ├──                Solid    at 0x7f4a4cafad00, Location(...))
│   └──                Solid    at 0x7f4a11a52790, Location(...))
└── c3 is 2nd          Compound at 0x7f4a4cafad60, Location(...))
    ├──                Solid    at 0x7f4a11a52700, Location(...))
    └──                Solid    at 0x7f4a11a58550, Location(...))

::: :::

Parameters[:]{.colon}
  • limit_class -- type of displayed leaf node. Defaults to 'Vertex'.

  • show_center (bool, optional) -- If None, shows the Location of Compound 'assemblies' and the bounding box center of Shapes. True or False forces the display. Defaults to None.

Returns[:]{.colon}

tree representation of internal structure

Return type[:]{.colon}

str

[[solid]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.sig-return-typehint}]{.sig-return}

Return the Solid

[[solids]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

solids - all the solids in this Shape

[[split]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tool]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TrimmingTool]{.pre}]{.n}, keep]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Literal]{.pre}[[[]{.pre}]{.p}[Keep.TOP]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Keep.BOTTOM]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[Self]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.sig-return-typehint}]{.sig-return}\
[[split]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tool]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TrimmingTool]{.pre}]{.n}, keep]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Literal]{.pre}[[[]{.pre}]{.p}[Keep.ALL]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[list]{.pre}[[[]{.pre}]{.p}[Self]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}\
[[split]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tool]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TrimmingTool]{.pre}]{.n}, keep]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Literal]{.pre}[[[]{.pre}]{.p}[Keep.BOTH]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[Self]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[None]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Self]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[None]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}\
[[split]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tool]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TrimmingTool]{.pre}]{.n}, keep]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Literal]{.pre}[[[]{.pre}]{.p}[Keep.INSIDE]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Keep.OUTSIDE]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[None]{.pre}]{.sig-return-typehint}]{.sig-return}\
[[split]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tool]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TrimmingTool]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[Self]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.sig-return-typehint}]{.sig-return}

split

Split this shape by the provided plane or face.

Parameters[:]{.colon}
  • surface (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal} | Face{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- surface to segment shape

  • keep (Keep{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- which object(s) to save. Defaults to Keep.TOP.

Returns[:]{.colon}

result of split

Return type[:]{.colon}

Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}

Returns[:]{.colon}

Self | list[Self] | None, Tuple[Self | list[Self] | None]: The result of the split operation.

  • Keep.TOP: Returns the top as a <cite>{=html}Self</cite>{=html} or <cite>{=html}list[Self]</cite>{=html}, or <cite>{=html}None</cite>{=html} if no top is found.

  • Keep.BOTTOM: Returns the bottom as a <cite>{=html}Self</cite>{=html} or <cite>{=html}list[Self]</cite>{=html}, or <cite>{=html}None</cite>{=html} if no bottom is found.

  • Keep.BOTH: Returns a tuple <cite>{=html}(inside, outside)</cite>{=html} where each element is either a <cite>{=html}Self</cite>{=html} or <cite>{=html}list[Self]</cite>{=html}, or <cite>{=html}None</cite>{=html} if no corresponding part is found.

</p>
[[split_by_perimeter]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[perimeter]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, keep]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Literal]{.pre}[[[]{.pre}]{.p}[Keep.INSIDE]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Keep.OUTSIDE]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.sig-return-typehint}]{.sig-return}\
[[split_by_perimeter]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[perimeter]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, keep]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Literal]{.pre}[[[]{.pre}]{.p}[Keep.BOTH]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[None]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}\
[[split_by_perimeter]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[perimeter]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.sig-return-typehint}]{.sig-return}

split_by_perimeter

Divide the faces of this object into those within the perimeter and those outside the perimeter.

Note: this method may fail if the perimeter intersects shape edges.

Parameters[:]{.colon}
  • perimeter (Union[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal},Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- closed perimeter

  • keep (Keep{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- which object(s) to return. Defaults to Keep.INSIDE.

Raises[:]{.colon}
  • ValueError -- perimeter must be closed

  • ValueError -- keep must be one of Keep.INSIDE|OUTSIDE|BOTH

Returns[:]{.colon}

Union[Face | Shell | ShapeList[Face] | None, Tuple[Face | Shell | ShapeList[Face] | None]: The result of the split operation.

  • Keep.INSIDE: Returns the inside part as a <cite>{=html}Shell</cite>{=html} or <cite>{=html}Face</cite>{=html}, or <cite>{=html}None</cite>{=html} if no inside part is found.

  • Keep.OUTSIDE: Returns the outside part as a <cite>{=html}Shell</cite>{=html} or <cite>{=html}Face</cite>{=html}, or <cite>{=html}None</cite>{=html} if no outside part is found.

  • Keep.BOTH: Returns a tuple <cite>{=html}(inside, outside)</cite>{=html} where each element is either a <cite>{=html}Shell</cite>{=html}, <cite>{=html}Face</cite>{=html}, or <cite>{=html}None</cite>{=html} if no corresponding part is found.

</p>
[property]{.pre}[ ]{.w}[[static_moments]{.pre}]{.sig-name .descname}:]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}

Compute the static moments (first moments of mass) of the shape.

The static moments represent the weighted sum of the coordinates with respect to the mass distribution, providing insight into the center of mass and mass distribution of the shape.

Returns[:]{.colon}

The static moments (Mx, My, Mz), where: - Mx is the first moment of mass about the YZ plane. - My is the first moment of mass about the XZ plane. - Mz is the first moment of mass about the XY plane.

Return type[:]{.colon}

tuple[float, float, float]

Example

::: {.doctest .highlight-default .notranslate} ::: highlight >>> obj = MyShape() >>> obj.static_moments (150.0, 200.0, 50.0) ::: :::

[[tessellate]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[angular_tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.1]{.pre}]{.default_value}[)]{.sig-paren} →]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[list]{.pre}[[[]{.pre}]{.p}[Vector]{.pre}[[{.pre}]{.p},]{.pre}]{.p}[ ]{.w}[list]{.pre}[[[]{.pre}]{.p}[tuple]{.pre}[[[]{.pre}]{.p}[int]{.pre}[[,]{.pre}]{.p}[ ]{.w}[int]{.pre}[[,]{.pre}]{.p}[ ]{.w}[int]{.pre}[[{.pre}]{.p}{.pre}]{.p}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

General triangulated approximation

[[to_splines]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[degree]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[int]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[3]{.pre}]{.default_value}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.001]{.pre}]{.default_value}, [[nurbs]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

A shape-processing utility that forces all geometry in a shape to be converted into BSplines. It's useful when working with tools or export formats that require uniform geometry, or for downstream processing that only understands BSpline representations.

Parameters[:]{.colon}
  • degree (int, optional) -- Maximum degree. Defaults to 3.

  • tolerance (float, optional) -- Approximation tolerance. Defaults to 1e-3.

  • nurbs (bool, optional) -- Use rational splines. Defaults to False.

Returns[:]{.colon}

Approximated shape

Return type[:]{.colon}

Self

[[transform_geometry]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[t_matrix]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Matrix]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Apply affine transform

WARNING: transform_geometry will sometimes convert lines and circles to splines, but it also has the ability to handle skew and stretching transformations.

If your transformation is only translation and rotation, it is safer to use transform_shape(){.xref .py .py-meth .docutils .literal .notranslate}{.hxr-hoverxref .hxr-tooltip .reference .internal}, which doesn't change the underlying type of the geometry, but cannot handle skew transformations.

Parameters[:]{.colon}

t_matrix (Matrix{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- affine transformation matrix

Returns[:]{.colon}

a copy of the object, but with geometry transformed

Return type[:]{.colon}

Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[transform_shape]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[t_matrix]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Matrix]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Apply affine transform without changing type

Transforms a copy of this Shape by the provided 3D affine transformation matrix. Note that not all transformation are supported - primarily designed for translation and rotation. See :transform_geometry: for more comprehensive transformations.

Parameters[:]{.colon}

t_matrix (Matrix{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- affine transformation matrix

Returns[:]{.colon}

copy of transformed shape with all objects keeping their type

Return type[:]{.colon}

Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[transformed]{.pre}]{.sig-name .descname}[(]{.sig-paren}rotate]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[(0,]{.pre} [0,]{.pre} [0)]{.pre}]{.default_value}, offset]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[(0,]{.pre} [0,]{.pre} [0)]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Transform Shape

Rotate and translate the Shape by the three angles (in degrees) and offset.

Parameters[:]{.colon}
  • rotate (VectorLike, optional) -- 3-tuple of angles to rotate, in degrees. Defaults to (0, 0, 0).

  • offset (VectorLike, optional) -- 3-tuple to offset. Defaults to (0, 0, 0).

Returns[:]{.colon}

transformed object

Return type[:]{.colon}

Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[translate]{.pre}]{.sig-name .descname}[(]{.sig-paren}vector]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Translates this shape through a transformation.

Parameters[:]{.colon}

vector -- VectorLike:

Returns:

[[vertex]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.sig-return-typehint}]{.sig-return}

Return the Vertex

[[vertices]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

vertices - all the vertices in this Shape

[[wire]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.sig-return-typehint}]{.sig-return}

Return the Wire

[[wires]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

wires - all the wires in this Shape

[property]{.pre}[ ]{.w}[[wrapped]{.pre}]{.sig-name .descname}
<!-- -->
[class]{.pre}[ ]{.w}[[ShapeList]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[iterable]{.pre}]{.n}[[=]{.pre}]{.o}[[()]{.pre}]{.default_value}, [[/]{.pre}]{.o}[)]{.sig-paren}

Subclass of list with custom filter and sort methods appropriate to CAD

[[__and__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[T]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Intersect two ShapeLists operator &

[[__getitem__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[key]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[SupportsIndex]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[T]{.pre}]{.sig-return-typehint}]{.sig-return}\
[[__getitem__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[key]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[slice]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[T]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Return slices of ShapeList as ShapeList

[[__gt__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[sort_by]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[SortBy]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[((0.0,]{.pre} [0.0,]{.pre} [0.0),]{.pre} [(0.0,]{.pre} [0.0,]{.pre} [1.0))]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[T]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Sort operator >

[[__lshift__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[group_by]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[SortBy]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[((0.0,]{.pre} [0.0,]{.pre} [0.0),]{.pre} [(0.0,]{.pre} [0.0,]{.pre} [1.0))]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[T]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Group and select smallest group operator <<

[[__lt__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[sort_by]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[SortBy]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[((0.0,]{.pre} [0.0,]{.pre} [0.0),]{.pre} [(0.0,]{.pre} [0.0,]{.pre} [1.0))]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[T]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Reverse sort operator <

[[__or__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[filter_by]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[GeomType]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[((0.0,]{.pre} [0.0,]{.pre} [0.0),]{.pre} [(0.0,]{.pre} [0.0,]{.pre} [1.0))]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[T]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Filter by axis or geomtype operator |

[[__rshift__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[group_by]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[SortBy]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[((0.0,]{.pre} [0.0,]{.pre} [0.0),]{.pre} [(0.0,]{.pre} [0.0,]{.pre} [1.0))]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[T]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Group and select largest group operator >>

[[__sub__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[T]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Differences between two ShapeLists operator -

[[center]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

The average of the center of objects within the ShapeList

[[compound]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return the Compound

[[compounds]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

compounds - all the compounds in this ShapeList

[[edge]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return the Edge

[[edges]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

edges - all the edges in this ShapeList

[[face]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return the Face

[[faces]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

faces - all the faces in this ShapeList

[[filter_by]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[filter_by]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[ShapePredicate]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Plane]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[GeomType]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[property]{.pre}]{.n}, [[reverse]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1e-05]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[T]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

filter by Axis, Plane, or GeomType

Either: - filter objects of type planar Face or linear Edge by their normal or tangent (respectively) and sort the results by the given axis, or - filter the objects by the provided type. Note that not all types apply to all objects.

Parameters[:]{.colon}
  • filter_by (Union[Axis{.hxr-hoverxref .hxr-tooltip .reference .internal},Plane{.hxr-hoverxref .hxr-tooltip .reference .internal},GeomType{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- axis, plane, or geom type to filter and possibly sort by. Filtering by a plane returns faces/edges parallel to that plane.

  • reverse (bool, optional) -- invert the geom type filter. Defaults to False.

  • tolerance (float, optional) -- maximum deviation from axis. Defaults to 1e-5.

Raises[:]{.colon}

ValueError -- Invalid filter_by type

Returns[:]{.colon}

filtered list of objects

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[filter_by_position]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[axis]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}]{.n}, [[minimum]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[maximum]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, inclusive]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[bool]{.pre}[[,]{.pre}]{.p}[ ]{.w}[bool]{.pre}[[{.pre}]{.p}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[(True,]{.pre} [True)]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[T]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

filter by position

Filter and sort objects by the position of their centers along given axis. min and max values can be inclusive or exclusive depending on the inclusive tuple.

Parameters[:]{.colon}
  • axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- axis to sort by

  • minimum (float) -- minimum value

  • maximum (float) -- maximum value

  • inclusive (tuple[bool, bool], optional) -- include min,max values. Defaults to (True, True).

Returns[:]{.colon}

filtered object list

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}

[property]{.pre}[ ]{.w}[[first]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[T]{.pre}

First element in the ShapeList

[[group_by]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[group_by]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Callable]{.pre}[[[]{.pre}]{.p}[[[]{.pre}]{.p}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p},]{.pre}]{.p}[ ]{.w}[K]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[SortBy]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[property]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[((0.0,]{.pre} [0.0,]{.pre} [0.0),]{.pre} [(0.0,]{.pre} [0.0,]{.pre} [1.0))]{.pre}]{.default_value}, [[reverse]{.pre}]{.n}[[=]{.pre}]{.o}[[False]{.pre}]{.default_value}, [[tol_digits]{.pre}]{.n}[[=]{.pre}]{.o}[[6]{.pre}]{.default_value}[)]{.sig-paren} →]{.sig-return-icon} [[GroupBy]{.pre}[[[]{.pre}]{.p}[T]{.pre}[[,]{.pre}]{.p}[ ]{.w}[K]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

group by

Group objects by provided criteria and then sort the groups according to the criteria. Note that not all group_by criteria apply to all objects.

Parameters[:]{.colon}
  • group_by (SortBy{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- group and sort criteria. Defaults to Axis.Z.

  • reverse (bool, optional) -- flip order of sort. Defaults to False.

  • tol_digits (int, optional) -- Tolerance for building the group keys by round(key, tol_digits)

Returns[:]{.colon}

sorted list of ShapeLists

Return type[:]{.colon}

GroupBy[K, ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}]

[property]{.pre}[ ]{.w}[[last]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[T]{.pre}

Last element in the ShapeList

[[shell]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return the Shell

[[shells]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

shells - all the shells in this ShapeList

[[solid]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return the Solid

[[solids]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

solids - all the solids in this ShapeList

[[sort_by]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[sort_by]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Callable]{.pre}[[[]{.pre}]{.p}[[[]{.pre}]{.p}[T]{.pre}[[{.pre}]{.p},]{.pre}]{.p}[ ]{.w}[K]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[SortBy]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[property]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[((0.0,]{.pre} [0.0,]{.pre} [0.0),]{.pre} [(0.0,]{.pre} [0.0,]{.pre} [1.0))]{.pre}]{.default_value}, [[reverse]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[T]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

sort by

Sort objects by provided criteria. Note that not all sort_by criteria apply to all objects.

Parameters[:]{.colon}
  • sort_by (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal} | Callable[[T], K] | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal} | SortBy{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- sort criteria. Defaults to Axis.Z.

  • reverse (bool, optional) -- flip order of sort. Defaults to False.

Raises[:]{.colon}
  • ValueError -- Cannot sort by an empty axis

  • ValueError -- Cannot sort by an empty object

  • ValueError -- Invalid sort_by criteria provided

Returns[:]{.colon}

sorted list of objects

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[sort_by_distance]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, [[reverse]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[]{.pre}]{.p}[T]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Sort by distance

Sort by minimal distance between objects and other

Parameters[:]{.colon}
  • other (Union[Shape{.hxr-hoverxref .hxr-tooltip .reference .internal},VectorLike]) -- reference object

  • reverse (bool, optional) -- flip order of sort. Defaults to False.

Returns[:]{.colon}

Sorted shapes

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[vertex]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return the Vertex

[[vertices]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

vertices - all the vertices in this ShapeList

[[wire]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return the Wire

[[wires]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

wires - all the wires in this ShapeList

<!-- -->
[class]{.pre}[ ]{.w}[[Shell]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Shell]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Iterable]{.pre}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Color]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

A Shell is a fundamental component in build123d's topological data structure representing a connected set of faces forming a closed surface in 3D space. As part of a geometric model, it defines a watertight enclosure, commonly encountered in solid modeling. Shells group faces in a coherent manner, playing a crucial role in representing complex shapes with voids and surfaces. This hierarchical structure allows for efficient handling of surfaces within a model, supporting various operations and analyses.

[[center]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

Center of mass of the shell

[classmethod]{.pre}[ ]{.w}[[extrude]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Extrude a Wire into a Shell.

Parameters[:]{.colon}

direction (VectorLike) -- direction and magnitude of extrusion

Raises[:]{.colon}
  • ValueError -- Unsupported class

  • RuntimeError -- Generated invalid result

Returns[:]{.colon}

extruded shape

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[location_at]{.pre}]{.sig-name .descname}[(]{.sig-paren}surface_point]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, [[*]{.pre}]{.o}, x_dir]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Location]{.pre}]{.sig-return-typehint}]{.sig-return}

Get the location (origin and orientation) on the surface of the shell.

Parameters[:]{.colon}
  • surface_point (VectorLike) -- A 3D point near the surface.

  • x_dir (VectorLike, optional) -- Direction for the local X axis. If not given, the tangent in the U direction is used.

Returns[:]{.colon}

A full 3D placement at the specified point on the shell surface.

Return type[:]{.colon}

Location{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_loft]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[objs]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}, [[ruled]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

make loft

Makes a loft from a list of wires and vertices. Vertices can appear only at the beginning or end of the list, but cannot appear consecutively within the list nor between wires. Wires may be closed or opened.

Parameters[:]{.colon}
  • objs (list[Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal}, Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- wire perimeters or vertices

  • ruled (bool, optional) -- stepped or smooth. Defaults to False (smooth).

Raises[:]{.colon}

ValueError -- Too few wires

Returns[:]{.colon}

Lofted object

Return type[:]{.colon}

Shell{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[order]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[2.5]{.pre}
[classmethod]{.pre}[ ]{.w}[[revolve]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[profile]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Curve]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[axis]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

sweep

Revolve a 1D profile around an axis.

Parameters[:]{.colon}
  • profile (Curve{.hxr-hoverxref .hxr-tooltip .reference .internal} | Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- the object to revolve

  • angle (float) -- the angle to revolve through

  • axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- rotation Axis

Returns[:]{.colon}

resulting shell

Return type[:]{.colon}

Shell{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[sweep]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[profile:]{.pre} [Curve]{.pre} [|]{.pre} [Edge]{.pre} [|]{.pre} [Wire]{.pre}]{.n}, [[path:]{.pre} [Curve]{.pre} [|]{.pre} [Edge]{.pre} [|]{.pre} [Wire]{.pre}]{.n}, [[transition=<Transition.TRANSFORMED>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Sweep a 1D profile along a 1D path

Parameters[:]{.colon}
  • profile (Union[Curve{.hxr-hoverxref .hxr-tooltip .reference .internal}, Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}, Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- the object to sweep

  • path (Union[Curve{.hxr-hoverxref .hxr-tooltip .reference .internal}, Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}, Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- the path to follow when sweeping

  • transition (Transition{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- handling of profile orientation at C1 path discontinuities. Defaults to Transition.TRANSFORMED.

Returns[:]{.colon}

resulting Shell, may be non-planar

Return type[:]{.colon}

Shell{.hxr-hoverxref .hxr-tooltip .reference .internal}

[property]{.pre}[ ]{.w}[[volume]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

volume - the volume of this Shell if manifold, otherwise zero

<!-- -->
[class]{.pre}[ ]{.w}[[Solid]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Solid]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Color]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[material]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[joints]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[dict]{.pre}[[[]{.pre}]{.p}[str]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Joint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

A Solid in build123d represents a three-dimensional solid geometry in a topological structure. A solid is a closed and bounded volume, enclosing a region in 3D space. It comprises faces, edges, and vertices connected in a well-defined manner. Solid modeling operations, such as Boolean operations (union, intersection, and difference), are often performed on Solid objects to create or modify complex geometries.

[[draft]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[faces]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}, [[neutral_plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}]{.n}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Apply a draft angle to the given faces of the solid.

Parameters[:]{.colon}
  • faces -- Faces to which the draft should be applied.

  • neutral_plane -- Plane defining the neutral direction and position.

  • angle -- Draft angle in degrees.

Returns[:]{.colon}

Solid with the specified draft angles applied.

Raises[:]{.colon}

RuntimeError -- If draft application fails on any face or during build.

[classmethod]{.pre}[ ]{.w}[[extrude]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Extrude a Face into a Solid.

Parameters[:]{.colon}

direction (VectorLike) -- direction and magnitude of extrusion

Raises[:]{.colon}
  • ValueError -- Unsupported class

  • RuntimeError -- Generated invalid result

Returns[:]{.colon}

extruded shape

Return type[:]{.colon}

Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[extrude_linear_with_rotation]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[section]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, center]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, normal]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[inner_wires]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[list]{.pre}[[[]{.pre}]{.p}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Extrude with Rotation

Creates a 'twisted prism' by extruding, while simultaneously rotating around the extrusion vector.

Parameters[:]{.colon}
  • section (Union[Face{.hxr-hoverxref .hxr-tooltip .reference .internal},Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- cross section

  • vec_center (VectorLike) -- the center point about which to rotate

  • vec_normal (VectorLike) -- a vector along which to extrude the wires

  • angle (float) -- the angle to rotate through while extruding

  • inner_wires (list[Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- holes - only used if section is of type Wire. Defaults to None.

Returns[:]{.colon}

extruded object

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[extrude_taper]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[profile]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, [[taper]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[flip_inner]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[True]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Extrude a cross section with a taper

Extrude a cross section into a prismatic solid in the provided direction.

Note that two difference algorithms are used. If direction aligns with the profile normal (which must be positive), the taper is positive and the profile contains no holes the OCP LocOpe_DPrism algorithm is used as it generates the most accurate results. Otherwise, a loft is created between the profile and the profile with a 2D offset set at the appropriate direction.

Parameters[:]{.colon}
  • section (Face{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- cross section

  • normal (VectorLike) -- a vector along which to extrude the wires. The length of the vector controls the length of the extrusion.

  • taper (float) -- taper angle in degrees.

  • flip_inner (bool, optional) -- outer and inner geometry have opposite tapers to allow for part extraction when injection molding.

Returns[:]{.colon}

extruded cross section

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[extrude_until]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[profile:]{.pre} [Face]{.pre}]{.n}, [[target:]{.pre} [Compound]{.pre} [|]{.pre} [Solid]{.pre}]{.n}, [[direction:]{.pre} [VectorLike]{.pre}]{.n}, [[until:]{.pre} [Until]{.pre} [=]{.pre} [<Until.NEXT>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Extrude <cite>{=html}profile</cite>{=html} in the provided <cite>{=html}direction</cite>{=html} until it encounters a bounding surface on the <cite>{=html}target</cite>{=html}. The termination surface is chosen according to the <cite>{=html}until</cite>{=html} option:

  • Until.NEXT{.docutils .literal .notranslate} --- Extrude forward until the first intersecting surface.

  • Until.LAST{.docutils .literal .notranslate} --- Extrude forward through all intersections, stopping at

the farthest surface. * Until.PREVIOUS{.docutils .literal .notranslate} --- Reverse the extrusion direction and stop at the first intersecting surface behind the profile. * Until.FIRST{.docutils .literal .notranslate} --- Reverse the direction and stop at the farthest surface behind the profile.

When Until.PREVIOUS{.docutils .literal .notranslate} or Until.FIRST{.docutils .literal .notranslate} are used, the extrusion direction is automatically inverted before execution.

::: {.admonition .note} Note

The bounding surface on the target must be large enough to completely cover the extruded profile at the contact region. Partial overlaps may yield open or invalid solids. :::

Parameters[:]{.colon}
  • profile (Face{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- The face to extrude.

  • target (Union[Compound{.hxr-hoverxref .hxr-tooltip .reference .internal}, Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- The object that limits the extrusion.

  • direction (VectorLike) -- Extrusion direction.

  • until (Until{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Surface selection mode controlling which intersection to stop at. Defaults to Until.NEXT{.docutils .literal .notranslate}.

Raises[:]{.colon}

ValueError -- If the provided profile does not intersect the target.

Returns[:]{.colon}

The extruded and limited solid.

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[from_bounding_box]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[bbox]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[BoundBox]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[OrientedBoundBox]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

A box of the same dimensions and location

[classmethod]{.pre}[ ]{.w}[[make_box]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[length]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[width]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[height]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[Plane(o=(0.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [x=(1.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [z=(0.00,]{.pre} [0.00,]{.pre} [1.00))]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

make box

Make a box at the origin of plane extending in positive direction of each axis.

Parameters[:]{.colon}
  • length (float)

  • width (float)

  • height (float)

  • plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- base plane. Defaults to Plane.XY.

Returns[:]{.colon}

Box

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_cone]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[base_radius]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[top_radius]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[height]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[Plane(o=(0.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [x=(1.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [z=(0.00,]{.pre} [0.00,]{.pre} [1.00))]{.pre}]{.default_value}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[360]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

make cone

Make a cone with given radii and height

Parameters[:]{.colon}
  • base_radius (float)

  • top_radius (float)

  • height (float)

  • plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- base plane. Defaults to Plane.XY.

  • angle (float, optional) -- arc size. Defaults to 360.

Returns[:]{.colon}

Full or partial cone

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_cylinder]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[radius]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[height]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[Plane(o=(0.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [x=(1.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [z=(0.00,]{.pre} [0.00,]{.pre} [1.00))]{.pre}]{.default_value}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[360]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

make cylinder

Make a cylinder with a given radius and height with the base center on plane origin.

Parameters[:]{.colon}
  • radius (float)

  • height (float)

  • plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- base plane. Defaults to Plane.XY.

  • angle (float, optional) -- arc size. Defaults to 360.

Returns[:]{.colon}

Full or partial cylinder

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_loft]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[objs]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}, [[ruled]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

make loft

Makes a loft from a list of wires and vertices. Vertices can appear only at the beginning or end of the list, but cannot appear consecutively within the list nor between wires.

Parameters[:]{.colon}
  • objs (list[Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal}, Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- wire perimeters or vertices

  • ruled (bool, optional) -- stepped or smooth. Defaults to False (smooth).

Raises[:]{.colon}

ValueError -- Too few wires

Returns[:]{.colon}

Lofted object

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_sphere]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[radius]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[Plane(o=(0.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [x=(1.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [z=(0.00,]{.pre} [0.00,]{.pre} [1.00))]{.pre}]{.default_value}, [[angle1]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[-90]{.pre}]{.default_value}, [[angle2]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[90]{.pre}]{.default_value}, [[angle3]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[360]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Sphere

Make a full or partial sphere - with a given radius center on the origin or plane.

Parameters[:]{.colon}
  • radius (float)

  • plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- base plane. Defaults to Plane.XY.

  • angle1 (float, optional) -- Defaults to -90.

  • angle2 (float, optional) -- Defaults to 90.

  • angle3 (float, optional) -- Defaults to 360.

Returns[:]{.colon}

sphere

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_torus]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[major_radius]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[minor_radius]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[Plane(o=(0.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [x=(1.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [z=(0.00,]{.pre} [0.00,]{.pre} [1.00))]{.pre}]{.default_value}, [[start_angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0]{.pre}]{.default_value}, [[end_angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[360]{.pre}]{.default_value}, [[major_angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[360]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

make torus

Make a torus with a given radii and angles

Parameters[:]{.colon}
  • major_radius (float)

  • minor_radius (float)

  • plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- base plane. Defaults to Plane.XY.

  • start_angle (float, optional) -- start major arc. Defaults to 0.

  • end_angle (float, optional) -- end major arc. Defaults to 360.

Returns[:]{.colon}

Full or partial torus

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_wedge]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[delta_x]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[delta_y]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[delta_z]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[min_x]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[min_z]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[max_x]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[max_z]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[Plane(o=(0.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [x=(1.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [z=(0.00,]{.pre} [0.00,]{.pre} [1.00))]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Make a wedge

Parameters[:]{.colon}
  • delta_x (float)

  • delta_y (float)

  • delta_z (float)

  • min_x (float)

  • min_z (float)

  • max_x (float)

  • max_z (float)

  • plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- base plane. Defaults to Plane.XY.

Returns[:]{.colon}

wedge

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[order]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[3.0]{.pre}
[classmethod]{.pre}[ ]{.w}[[revolve]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[section]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[angle]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[axis]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Axis]{.pre}]{.n}, [[inner_wires]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[list]{.pre}[[[]{.pre}]{.p}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Revolve

Revolve a cross section about the given Axis by the given angle.

Parameters[:]{.colon}
  • section (Union[Face{.hxr-hoverxref .hxr-tooltip .reference .internal},Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- cross section

  • angle (float) -- the angle to revolve through

  • axis (Axis{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- rotation Axis

  • inner_wires (list[Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}], optional) -- holes - only used if section is of type Wire. Defaults to [].

Returns[:]{.colon}

the revolved cross section

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[sweep]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[section:]{.pre} [~topology.two_d.Face]{.pre} [|]{.pre} [~topology.one_d.Wire]{.pre}]{.n}, [[path:]{.pre} [~topology.one_d.Wire]{.pre} [|]{.pre} [~topology.one_d.Edge]{.pre}]{.n}, inner_wires:]{.pre} [list[~topology.one_d.Wire{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[make_solid:]{.pre} [bool]{.pre} [=]{.pre} [True]{.pre}]{.n}, [[is_frenet:]{.pre} [bool]{.pre} [=]{.pre} [False]{.pre}]{.n}, [[mode:]{.pre} [~build123d.geometry.Vector]{.pre} [|]{.pre} [~topology.one_d.Wire]{.pre} [|]{.pre} [~topology.one_d.Edge]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}, [[transition:]{.pre} [~build123d.build_enums.Transition]{.pre} [=]{.pre} [<Transition.TRANSFORMED>]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Sweep

Sweep the given cross section into a prismatic solid along the provided path

The is_frenet parameter controls how the profile orientation changes as it follows along the sweep path. If is_frenet is False, the orientation of the profile is kept consistent from point to point. The resulting shape has the minimum possible twisting. Unintuitively, when a profile is swept along a helix, this results in the orientation of the profile slowly creeping (rotating) as it follows the helix. Setting is_frenet to True prevents this.

If is_frenet is True the orientation of the profile is based on the local curvature and tangency vectors of the path. This keeps the orientation of the profile consistent when sweeping along a helix (because the curvature vector of a straight helix always points to its axis). However, when path is not a helix, the resulting shape can have strange looking twists sometimes. For more information, see Frenet Serret formulas http://en.wikipedia.org/wiki/Frenet%E2%80%93Serret_formulas{.reference .external}.

Parameters[:]{.colon}
  • section (Union[Face{.hxr-hoverxref .hxr-tooltip .reference .internal}, Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- cross section to sweep

  • path (Union[Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}, Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- sweep path

  • inner_wires (list[Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- holes - only used if section is a wire

  • make_solid (bool, optional) -- return Solid or Shell. Defaults to True.

  • is_frenet (bool, optional) -- Frenet mode. Defaults to False.

  • mode (Union[Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}, Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}, Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}, None], optional) -- additional sweep mode parameters. Defaults to None.

  • transition (Transition{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- handling of profile orientation at C1 path discontinuities. Defaults to Transition.TRANSFORMED.

Returns[:]{.colon}

the swept cross section

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[sweep_multi]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[profiles]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}, [[path]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[make_solid]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[True]{.pre}]{.default_value}, [[is_frenet]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}, [[binormal]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Multi section sweep

Sweep through a sequence of profiles following a path.

The is_frenet parameter controls how the profile orientation changes as it follows along the sweep path. If is_frenet is False, the orientation of the profile is kept consistent from point to point. The resulting shape has the minimum possible twisting. Unintuitively, when a profile is swept along a helix, this results in the orientation of the profile slowly creeping (rotating) as it follows the helix. Setting is_frenet to True prevents this.

If is_frenet is True the orientation of the profile is based on the local curvature and tangency vectors of the path. This keeps the orientation of the profile consistent when sweeping along a helix (because the curvature vector of a straight helix always points to its axis). However, when path is not a helix, the resulting shape can have strange looking twists sometimes. For more information, see Frenet Serret formulas http://en.wikipedia.org/wiki/Frenet%E2%80%93Serret_formulas{.reference .external}.

Parameters[:]{.colon}
  • profiles (Iterable[Union[Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}, Face{.hxr-hoverxref .hxr-tooltip .reference .internal}]]) -- list of profiles

  • path (Union[Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}, Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- The wire to sweep the face resulting from the wires over

  • make_solid (bool, optional) -- Solid or Shell. Defaults to True.

  • is_frenet (bool, optional) -- Select frenet mode. Defaults to False.

  • binormal (Union[Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}, Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}, Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}, None], optional) -- additional sweep mode parameters. Defaults to None.

Returns[:]{.colon}

swept object

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[thicken]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[surface]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Face]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Shell]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[depth]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, normal_override]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Thicken Face or Shell

Create a solid from a potentially non planar face or shell by thickening along the normals.

Non-planar faces are thickened both towards and away from the center of the sphere.

Parameters[:]{.colon}
  • depth (float) -- Amount to thicken face(s), can be positive or negative.

  • normal_override (Vector{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- Face only. The normal_override vector can be used to indicate which way is 'up', potentially flipping the face normal direction such that many faces with different normals all go in the same direction (direction need only be +/- 90 degrees from the face normal). Defaults to None.

Raises[:]{.colon}

RuntimeError -- Opencascade internal failures

Returns[:]{.colon}

The resulting Solid object

Return type[:]{.colon}

Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}

[property]{.pre}[ ]{.w}[[volume]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

volume - the volume of this Solid

<!-- -->
[class]{.pre}[ ]{.w}[[Wire]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Wire]{.pre}]{.n}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Color]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}\
[class]{.pre}[ ]{.w}[[Wire]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[edge]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Color]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}\
[class]{.pre}[ ]{.w}[[Wire]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[wire]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Color]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}\
[class]{.pre}[ ]{.w}[[Wire]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[wire]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Curve]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Color]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}\
[class]{.pre}[ ]{.w}[[Wire]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[edges]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}, [[sequenced]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[False]{.pre}]{.default_value}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Color]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

A Wire in build123d is a topological entity representing a connected sequence of edges forming a continuous curve or path in 3D space. Wires are essential components in modeling complex objects, defining boundaries for surfaces or solids. They store information about the connectivity and order of edges, allowing precise definition of paths within a 3D model.

[[chamfer_2d]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[distance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[distance2]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[vertices]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}, [[edge]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Apply 2D chamfer to a wire

Parameters[:]{.colon}
  • distance (float) -- chamfer length

  • distance2 (float) -- chamfer length

  • vertices (Iterable[Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- vertices to chamfer

  • edge (Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- identifies the side where length is measured. The vertices must be part of the edge

Returns[:]{.colon}

chamfered wire

Return type[:]{.colon}

Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[close]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Close a Wire

[classmethod]{.pre}[ ]{.w}[[combine]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[wires]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}, [[tol]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[1e-09]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Combine a list of wires and edges into a list of Wires.

Parameters[:]{.colon}
  • wires (Iterable[Wire{.hxr-hoverxref .hxr-tooltip .reference .internal} | Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- unsorted

  • tol (float, optional) -- tolerance. Defaults to 1e-9.

Returns[:]{.colon}

Wires

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}]

[[edges]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

edges - all the edges in this Shape

[classmethod]{.pre}[ ]{.w}[[extrude]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

extrude - invalid operation for Wire

[[fillet_2d]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[radius]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[vertices]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Apply 2D fillet to a wire

Parameters[:]{.colon}
  • radius (float)

  • vertices (Iterable[Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- vertices to fillet

Raises[:]{.colon}
  • RuntimeError -- Internal error

  • ValueError -- empty wire

Returns[:]{.colon}

filleted wire

Return type[:]{.colon}

Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[fix_degenerate_edges]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[precision]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Fix a Wire that contains degenerate (very small) edges

Parameters[:]{.colon}

precision (float) -- minimum value edge length

Returns[:]{.colon}

fixed wire

Return type[:]{.colon}

Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[geom_adaptor]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[BRepAdaptor_CompCurve]{.pre}]{.sig-return-typehint}]{.sig-return}

Return the Geom Comp Curve for this Wire

[classmethod]{.pre}[ ]{.w}[[make_circle]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[radius]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[Plane(o=(0.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [x=(1.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [z=(0.00,]{.pre} [0.00,]{.pre} [1.00))]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Makes a circle centered at the origin of plane

Parameters[:]{.colon}
  • radius (float) -- circle radius

  • plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- base plane. Defaults to Plane.XY

Returns[:]{.colon}

a circle

Return type[:]{.colon}

Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_convex_hull]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[edges]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}, [[tolerance]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[0.001]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Create a wire of minimum length enclosing all of the provided edges.

Note that edges can't overlap each other.

Parameters[:]{.colon}
  • edges (Iterable[Edge{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- edges defining the convex hull

  • tolerance (float) -- allowable error as a fraction of each edge length. Defaults to 1e-3.

Raises[:]{.colon}

ValueError -- edges overlap

Returns[:]{.colon}

convex hull perimeter

Return type[:]{.colon}

Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_ellipse]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[x_radius:]{.pre} [float]{.pre}]{.n}, [[y_radius:]{.pre} [float]{.pre}]{.n}, [[plane:]{.pre} [~build123d.geometry.Plane]{.pre} [=]{.pre} [Plane(o=(0.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[x=(1.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[0.00)]{.pre}]{.n}, [[z=(0.00]{.pre}]{.n}, [[0.00]{.pre}]{.n}, [[1.00))]{.pre}]{.n}, [[start_angle:]{.pre} [float]{.pre} [=]{.pre} [360.0]{.pre}]{.n}, [[end_angle:]{.pre} [float]{.pre} [=]{.pre} [360.0]{.pre}]{.n}, [[angular_direction:]{.pre} [~build123d.build_enums.AngularDirection]{.pre} [=]{.pre} [<AngularDirection.COUNTER_CLOCKWISE>]{.pre}]{.n}, [[closed:]{.pre} [bool]{.pre} [=]{.pre} [True]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

make ellipse

Makes an ellipse centered at the origin of plane.

Parameters[:]{.colon}
  • x_radius (float) -- x radius of the ellipse (along the x-axis of plane)

  • y_radius (float) -- y radius of the ellipse (along the y-axis of plane)

  • plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- base plane. Defaults to Plane.XY.

  • start_angle (float, optional) -- _description_. Defaults to 360.0.

  • end_angle (float, optional) -- _description_. Defaults to 360.0.

  • angular_direction (AngularDirection, optional) -- arc direction. Defaults to AngularDirection.COUNTER_CLOCKWISE.

  • closed (bool, optional) -- close the arc. Defaults to True.

Returns[:]{.colon}

an ellipse

Return type[:]{.colon}

Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_polygon]{.pre}]{.sig-name .descname}[(]{.sig-paren}vertices]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}{.pre}]{.p}]{.n}, [[close]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[bool]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[True]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Create an irregular polygon by defining vertices

Parameters[:]{.colon}
  • vertices (Iterable[VectorLike])

  • close (bool, optional) -- close the polygon. Defaults to True.

Returns[:]{.colon}

an irregular polygon

Return type[:]{.colon}

Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}

[classmethod]{.pre}[ ]{.w}[[make_rect]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[width]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[height]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[plane]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Plane]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[Plane(o=(0.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [x=(1.00,]{.pre} [0.00,]{.pre} [0.00),]{.pre} [z=(0.00,]{.pre} [0.00,]{.pre} [1.00))]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Make Rectangle

Make a Rectangle centered on center with the given normal

Parameters[:]{.colon}
  • width (float) -- width (local x)

  • height (float) -- height (local y)

  • plane (Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}, optional) -- plane containing rectangle. Defaults to Plane.XY.

Returns[:]{.colon}

The centered rectangle

Return type[:]{.colon}

Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[order]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[1.5]{.pre}
[static]{.pre}[ ]{.w}[[order_chamfer_edges]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[reference_edge]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}, [[edges]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[tuple]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[,]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[,]{.pre}]{.p}[ ]{.w}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Order the edges of a chamfer relative to a reference Edge

[[order_edges]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Edge]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Return the edges in self ordered by wire direction and orientation

[[param_at_point]{.pre}]{.sig-name .descname}[(]{.sig-paren}point]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[float]{.pre}]{.sig-return-typehint}]{.sig-return}

Return the normalized wire parameter for the point closest to this wire.

This method projects the given point onto the wire, finds the nearest edge, and accumulates arc lengths to determine the fractional position along the entire wire. The result is normalized to the interval [0.0, 1.0], where:

  • 0.0 corresponds to the start of the wire

  • 1.0 corresponds to the end of the wire

Unlike the edge version of this method, the returned value is not an OCCT curve parameter, but a normalized parameter across the wire as a whole.

Parameters[:]{.colon}

point (VectorLike) -- The point to project onto the wire.

Raises[:]{.colon}

ValueError -- Can't find point on empty wire

Returns[:]{.colon}

Normalized parameter in [0.0, 1.0] representing the relative position of the projected point along the wire.

Return type[:]{.colon}

float

[[project_to_shape]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[target_object]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, center]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren} [[→]{.sig-return-icon} [[list]{.pre}[[[]{.pre}]{.p}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Project Wire

Project a Wire onto a Shape generating new wires on the surfaces of the object one and only one of <cite>{=html}direction</cite>{=html} or <cite>{=html}center</cite>{=html} must be provided. Note that one or more wires may be generated depending on the topology of the target object and location/direction of projection.

To avoid flipping the normal of a face built with the projected wire the orientation of the output wires are forced to be the same as self.

Parameters[:]{.colon}
  • target_object -- Object to project onto

  • direction -- Parallel projection direction. Defaults to None.

  • center -- Conical center of projection. Defaults to None.

  • target_object -- Shape:

  • direction -- VectorLike: (Default value = None)

  • center -- VectorLike: (Default value = None)

Returns[:]{.colon}

Projected wire(s)

Raises[:]{.colon}

ValueError -- Only one of direction or center must be provided

[[stitch]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Attempt to stitch wires

Parameters[:]{.colon}

other (Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- wire to combine

Raises[:]{.colon}

ValueError -- Can't stitch empty wires

Returns[:]{.colon}

stitched wires

Return type[:]{.colon}

Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[to_wire]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return Wire - used as a pair with Edge.to_wire when self is Wire | Edge

[[trim]{.pre}]{.sig-name .descname}[(]{.sig-paren}start]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}, end]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Trim a wire between [start, end] normalized over total length.

Parameters[:]{.colon}
  • start (float | VectorLike) -- normalized start position (0.0 to <1.0) or point

  • end (float | VectorLike) -- normalized end position (>0.0 to 1.0) or point

Returns[:]{.colon}

trimmed Wire

Return type[:]{.colon}

Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[class]{.pre}[ ]{.w}[[Vertex]{.pre}]{.sig-name .descname}\
[class]{.pre}[ ]{.w}[[Vertex]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[ocp_vx]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Vertex]{.pre}]{.n}[)]{.sig-paren}\
[class]{.pre}[ ]{.w}[[Vertex]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[X]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[Y]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}, [[Z]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren}\
[class]{.pre}[ ]{.w}[[Vertex]{.pre}]{.sig-name .descname}[(]{.sig-paren}v]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Iterable]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren}

A Vertex in build123d represents a zero-dimensional point in the topological data structure. It marks the endpoints of edges within a 3D model, defining precise locations in space. Vertices play a crucial role in defining the geometry of objects and the connectivity between edges, facilitating accurate representation and manipulation of 3D shapes. They hold coordinate information and are essential for constructing complex structures like wires, faces, and solids.

[[__add__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Add

Add to a Vertex with a Vertex, Vector or Tuple

Parameters[:]{.colon}

other -- Value to add

Raises[:]{.colon}

TypeError -- other not in [Tuple,Vector,Vertex]

Returns[:]{.colon}

Result

Example

part.faces(">z").vertices("<y and <x").val() + (0, 0, 15)

which creates a new Vertex 15 above one extracted from a part. One can add or subtract a <cite>{=html}Vertex</cite>{=html} , <cite>{=html}Vector</cite>{=html} or <cite>{=html}tuple</cite>{=html} of float values to a Vertex.

[[__sub__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[other]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[tuple]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Subtract

Subtract a Vertex with a Vertex, Vector or Tuple from self

Parameters[:]{.colon}

other -- Value to add

Raises[:]{.colon}

TypeError -- other not in [Tuple,Vector,Vertex]

Returns[:]{.colon}

Result

Example

part.faces(">z").vertices("<y and <x").val() - Vector(10, 0, 0)

[classmethod]{.pre}[ ]{.w}[[cast]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Shape]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Self]{.pre}]{.sig-return-typehint}]{.sig-return}

Returns the right type of wrapper, given a OCCT object

[[center]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

The center of a vertex is itself!

[classmethod]{.pre}[ ]{.w}[[extrude]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}, direction]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Vector]{.pre}[ ]{.w}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}[ ]{.w}]{.pre}]{.p}[ ]{.w}[Sequence]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[{.pre}]{.p}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

extrude - invalid operation for Vertex

[[intersect]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[to_intersect]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Vector]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Location]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Axis]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Plane]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.sig-return-typehint}]{.sig-return}

Intersection of vertex and geometric objects or shapes.

Parameters[:]{.colon}

to_intersect (sequence of [Shape{.hxr-hoverxref .hxr-tooltip .reference .internal} | Vector{.hxr-hoverxref .hxr-tooltip .reference .internal} | Location{.hxr-hoverxref .hxr-tooltip .reference .internal} | Axis{.hxr-hoverxref .hxr-tooltip .reference .internal} | Plane{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- Objects(s) to intersect with

Returns[:]{.colon}

Vertex intersection in a ShapeList or None

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal}] | None

[[order]{.pre}]{.sig-name .descname}[ ]{.w}[[=]{.pre}]{.p}[ ]{.w}[0.0]{.pre}
[[split]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[tool:]{.pre} [TrimmingTool]{.pre}]{.n}, [[keep:]{.pre} [Keep]{.pre} [=]{.pre} [<Keep.TOP>]{.pre}]{.n}[)]{.sig-paren}

split - not implemented

to_tuple]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[,]{.pre}]{.p}[ ]{.w}[float]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

Return vertex as three tuple of floats

[[transform_shape]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[t_matrix]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Matrix]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Apply affine transform without changing type

Transforms a copy of this Vertex by the provided 3D affine transformation matrix. Note that not all transformation are supported - primarily designed for translation and rotation. See :transform_geometry: for more comprehensive transformations.

Parameters[:]{.colon}

t_matrix (Matrix{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- affine transformation matrix

Returns[:]{.colon}

copy of transformed shape with all objects keeping their type

Return type[:]{.colon}

Vertex{.hxr-hoverxref .hxr-tooltip .reference .internal}

[[vertex]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.sig-return-typehint}]{.sig-return}

Return the Vertex

[[vertices]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Vertex]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

vertices - all the vertices in this Shape

[property]{.pre}[ ]{.w}[[volume]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[float]{.pre}

volume - the volume of this Vertex, which is always zero

<!-- -->
[class]{.pre}[ ]{.w}[[Curve]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Compound]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Iterable]{.pre}[[[]{.pre}]{.p}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Color]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[material]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[joints]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[dict]{.pre}[[[]{.pre}]{.p}[str]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Joint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[children]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Sequence]{.pre}[[[]{.pre}]{.p}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

A Compound containing 1D objects - aka Edges

[[__matmul__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[position]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

Position on curve operator @ - only works if continuous

[[__mod__]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[position]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[float]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Vector]{.pre}]{.sig-return-typehint}]{.sig-return}

Tangent on wire operator % - only works if continuous

[[wires]{.pre}]{.sig-name .descname}[(]{.sig-paren}[)]{.sig-paren} [[→]{.sig-return-icon} [[ShapeList]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[[[]{.pre}]{.p}[Wire]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

A list of wires created from the edges

<!-- -->
[class]{.pre}[ ]{.w}[[Part]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Compound]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Iterable]{.pre}[[[]{.pre}]{.p}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Color]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[material]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[joints]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[dict]{.pre}[[[]{.pre}]{.p}[str]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Joint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[children]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Sequence]{.pre}[[[]{.pre}]{.p}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

A Compound containing 3D objects - aka Solids

<!-- -->
[class]{.pre}[ ]{.w}[[Sketch]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[obj]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[TopoDS_Compound]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Iterable]{.pre}[[[]{.pre}]{.p}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[color]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Color]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[material]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[['']{.pre}]{.default_value}, [[joints]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[dict]{.pre}[[[]{.pre}]{.p}[str]{.pre}[[,]{.pre}]{.p}[ ]{.w}[Joint]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}, [[children]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[Sequence]{.pre}[[[]{.pre}]{.p}[Shape]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}{.pre}]{.p}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[None]{.pre}]{.n}[ ]{.w}[[=]{.pre}]{.o}[ ]{.w}[[None]{.pre}]{.default_value}[)]{.sig-paren}

A Compound containing 2D objects - aka Faces :::

::: {#direct_api_reference.xhtml#import-export .section}

Import/Export

Methods and functions specific to exporting and importing build123d objects are defined below.

[[import_brep]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[file_name]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[PathLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[str]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[bytes]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Shape]{.pre}]{.sig-return-typehint}]{.sig-return}

Import shape from a BREP file

Parameters[:]{.colon}

file_name (Union[PathLike, str, bytes]) -- brep file

Raises[:]{.colon}

ValueError -- file not found

Returns[:]{.colon}

build123d object

Return type[:]{.colon}

Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[[import_step]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[filename]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[PathLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[str]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[bytes]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Compound]{.pre}]{.sig-return-typehint}]{.sig-return}

Extract shapes from a STEP file and return them as a Compound object.

Parameters[:]{.colon}

file_name (Union[PathLike, str, bytes]) -- file path of STEP file to import

Raises[:]{.colon}

ValueError -- can't open file

Returns[:]{.colon}

contents of STEP file

Return type[:]{.colon}

Compound{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[[import_stl]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[file_name]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[PathLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[str]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[bytes]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Face]{.pre}]{.sig-return-typehint}]{.sig-return}

Extract shape from an STL file and return it as a Face reference object.

Note that importing with this method and creating a reference is very fast while creating an editable model (with Mesher) may take minutes depending on the size of the STL file.

Parameters[:]{.colon}

file_name (Union[PathLike, str, bytes]) -- file path of STL file to import

Raises[:]{.colon}

ValueError -- Could not import file

Returns[:]{.colon}

STL model

Return type[:]{.colon}

Face{.hxr-hoverxref .hxr-tooltip .reference .internal}

<!-- -->
[[import_svg]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[svg_file:]{.pre} [str]{.pre} [|]{.pre} [~pathlib.Path]{.pre} [|]{.pre} [~typing.TextIO]{.pre}]{.n}, [[*]{.pre}]{.n}, [[flip_y:]{.pre} [bool]{.pre} [=]{.pre} [True]{.pre}]{.n}, [[align:]{.pre} [~build123d.build_enums.Align]{.pre} [|]{.pre} [tuple[~build123d.build_enums.Align]{.pre}]{.n}, ~build123d.build_enums.Align{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [<Align.MIN>]{.pre}]{.n}, [[ignore_visibility:]{.pre} [bool]{.pre} [=]{.pre} [False]{.pre}]{.n}, [[label_by:]{.pre} [~typing.Literal['id']{.pre}]{.n}, [['class']{.pre}]{.n}, 'inkscape:label'{.pre} [|]{.pre} [str]{.pre} [=]{.pre} ['id']{.pre}]{.n}, [[is_inkscape_label:]{.pre} [bool]{.pre} [|]{.pre} [None]{.pre} [=]{.pre} [None]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[ShapeList]{.pre}[[[]{.pre}]{.p}[Wire]{.pre}[ ]{.w}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}
Parameters[:]{.colon}
  • svg_file (Union[str, Path, TextIO]) -- svg file

  • flip_y (bool, optional) -- flip objects to compensate for svg orientation. Defaults to True.

  • align (Align{.hxr-hoverxref .hxr-tooltip .reference .internal} | tuple[Align{.hxr-hoverxref .hxr-tooltip .reference .internal}, Align{.hxr-hoverxref .hxr-tooltip .reference .internal}] | None, optional) -- alignment of the SVG's viewbox, if None, the viewbox's origin will be at <cite>{=html}(0,0,0)</cite>{=html}. Defaults to Align.MIN.

  • ignore_visibility (bool, optional) -- Defaults to False.

  • label_by (str, optional) -- XML attribute to use for imported shapes' <cite>{=html}label</cite>{=html} property. Defaults to "id". Use <cite>{=html}inkscape:label</cite>{=html} to read labels set from Inkscape's "Layers and Objects" panel.

Raises[:]{.colon}

ValueError -- unexpected shape type

Returns[:]{.colon}

objects contained in svg

Return type[:]{.colon}

ShapeList{.hxr-hoverxref .hxr-tooltip .reference .internal}[Union[Wire{.hxr-hoverxref .hxr-tooltip .reference .internal}, Face{.hxr-hoverxref .hxr-tooltip .reference .internal}]]

<!-- -->
[[import_svg_as_buildline_code]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[file_name]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[PathLike]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[str]{.pre}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[bytes]{.pre}]{.n}[)]{.sig-paren} →]{.sig-return-icon} [[tuple]{.pre}[[[]{.pre}]{.p}[str]{.pre}[[,]{.pre}]{.p}[ ]{.w}[str]{.pre}[[{.pre}]{.p}]{.sig-return-typehint}]{.sig-return}

translate_to_buildline_code

Translate the contents of the given svg file into executable build123d/BuildLine code.

Parameters[:]{.colon}

file_name (Union[PathLike, str, bytes]) -- svg file name

Returns[:]{.colon}

code, builder instance name

Return type[:]{.colon}

tuple[str, str] :::

::: {#direct_api_reference.xhtml#joint-object .section}

Joint Object

Base Joint class which is used to position Solid and Compound objects relative to each other are defined below. The [Joints]{.std .std-ref}{.reference .internal} section contains the class description of the derived Joint classes.

[class]{.pre}[ ]{.w}[[Joint]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[label]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[str]{.pre}]{.n}, [[parent]{.pre}]{.n}[[:]{.pre}]{.p}[ ]{.w}[[BuildPart]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Solid]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}[ ]{.w}[[|]{.pre}]{.p}[ ]{.w}[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}]{.n}[)]{.sig-paren}

Abstract Base Joint class - used to join two components together

Parameters[:]{.colon}

parent (Union[Solid{.hxr-hoverxref .hxr-tooltip .reference .internal}, Compound{.hxr-hoverxref .hxr-tooltip .reference .internal}]) -- object that joint to bound to

Variables[:]{.colon}
  • label (str) -- user assigned label

  • parent (Shape{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- object joint is bound to

  • connected_to (Joint{.hxr-hoverxref .hxr-tooltip .reference .internal}) -- joint that is connect to this joint

[abstract]{.pre}[ ]{.w}[[connect_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}, [[**]{.pre}]{.o}[[kwargs]{.pre}]{.n}[)]{.sig-paren}

All derived classes must provide a connect_to method

[abstract]{.pre}[ ]{.w}[property]{.pre}[ ]{.w}[[location]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Location]{.pre}

Location of joint

[abstract]{.pre}[ ]{.w}[[relative_to]{.pre}]{.sig-name .descname}[(]{.sig-paren}[[*]{.pre}]{.o}[[args]{.pre}]{.n}, [[**]{.pre}]{.o}[[kwargs]{.pre}]{.n}[)]{.sig-paren} [[→]{.sig-return-icon} [[Location]{.pre}]{.sig-return-typehint}]{.sig-return}

Return relative location to another joint

[abstract]{.pre}[ ]{.w}[property]{.pre}[ ]{.w}[[symbol]{.pre}]{.sig-name .descname}[[:]{.pre}]{.p}[ ]{.w}[Compound]{.pre}{.hxr-hoverxref .hxr-tooltip .reference .internal}

A CAD object positioned in global space to illustrate the joint ::: :::

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#py-modindex.xhtml}

::: document ::: documentwrapper ::: {.body role="main"}

Python Module Index

::: modindex-jumpbox b | e | g | i | j | o | p | t :::


                                                                           
 **b**                                                                     
 [`build_enums`{.xref}](#builder_api_reference.xhtml#module-build_enums)   
 [`build_line`{.xref}](#build_line.xhtml#module-build_line)                
 [`build_part`{.xref}](#build_part.xhtml#module-build_part)                
 [`build_sketch`{.xref}](#build_sketch.xhtml#module-build_sketch)          
                                                                           
 **e**                                                                     
 [`exporters3d`{.xref}](#import_export.xhtml#module-exporters3d)           
                                                                           
 **g**                                                                     
 [`geometry`{.xref}](#direct_api_reference.xhtml#module-geometry)          
                                                                           
 **i**                                                                     
 [`importers`{.xref}](#import_export.xhtml#module-importers)               
                                                                           
 **j**                                                                     
 [`joints`{.xref}](#joints.xhtml#module-joints)                            
                                                                           
 **o**                                                                     
 [`objects_curve`{.xref}](#objects.xhtml#module-objects_curve)             
 [`objects_part`{.xref}](#objects.xhtml#module-objects_part)               
 [`objects_sketch`{.xref}](#objects.xhtml#module-objects_sketch)           
                                                                           
 **p**                                                                     
 [`pack`{.xref}](#assemblies.xhtml#module-pack)                            
                                                                           
 **t**                                                                     
 [`topology`{.xref}](#direct_api_reference.xhtml#module-topology)          

::: clearer ::: ::: :::

::: clearer ::: :::

[]{#genindex.xhtml}

::: document ::: documentwrapper ::: {.body role="main"}

Index

::: genindex-jumpbox _ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | R | S | T | U | V | W | X | Y | Z :::

_

+--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+ | - __abs__() (Vector method) | - __gt__() (ShapeList method) | | - __add__() (Shape method) | - __hash__() (Shape method) | | - (Vector method) | - __lshift__() (ShapeList method) | | - (Vertex method) | - __lt__() (ShapeList method) | | - __and__() (Shape method) | - __matmul__() (Curve method) | | - (ShapeList method) | - (Mixin1D method) | | - __copy__() (Axis method) | - __mod__() (Curve method) | | - (Color method) | - (Mixin1D method) | | - (Location method) | - __mul__() (Location method) | | - (Matrix method) | - (Plane method) | | - (Plane method) | - (Vector method) | | - (Shape method) | - __neg__() (Axis method) | | - (Vector method) | - (Location method) | | - __deepcopy__() (Axis method) | - (Plane method) | | - (Color method) | - (Vector method) | | - (Location method) | - __or__() (ShapeList method) | | - (Matrix method) | - __pow__() (Location method) | | - (Plane method) | - __rmul__() (Shape method) | | - (Shape method) | - (Vector method) | | - (Vector method) | - __rshift__() (ShapeList method) | | - __eq__() (Location method) | - __sub__() (Shape method) | | - (Plane method) | - (ShapeList method) | | - (Shape method) | - (Vector method) | | - (Vector method) | - (Vertex method) | | - __getitem__() (ShapeList method) | - __truediv__() (Vector method) | +--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+

A

+-------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+ | - A (Triangle attribute) | - angle_between() (Axis method) | | - a (Triangle attribute) | - apothem (RegularPolygon attribute) | | - ADD (Mode attribute) | - ARC (Kind attribute) | | - add() (BoundBox method) | - arc_center (Edge property) | | - (in module operations_generic) | - ArcArcTangentArc (class in objects_curve) | | - (Vector method) | - ArcArcTangentLine (class in objects_curve) | | - add_code_to_metadata() (Mesher method) | - area (Shape property) | | - add_meta_data() (Mesher method) | - AREA (SortBy attribute) | | - add_shape() (Mesher method) | - area_without_holes (Face property) | | - Airfoil (class in objects_curve) | - Arrow (class in drafting) | | - Align (class in build_enums) | - ArrowHead (class in drafting) | | - ALL (Keep attribute) | - axes_of_symmetry (Face property) | | - (Select attribute) | - Axis (class in geometry) | | | - axis_of_rotation (Face property) | +-------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+

B

+---------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+ | - B (Triangle attribute) | - bounding_box() (in module operations_generic) | | - b (Triangle attribute) | - (Shape method) | | - BallJoint (class in joints) | - Box (class in objects_part) | | - BaseLineObject (class in objects_curve) | - BSPLINE (GeomType attribute) | | - BasePartObject (class in objects_part) | - build_enums | | - BaseSketchObject (class in objects_sketch) | - module | | - Bezier (class in objects_curve) | - build_line | | - BEZIER (GeomType attribute) | - module | | - BlendCurve (class in objects_curve) | - build_part | | - BOLD (FontStyle attribute) | - module | | - BOLDITALIC (FontStyle attribute) | - build_sketch | | - BOTH (Keep attribute) | - module | | - BOTTOM (Keep attribute) | - BuildLine (class in build_line) | | - BoundBox (class in geometry) | - BuildPart (class in build_part) | | - BOUNDING_BOX (CenterOf attribute) | - BuildSketch (class in build_sketch) | +---------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+

C

+----------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------+ | - C (Triangle attribute) | - closest_points() (Shape method) | | - c (Triangle attribute) | - code (Airfoil attribute) | | - camber_line (Airfoil property) | - Color (class in geometry) | | - camber_pos (Airfoil attribute) | - color (Shape property) | | - cast() (Compound class method) | - combine() (Wire class method) | | - (Mixin1D class method) | - combined_center() (Shape static method) | | - (Mixin2D class method) | - common_plane() (Mixin1D method) | | - (Mixin3D class method) | - Compound (class in topology) | | - (Shape class method) | - compound() (Compound method) | | - (Vertex class method) | - (Shape method) | | - categorical_set() (Color class method) | - (ShapeList method) | | - CENTER (Align attribute) | - compounds() (Compound method) | | - center() (BoundBox method) | - (Shape method) | | - (Compound method) | - (ShapeList method) | | - (Face method) | - compute_mass() (Shape static method) | | - (Location method) | - Cone (class in objects_part) | | - (Mixin1D method) | - CONE (GeomType attribute) | | - (Mixin3D method) | - connect_to() (BallJoint method) | | - (ShapeList method) | - (CylindricalJoint method) | | - (Shell method) | - (Joint method) | | - (Vector method) | - (LinearJoint method) | | - (Vertex method) | - (RevoluteJoint method) | | - center_location (Face property) | - (RigidJoint method) | | - CenterArc (class in objects_curve) | - consolidate_edges() (BuildSketch method) | | - CenterOf (class in build_enums) | - contains() (Plane method) | | - chamfer() (in module operations_generic) | - copy_attributes_to() (Shape method) | | - (Mixin3D method) | - CounterBoreHole (class in objects_part) | | - chamfer_2d() (Face method) | - CounterSinkHole (class in objects_part) | | - (Wire method) | - cross() (Vector method) | | - Circle (class in objects_sketch) | - curvature_comb() (Mixin1D method) | | - CIRCLE (GeomType attribute) | - Curve (class in topology) | | - clean() (Shape method) | - cut() (Shape method) | | - close() (Edge method) | - Cylinder (class in objects_part) | | - (Wire method) | - CYLINDER (GeomType attribute) | | | - CylindricalJoint (class in joints) | +----------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------+

D

+--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+ | - default() (LocationEncoder method) | - distance_to_plane() (Vector method) | | - derivative_at() (Mixin1D method) | - distance_to_with_closest_points() (Shape method) | | - diagonal (BoundBox property) | - distances() (Shape method) | | - dimension (DimensionLine attribute) | - distribute_locations() (Edge method) | | - (ExtensionLine attribute) | - do_children_intersect() (Compound method) | | - DimensionLine (class in drafting) | - dot() (Vector method) | | - direction (Axis property) | - DoubleTangentArc (class in objects_curve) | | - DISTANCE (SortBy attribute) | - downcast_LUT (Shape attribute) | | - distance() (Shape method) | - dprism() (Mixin3D method) | | - distance_to() (Shape method) | - draft() (in module operations_part) | | | - (Solid method) | +--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+

E

+------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+ | - Edge (class in topology) | - ExtensionLine (class in drafting) | | - edge() (in module build_common) | - extrude() (Compound class method) | | - (Shape method) | - (Edge class method) | | - (ShapeList method) | - (Face class method) | | - edge_a (Triangle attribute) | - (in module operations_part) | | - edge_b (Triangle attribute) | - (Mixin1D class method) | | - edge_c (Triangle attribute) | - (Mixin2D class method) | | - edges() (Builder method) | - (Mixin3D class method) | | - (in module build_common) | - (Shape class method) | | - (Shape method) | - (Shell class method) | | - (ShapeList method) | - (Solid class method) | | - (Wire method) | - (Vertex class method) | | - Ellipse (class in objects_sketch) | - (Wire class method) | | - ELLIPSE (GeomType attribute) | - extrude_linear_with_rotation() (Solid class method) | | - EllipticalCenterArc (class in objects_curve) | - extrude_taper() (Solid class method) | | - end_point() (Mixin1D method) | - extrude_until() (Solid class method) | | - entities() (Shape method) | - EXTRUSION (GeomType attribute) | | - exporters3d | | | - module | | +------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+

F

+------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------+ | - Face (class in topology) | - filter_by_position() (ShapeList method) | | - face() (BuildLine method) | - find_intersection_points() (Edge method) | | - (in module build_common) | - (Mixin2D method) | | - (Shape method) | - (Mixin3D method) | | - (ShapeList method) | - find_outside_box_2d() (BoundBox static method) | | - faces() (Builder method) | - find_tangent() (Edge method) | | - (BuildLine method) | - finite_te (Airfoil attribute) | | - (in module build_common) | - first (ShapeList property) | | - (Shape method) | - FIRST (Until attribute) | | - (ShapeList method) | - fix() (Shape method) | | - faces_intersected_by_axis() (Shape method) | - fix_degenerate_edges() (Wire method) | | - fillet() (in module operations_generic) | - FontStyle (class in build_enums) | | - (Mixin3D method) | - from_bounding_box() (Solid class method) | | - fillet_2d() (Face method) | - from_local_coords() (Plane method) | | - (Wire method) | - from_topo_ds() (BoundBox class method) | | - FilletPolyline (class in objects_curve) | - full_round() (in module operations_sketch) | | - filter_by() (ShapeList method) | - fuse() (Shape method) | +------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------+

G

+-------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------+ | - geom_adaptor() (Edge method) | - get_mesh_properties() (Mesher method) | | - (Face method) | - get_meta_data() (Mesher method) | | - (Wire method) | - get_meta_data_by_key() (Mesher method) | | - geom_LUT_EDGE (Shape attribute) | - get_shape_list() (Shape static method) | | - geom_LUT_FACE (Shape attribute) | - get_signed_angle() (Vector method) | | - geom_type (Shape property) | - get_single_shape() (Shape static method) | | - geometry | - get_top_level_shapes() (Shape method) | | - module | - get_topods_face_normal() (Plane static method) | | - GEOMETRY (CenterOf attribute) | - get_type() (Compound method) | | - geometry (Face property) | - global_location (Shape property) | | - GeomType (class in build_enums) | - GridLocations (class in build_common) | | - get_angle() (Vector method) | - group_by() (ShapeList method) | +-------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------+

H

+----------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+ | - Helix (class in objects_curve) | - hollow() (Mixin3D method) | | - HexLocations (class in build_common) | - HYPERBOLA (GeomType attribute) | | - Hole (class in objects_part) | - HyperbolicCenterArc (class in objects_curve) | +----------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+

I

+-------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------+ | - import_brep() (in module importers) | - inverse_shape_LUT (Shape attribute) | | - import_step() (in module importers) | - is_circular_concave (Face property) | | - import_stl() (in module importers) | - is_circular_convex (Face property) | | - import_svg() (in module importers) | - is_closed (Mixin1D property) | | - import_svg_as_buildline_code() (in module importers) | - is_coaxial() (Axis method) | | - importers | - is_coplanar() (Face method) | | - module | - is_equal() (Shape method) | | - inner_wires() (Face method) | - is_forward (Mixin1D property) | | - INSIDE (Keep attribute) | - is_inside() (BoundBox method) | | - INTERSECT (Mode attribute) | - (Face method) | | - intersect() (Axis method) | - (Mixin3D method) | | - (Compound method) | - is_interior (Mixin1D property) | | - (Location method) | - is_manifold (Shape property) | | - (Mixin1D method) | - is_normal() (Axis method) | | - (Mixin2D method) | - is_null (Shape property) | | - (Mixin3D method) | - is_opposite() (Axis method) | | - (Plane method) | - is_parallel() (Axis method) | | - (Shape method) | - is_planar (Face property) | | - (Vector method) | - is_planar_face (Shape property) | | - (Vertex method) | - is_same() (Shape method) | | - IntersectingLine (class in objects_curve) | - is_skew() (Axis method) | | - INTERSECTION (Kind attribute) | - is_valid (Shape property) | | - inverse() (Location method) | - ITALIC (FontStyle attribute) | | - (Matrix method) | | +-------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------+

J

+------------------------------------------------------------------------------+-----------------------------------------------+ | - JernArc (class in objects_curve) | - joints | | - Joint (class in topology) | - module | +------------------------------------------------------------------------------+-----------------------------------------------+

K

+----------------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | - Keep (class in build_enums) | - Kind (class in build_enums) | +----------------------------------------------------------------------------------+----------------------------------------------------------------------------------+

L

+--------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ | - LAST (Select attribute) | - Location (class in geometry) | | - last (ShapeList property) | - location (CylindricalJoint property) | | - LAST (Until attribute) | - (Joint property) | | - length (Face property) | - (LinearJoint property) | | - (Mixin1D property) | - (Plane property) | | - LENGTH (SortBy attribute) | - (RevoluteJoint property) | | - length (Vector property) | - (RigidJoint property) | | - library_version (Mesher property) | - (Shape property) | | - line (BuildLine property) | - location_at() (Face method) | | - Line (class in objects_curve) | - (Mixin1D method) | | - LINE (GeomType attribute) | - (Mixin2D method) | | - LinearJoint (class in joints) | - (Shell method) | | - local_locations (GridLocations attribute) | - location_between() (Plane method) | | - (HexLocations attribute) | - location_hook() (LocationEncoder static method) | | - (Locations attribute) | - LocationEncoder (class in geometry) | | - (PolarLocations attribute) | - Locations (class in build_common) | | - locate() (Shape method) | - locations() (Mixin1D method) | | - located() (Axis method) | - loft() (in module operations_part) | | - (Shape method) | | | - location (Axis property) | | | - (BallJoint property) | | | - (BuildPart property) | | +--------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+

M

+--------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+ | - make_bezier() (Edge class method) | - margin (TechnicalDrawing attribute) | | - make_bezier_surface() (Face class method) | - MASS (CenterOf attribute) | | - make_box() (Solid class method) | - Matrix (class in geometry) | | - make_brake_formed() (in module operations_part) | - matrix_of_inertia (Shape property) | | - make_circle() (Edge class method) | - MAX (Align attribute) | | - (Wire class method) | - max (GridLocations attribute) | | - make_cone() (Solid class method) | - max_camber (Airfoil attribute) | | - make_constrained_arcs() (Edge class method) | - max_fillet() (Mixin3D method) | | - make_constrained_lines() (Edge class method) | - measure (BoundBox property) | | - make_convex_hull() (Wire class method) | - mesh() (Shape method) | | - make_cylinder() (Solid class method) | - mesh_count (Mesher property) | | - make_ellipse() (Edge class method) | - Mesher (class in mesher) | | - (Wire class method) | - MIN (Align attribute) | | - make_face() (in module operations_sketch) | - min (GridLocations attribute) | | - make_gordon_surface() (Face class method) | - mirror() (in module operations_generic) | | - make_helix() (Edge class method) | - (Location method) | | - make_holes() (Face method) | - (Shape method) | | - make_hull() (in module operations_sketch) | - Mixin1D (class in topology) | | - make_hyperbola() (Edge class method) | - Mixin2D (class in topology) | | - make_line() (Edge class method) | - Mixin3D (class in topology) | | - make_loft() (Shell class method) | - Mode (class in build_enums) | | - (Solid class method) | - model_unit (Mesher property) | | - make_mid_way() (Edge class method) | - module | | - make_parabola() (Edge class method) | - build_enums | | - make_plane() (Face class method) | - build_line | | - make_polygon() (Wire class method) | - build_part | | - make_rect() (Face class method) | - build_sketch | | - (Wire class method) | - exporters3d | | - make_sphere() (Solid class method) | - geometry | | - make_spline() (Edge class method) | - importers | | - make_spline_approx() (Edge class method) | - joints | | - make_surface() (Face class method) | - objects_curve | | - make_surface_from_array_of_points() (Face class method) | - objects_part | | - make_surface_from_curves() (Face class method) | - objects_sketch | | - make_surface_patch() (Face class method) | - pack | | - make_tangent_arc() (Edge class method) | - topology | | - make_text() (Compound class method) | - move() (Plane method) | | - make_three_point_arc() (Edge class method) | - (Shape method) | | - make_torus() (Solid class method) | - moved() (Shape method) | | - make_triad() (Compound class method) | - multiply() (Matrix method) | | - make_wedge() (Solid class method) | - (Vector method) | +--------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+

N

+-----------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ | - NEW (Select attribute) | - normal() (Mixin1D method) | | - NEXT (Until attribute) | - normal_at() (Face method) | | - NONE (Align attribute) | - normalized() (Vector method) | +-----------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+

O

+---------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------+ | - objects_curve | - order_chamfer_edges() (Wire static method) | | - module | - order_edges() (Wire method) | | - objects_part | - orientation (Location property) | | - module | - (Shape property) | | - objects_sketch | - oriented_bounding_box() (Shape method) | | - module | - origin (Plane property) | | - OFFSET (GeomType attribute) | - OTHER (GeomType attribute) | | - offset() (in module operations_generic) | - outer_wire() (Face method) | | - (Mixin2D method) | - OUTSIDE (Keep attribute) | | - (Plane method) | | | - offset_2d() (Mixin1D method) | | | - offset_3d() (Mixin3D method) | | | - order (Compound attribute) | | | - (Edge attribute) | | | - (Face attribute) | | | - (Shell attribute) | | | - (Solid attribute) | | | - (Vertex attribute) | | | - (Wire attribute) | | +---------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------+

P

+----------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+ | - pack | - Pos (class in geometry) | | - module | - position (Axis property) | | - pack() (in module pack) | - (Location property) | | - page_sizes (TechnicalDrawing attribute) | - (Shape property) | | - PARABOLA (GeomType attribute) | - position_at() (Face method) | | - ParabolicCenterArc (class in objects_curve) | - (Mixin1D method) | | - param_at() (Mixin1D method) | - positions() (Mixin1D method) | | - param_at_point() (Edge method) | - PREVIOUS (Until attribute) | | - (Wire method) | - principal_properties (Shape property) | | - parse_naca4() (Airfoil static method) | - PRIVATE (Mode attribute) | | - part (BuildPart property) | - project() (in module operations_generic) | | - Part (class in topology) | - (Mixin1D method) | | - pending_edges_as_wire (BuildPart property) | - project_faces() (Shape method) | | - perpendicular_line() (Mixin1D method) | - project_to_line() (Vector method) | | - Plane (class in geometry) | - project_to_plane() (Vector method) | | - PLANE (GeomType attribute) | - project_to_shape() (Edge method) | | - PointArcTangentArc (class in objects_curve) | - (Face method) | | - PointArcTangentLine (class in objects_curve) | - (Wire method) | | - PolarLine (class in objects_curve) | - project_to_viewport() (Compound method) | | - PolarLocations (class in build_common) | - (Mixin1D method) | | - Polygon (class in objects_sketch) | - (Mixin2D method) | | - Polyline (class in objects_curve) | - (Mixin3D method) | | | - project_workplane() (in module operations_part) | +----------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+

R

+----------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+ | - radii (Face property) | - REPLACE (Mode attribute) | | - radius (Face property) | - reverse() (Axis method) | | - (Mixin1D property) | - (Plane method) | | - (RegularPolygon attribute) | - (Vector method) | | - RADIUS (SortBy attribute) | - reversed() (Edge method) | | - radius_of_gyration() (Shape method) | - RevoluteJoint (class in joints) | | - RadiusArc (class in objects_curve) | - REVOLUTION (GeomType attribute) | | - read() (Mesher method) | - revolve() (Face class method) | | - Rectangle (class in objects_sketch) | - (in module operations_part) | | - RectangleRounded (class in objects_sketch) | - (Shell class method) | | - REGULAR (FontStyle attribute) | - (Solid class method) | | - RegularPolygon (class in objects_sketch) | - RIGHT (Transition attribute) | | - relative_to() (BallJoint method) | - RigidJoint (class in joints) | | - (CylindricalJoint method) | - Rot (in module geometry) | | - (Joint method) | - rotate() (Matrix method) | | - (LinearJoint method) | - (Shape method) | | - (RevoluteJoint method) | - (Vector method) | | - (RigidJoint method) | - rotated() (Plane method) | | - relocate() (Shape method) | - Rotation (class in geometry) | | | - ROUND (Transition attribute) | +----------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+

S

+----------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------+ | - SagittaArc (class in objects_curve) | - solids() (Builder method) | | - scale() (in module operations_generic) | - (BuildLine method) | | - (Shape method) | - (BuildSketch method) | | - section() (in module operations_part) | - (in module build_common) | | - Select (class in build_enums) | - (Shape method) | | - semi_angle (Face property) | - (ShapeList method) | | - sew_faces() (Face class method) | - sort_by() (ShapeList method) | | - Shape (class in topology) | - sort_by_distance() (ShapeList method) | | - shape_LUT (Shape attribute) | - SortBy (class in build_enums) | | - shape_properties_LUT (Shape attribute) | - Sphere (class in objects_part) | | - shape_type (Shape property) | - SPHERE (GeomType attribute) | | - ShapeList (class in topology) | - Spline (class in objects_curve) | | - Shell (class in topology) | - split() (in module operations_generic) | | - shell() (Shape method) | - (Shape method) | | - (ShapeList method) | - (Vertex method) | | - shells() (Shape method) | - split_by_perimeter() (Shape method) | | - (ShapeList method) | - start_point() (Mixin1D method) | | - shift_origin() (Plane method) | - static_moments (Shape property) | | - show_topology() (Shape method) | - stitch() (Wire method) | | - signed_distance_from_plane() (Vector method) | - sub() (Vector method) | | - size (GridLocations attribute) | - SUBTRACT (Mode attribute) | | - sketch (BuildSketch property) | - sweep() (Face class method) | | - Sketch (class in topology) | - (in module operations_generic) | | - sketch_local (BuildSketch property) | - (Shell class method) | | - SlotArc (class in objects_sketch) | - (Solid class method) | | - SlotCenterPoint (class in objects_sketch) | - sweep_multi() (Solid class method) | | - SlotCenterToCenter (class in objects_sketch) | - symbol (BallJoint property) | | - SlotOverall (class in objects_sketch) | - (CylindricalJoint property) | | - Solid (class in topology) | - (Joint property) | | - solid() (BuildLine method) | - (LinearJoint property) | | - (BuildSketch method) | - (RevoluteJoint property) | | - (in module build_common) | - (RigidJoint property) | | - (Shape method) | | | - (ShapeList method) | | +----------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------+

T

+----------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+ | - TANGENT (Kind attribute) | - to_wire() (Edge method) | | - tangent_angle_at() (Mixin1D method) | - (Wire method) | | - tangent_at() (Mixin1D method) | - TOP (Keep attribute) | | - TangentArc (class in objects_curve) | - topology | | - TechnicalDrawing (class in drafting) | - module | | - tessellate() (Shape method) | - Torus (class in objects_part) | | - Text (class in objects_sketch) | - TORUS (GeomType attribute) | | - thicken() (in module operations_part) | - trace() (in module operations_sketch) | | - (Solid class method) | - transform() (Vector method) | | - thickness (Airfoil attribute) | - transform_geometry() (Shape method) | | - ThreePointArc (class in objects_curve) | - transform_shape() (Shape method) | | - to_align_offset() (BoundBox method) | - (Vertex method) | | - to_arcs() (Face method) | - TRANSFORMED (Transition attribute) | | - to_axis() (Edge method) | - transformed() (Shape method) | | - (Location method) | - Transition (class in build_enums) | | - to_dir() (Vector method) | - translate() (Shape method) | | - to_gp_ax2() (Plane method) | - transposed_list() (Matrix method) | | - to_local_coords() (Plane method) | - Trapezoid (class in objects_sketch) | | - to_plane() (Axis method) | - Triangle (class in objects_sketch) | | - to_pnt() (Vector method) | - triangle_counts (Mesher property) | | - to_splines() (Shape method) | - trim() (Edge method) | | - to_tuple() (Location method) | - (Wire method) | | - (Vector method) | - trim_to_length() (Edge method) | | - (Vertex method) | | +----------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+

U

+------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------+ | - Until (class in build_enums) | - unwrap() (Compound method) | +------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------+

V

+-----------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+ | - Vector (class in geometry) | - volume (Compound property) | | - Vertex (class in topology) | - (Face property) | | - vertex() (in module build_common) | - (Mixin1D property) | | - (Shape method) | - (Shell property) | | - (ShapeList method) | - (Solid property) | | - (Vertex method) | - VOLUME (SortBy attribute) | | - vertex_A (Triangle attribute) | - volume (Vertex property) | | - vertex_B (Triangle attribute) | | | - vertex_C (Triangle attribute) | | | - vertex_counts (Mesher property) | | | - vertices() (Builder method) | | | - (in module build_common) | | | - (Shape method) | | | - (ShapeList method) | | | - (Vertex method) | | +-----------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+

W

+-----------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------+ | - Wedge (class in objects_part) | - without_holes() (Face method) | | - width (Face property) | - wrap() (Face method) | | - Wire (class in topology) | - wrap_faces() (Face method) | | - wire() (Face method) | - wrapped (Shape property) | | - (in module build_common) | - (Vector property) | | - (Shape method) | - write() (Mesher method) | | - (ShapeList method) | - write_stream() (Mesher method) | | - wires() (Builder method) | | | - (Curve method) | | | - (in module build_common) | | | - (Shape method) | | | - (ShapeList method) | | +-----------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------+

X

+--------------------------------------------------------------------------+----------------------------------------------------------------------------------------+ | - X (Vector property) | - x_axis (Location property) | +--------------------------------------------------------------------------+----------------------------------------------------------------------------------------+

Y

+--------------------------------------------------------------------------+----------------------------------------------------------------------------------------+ | - Y (Vector property) | - y_axis (Location property) | +--------------------------------------------------------------------------+----------------------------------------------------------------------------------------+

Z

+--------------------------------------------------------------------------+----------------------------------------------------------------------------------------+ | - Z (Vector property) | - z_axis (Location property) | +--------------------------------------------------------------------------+----------------------------------------------------------------------------------------+

::: clearer ::: ::: :::

::: clearer ::: :::