From 5f93a2dc0cbab470ee57c794a47089f15f48c19a Mon Sep 17 00:00:00 2001 From: gumyr Date: Sat, 20 Jan 2024 13:54:30 -0500 Subject: [PATCH] Added to FAQ --- docs/assets/sketch_on_custom_plane.png | Bin 0 -> 26140 bytes docs/assets/vertical_sketch.png | Bin 0 -> 16968 bytes docs/build_sketch.rst | 2 + docs/tips.rst | 81 ++++++++++++++++++++++++- docs/tttt.rst | 4 +- src/build123d/operations_generic.py | 43 ++++++------- src/build123d/topology.py | 6 +- 7 files changed, 108 insertions(+), 28 deletions(-) create mode 100644 docs/assets/sketch_on_custom_plane.png create mode 100644 docs/assets/vertical_sketch.png diff --git a/docs/assets/sketch_on_custom_plane.png b/docs/assets/sketch_on_custom_plane.png new file mode 100644 index 0000000000000000000000000000000000000000..447ddac00749ede683d2fa4d52536777c0990fe9 GIT binary patch literal 26140 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 Wsr^{#`PyF~J3L+eT-G@yGywo5JYd)W literal 0 HcmV?d00001 diff --git a/docs/assets/vertical_sketch.png b/docs/assets/vertical_sketch.png new file mode 100644 index 0000000000000000000000000000000000000000..e64aae0b162611e95786731911286ed631e687cf GIT binary patch literal 16968 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 N44$rjF6*2UngBIQ;35D3 literal 0 HcmV?d00001 diff --git a/docs/build_sketch.rst b/docs/build_sketch.rst index 00c0324..803dcb7 100644 --- a/docs/build_sketch.rst +++ b/docs/build_sketch.rst @@ -36,6 +36,8 @@ and ``PRIVATE``). .. image:: assets/circle_with_hole.svg :align: center +.. _sketching_on_other_planes: + ************************* Sketching on other Planes ************************* diff --git a/docs/tips.rst b/docs/tips.rst index 28430e6..8cbe506 100644 --- a/docs/tips.rst +++ b/docs/tips.rst @@ -192,4 +192,83 @@ Writing build123d often involves live coding in a REPL or typing in editors with 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. \ No newline at end of file +available in the global namespace. + +*************************************** +Why doesn't BuildSketch(Plane.XZ) work? +*************************************** + +When creating a sketch not on the default ``Plane.XY`` users may expect that they are drawing directly +on the workplane / coordinate system provided. For example: + +.. code-block:: python + + 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) + +.. image:: assets/vertical_sketch.png + +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`` independent of where they will be +ultimately placed; therefore, the ``sort_by(Axis.Z)`` is sorting two points that have a Z value of +zero as they are located on ``Plane.XY`` and effectively return a random point. + +Why does ``BuildSketch`` 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`` +of a 3D part but is simulated here by rotating a ``Plane``): + +.. code-block:: python + + 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) + +.. image:: assets/sketch_on_custom_plane.png + +Here one can see both ``sketch_local`` (with the light fill on ``Plane.XY``) and the ``sketch`` +(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 what could happen if the 3D part changed. For an +example of sketching on a 3D part, see :ref:`sketching_on_other_planes`. + +************************************************************************* +Why is BuildLine not working as expected within the scope of BuildSketch? +************************************************************************* + +As described above, all sketching is done on a local ``Plane.XY``; however, the following +is a common issue: + +.. code-block:: python + + with BuildSketch() as sketch: + with BuildLine(Plane.XZ): + Polyline(...) + make_face() + +Here ``BuildLine`` is within the scope of ``BuildSketch``; therefore, all of the +drawing should be done on ``Plane.XY``; however, the user has specified ``Plane.XZ`` +when creating the ``BuildLine`` instance. Although this isn't absolutely incorrect +it's almost certainly not what the user intended. Here the face created by ``make_face`` will +be reoriented to ``Plane.XY`` as all sketching must be done on that plane. This reorienting +of objects to ``Plane.XY`` allows a user to ``add`` 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`` object will be +reoriented, all ``BuildLine`` instances within the scope of ``BuildSketch`` should be done +on the default ``Plane.XY``. + +*************************************************************** +Don't Builders inherent workplane/coordinate sytems when nested +*************************************************************** + +Some users expect that nested Builders will inherent 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``. 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. Inherenting coordinate systems isn't necessarily +incorrect, it was considered for build123d but ultimately the simple static approach was taken. \ No newline at end of file diff --git a/docs/tttt.rst b/docs/tttt.rst index 6a542b4..32c7e68 100644 --- a/docs/tttt.rst +++ b/docs/tttt.rst @@ -1,6 +1,6 @@ -####################### +############################# Too Tall Toby (TTT) Tutorials -####################### +############################# .. image:: assets/ttt.png :align: center diff --git a/src/build123d/operations_generic.py b/src/build123d/operations_generic.py index 8e3637a..5d00e21 100644 --- a/src/build123d/operations_generic.py +++ b/src/build123d/operations_generic.py @@ -532,32 +532,29 @@ def offset( ) -> Union[Curve, Sketch, Part, Compound]: """Generic Operation: offset - Applies to 1, 2, and 3 dimensional objects. + 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. + 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. - Args: - objects (Union[Edge, Face, Solid, Compound] or Iterable of): objects to offset - amount (float): positive values external, negative internal - openings (list[Face], optional), sequence of faces to open in part. - Defaults to None. - kind (Kind, 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. - <<<<<<< Updated upstream - min_edge_length (float, optional): repair degenerate edges generated by offset - by eliminating edges of minimum length in offset wire. Defaults to None. - ======= - >>>>>>> Stashed changes - mode (Mode, optional): combination mode. Defaults to Mode.REPLACE. + Args: + objects (Union[Edge, Face, Solid, Compound] or Iterable of): objects to offset + amount (float): positive values external, negative internal + openings (list[Face], optional), sequence of faces to open in part. + Defaults to None. + kind (Kind, 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, optional): combination mode. Defaults to Mode.REPLACE. - Raises: - ValueError: missing objects - ValueError: Invalid object type + Raises: + ValueError: missing objects + ValueError: Invalid object type """ context: Builder = Builder._get_context("offset") diff --git a/src/build123d/topology.py b/src/build123d/topology.py index 0044688..736f01e 100644 --- a/src/build123d/topology.py +++ b/src/build123d/topology.py @@ -5603,7 +5603,9 @@ class Face(Shape): chamfer_builder = BRepFilletAPI_MakeFillet2d(self.wrapped) vertex_edge_map = TopTools_IndexedDataMapOfShapeListOfShape() - TopExp.MapShapesAndAncestors_s(self.wrapped, ta.TopAbs_VERTEX, ta.TopAbs_EDGE, vertex_edge_map) + TopExp.MapShapesAndAncestors_s( + self.wrapped, ta.TopAbs_VERTEX, ta.TopAbs_EDGE, vertex_edge_map + ) for v in vertices: edges = vertex_edge_map.FindFromKey(v.wrapped) @@ -5623,7 +5625,7 @@ class Face(Shape): edge2 = [x for x in edges if x != reference_edge][0] else: edge1, edge2 = edges - + chamfer_builder.AddChamfer( TopoDS.Edge_s(edge1.wrapped), TopoDS.Edge_s(edge2.wrapped),