-
-
Notifications
You must be signed in to change notification settings - Fork 88
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
155 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"accessors":[{"bufferView":0,"byteOffset":0,"componentType":5126,"count":24,"max":[-7.105427357601002e-18,0.006913104915604911,0.002],"min":[-0.009436234540229034,-0.0036398224847742895,-0.002],"type":"VEC3"},{"bufferView":0,"byteOffset":288,"componentType":5126,"count":24,"max":[0.009436234540229023,0.0069131049156049158,0.002],"min":[-7.105427357601002e-18,-0.0036398224847742895,-0.002],"type":"VEC3"},{"bufferView":0,"byteOffset":576,"componentType":5126,"count":292,"max":[0.01198149810812791,0.01857053825460047,-0.0019999999999999998],"min":[-0.01198149810812791,-0.0036398224847742895,-0.002],"type":"VEC3"},{"bufferView":0,"byteOffset":4080,"componentType":5126,"count":126,"max":[-0.0019938355257575945,0.01857053825460047,0.002],"min":[-0.01198149810812791,0.006913104915604911,-0.002],"type":"VEC3"},{"bufferView":0,"byteOffset":5592,"componentType":5126,"count":292,"max":[0.01198149810812791,0.01857053825460047,0.002],"min":[-0.01198149810812791,-0.003639822484774289,0.0019999999999999998],"type":"VEC3"},{"bufferView":0,"byteOffset":9096,"componentType":5126,"count":126,"max":[0.01198149810812791,0.01857053825460047,0.002],"min":[0.001993835525757599,0.0069131049156049158,-0.002],"type":"VEC3"},{"bufferView":0,"byteOffset":10608,"componentType":5126,"count":4,"max":[4.440892098500626e-19,0.017556842459256918,0.002],"min":[-0.0019938355257575945,0.016288471659604506,-0.002],"type":"VEC3"},{"bufferView":0,"byteOffset":10656,"componentType":5126,"count":4,"max":[0.001993835525757599,0.017556842459256918,0.002],"min":[4.440892098500626e-19,0.016288471659604506,-0.002],"type":"VEC3"},{"bufferView":0,"byteOffset":10704,"componentType":5126,"count":20,"max":[0.008219755366121646,0.008500611897940111,-0.0005],"min":[0.0,3.1086244689504385e-18,-0.002],"type":"VEC3"},{"bufferView":0,"byteOffset":10944,"componentType":5126,"count":126,"max":[0.00998186091312856,0.016571142671090886,-0.0005],"min":[0.0030673252791798804,0.008500611897940111,-0.002],"type":"VEC3"},{"bufferView":0,"byteOffset":12456,"componentType":5126,"count":4,"max":[0.0030673252791798804,0.015869353274314578,-0.0005],"min":[0.0,0.013918086097615449,-0.002],"type":"VEC3"},{"bufferView":0,"byteOffset":12504,"componentType":5126,"count":4,"max":[0.0,0.015869353274314578,-0.0005],"min":[-0.0030673252791798804,0.013918086097615449,-0.002],"type":"VEC3"},{"bufferView":0,"byteOffset":12552,"componentType":5126,"count":126,"max":[-0.0030673252791798804,0.016571142671090886,-0.0005],"min":[-0.00998186091312856,0.008500611897940111,-0.002],"type":"VEC3"},{"bufferView":0,"byteOffset":14064,"componentType":5126,"count":20,"max":[0.0,0.008500611897940111,-0.0005],"min":[-0.008219755366121646,3.1086244689504385e-18,-0.002],"type":"VEC3"},{"bufferView":0,"byteOffset":14304,"componentType":5126,"count":20,"max":[0.008219755366121646,0.008500611897940111,0.002],"min":[0.0,3.1086244689504385e-18,0.0005],"type":"VEC3"},{"bufferView":0,"byteOffset":14544,"componentType":5126,"count":126,"max":[0.00998186091312856,0.016571142671090886,0.002],"min":[0.0030673252791798804,0.008500611897940111,0.0004999999999999999],"type":"VEC3"},{"bufferView":0,"byteOffset":16056,"componentType":5126,"count":4,"max":[0.0030673252791798804,0.015869353274314578,0.002],"min":[0.0,0.013918086097615449,0.0005],"type":"VEC3"},{"bufferView":0,"byteOffset":16104,"componentType":5126,"count":4,"max":[0.0,0.015869353274314578,0.002],"min":[-0.0030673252791798804,0.013918086097615449,0.0005],"type":"VEC3"},{"bufferView":0,"byteOffset":16152,"componentType":5126,"count":126,"max":[-0.0030673252791798804,0.016571142671090886,0.002],"min":[-0.00998186091312856,0.008500611897940111,0.0004999999999999999],"type":"VEC3"},{"bufferView":0,"byteOffset":17664,"componentType":5126,"count":20,"max":[0.0,0.008500611897940111,0.002],"min":[-0.008219755366121646,3.1086244689504385e-18,0.0005],"type":"VEC3"},{"bufferView":0,"byteOffset":17904,"componentType":5126,"count":691,"max":[0.00998186091312856,0.016571142671090886,-0.0005],"min":[0.0,3.1086244689504385e-18,-0.002127444137200837],"type":"VEC3"},{"bufferView":0,"byteOffset":26196,"componentType":5126,"count":691,"max":[4.1928858097199226e-19,0.016571142671090886,-0.0005],"min":[-0.00998186091312856,3.1086244689504385e-18,-0.002127444137200837],"type":"VEC3"},{"bufferView":0,"byteOffset":34488,"componentType":5126,"count":691,"max":[0.00998186091312856,0.016571142671090886,0.0021274441372008368],"min":[0.0,3.1086244689504385e-18,0.0004999999999999999],"type":"VEC3"},{"bufferView":0,"byteOffset":42780,"componentType":5126,"count":691,"max":[4.1928858097199226e-19,0.016571142671090886,0.0021274441372008368],"min":[-0.00998186091312856,3.1086244689504385e-18,0.0004999999999999999],"type":"VEC3"},{"bufferView":1,"byteOffset":0,"componentType":5126,"count":24,"type":"VEC3"},{"bufferView":1,"byteOffset":288,"componentType":5126,"count":24,"type":"VEC3"},{"bufferView":1,"byteOffset":576,"componentType":5126,"count":292,"type":"VEC3"},{"bufferView":1,"byteOffset":4080,"componentType":5126,"count":126,"type":"VEC3"},{"bufferView":1,"byteOffset":5592,"componentType":5126,"count":292,"type":"VEC3"},{"bufferView":1,"byteOffset":9096,"componentType":5126,"count":126,"type":"VEC3"},{"bufferView":1,"byteOffset":10608,"componentType":5126,"count":4,"type":"VEC3"},{"bufferView":1,"byteOffset":10656,"componentType":5126,"count":4,"type":"VEC3"},{"bufferView":1,"byteOffset":10704,"componentType":5126,"count":20,"type":"VEC3"},{"bufferView":1,"byteOffset":10944,"componentType":5126,"count":126,"type":"VEC3"},{"bufferView":1,"byteOffset":12456,"componentType":5126,"count":4,"type":"VEC3"},{"bufferView":1,"byteOffset":12504,"componentType":5126,"count":4,"type":"VEC3"},{"bufferView":1,"byteOffset":12552,"componentType":5126,"count":126,"type":"VEC3"},{"bufferView":1,"byteOffset":14064,"componentType":5126,"count":20,"type":"VEC3"},{"bufferView":1,"byteOffset":14304,"componentType":5126,"count":20,"type":"VEC3"},{"bufferView":1,"byteOffset":14544,"componentType":5126,"count":126,"type":"VEC3"},{"bufferView":1,"byteOffset":16056,"componentType":5126,"count":4,"type":"VEC3"},{"bufferView":1,"byteOffset":16104,"componentType":5126,"count":4,"type":"VEC3"},{"bufferView":1,"byteOffset":16152,"componentType":5126,"count":126,"type":"VEC3"},{"bufferView":1,"byteOffset":17664,"componentType":5126,"count":20,"type":"VEC3"},{"bufferView":1,"byteOffset":17904,"componentType":5126,"count":691,"type":"VEC3"},{"bufferView":1,"byteOffset":26196,"componentType":5126,"count":691,"type":"VEC3"},{"bufferView":1,"byteOffset":34488,"componentType":5126,"count":691,"type":"VEC3"},{"bufferView":1,"byteOffset":42780,"componentType":5126,"count":691,"type":"VEC3"},{"bufferView":2,"byteOffset":0,"componentType":5123,"count":66,"type":"SCALAR"},{"bufferView":2,"byteOffset":132,"componentType":5123,"count":66,"type":"SCALAR"},{"bufferView":2,"byteOffset":264,"componentType":5123,"count":876,"type":"SCALAR"},{"bufferView":2,"byteOffset":2016,"componentType":5123,"count":372,"type":"SCALAR"},{"bufferView":2,"byteOffset":2760,"componentType":5123,"count":876,"type":"SCALAR"},{"bufferView":2,"byteOffset":4512,"componentType":5123,"count":372,"type":"SCALAR"},{"bufferView":2,"byteOffset":5256,"componentType":5123,"count":6,"type":"SCALAR"},{"bufferView":2,"byteOffset":5268,"componentType":5123,"count":6,"type":"SCALAR"},{"bufferView":2,"byteOffset":5280,"componentType":5123,"count":54,"type":"SCALAR"},{"bufferView":2,"byteOffset":5388,"componentType":5123,"count":372,"type":"SCALAR"},{"bufferView":2,"byteOffset":6132,"componentType":5123,"count":6,"type":"SCALAR"},{"bufferView":2,"byteOffset":6144,"componentType":5123,"count":6,"type":"SCALAR"},{"bufferView":2,"byteOffset":6156,"componentType":5123,"count":372,"type":"SCALAR"},{"bufferView":2,"byteOffset":6900,"componentType":5123,"count":54,"type":"SCALAR"},{"bufferView":2,"byteOffset":7008,"componentType":5123,"count":54,"type":"SCALAR"},{"bufferView":2,"byteOffset":7116,"componentType":5123,"count":372,"type":"SCALAR"},{"bufferView":2,"byteOffset":7860,"componentType":5123,"count":6,"type":"SCALAR"},{"bufferView":2,"byteOffset":7872,"componentType":5123,"count":6,"type":"SCALAR"},{"bufferView":2,"byteOffset":7884,"componentType":5123,"count":372,"type":"SCALAR"},{"bufferView":2,"byteOffset":8628,"componentType":5123,"count":54,"type":"SCALAR"},{"bufferView":2,"byteOffset":8736,"componentType":5123,"count":3873,"type":"SCALAR"},{"bufferView":2,"byteOffset":16484,"componentType":5123,"count":3873,"type":"SCALAR"},{"bufferView":2,"byteOffset":24232,"componentType":5123,"count":3873,"type":"SCALAR"},{"bufferView":2,"byteOffset":31980,"componentType":5123,"count":3873,"type":"SCALAR"}],"asset":{"generator":"Open CASCADE Technology 7.7 [dev.opencascade.org]","version":"2.0"},"bufferViews":[{"buffer":0,"byteLength":51072,"byteOffset":0,"byteStride":12,"target":34962},{"buffer":0,"byteLength":51072,"byteOffset":51072,"byteStride":12,"target":34962},{"buffer":0,"byteLength":39728,"byteOffset":102144,"target":34963}],"buffers":[{"byteLength":141872,"uri":"heart_token.bin"}],"materials":[{"name":"mat_0","pbrMetallicRoughness":{"baseColorFactor":[0.6000000238418579,0.0,0.0,1.0]},"doubleSided":true}],"meshes":[{"name":"COMPOUND","primitives":[{"attributes":{"NORMAL":24,"POSITION":0},"indices":48,"material":0,"mode":4},{"attributes":{"NORMAL":25,"POSITION":1},"indices":49,"material":0,"mode":4},{"attributes":{"NORMAL":26,"POSITION":2},"indices":50,"material":0,"mode":4},{"attributes":{"NORMAL":27,"POSITION":3},"indices":51,"material":0,"mode":4},{"attributes":{"NORMAL":28,"POSITION":4},"indices":52,"material":0,"mode":4},{"attributes":{"NORMAL":29,"POSITION":5},"indices":53,"material":0,"mode":4},{"attributes":{"NORMAL":30,"POSITION":6},"indices":54,"material":0,"mode":4},{"attributes":{"NORMAL":31,"POSITION":7},"indices":55,"material":0,"mode":4},{"attributes":{"NORMAL":32,"POSITION":8},"indices":56,"material":0,"mode":4},{"attributes":{"NORMAL":33,"POSITION":9},"indices":57,"material":0,"mode":4},{"attributes":{"NORMAL":34,"POSITION":10},"indices":58,"material":0,"mode":4},{"attributes":{"NORMAL":35,"POSITION":11},"indices":59,"material":0,"mode":4},{"attributes":{"NORMAL":36,"POSITION":12},"indices":60,"material":0,"mode":4},{"attributes":{"NORMAL":37,"POSITION":13},"indices":61,"material":0,"mode":4},{"attributes":{"NORMAL":38,"POSITION":14},"indices":62,"material":0,"mode":4},{"attributes":{"NORMAL":39,"POSITION":15},"indices":63,"material":0,"mode":4},{"attributes":{"NORMAL":40,"POSITION":16},"indices":64,"material":0,"mode":4},{"attributes":{"NORMAL":41,"POSITION":17},"indices":65,"material":0,"mode":4},{"attributes":{"NORMAL":42,"POSITION":18},"indices":66,"material":0,"mode":4},{"attributes":{"NORMAL":43,"POSITION":19},"indices":67,"material":0,"mode":4},{"attributes":{"NORMAL":44,"POSITION":20},"indices":68,"material":0,"mode":4},{"attributes":{"NORMAL":45,"POSITION":21},"indices":69,"material":0,"mode":4},{"attributes":{"NORMAL":46,"POSITION":22},"indices":70,"material":0,"mode":4},{"attributes":{"NORMAL":47,"POSITION":23},"indices":71,"material":0,"mode":4}]}],"nodes":[{"rotation":[-0.7071067811865475,0.0,0.0,0.7071067811865475],"mesh":0,"name":"=>[0:1:1:2]"}],"scene":0,"scenes":[{"nodes":[0]}]} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
################ | ||
Surface Modeling | ||
################ | ||
|
||
Surface modeling is employed to create objects with non-planar surfaces that can't be | ||
generated using functions like :func:`~operations_part.extrude`, | ||
:func:`~operations_generic.sweep`, or :func:`~operations_part.revolve`. Since there are no | ||
specific builders designed to assist with the creation of non-planar surfaces or objects, | ||
the following should be considered a more advanced technique. | ||
|
||
As described in the `topology_` section, a BREP model consists of vertices, edges, faces, | ||
and other elements that define the boundary of an object. When creating objects with | ||
non-planar faces, it is often more convenient to explicitly create the boundary faces of | ||
the object. To illustrate this process, we will create the following game token: | ||
|
||
.. raw:: html | ||
|
||
<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;"></model-viewer> | ||
|
||
There are several methods of the :class:`~topology.Face` class that can be used to create | ||
non-planar surfaces: | ||
- :meth:`~topology.Face.make_bezier_surface`, | ||
- :meth:`~topology.Face.make_surface`, and | ||
- :meth:`~topology.Face.make_surface_from_array_of_points`. | ||
|
||
In this case, we'll use the ``make_surface`` method, providing it with the edges that define | ||
the perimeter of the surface and a central point on that surface. | ||
|
||
To create the perimeter, we'll use a ``BuildLine`` instance as follows. Since the heart is | ||
symmetric, we'll only create half of its surface here: | ||
|
||
.. code-block:: python | ||
with BuildLine() as heart_half: | ||
l1 = JernArc((0, 0), (1, 1.4), 40, -17) | ||
l2 = JernArc(l1 @ 1, l1 % 1, 4.5, 175) | ||
l3 = IntersectingLine(l2 @ 1, l2 % 1, other=Edge.make_line((0, 0), (0, 20))) | ||
l4 = ThreePointArc(l3 @ 1, Vector(0, 0, 1.5) + (l3 @ 1 + l1 @ 0) / 2, l1 @ 0) | ||
Note that ``l4`` is not in the same plane as the other lines; it defines the center line | ||
of the heart and archs up off ``Plane.XY``. | ||
|
||
.. image:: ./assets/token_heart_perimeter.png | ||
:align: center | ||
:alt: token perimeter | ||
|
||
In preparation for creating the surface, we'll define a point on the surface: | ||
|
||
.. code-block:: python | ||
surface_pnt = l2.edge().arc_center + Vector(0, 0, 1.5) | ||
We will then use this point to create a non-planar ``Face``: | ||
|
||
.. code-block:: python | ||
top_right_surface = -Face.make_surface(heart_half.wire(), [surface_pnt]).locate( | ||
Pos(Z=0.5) | ||
) | ||
.. image:: ./assets/token_heart_perimeter.png | ||
:align: center | ||
:alt: token perimeter | ||
|
||
Note that the surface was raised up by 0.5 using the locate method. Also, note that | ||
the ``-`` in front of ``Face`` simply flips the face normal so that the colored side | ||
is up, which isn't necessary but helps with viewing. | ||
|
||
Now that one half of the top of the heart has been created, the remainder of the top | ||
and bottom can be created by mirroring: | ||
|
||
.. code-block:: python | ||
top_left_surface = top_right_surface.mirror(Plane.YZ) | ||
bottom_right_surface = top_right_surface.mirror(Plane.XY) | ||
bottom_left_surface = -top_left_surface.mirror(Plane.XY) | ||
The sides of the heart are going to be created by extruding the outside of the perimeter | ||
as follows: | ||
|
||
.. code-block:: python | ||
left_wire = Wire([l3.edge(), l2.edge(), l1.edge()]) | ||
left_side = Face.extrude(left_wire, (0, 0, 1)).locate(Pos(Z=-0.5)) | ||
right_side = left_side.mirror(Plane.YZ) | ||
.. image:: ./assets/token_sides.png | ||
:align: center | ||
:alt: token sides | ||
|
||
With the top, bottom, and sides, the complete boundary of the object is defined. We can | ||
now put them together, first into a :class:`~topology.Shell` and then into a | ||
:class:`~topology.Solid`: | ||
|
||
.. code-block:: python | ||
heart = Solid( | ||
Shell( | ||
[ | ||
top_right_surface, | ||
top_left_surface, | ||
bottom_right_surface, | ||
bottom_left_surface, | ||
left_side, | ||
right_side, | ||
] | ||
) | ||
) | ||
.. image:: ./assets/token_heart_solid.png | ||
:align: center | ||
:alt: token heart solid | ||
|
||
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: | ||
|
||
.. code-block:: python | ||
with BuildPart() as heart_token: | ||
with BuildSketch() as outline: | ||
with BuildLine(): | ||
add(l1) | ||
add(l2) | ||
add(l3) | ||
Line(l3 @ 1, l1 @ 0) | ||
make_face() | ||
mirror(about=Plane.YZ) | ||
center = outline.sketch | ||
offset(amount=2, kind=Kind.INTERSECTION) | ||
add(center, mode=Mode.SUBTRACT) | ||
extrude(amount=2, both=True) | ||
add(heart) | ||
Note that an additional planar line is used to close ``l1`` and ``l3`` so a ``Face`` | ||
can be created. The :func:`~operations_generic.offset` function defines the outside of | ||
the frame as a constant distance from the heart itself. | ||
|
||
Certainly! Here is a summary of the tutorial: | ||
|
||
Summary | ||
------- | ||
|
||
In this tutorial, we've explored surface modeling techniques to create a non-planar | ||
heart-shaped object using Build123d. By utilizing methods from the :class:`~topology.Face` | ||
class, such as :meth:`~topology.Face.make_surface`, we constructed the perimeter and | ||
central point of the surface. We then assembled the complete boundary of the object | ||
by creating the top, bottom, and sides, and combined them into a :class:`~topology.Shell` | ||
and eventually a :class:`~topology.Solid`. Finally, we added a frame around the heart | ||
using the :func:`~operations_generic.offset` function to maintain a constant distance | ||
from the heart. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters