Refactored direct_api into geometry and topology

This commit is contained in:
Roger Maitland 2023-03-03 11:57:43 -05:00
parent ff941322d0
commit f0ca2c8de0
19 changed files with 356 additions and 1938 deletions

View file

@ -3,11 +3,11 @@ 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 :class:`~direct_api.Compound` object
they can be treated as a unit - i.e. :meth:`~direct_api.Shape.moved` or exported.
some type of assembly. Once parts have been assembled in a :class:`~topology.Compound` object
they can be treated as a unit - i.e. :meth:`~topology.Shape.moved` or exported.
To create an assembly in build123d, one needs to
create a tree of parts by simply assigning either a :class:`~direct_api.Compound` object's ``parent`` or
create a tree of parts by simply assigning either a :class:`~topology.Compound` object's ``parent`` or
``children`` attributes. To illustrate the process, we'll extend the
:ref:`Joint Tutorial <joint_tutorial>`.
@ -15,7 +15,7 @@ create a tree of parts by simply assigning either a :class:`~direct_api.Compound
Assigning Labels
****************
In order keep track of objects one can assign a ``label`` to all :class:`~direct_api.Shape` objects.
In order keep track of objects one can assign a ``label`` to all :class:`~topology.Shape` objects.
Here we'll assign labels to all of the components that will be part of the box
assembly:
@ -30,14 +30,14 @@ within the assembly).
Create the Assembly Compound
****************************
Creation of the assembly is done by simply creating a :class:`~direct_api.Compound` object and assigning
Creation of the assembly is done by simply creating a :class:`~topology.Compound` object and assigning
appropriate ``parent`` and ``children`` attributes as shown here:
.. literalinclude:: tutorial_joints.py
:start-after: [Create assembly]
:end-before: [Display assembly]
To display the topology of an assembly :class:`~direct_api.Compound`, the :meth:`~direct_api.Shape.show_topology`
To display the topology of an assembly :class:`~topology.Compound`, the :meth:`~topology.Shape.show_topology`
method can be used as follows:
.. literalinclude:: tutorial_joints.py
@ -54,7 +54,7 @@ which results in:
├── 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 :class:`~direct_api.Compound` one can change either ``children`` or ``parent`` attributes.
To add to an assembly :class:`~topology.Compound` one can change either ``children`` or ``parent`` attributes.
.. literalinclude:: tutorial_joints.py
:start-after: [Add to the assembly by assigning the parent attribute of an object]
@ -78,14 +78,14 @@ Shallow vs. Deep Copies of Shapes
Build123d supports the standard python ``copy`` module which provides two different types of
copy operations ``copy.copy()`` and ``copy.deepcopy()``.
Build123d's implementation of ``deepcopy()`` for the :class:`~direct_api.Shape` class (e.g. ``Solid``, ``Face``, etc.)
Build123d's implementation of ``deepcopy()`` for the :class:`~topology.Shape` class (e.g. ``Solid``, ``Face``, etc.)
does just that, creates a complete copy of the original all the way down to the CAD object.
``deepcopy`` 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()`` is
very useful as it copies all of the :class:`~direct_api.Shape` except for the actual CAD object
very useful as it copies all of the :class:`~topology.Shape` except for the actual CAD object
which instead is a reference to the original (OpenCascade refers this as a ``TShape``). As
it's a reference any changes to the original will be seen in all of the shallow copies.
@ -129,8 +129,8 @@ Shapes are Anytree Nodes
The build123d assembly constructs are built using the python
`anytree <https://anytree.readthedocs.io/en/latest/>`_ package by making the build123d
:class:`~direct_api.Shape` class a sub-class of anytree's ``NodeMixin`` class. Doing so
adds the following attributes to :class:`~direct_api.Shape`:
:class:`~topology.Shape` class a sub-class of anytree's ``NodeMixin`` class. Doing so
adds the following attributes to :class:`~topology.Shape`:
* ``parent`` - Parent Node. On set, the node is detached from any previous parent node and attached to the new node.
* ``children`` - Tuple of all child nodes.
@ -151,5 +151,5 @@ adds the following attributes to :class:`~direct_api.Shape`:
Changing the ``children`` attribute
Any iterator can be assigned to the ``children`` attribute but subsequently the children
are stored as immutable ``tuple`` objects. To add a child to an existing :class:`~direct_api.Compound`
are stored as immutable ``tuple`` objects. To add a child to an existing :class:`~topology.Compound`
object, the ``children`` attribute will have to be reassigned.

View file

@ -136,12 +136,12 @@ which generates:
.. 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 :meth:`~direct_api.SVG.translate_to_buildline_code`
method. For example:
into BuildLine source code with the :func:`~importers.import_svg_as_buildline_code`
function. For example:
.. code::
svg_code, builder_name = SVG.translate_to_buildline_code("club.svg")
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

View file

@ -126,19 +126,19 @@ Cheat Sheet
+----------+------------------------------------------------------------+---------------------------------------------------+
| Operator | Operand | Method |
+==========+============================================================+===================================================+
| > | :class:`~build_enums.SortBy`, :class:`~build_common.Axis` | :meth:`~direct_api.ShapeList.sort_by` |
| > | :class:`~build_enums.SortBy`, :class:`~build_common.Axis` | :meth:`~topology.ShapeList.sort_by` |
+----------+------------------------------------------------------------+---------------------------------------------------+
| < | :class:`~build_enums.SortBy`, :class:`~build_common.Axis` | :meth:`~direct_api.ShapeList.sort_by` |
| < | :class:`~build_enums.SortBy`, :class:`~build_common.Axis` | :meth:`~topology.ShapeList.sort_by` |
+----------+------------------------------------------------------------+---------------------------------------------------+
| >> | :class:`~build_enums.SortBy`, :class:`~build_common.Axis` | :meth:`~direct_api.ShapeList.group_by`\[-1\] |
| >> | :class:`~build_enums.SortBy`, :class:`~build_common.Axis` | :meth:`~topology.ShapeList.group_by`\[-1\] |
+----------+------------------------------------------------------------+---------------------------------------------------+
| << | :class:`~build_enums.SortBy`, :class:`~build_common.Axis` | :meth:`~direct_api.ShapeList.group_by`\[0\] |
| << | :class:`~build_enums.SortBy`, :class:`~build_common.Axis` | :meth:`~topology.ShapeList.group_by`\[0\] |
+----------+------------------------------------------------------------+---------------------------------------------------+
| \| | :class:`~direct_api.Axis`, :class:`~build_enums.GeomType` | :meth:`~direct_api.ShapeList.filter_by` |
| \| | :class:`~geometry.Axis`, :class:`~build_enums.GeomType` | :meth:`~topology.ShapeList.filter_by` |
+----------+------------------------------------------------------------+---------------------------------------------------+
| [] | | python indexing / slicing |
+----------+------------------------------------------------------------+---------------------------------------------------+
| | :class:`~direct_api.Axis` | :meth:`~direct_api.ShapeList.filter_by_position` |
| | :class:`~geometry.Axis` | :meth:`~topology.ShapeList.filter_by_position` |
+----------+------------------------------------------------------------+---------------------------------------------------+
.. card:: Edge and Wire Operators
@ -146,9 +146,9 @@ Cheat Sheet
+----------+---------------------+-----------------------------------------+---------------------------------+
| Operator | Operand | Method | Description |
+==========+=====================+=========================================+=================================+
| @ | 0.0 <= float <= 1.0 | :meth:`~direct_api.Mixin1D.position_at` | Position as Vector along object |
| @ | 0.0 <= float <= 1.0 | :meth:`~topology.Mixin1D.position_at` | Position as Vector along object |
+----------+---------------------+-----------------------------------------+---------------------------------+
| % | 0.0 <= float <= 1.0 | :meth:`~direct_api.Mixin1D.tangent_at` | Tangent as Vector along object |
| % | 0.0 <= float <= 1.0 | :meth:`~topology.Mixin1D.tangent_at` | Tangent as Vector along object |
+----------+---------------------+-----------------------------------------+---------------------------------+
.. card:: Shape Operators
@ -156,7 +156,7 @@ Cheat Sheet
+----------+---------------------+-----------------------------------------+---------------------------------------------+
| Operator | Operand | Method | Description |
+==========+=====================+=========================================+=============================================+
| == | Any | :meth:`~direct_api.Shape.is_same` | Compare CAD objects not including meta data |
| == | Any | :meth:`~topology.Shape.is_same` | Compare CAD objects not including meta data |
+----------+---------------------+-----------------------------------------+---------------------------------------------+
@ -165,13 +165,13 @@ Cheat Sheet
+----------+----------------------------+-----------------------------+
| Operator | Operand | Description |
+==========+============================+=============================+
| == | :class:`~direct_api.Plane` | Check for equality |
| == | :class:`~geometry.Plane` | Check for equality |
+----------+----------------------------+-----------------------------+
| != | :class:`~direct_api.Plane` | Check for inequality |
| != | :class:`~geometry.Plane` | Check for inequality |
+----------+----------------------------+-----------------------------+
| \- | :class:`~direct_api.Plane` | Reverse direction of normal |
| \- | :class:`~geometry.Plane` | Reverse direction of normal |
+----------+----------------------------+-----------------------------+
| \* | :class:`~direct_api.Plane` | Relocate by Location |
| \* | :class:`~geometry.Plane` | Relocate by Location |
+----------+----------------------------+-----------------------------+
.. card:: Vector Operators
@ -179,13 +179,13 @@ Cheat Sheet
+----------+------------------------------+-------------------------------------+---------------------+
| Operator | Operand | Method | Description |
+==========+==============================+=====================================+=====================+
| \+ | :class:`~direct_api.Vector` | :meth:`~direct_api.Vector.add` | add |
| \+ | :class:`~geometry.Vector` | :meth:`~geometry.Vector.add` | add |
+----------+------------------------------+-------------------------------------+---------------------+
| \- | :class:`~direct_api.Vector` | :meth:`~direct_api.Vector.sub` | subtract |
| \- | :class:`~geometry.Vector` | :meth:`~geometry.Vector.sub` | subtract |
+----------+------------------------------+-------------------------------------+---------------------+
| \* | ``float`` | :meth:`~direct_api.Vector.multiply` | multiply by scalar |
| \* | ``float`` | :meth:`~geometry.Vector.multiply` | multiply by scalar |
+----------+------------------------------+-------------------------------------+---------------------+
| \/ | ``float`` | :meth:`~direct_api.Vector.multiply` | divide by scalar |
| \/ | ``float`` | :meth:`~geometry.Vector.multiply` | divide by scalar |
+----------+------------------------------+-------------------------------------+---------------------+
.. card:: Vertex Operators
@ -193,33 +193,35 @@ Cheat Sheet
+----------+-----------------------------+-------------------------------------+
| Operator | Operand | Method |
+==========+=============================+=====================================+
| \+ | :class:`~direct_api.Vertex` | :meth:`~direct_api.Vertex.add` |
| \+ | :class:`~topology.Vertex` | :meth:`~topology.Vertex.add` |
+----------+-----------------------------+-------------------------------------+
| \- | :class:`~direct_api.Vertex` | :meth:`~direct_api.Vertex.sub` |
| \- | :class:`~topology.Vertex` | :meth:`~topology.Vertex.sub` |
+----------+-----------------------------+-------------------------------------+
.. card:: Enums
+----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| :class:`~build_enums.Align` | MIN, CENTER, MAX |
+----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| :class:`~build_enums.ApproxOption`| ARC, NONE, SPLINE |
+-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| :class:`~build_enums.CenterOf` | GEOMETRY, MASS, BOUNDING_BOX |
+----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| :class:`~build_enums.FontStyle` | REGULAR, BOLD, ITALIC |
+----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| :class:`~build_enums.GeomType` | BEZIER, BSPLINE, CIRCLE, CONE, CYLINDER, ELLIPSE, EXTRUSION, HYPERBOLA, LINE, OFFSET, OTHER, PARABOLA, PLANE, REVOLUTION, SPHERE, TORUS |
+----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| :class:`~build_enums.Keep` | TOP, BOTTOM, BOTH |
+----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| :class:`~build_enums.Kind` | ARC, INTERSECTION, TANGENT |
+----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| :class:`~build_enums.Mode` | ADD, SUBTRACT, INTERSECT, REPLACE, PRIVATE |
+----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| :class:`~build_enums.Select` | ALL, LAST |
+----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| :class:`~build_enums.SortBy` | LENGTH, RADIUS, AREA, VOLUME, DISTANCE |
+----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| :class:`~build_enums.Transition` | RIGHT, ROUND, TRANSFORMED |
+----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| :class:`~build_enums.Until` | NEXT, LAST |
+----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+

View file

@ -12,38 +12,42 @@ with the following major changes:
* New ShapeList class enabling sorting and filtering of shape objects
* Literal strings replaced with Enums
.. py:module:: direct_api
The class inheritance diagram for the direct api is shown below. Note that the ``Mixin1D``
and ``Mixin3D`` classes add supplementary functionality specific to 1D
(``Edge`` and ``Wire``) and 3D (``Compound`` and ``Solid``) objects respectively.
Note that a ``Compound`` may be contain only 1D, 2D (``Face``) or 3D objects.
.. inheritance-diagram:: direct_api
:parts: 1
*****************
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.
.. inheritance-diagram:: geometry
:parts: 1
.. py:module:: geometry
.. autoclass:: Axis
.. autoclass:: BoundBox
.. autoclass:: Color
.. autoclass:: Location
.. autoclass:: Matrix
.. autoclass:: Plane
.. autoclass:: Rotation
.. autoclass:: Vector
.. autoclass:: Vertex
***********
CAD Objects
***********
The CAD object classes defined by build123d are defined below.
*******************
Topological Objects
*******************
The topological object classes defined by build123d are defined below.
Note that the :class:`~topology.Mixin1D` and :class:`~topology.Mixin3D` classes add
supplementary functionality specific to 1D
(:class:`~topology.Edge` and :class:`~topology.Wire`) and 3D (:class:`~topology.Compound` and
`~topology.Solid`) objects respectively.
Note that a :class:`~topology.Compound` may be contain only 1D, 2D (:class:`~topology.Face`) or 3D objects.
.. inheritance-diagram:: topology
:parts: 1
.. py:module:: topology
.. autoclass:: BoundBox
.. autoclass:: Color
.. autoclass:: Compound
.. autoclass:: Edge
.. autoclass:: Face
@ -54,13 +58,37 @@ The CAD object classes defined by build123d are defined below.
.. autoclass:: Shell
.. autoclass:: Solid
.. autoclass:: Wire
.. autoclass:: Vertex
*************************
Importer/Exporter Objects
*************************
Classes specific to importing and exporting build123d objects are defined below.
Methods and functions specific to exporting and importing build123d objects are defined below.
.. py:module:: topology
:noindex:
.. automethod:: Shape.export_brep
:noindex:
.. automethod:: Shape.export_dxf
:noindex:
.. automethod:: Shape.export_stl
:noindex:
.. automethod:: Shape.export_step
:noindex:
.. automethod:: Shape.export_stl
:noindex:
.. automethod:: Shape.export_svg
:noindex:
.. py:module:: importers
.. autofunction:: import_brep
.. autofunction:: import_step
.. autofunction:: import_stl
.. autofunction:: import_svg
.. autofunction:: import_svg_as_buildline_code
.. autoclass:: SVG
*************
Joint Objects
@ -68,6 +96,9 @@ Joint Objects
Joint classes which are used to position Solid and Compound objects relative to each
other are defined below.
.. py:module:: topology
:noindex:
.. autoclass:: Joint
.. autoclass:: RigidJoint
.. autoclass:: RevoluteJoint

View file

@ -140,7 +140,7 @@ these two methods require an edge or a list of edges to operate on. To select al
edges, you could simply pass-in ``*ex9.edges()``. Note that the star (\*) unpacks
the list.
Note that :meth:`~direct_api.ShapeList.group_by` ``(Axis.Z)`` returns a list of lists of edges that is grouped by
Note that :meth:`~topolory.ShapeList.group_by` ``(Axis.Z)`` returns a list of lists of edges that is grouped by
their z-position. In this case we want to use the ``[-1]`` group which, by
convention, will be the highest z-dimension group.
@ -222,14 +222,14 @@ Counter-sink and counter-bore holes are useful for creating recessed areas for f
------------------------------------------------------------
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 :meth:`~direct_api.Mixin1D.position_at` operator.
Similarly the :meth:`~direct_api.Mixin1D.tangent_at` operator returns the line direction at a given point.
is normalized between 0 and 1 and can be accessed using the :meth:`~topolory.Mixin1D.position_at` operator.
Similarly the :meth:`~topolory.Mixin1D.tangent_at` 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.
It is also possible to use :class:`~direct_api.Vector` addition (and other vector math operations)
It is also possible to use :class:`~geometry.Vector` addition (and other vector math operations)
as seen in the ``l3`` variable.
The :class:`~build_part.Sweep` method takes any pending faces and sweeps them through the provided
@ -275,7 +275,7 @@ method shifts the plane in the normal direction (positive or negative).
17. Mirroring From Faces
---------------------------------------------------
Here we select the farthest face in the Y-direction and turn it into a :class:`~direct_api.Plane` using the
Here we select the farthest face in the Y-direction and turn it into a :class:`~geometry.Plane` using the
``Plane()`` class.
.. image:: assets/general_ex17.svg
@ -302,8 +302,8 @@ with a negative distance and Mode.SUBTRACT to cut it out from the main body.
---------------------------------------------------
Here a face is selected and passed to :class:`~build_common.Workplanes`, and two different strategies are used to select vertices.
Firstly ``vtx`` uses :meth:`~direct_api.ShapeList.group_by` and ``Axis.X`` to select a particular vertex. The second strategy uses a custom
defined Axis ``vtx2Axis`` that is pointing roughly in the direction of a vertex to select, and then :meth:`~direct_api.ShapeList.sort_by`
Firstly ``vtx`` uses :meth:`~topolory.ShapeList.group_by` and ``Axis.X`` to select a particular vertex. The second strategy uses a custom
defined Axis ``vtx2Axis`` that is pointing roughly in the direction of a vertex to select, and then :meth:`~topolory.ShapeList.sort_by`
this custom Axis. Then the X and Y positions of these vertices are selected and passed to :class:`~build_common.Locations`
as the center points for a :class:`~build_sketch.BuildSketch` which is used to place two circles that cuts through the main part.
Note that if you passed the variable ``vtx`` directly to :class:`~build_common.Locations` then the part would be offset from
@ -346,7 +346,7 @@ positioning another cylinder perpendicular and halfway along the first.
---------------------------------------------------
It is also possible to create a rotated workplane, building upon some of the concepts in an earlier
example with the :meth:`~direct_api.Plane.rotated` method.
example with the :meth:`~geometry.Plane.rotated` method.
:class:`~build_common.GridLocations` places 4 Circles on 4 points on this rotated workplane, and then the Circles are
extruded in the "both" (positive and negative) normal direction.

View file

@ -46,13 +46,13 @@ The following tables describes the build123d selectors:
The operand types are: Axis, SortBy, and GeomType. An Axis is a base object with an origin and a
direction with several predefined values such as ``Axis.X``, ``Axis.Y``, and ``Axis.Z``; however,
any Axis could be used as an operand (e.g. ``Axis((1,2,3),(0.5,0,-0.5))`` is valid) - see
:class:`~direct_api::Axis` for a complete description. SortBy and GeomType are python
:class:`~geometry.Axis` for a complete description. SortBy and GeomType are python
Enum class described here:
:class:`~build_enums::GeomType`
:class:`~build_enums.GeomType`
BEZIER, BSPLINE, CIRCLE, CONE, CYLINDER, ELLIPSE, EXTRUSION, HYPERBOLA, LINE, OFFSET, OTHER,
PARABOLA, PLANE, REVOLUTION, SPHERE, TORUS
:class:`~build_enums::SortBy`
:class:`~build_enums.SortBy`
LENGTH, RADIUS, AREA, VOLUME, DISTANCE
@ -60,9 +60,8 @@ 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 `list`, a `ShapeList` with
custom filtering and sorting methods and operations as follows. The full ShapeList API is can be
found in :class:`~direct_api::ShapeList`.
they are building. All of these methods return objects of a subclass of `list`, a :class:`~geometry.ShapeList` with
custom filtering and sorting methods and operations as follows.
Custom Sorting and Filtering
----------------------------

View file

@ -4,32 +4,32 @@
Joint Tutorial
##############
This tutorial provides a step by step guide in using :class:`~direct_api.Joint`'s as we create
This tutorial provides a step by step guide in using :class:`~topology.Joint`'s as we create
a box with a hinged lid. They allow 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. :class:`~direct_api.Joint`'s always work
in pairs - a :class:`~direct_api.Joint` can only be connected to another :class:`~direct_api.Joint` as follows:
that is found with the equivalent physical joints. :class:`~topology.Joint`'s always work
in pairs - a :class:`~topology.Joint` can only be connected to another :class:`~topology.Joint` as follows:
+---------------------------------------+---------------------------------------------------------------------+--------------------+
| :class:`~direct_api.Joint` | connect_to | Example |
| :class:`~topology.Joint` | connect_to | Example |
+=======================================+=====================================================================+====================+
| :class:`~direct_api.BallJoint` | :class:`~direct_api.RigidJoint` | Gimbal |
| :class:`~topology.BallJoint` | :class:`~topology.RigidJoint` | Gimbal |
+---------------------------------------+---------------------------------------------------------------------+--------------------+
| :class:`~direct_api.CylindricalJoint` | :class:`~direct_api.RigidJoint` | Screw |
| :class:`~topology.CylindricalJoint` | :class:`~topology.RigidJoint` | Screw |
+---------------------------------------+---------------------------------------------------------------------+--------------------+
| :class:`~direct_api.LinearJoint` | :class:`~direct_api.RigidJoint`, :class:`~direct_api.RevoluteJoint` | Slider or Pin Slot |
| :class:`~topology.LinearJoint` | :class:`~topology.RigidJoint`, :class:`~topology.RevoluteJoint` | Slider or Pin Slot |
+---------------------------------------+---------------------------------------------------------------------+--------------------+
| :class:`~direct_api.RevoluteJoint` | :class:`~direct_api.RigidJoint` | Hinge |
| :class:`~topology.RevoluteJoint` | :class:`~topology.RigidJoint` | Hinge |
+---------------------------------------+---------------------------------------------------------------------+--------------------+
| :class:`~direct_api.RigidJoint` | :class:`~direct_api.RigidJoint` | Fixed |
| :class:`~topology.RigidJoint` | :class:`~topology.RigidJoint` | Fixed |
+---------------------------------------+---------------------------------------------------------------------+--------------------+
Objects may have many joints bound to them each with an identifying label. All :class:`~direct_api.Joint`
Objects may have many joints bound to them each with an identifying label. All :class:`~topology.Joint`
objects have a ``symbol`` property that can be displayed to help visualize
their position and orientation.
In this tutorial, a box with a hinged lid will be created to illustrate the
use of three different :class:`~direct_api.Joint` types.
use of three different :class:`~topology.Joint` types.
.. image:: assets/tutorial_joint.svg
:align: center
@ -75,14 +75,14 @@ Step 3: Add Joints to the Hinge Leaf
The hinge includes five joints:
* A :class:`~direct_api.RigidJoint` to attach the leaf
* A :class:`~direct_api.RigidJoint` or :class:`~direct_api.RevoluteJoint` as the hinge Axis
* Three :class:`~direct_api.CylindricalJoint`'s for the countersunk screws
* A :class:`~topology.RigidJoint` to attach the leaf
* A :class:`~topology.RigidJoint` or :class:`~topology.RevoluteJoint` as the hinge Axis
* Three :class:`~topology.CylindricalJoint`'s for the countersunk screws
Step 3a: Leaf Joint
-------------------
The first joint to add is a :class:`~direct_api.RigidJoint` that is used to fix the hinge leaf to the box
The first joint to add is a :class:`~topology.RigidJoint` that is used to fix the hinge leaf to the box
or lid.
.. literalinclude:: tutorial_joints.py
@ -92,13 +92,13 @@ or lid.
Each joint has a label which identifies it - here the string "leaf" is used, the ``to_part``
binds the joint to ``leaf_builder.part`` (i.e. the part being built), and ``joint_location``
is specified as middle of the leaf along the edge of the pin. Note that
:class:`~direct_api.Location` objects describe both a position and orientation which is
:class:`~topology.Location` 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).
Step 3b: Hinge Joint
--------------------
The second joint to add is either a :class:`~direct_api.RigidJoint` (on the inner leaf) or a :class:`~direct_api.RevoluteJoint`
The second joint to add is either a :class:`~topology.RigidJoint` (on the inner leaf) or a :class:`~topology.RevoluteJoint`
(on the outer leaf) that describes the hinge axis.
.. literalinclude:: tutorial_joints.py
@ -106,9 +106,9 @@ The second joint to add is either a :class:`~direct_api.RigidJoint` (on the inne
:end-before: [Fastener holes]
:emphasize-lines: 10-25
The inner leaf just pivots around the outer leaf and therefore the simple :class:`~direct_api.RigidJoint` is
The inner leaf just pivots around the outer leaf and therefore the simple :class:`~topology.RigidJoint` is
used to define the Location of this pivot. The outer leaf contains the more complex
:class:`~direct_api.RevoluteJoint` which defines an axis of rotation and angular limits to that rotation (90
:class:`~topology.RevoluteJoint` 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.
@ -116,14 +116,14 @@ than 360°. Other types of joints have linear ranges as well as angular ranges.
Step 3c: Fastener Joints
------------------------
The third set of joints to add are :class:`~direct_api.CylindricalJoint`'s that describe how the countersunk
The third set of joints to add are :class:`~topology.CylindricalJoint`'s that describe how the countersunk
screws used to attach the leaves move.
.. literalinclude:: tutorial_joints.py
:start-after: [Fastener holes]
:end-before: [End Fastener holes]
Much like the :class:`~direct_api.RevoluteJoint`, a :class:`~direct_api.CylindricalJoint` has an Axis of motion but this type
Much like the :class:`~topology.RevoluteJoint`, a :class:`~topology.CylindricalJoint` 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
@ -166,17 +166,17 @@ the joint used to attach the outer hinge leaf.
:end-before: [Demonstrate that objects with Joints can be moved and the joints follow]
:emphasize-lines: 13-17
Since the hinge will be fixed to the box another :class:`~direct_api.RigidJoint` is used mark where the hinge
will go. Note that the orientation of this :class:`~direct_api.Joint` will control how the hinge leaf is
Since the hinge will be fixed to the box another :class:`~topology.RigidJoint` is used mark where the hinge
will go. Note that the orientation of this :class:`~topology.Joint` will control how the hinge leaf is
attached and is independent of the orientation of the hinge as it was constructed.
Step 4a: Relocate Box
---------------------
Note that the position and orientation of the box's joints are given as a global :class:`~direct_api.Location`
when created but will be translated to a relative :class:`~direct_api.Location` internally to allow the :class:`~direct_api.Joint`
Note that the position and orientation of the box's joints are given as a global :class:`~topology.Location`
when created but will be translated to a relative :class:`~topology.Location` internally to allow the :class:`~topology.Joint`
to "move" with the parent object. This allows users the freedom to relocate objects without
having to recreate or modify :class:`~direct_api.Joint`'s. Here is the box is moved upwards to show this
having to recreate or modify :class:`~topology.Joint`'s. Here is the box is moved upwards to show this
property.
.. literalinclude:: tutorial_joints.py
@ -187,7 +187,7 @@ property.
Step 5: Create the Lid
**********************
Much like the box, the lid is created in a :class:`~build_part.BuildPart` context and is assigned a :class:`~direct_api.RigidJoint`.
Much like the box, the lid is created in a :class:`~build_part.BuildPart` context and is assigned a :class:`~topology.RigidJoint`.
.. image:: assets/tutorial_joint_lid.svg
@ -204,7 +204,7 @@ joints are connected together the parts will move into the correct position.
Step 6: Import a Screw and bind a Joint to it
*********************************************
:class:`~direct_api.Joint`'s can be bound to simple objects the a :class:`~direct_api.Compound` imported - in this case a
:class:`~topology.Joint`'s can be bound to simple objects the a :class:`~topology.Compound` imported - in this case a
screw.
.. image:: assets/tutorial_joint_m6_screw.svg
@ -213,8 +213,8 @@ screw.
:start-after: [A screw to attach the hinge to the box]
:end-before: [End of screw creation]
Here a simple :class:`~direct_api.RigidJoint` is bound to the top of the screw head such that it can be
connected to the hinge's :class:`~direct_api.CylindricalJoint`.
Here a simple :class:`~topology.RigidJoint` is bound to the top of the screw head such that it can be
connected to the hinge's :class:`~topology.CylindricalJoint`.
***********************************
Step 7: Connect the Joints together
@ -248,7 +248,7 @@ box.
:start-after: [Connect Hinge Leaves]
:end-before: [Connect Hinge Leaves]
As ``hinge_outer.joints["hinge_axis"]`` is a :class:`~direct_api.RevoluteJoint` there is an ``angle``
As ``hinge_outer.joints["hinge_axis"]`` is a :class:`~topology.RevoluteJoint` there is an ``angle``
parameter that can be set (angles default to the minimum range value) - here to 120°.
This is what that looks like:
@ -291,9 +291,9 @@ Try changing these position and angle values to "tighten" the screw.
Conclusion
**********
Use a :class:`~direct_api.Joint` to locate two objects relative to each other with some degree of motion.
Use a :class:`~topology.Joint` to locate two objects relative to each other with some degree of motion.
Keep in mind that when using the ``connect_to`` method, ``self`` is always fixed
and ``other`` will move to the appropriate :class:`~direct_api.Location`.
and ``other`` will move to the appropriate :class:`~topology.Location`.
.. note::

View file

@ -53,7 +53,7 @@ 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`` instance was assigned the identifier ``example`` so
``example.faces()`` will extract all of the Faces from that part into a custom
python ``list`` - a ``ShapeList`` (see :class:`~direct_api.ShapeList` for a full description).
python ``list`` - a ``ShapeList`` (see :class:`~topology.ShapeList` for a full description).
Step 3b: Get top Face
---------------------

View file

@ -65,7 +65,7 @@ class Club(BaseSketchObject):
Scale(by=height / club.sketch.bounding_box().size.Y)
# Pass the shape to the BaseSketchObject class to create a new Club object
super().__init__(face=club.sketch, rotation=rotation, align=align, mode=mode)
super().__init__(obj=club.sketch, rotation=rotation, align=align, mode=mode)
class Spade(BaseSketchObject):
@ -85,7 +85,7 @@ class Spade(BaseSketchObject):
Mirror(about=Plane.YZ)
MakeFace()
Scale(by=height / spade.sketch.bounding_box().size.Y)
super().__init__(face=spade.sketch, rotation=rotation, align=align, mode=mode)
super().__init__(obj=spade.sketch, rotation=rotation, align=align, mode=mode)
class Heart(BaseSketchObject):
@ -106,7 +106,7 @@ class Heart(BaseSketchObject):
Mirror(about=Plane.YZ)
MakeFace()
Scale(by=height / heart.sketch.bounding_box().size.Y)
super().__init__(face=heart.sketch, rotation=rotation, align=align, mode=mode)
super().__init__(obj=heart.sketch, rotation=rotation, align=align, mode=mode)
class Diamond(BaseSketchObject):
@ -124,7 +124,7 @@ class Diamond(BaseSketchObject):
Mirror(about=Plane.YZ)
MakeFace()
Scale(by=height / diamond.sketch.bounding_box().size.Y)
super().__init__(face=diamond.sketch, rotation=rotation, align=align, mode=mode)
super().__init__(obj=diamond.sketch, rotation=rotation, align=align, mode=mode)
# The inside of the box fits 2.5x3.5" playing card deck with a small gap

View file

@ -4,7 +4,8 @@ from build123d.build_line import *
from build123d.build_sketch import *
from build123d.build_part import *
from build123d.build_generic import *
from build123d.direct_api import *
from build123d.geometry import *
from build123d.topology import *
from build123d.build_enums import ApproxOption
from build123d.importers import *

View file

@ -39,21 +39,24 @@ from build123d.build_enums import (
Mode,
)
from build123d.direct_api import (
from build123d.geometry import (
Axis,
Edge,
Wire,
Location,
Plane,
Vector,
VectorLike,
Location,
Face,
Solid,
Compound,
Shape,
Vertex,
Plane,
ShapeList,
)
from build123d.topology import (
Compound,
Edge,
Face,
Shape,
ShapeList,
Solid,
Vertex,
Wire,
)
# Create a build123d logger to distinguish these logs from application logs.
# If the user doesn't configure logging, all build123d logs will be discarded.

View file

@ -30,22 +30,27 @@ import copy
import logging
from typing import Union
from build123d.build_enums import Mode, Kind, Keep
from build123d.direct_api import (
Edge,
Wire,
Vector,
Compound,
from build123d.geometry import (
Axis,
Location,
Matrix,
Plane,
Rotation,
RotationLike,
Vector,
)
from build123d.topology import (
Compound,
Edge,
Face,
Plane,
Matrix,
Rotation,
RotationLike,
Shape,
Vertex,
Solid,
Axis,
Vertex,
Wire,
)
from build123d.build_line import BuildLine
from build123d.build_sketch import BuildSketch
from build123d.build_part import BuildPart

View file

@ -30,18 +30,21 @@ import inspect
from math import sin, cos, radians, sqrt, copysign
from typing import Union, Iterable
from build123d.build_enums import AngularDirection, LengthMode, Mode, Select
from build123d.direct_api import (
from build123d.geometry import (
Axis,
Edge,
Wire,
Vector,
Compound,
Location,
VectorLike,
ShapeList,
Face,
Plane,
Vector,
VectorLike,
)
from build123d.topology import (
Compound,
Edge,
Face,
ShapeList,
Wire,
)
from build123d.build_common import Builder, WorkplaneList, logger

View file

@ -32,20 +32,22 @@ import inspect
from math import radians, tan
from typing import Union, Iterable
from build123d.build_enums import Mode, Until, Transition, Align
from build123d.direct_api import (
Edge,
Wire,
Vector,
Solid,
Compound,
Location,
VectorLike,
Face,
Plane,
from build123d.geometry import (
Axis,
Location,
Plane,
Rotation,
RotationLike,
Vector,
VectorLike,
)
from build123d.topology import (
Compound,
Edge,
Face,
Shell,
Solid,
Wire,
)
from build123d.build_common import (

View file

@ -38,18 +38,21 @@ import inspect
from math import pi, sin, cos, tan, radians
from typing import Union
from build123d.build_enums import Align, FontStyle, Mode
from build123d.direct_api import (
Edge,
Wire,
Vector,
Compound,
Location,
VectorLike,
ShapeList,
Face,
Plane,
from build123d.geometry import (
Axis,
Location,
Plane,
Vector,
VectorLike,
)
from build123d.topology import (
Compound,
Edge,
Face,
ShapeList,
Wire,
)
from build123d.build_common import (
Builder,
logger,

View file

@ -38,17 +38,20 @@ from OCP.STEPControl import STEPControl_Reader
import OCP.IFSelect
from OCP.RWStl import RWStl
from build123d.direct_api import Shape, Face, Compound, Edge, ShapeList
from build123d.topology import Compound, Edge, Face, Shape, ShapeList
def import_brep(file_name: str) -> Shape:
"""Import shape from a BREP file
Args:
f: Union[str, BytesIO]:
file_name (str): brep file
Raises:
ValueError: file not found
Returns:
Shape: build123d object
"""
shape = TopoDS_Shape()
builder = BRep_Builder()

View file

@ -30,7 +30,7 @@ from IPython.display import Javascript
from vtkmodules.vtkIOXML import vtkXMLPolyDataWriter
from build123d.direct_api import Shape
from build123d.topology import Shape
DEFAULT_COLOR = [1, 0.8, 0, 1]

File diff suppressed because it is too large Load diff

View file

@ -25,7 +25,7 @@ from build123d import *
from build123d import Shape, Matrix, BoundBox
# Direct API Functions
from build123d.direct_api import (
from build123d.topology import (
downcast,
edges_to_wires,
fix,
@ -290,11 +290,11 @@ class TestBoundBox(unittest.TestCase):
def test_combined_center_of_boundbox(self):
pass
def test_to_solid(self):
bbox = Solid.make_sphere(1).bounding_box()
self.assertTupleAlmostEquals(bbox.min.to_tuple(), (-1, -1, -1), 5)
self.assertTupleAlmostEquals(bbox.max.to_tuple(), (1, 1, 1), 5)
self.assertAlmostEqual(bbox.to_solid().volume, 2**3, 5)
# def test_to_solid(self):
# bbox = Solid.make_sphere(1).bounding_box()
# self.assertTupleAlmostEquals(bbox.min.to_tuple(), (-1, -1, -1), 5)
# self.assertTupleAlmostEquals(bbox.max.to_tuple(), (1, 1, 1), 5)
# self.assertAlmostEqual(bbox.to_solid().volume, 2**3, 5)
class TestCadObjects(unittest.TestCase):