688 lines
22 KiB
ReStructuredText
688 lines
22 KiB
ReStructuredText
.. _examples:
|
|
|
|
*********************************
|
|
CadQuery Examples
|
|
*********************************
|
|
|
|
.. automodule:: cadquery
|
|
|
|
|
|
The examples on this page can help you learn how to build objects with CadQuery.
|
|
|
|
They are organized from simple to complex, so working through them in order is the best way to absorb them.
|
|
|
|
Each example lists the api elements used in the example for easy reference.
|
|
Items introduced in the example are marked with a **!**
|
|
|
|
.. note::
|
|
|
|
You may want to work through these examples by pasting the text into a scratchpad on the live website.
|
|
If you do, make sure to take these steps so that they work:
|
|
|
|
1. paste the content into the build() method, properly intented, and
|
|
2. add the line 'return result' at the end. The samples below are autogenerated, but they use a different
|
|
syntax than the models on the website need to be.
|
|
|
|
.. warning::
|
|
|
|
* You have to have an svg capable browser to view these!
|
|
* For brevity, these examples do not include the MetaData and Header sections required for a
|
|
fully functional parametric part. See the :ref:`quickstart` for a guide that includes those portions
|
|
|
|
.. contents:: List of Examples
|
|
:backlinks: entry
|
|
|
|
|
|
Simple Rectangular Plate
|
|
------------------------
|
|
|
|
Just about the simplest possible example, a rectangular box
|
|
|
|
.. cq_plot::
|
|
|
|
result = Workplane("front").box(2.0,2.0,0.5)
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane` **!**
|
|
* :py:meth:`Workplane.box` **!**
|
|
|
|
Plate with Hole
|
|
------------------------
|
|
|
|
A rectangular box, but with a hole added.
|
|
|
|
"\>Z" selects the top most face of the resulting box. The hole is located in the center because the default origin
|
|
of a working plane is at the center of the face. The default hole depth is through the entire part.
|
|
|
|
.. cq_plot::
|
|
|
|
result = Workplane("front").box(2.0,2.0,0.5).faces(">Z").hole(0.5)
|
|
|
|
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.hole` **!**
|
|
* :py:meth:`Workplane.box`
|
|
* :py:meth:`Workplane.box`
|
|
|
|
An extruded prismatic solid
|
|
-------------------------------
|
|
|
|
Build a prismatic solid using extrusion. After a drawing operation, the center of the previous object
|
|
is placed on the stack, and is the reference for the next operation. So in this case, the rect() is drawn
|
|
centered on the previously draw circle.
|
|
|
|
By default, rectangles and circles are centered around the previous working point.
|
|
|
|
.. cq_plot::
|
|
|
|
result = Workplane("front").circle(2.0).rect(0.5,0.75).extrude(0.5)
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.circle` **!**
|
|
* :py:meth:`Workplane.rect` **!**
|
|
* :py:meth:`Workplane.extrude` **!**
|
|
* :py:meth:`Workplane`
|
|
|
|
Building Profiles using lines and arcs
|
|
--------------------------------------
|
|
|
|
Sometimes you need to build complex profiles using lines and arcs. This example builds a prismatic
|
|
solid from 2-d operations.
|
|
|
|
2-d operations maintain a current point, which is initially at the origin. Use close() to finish a
|
|
closed curve.
|
|
|
|
|
|
.. cq_plot::
|
|
|
|
result = Workplane("front").lineTo(2.0,0).lineTo(2.0,1.0).threePointArc((1.0,1.5),(0.0,1.0))\
|
|
.close().extrude(0.25)
|
|
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.threePointArc` **!**
|
|
* :py:meth:`Workplane.lineTo` **!**
|
|
* :py:meth:`Workplane.extrude`
|
|
* :py:meth:`Workplane`
|
|
|
|
Moving The Current working point
|
|
---------------------------------
|
|
|
|
In this example, a closed profile is required, with some interior features as well.
|
|
|
|
This example also demonstrates using multiple lines of code instead of longer chained commands,
|
|
though of course in this case it was possible to do it in one long line as well.
|
|
|
|
A new work plane center can be established at any point.
|
|
|
|
.. cq_plot::
|
|
|
|
result = Workplane("front").circle(3.0) #current point is the center of the circle, at (0,0)
|
|
result = result.center(1.5,0.0).rect(0.5,0.5) # new work center is (1.5,0.0)
|
|
|
|
result = result.center(-1.5,1.5).circle(0.25) # new work center is ( 0.0,1.5).
|
|
#the new center is specified relative to the previous center, not global coordinates!
|
|
|
|
result = result.extrude(0.25)
|
|
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.center` **!**
|
|
* :py:meth:`Workplane`
|
|
* :py:meth:`Workplane.circle`
|
|
* :py:meth:`Workplane.rect`
|
|
* :py:meth:`Workplane.extrude`
|
|
|
|
Using Point Lists
|
|
---------------------------
|
|
|
|
Sometimes you need to create a number of features at various locations, and using :py:meth:`Workplane.center`
|
|
is too cumbersome.
|
|
|
|
You can use a list of points to construct multiple objects at once. Most construction methods,
|
|
like :py:meth:`Workplane.circle` and :py:meth:`Workplane.rect`, will operate on multiple points if they are on the stack
|
|
|
|
.. cq_plot::
|
|
|
|
r = Workplane("front").circle(2.0) # make base
|
|
r = r.pushPoints( [ (1.5,0),(0,1.5),(-1.5,0),(0,-1.5) ] ) # now four points are on the stack
|
|
r = r.circle( 0.25 ) # circle will operate on all four points
|
|
result = r.extrude(0.125 ) # make prism
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.points` **!**
|
|
* :py:meth:`Workplane`
|
|
* :py:meth:`Workplane.circle`
|
|
* :py:meth:`Workplane.extrude`
|
|
|
|
Polygons
|
|
-------------------------
|
|
|
|
You can create polygons for each stack point if you would like. Useful in 3d printers whos firmware does not
|
|
correct for small hole sizes.
|
|
|
|
.. cq_plot::
|
|
|
|
result = Workplane("front").box(3.0,4.0,0.25).pushPoints ( [ ( 0,0.75 ),(0,-0.75) ]) \
|
|
.polygon(6,1.0).cutThruAll()
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.polygon` **!**
|
|
* :py:meth:`Workplane.pushPoints`
|
|
* :py:meth:`Workplane.box`
|
|
|
|
Polylines
|
|
-------------------------
|
|
|
|
:py:meth:`Workplane.polyline` 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 mirrored to create the final profile.
|
|
|
|
.. cq_plot::
|
|
|
|
(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)
|
|
]
|
|
result = Workplane("front").polyline(pts).mirrorY().extrude(L)
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.polyline` **!**
|
|
* :py:meth:`Workplane`
|
|
* :py:meth:`Workplane.mirrorY`
|
|
* :py:meth:`Workplane.extrude`
|
|
|
|
|
|
|
|
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
|
|
|
|
.. cq_plot::
|
|
|
|
s = Workplane("XY")
|
|
sPnts = [
|
|
(2.75,1.5),
|
|
(2.5,1.75),
|
|
(2.0,1.5),
|
|
(1.5,1.0),
|
|
(1.0,1.25),
|
|
(0.5,1.0),
|
|
(0,1.0)
|
|
]
|
|
r = s.lineTo(3.0,0).lineTo(3.0,1.0).spline(sPnts).close()
|
|
result = r.extrude(0.5)
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.spline` **!**
|
|
* :py:meth:`Workplane`
|
|
* :py:meth:`Workplane.close`
|
|
* :py:meth:`Workplane.lineTo`
|
|
* :py:meth:`Workplane.extrude`
|
|
|
|
Mirroring Symmetric Geometry
|
|
-----------------------------
|
|
|
|
You can mirror 2-d geometry when your shape is symmetric. In this example we also
|
|
introduce horizontal and vertical lines, which make for slightly easier coding.
|
|
|
|
|
|
.. cq_plot::
|
|
|
|
r = Workplane("front").hLine(1.0) # 1.0 is the distance, not coordinate
|
|
r = r.vLine(0.5).hLine(-0.25).vLine(-0.25).hLineTo(0.0) # hLineTo allows using xCoordinate not distance
|
|
result =r.mirrorY().extrude(0.25 ) # mirror the geometry and extrude
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.hLine` **!**
|
|
* :py:meth:`Workplane.vLine` **!**
|
|
* :py:meth:`Workplane.hLineTo` **!**
|
|
* :py:meth:`Workplane.mirrorY` **!**
|
|
* :py:meth:`Workplane.mirrorX` **!**
|
|
* :py:meth:`Workplane`
|
|
* :py:meth:`Workplane.extrude`
|
|
|
|
|
|
Creating Workplanes on Faces
|
|
-----------------------------
|
|
|
|
This example shows how to locate a new workplane on the face of a previously created feature.
|
|
|
|
.. note::
|
|
Using workplanes in this way are a key feature of CadQuery. Unlike typical 3d scripting language,
|
|
using work planes frees you from tracking the position of various features in variables, and
|
|
allows the model to adjust itself with removing redundant dimensions
|
|
|
|
The :py:meth:`Workplane.faces()` method allows you to select the faces of a resulting solid. It accepts
|
|
a selector string or object, that allows you to target a single face, and make a workplane oriented on that
|
|
face.
|
|
|
|
Keep in mind that the origin of new workplanes are located at the center of a face by default.
|
|
|
|
.. cq_plot::
|
|
|
|
result = Workplane("front").box(2,3,0.5) #make a basic prism
|
|
result = result.faces(">Z").workplane().hole(0.5) #find the top-most face and make a hole
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.faces` **!**
|
|
* :py:meth:`StringSyntaxSelector` **!**
|
|
* :ref:`selector_reference` **!**
|
|
* :py:meth:`Workplane.workplane`
|
|
* :py:meth:`Workplane.box`
|
|
* :py:meth:`Workplane`
|
|
|
|
Locating a Workplane on a vertex
|
|
---------------------------------
|
|
|
|
Normally, the :py:meth:`Workplane.workplane` method requires a face to be selected. But if a vertex is selected
|
|
**immediately after a face**, :py:meth:`Workplane.workplane` will locate the workplane on the face, with the origin at the vertex instead
|
|
of at the center of the face
|
|
|
|
The example also introduces :py:meth:`Workplane.cutThruAll`, which makes a cut through the entire part, no matter
|
|
how deep the part is
|
|
|
|
.. cq_plot::
|
|
|
|
result = Workplane("front").box(3,2,0.5) #make a basic prism
|
|
result = result.faces(">Z").vertices("<XY").workplane() #select the lower left vertex and make a workplane
|
|
result = result.circle(1.0).cutThruAll() #cut the corner out
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.cutThruAll` **!**
|
|
|
|
* :ref:`selector_reference` **!**
|
|
* :py:meth:`Workplane.vertices` **!**
|
|
* :py:meth:`Workplane.box`
|
|
* :py:meth:`Workplane`
|
|
* :py:meth:`StringSyntaxSelector` **!**
|
|
|
|
Offset Workplanes
|
|
--------------------------
|
|
|
|
Workplanes do not have to lie exactly on a face. When you make a workplane, you can define it at an offset
|
|
from an existing face.
|
|
|
|
This example uses an offset workplane to make a compound object, which is perfectly valid!
|
|
|
|
.. cq_plot::
|
|
|
|
result = Workplane("front").box(3,2,0.5) #make a basic prism
|
|
result = result.faces("<X").workplane(offset=0.75) #workplane is offset from the object surface
|
|
result = result.circle(1.0).extrude(0.5) #disc
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.extrude`
|
|
* :ref:`selector_reference` **!**
|
|
* :py:meth:`Workplane.box`
|
|
* :py:meth:`Workplane`
|
|
|
|
Rotated Workplanes
|
|
--------------------------
|
|
|
|
You can create a rotated work plane by specifying angles of rotation relative to another workplane
|
|
|
|
.. cq_plot::
|
|
|
|
result = Workplane("front").box(4.0,4.0,0.25).faces(">Z").workplane() \
|
|
.transformed(offset=Vector(0,-1.5,1.0),rotate=Vector(60,0,0)) \
|
|
.rect(1.5,1.5,forConstruction=True).vertices().hole(0.25)
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.transformed` **!**
|
|
* :py:meth:`Workplane.box`
|
|
* :py:meth:`Workplane.rect`
|
|
* :py:meth:`Workplane.faces`
|
|
|
|
Using construction Geometry
|
|
---------------------------
|
|
|
|
You can draw shapes to use the vertices as points to locate other features. Features that are used to
|
|
locate other features, rather than to create them, are called ``Construction Geometry``
|
|
|
|
In the example below, a rectangle is drawn, and its vertices are used to locate a set of holes.
|
|
|
|
.. cq_plot::
|
|
|
|
result = Workplane("front").box(2,2,0.5).faces(">Z").workplane() \
|
|
.rect(1.5,1.5,forConstruction=True).vertices().hole(0.125 )
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.rect` (forConstruction=True)
|
|
* :ref:`selector_reference`
|
|
* :py:meth:`Workplane.workplane`
|
|
* :py:meth:`Workplane.box`
|
|
* :py:meth:`Workplane.hole`
|
|
* :py:meth:`Workplane`
|
|
|
|
Shelling To Create Thin features
|
|
--------------------------------
|
|
|
|
Shelling converts a solid object into a shell of uniform thickness. To shell an object, one or more faces
|
|
are removed, and then the inside of the solid is 'hollowed out' to make the shell.
|
|
|
|
|
|
.. cq_plot::
|
|
|
|
result = Workplane("front").box(2,2,2).faces("+Z").shell(0.05)
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.shell` **!**
|
|
* :py:meth:`Workplane.box`
|
|
* :py:meth:`Workplane.faces`
|
|
* :py:meth:`Workplane`
|
|
|
|
Making Lofts
|
|
--------------------------------------------
|
|
|
|
A loft is a solid swept through a set of wires. This example creates lofted section between a rectangle
|
|
and a circular section.
|
|
|
|
.. cq_plot::
|
|
|
|
result = Workplane("front").box(4.0,4.0,0.25).faces(">Z").circle(1.5) \
|
|
.workplane(offset=3.0).rect(0.75,0.5).loft(combine=True)
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.loft` **!**
|
|
* :py:meth:`Workplane.box`
|
|
* :py:meth:`Workplane.faces`
|
|
* :py:meth:`Workplane.circle`
|
|
* :py:meth:`Workplane.rect`
|
|
|
|
Making Counter-bored and counter-sunk holes
|
|
----------------------------------------------
|
|
|
|
Counterbored and countersunk holes are so common that CadQuery creates macros to create them in a single step.
|
|
|
|
Similar to :py:meth:`Workplane.hole` , these functions operate on a list of points as well as a single point.
|
|
|
|
.. cq_plot::
|
|
|
|
result = Workplane(Plane.XY()).box(4,2,0.5).faces(">Z").workplane().rect(3.5,1.5,forConstruction=True)\
|
|
.vertices().cboreHole(0.125, 0.25,0.125,depth=None)
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.cboreHole` **!**
|
|
* :py:meth:`Workplane.cskHole` **!**
|
|
* :py:meth:`Workplane.box`
|
|
* :py:meth:`Workplane.rect`
|
|
* :py:meth:`Workplane.workplane`
|
|
* :py:meth:`Workplane.vertices`
|
|
* :py:meth:`Workplane.faces`
|
|
* :py:meth:`Workplane`
|
|
|
|
Rounding Corners with Fillet
|
|
-----------------------------
|
|
|
|
Filleting is done by selecting the edges of a solid, and using the fillet function.
|
|
|
|
Here we fillet all of the edges of a simple plate.
|
|
|
|
.. cq_plot::
|
|
|
|
result = Workplane("XY" ).box(3,3,0.5).edges("|Z").fillet(0.125)
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.fillet` **!**
|
|
* :py:meth:`Workplane.box`
|
|
* :py:meth:`Workplane.edges`
|
|
* :py:meth:`Workplane`
|
|
|
|
Splitting an Object
|
|
---------------------
|
|
|
|
You can split an object using a workplane, and retain either or both halves
|
|
|
|
.. cq_plot::
|
|
|
|
c = Workplane("XY").box(1,1,1).faces(">Z").workplane().circle(0.25).cutThruAll()
|
|
|
|
#now cut it in half sideways
|
|
result = c.faces(">Y").workplane(-0.5).split(keepTop=True)
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.split` **!**
|
|
* :py:meth:`Workplane.box`
|
|
* :py:meth:`Workplane.circle`
|
|
* :py:meth:`Workplane.cutThruAll`
|
|
* :py:meth:`Workplane.workplane`
|
|
* :py:meth:`Workplane`
|
|
|
|
The Classic OCC Bottle
|
|
----------------------
|
|
|
|
CadQuery is based on the OpenCascade.org (OCC) modeling Kernel. Those who are familiar with OCC know about the
|
|
famous 'bottle' example. http://www.opencascade.org/org/gettingstarted/appli/
|
|
|
|
A pythonOCC version is listed here
|
|
http://code.google.com/p/pythonocc/source/browse/trunk/src/examples/Tools/InteractiveViewer/scripts/Bottle.py?r=1046
|
|
|
|
Of course one difference between this sample and the OCC version is the length. This sample is one of the longer
|
|
ones at 13 lines, but that's very short compared to the pythonOCC version, which is 10x longer!
|
|
|
|
|
|
.. cq_plot::
|
|
|
|
(L,w,t) = (20.0,6.0,3.0)
|
|
s = Workplane("XY")
|
|
|
|
#draw half the profile of the bottle and extrude it
|
|
p = s.center(-L/2.0,0).vLine(w/2.0) \
|
|
.threePointArc((L/2.0, w/2.0 + t),(L,w/2.0)).vLine(-w/2.0) \
|
|
.mirrorX().extrude(30.0,True)
|
|
|
|
#make the neck
|
|
p.faces(">Z").workplane().circle(3.0).extrude(2.0,True)
|
|
|
|
#make a shell
|
|
result = p.faces(">Z").shell(0.3)
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 2
|
|
|
|
* :py:meth:`Workplane.extrude`
|
|
* :py:meth:`Workplane.mirrorX`
|
|
* :py:meth:`Workplane.threePointArc`
|
|
* :py:meth:`Workplane.workplane`
|
|
* :py:meth:`Workplane.vertices`
|
|
* :py:meth:`Workplane.vLine`
|
|
* :py:meth:`Workplane.faces`
|
|
* :py:meth:`Workplane`
|
|
|
|
A Parametric Enclosure
|
|
-----------------------
|
|
|
|
.. cq_plot::
|
|
:height: 400
|
|
|
|
#parameter definitions
|
|
p_outerWidth = 100.0 #Outer width of box enclosure
|
|
p_outerLength = 150.0 #Outer length of box enclosure
|
|
p_outerHeight = 50.0 #Outer height of box enclosure
|
|
|
|
p_thickness = 3.0 #Thickness of the box walls
|
|
p_sideRadius = 10.0 #Radius for the curves around the sides of the bo
|
|
p_topAndBottomRadius = 2.0 #Radius for the curves on the top and bottom edges of the box
|
|
|
|
p_screwpostInset = 12.0 #How far in from the edges the screwposts should be place.
|
|
p_screwpostID = 4.0 #nner Diameter of the screwpost holes, should be roughly screw diameter not including threads
|
|
p_screwpostOD = 10.0 #Outer Diameter of the screwposts.\nDetermines overall thickness of the posts
|
|
|
|
p_boreDiameter = 8.0 #Diameter of the counterbore hole, if any
|
|
p_boreDepth = 1.0 #Depth of the counterbore hole, if
|
|
p_countersinkDiameter = 0.0 #Outer diameter of countersink. Should roughly match the outer diameter of the screw head
|
|
p_countersinkAngle = 90.0 #Countersink angle (complete angle between opposite sides, not from center to one side)
|
|
p_flipLid = True #Whether to place the lid with the top facing down or not.
|
|
p_lipHeight = 1.0 #Height of lip on the underside of the lid.\nSits inside the box body for a snug fit.
|
|
|
|
#outer shell
|
|
oshell = Workplane("XY").rect(p_outerWidth,p_outerLength).extrude(p_outerHeight + p_lipHeight)
|
|
|
|
#weird geometry happens if we make the fillets in the wrong order
|
|
if p_sideRadius > p_topAndBottomRadius:
|
|
oshell.edges("|Z").fillet(p_sideRadius)
|
|
oshell.edges("#Z").fillet(p_topAndBottomRadius)
|
|
else:
|
|
oshell.edges("#Z").fillet(p_topAndBottomRadius)
|
|
oshell.edges("|Z").fillet(p_sideRadius)
|
|
|
|
#inner shell
|
|
ishell = oshell.faces("<Z").workplane(p_thickness,True)\
|
|
.rect((p_outerWidth - 2.0* p_thickness),(p_outerLength - 2.0*p_thickness))\
|
|
.extrude((p_outerHeight - 2.0*p_thickness),False) #set combine false to produce just the new boss
|
|
ishell.edges("|Z").fillet(p_sideRadius - p_thickness)
|
|
|
|
#make the box outer box
|
|
box = oshell.cut(ishell)
|
|
|
|
#make the screwposts
|
|
POSTWIDTH = (p_outerWidth - 2.0*p_screwpostInset)
|
|
POSTLENGTH = (p_outerLength -2.0*p_screwpostInset)
|
|
|
|
postCenters = box.faces(">Z").workplane(-p_thickness)\
|
|
.rect(POSTWIDTH,POSTLENGTH,forConstruction=True)\
|
|
.vertices()
|
|
|
|
for v in postCenters.all():
|
|
v.circle(p_screwpostOD/2.0).circle(p_screwpostID/2.0)\
|
|
.extrude((-1.0)*(p_outerHeight + p_lipHeight -p_thickness ),True)
|
|
|
|
#split lid into top and bottom parts
|
|
(lid,bottom) = box.faces(">Z").workplane(-p_thickness -p_lipHeight ).split(keepTop=True,keepBottom=True).all() #splits into two solids
|
|
|
|
#translate the lid, and subtract the bottom from it to produce the lid inset
|
|
lowerLid = lid.translate((0,0,-p_lipHeight))
|
|
cutlip = lowerLid.cut(bottom).translate((p_outerWidth + p_thickness ,0,p_thickness - p_outerHeight + p_lipHeight))
|
|
|
|
#compute centers for counterbore/countersink or counterbore
|
|
topOfLidCenters = cutlip.faces(">Z").workplane().rect(POSTWIDTH,POSTLENGTH,forConstruction=True).vertices()
|
|
|
|
#add holes of the desired type
|
|
if p_boreDiameter > 0 and p_boreDepth > 0:
|
|
topOfLid = topOfLidCenters.cboreHole(p_screwpostID,p_boreDiameter,p_boreDepth,(2.0)*p_thickness)
|
|
elif p_countersinkDiameter > 0 and p_countersinkAngle > 0:
|
|
topOfLid = topOfLidCenters.cskHole(p_screwpostID,p_countersinkDiameter,p_countersinkAngle,(2.0)*p_thickness)
|
|
else:
|
|
topOfLid= topOfLidCenters.hole(p_screwpostID,(2.0)*p_thickness)
|
|
|
|
#flip lid upside down if desired
|
|
if p_flipLid:
|
|
topOfLid.rotateAboutCenter((1,0,0),180)
|
|
|
|
#return the combined result
|
|
result =topOfLid.combineSolids(bottom)
|
|
|
|
.. topic:: Api References
|
|
|
|
.. hlist::
|
|
:columns: 3
|
|
|
|
* :py:meth:`Workplane.circle`
|
|
* :py:meth:`Workplane.rect`
|
|
* :py:meth:`Workplane.extrude`
|
|
* :py:meth:`Workplane.box`
|
|
* :py:meth:`CQ.all`
|
|
* :py:meth:`CQ.faces`
|
|
* :py:meth:`CQ.vertices`
|
|
* :py:meth:`CQ.edges`
|
|
* :py:meth:`CQ.workplane`
|
|
* :py:meth:`Workplane.fillet`
|
|
* :py:meth:`Workplane.cut`
|
|
* :py:meth:`Workplane.combineSolids`
|
|
* :py:meth:`Workplane.rotateAboutCenter`
|
|
* :py:meth:`Workplane.cboreHole`
|
|
* :py:meth:`Workplane.cskHole`
|
|
* :py:meth:`Workplane.hole` |