Moved examples to CadQuery library and adapted the UI to use those.

This commit is contained in:
Jeremy Mack Wright 2017-09-28 16:42:14 -04:00
parent fc5d11f2ef
commit 6a1aa83760
36 changed files with 5 additions and 1319 deletions

View File

@ -1,19 +0,0 @@
import cadquery as cq
# These can be modified rather than hardcoding values for each dimension.
length = 80.0 # Length of the block
height = 60.0 # Height of the block
thickness = 10.0 # Thickness of the block
# Create a 3D block based on the dimension variables above.
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the X and Y origins to define the workplane, meaning that the
# positive Z direction is "up", and the negative Z direction is "down".
result = cq.Workplane("XY").box(length, height, thickness)
# The following method is now outdated, but can still be used to display the
# results of the script if you want
# from Helpers import show
# show(result) # Render the result of this script
show_object(result)

View File

@ -1,20 +0,0 @@
import cadquery as cq
# These can be modified rather than hardcoding values for each dimension.
length = 80.0 # Length of the block
height = 60.0 # Height of the block
thickness = 10.0 # Thickness of the block
center_hole_dia = 22.0 # Diameter of center hole in block
# Create a block based on the dimensions above and add a 22mm center hole.
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the X and Y origins to define the workplane, meaning that the
# positive Z direction is "up", and the negative Z direction is "down".
# 2. The highest (max) Z face is selected and a new workplane is created on it.
# 3. The new workplane is used to drill a hole through the block.
# 3a. The hole is automatically centered in the workplane.
result = cq.Workplane("XY").box(length, height, thickness) \
.faces(">Z").workplane().hole(center_hole_dia)
# Displays the result of this script
show_object(result)

View File

@ -1,34 +0,0 @@
import cadquery as cq
# These can be modified rather than hardcoding values for each dimension.
length = 80.0 # Length of the block
height = 60.0 # Height of the block
thickness = 10.0 # Thickness of the block
center_hole_dia = 22.0 # Diameter of center hole in block
cbore_hole_diameter = 2.4 # Bolt shank/threads clearance hole diameter
cbore_diameter = 4.4 # Bolt head pocket hole diameter
cbore_depth = 2.1 # Bolt head pocket hole depth
# Create a 3D block based on the dimensions above and add a 22mm center hold
# and 4 counterbored holes for bolts
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the X and Y origins to define the workplane, meaning that the
# positive Z direction is "up", and the negative Z direction is "down".
# 2. The highest(max) Z face is selected and a new workplane is created on it.
# 3. The new workplane is used to drill a hole through the block.
# 3a. The hole is automatically centered in the workplane.
# 4. The highest(max) Z face is selected and a new workplane is created on it.
# 5. A for-construction rectangle is created on the workplane based on the
# block's overall dimensions.
# 5a. For-construction objects are used only to place other geometry, they
# do not show up in the final displayed geometry.
# 6. The vertices of the rectangle (corners) are selected, and a counter-bored
# hole is placed at each of the vertices (all 4 of them at once).
result = cq.Workplane("XY").box(length, height, thickness) \
.faces(">Z").workplane().hole(center_hole_dia) \
.faces(">Z").workplane() \
.rect(length - 8.0, height - 8.0, forConstruction=True) \
.vertices().cboreHole(cbore_hole_diameter, cbore_diameter, cbore_depth)
# Displays the result of this script
show_object(result)

View File

@ -1,29 +0,0 @@
import cadquery as cq
# These can be modified rather than hardcoding values for each dimension.
circle_radius = 50.0 # Radius of the plate
thickness = 13.0 # Thickness of the plate
rectangle_width = 13.0 # Width of rectangular hole in cylindrical plate
rectangle_length = 19.0 # Length of rectangular hole in cylindrical plate
# Extrude a cylindrical plate with a rectangular hole in the middle of it.
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the named plane orientation "front" to define the workplane, meaning
# that the positive Z direction is "up", and the negative Z direction
# is "down".
# 2. The 2D geometry for the outer circle is created at the same time as the
# rectangle that will create the hole in the center.
# 2a. The circle and the rectangle will be automatically centered on the
# workplane.
# 2b. Unlike some other functions like the hole(), circle() takes
# a radius and not a diameter.
# 3. The circle and rectangle are extruded together, creating a cylindrical
# plate with a rectangular hole in the center.
# 3a. circle() and rect() could be changed to any other shape to completely
# change the resulting plate and/or the hole in it.
result = cq.Workplane("front").circle(circle_radius) \
.rect(rectangle_width, rectangle_length) \
.extrude(thickness)
# Displays the result of this script
show_object(result)

View File

@ -1,32 +0,0 @@
import cadquery as cq
# These can be modified rather than hardcoding values for each dimension.
width = 2.0 # Overall width of the plate
thickness = 0.25 # Thickness of the plate
# Extrude a plate outline made of lines and an arc
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the named plane orientation "front" to define the workplane, meaning
# that the positive Z direction is "up", and the negative Z direction
# is "down".
# 2. Draws a line from the origin to an X position of the plate's width.
# 2a. The starting point of a 2D drawing like this will be at the center of the
# workplane (0, 0) unless the moveTo() function moves the starting point.
# 3. A line is drawn from the last position straight up in the Y direction
# 1.0 millimeters.
# 4. An arc is drawn from the last point, through point (1.0, 1.5) which is
# half-way back to the origin in the X direction and 0.5 mm above where
# the last line ended at. The arc then ends at (0.0, 1.0), which is 1.0 mm
# above (in the Y direction) where our first line started from.
# 5. close() is called to automatically draw the last line for us and close
# the sketch so that it can be extruded.
# 5a. Without the close(), the 2D sketch will be left open and the extrude
# operation will provide unpredictable results.
# 6. The 2D sketch is extruded into a solid object of the specified thickness.
result = cq.Workplane("front").lineTo(width, 0) \
.lineTo(width, 1.0) \
.threePointArc((1.0, 1.5), (0.0, 1.0)) \
.close().extrude(thickness)
# Displays the result of this script
show_object(result)

View File

@ -1,35 +0,0 @@
import cadquery as cq
# These can be modified rather than hardcoding values for each dimension.
circle_radius = 3.0 # The outside radius of the plate
thickness = 0.25 # The thickness of the plate
# Make a plate with two cutouts in it by moving the workplane center point
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the named plane orientation "front" to define the workplane, meaning
# that the positive Z direction is "up", and the negative Z direction
# is "down".
# 1b. The initial workplane center point is the center of the circle, at (0,0).
# 2. A circle is created at the center of the workplane
# 2a. Notice that circle() takes a radius and not a diameter
result = cq.Workplane("front").circle(circle_radius)
# 3. The work center is movide to (1.5, 0.0) by calling center().
# 3a. The new center is specified relative to the previous center,not
# relative to global coordinates.
# 4. A 0.5mm x 0.5mm 2D square is drawn inside the circle.
# 4a. The plate has not been extruded yet, only 2D geometry is being created.
result = result.center(1.5, 0.0).rect(0.5, 0.5)
# 5. The work center is moved again, this time to (-1.5, 1.5).
# 6. A 2D circle is created at that new center with a radius of 0.25mm.
result = result.center(-1.5, 1.5).circle(0.25)
# 7. All 2D geometry is extruded to the specified thickness of the plate.
# 7a. The small circle and the square are enclosed in the outer circle of the
# plate and so it is assumed that we want them to be cut out of the plate.
# A separate cut operation is not needed.
result = result.extrude(thickness)
# Displays the result of this script
show_object(result)

View File

@ -1,32 +0,0 @@
import cadquery as cq
# These can be modified rather than hardcoding values for each dimension.
plate_radius = 2.0 # The radius of the plate that will be extruded
hole_pattern_radius = 0.25 # Radius of circle where the holes will be placed
thickness = 0.125 # The thickness of the plate that will be extruded
# Make a plate with 4 holes in it at various points in a polar arrangement from
# the center of the workplane.
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the named plane orientation "front" to define the workplane, meaning
# that the positive Z direction is "up", and the negative Z direction
# is "down".
# 2. A 2D circle is drawn that will become though outer profile of the plate.
r = cq.Workplane("front").circle(plate_radius)
# 3. Push 4 points on the stack that will be used as the center points of the
# holes.
r = r.pushPoints([(1.5, 0), (0, 1.5), (-1.5, 0), (0, -1.5)])
# 4. This circle() call will operate on all four points, putting a circle at
# each one.
r = r.circle(hole_pattern_radius)
# 5. All 2D geometry is extruded to the specified thickness of the plate.
# 5a. The small hole circles are enclosed in the outer circle of the plate and
# so it is assumed that we want them to be cut out of the plate. A
# separate cut operation is not needed.
result = r.extrude(thickness)
# Displays the result of this script
show_object(result)

View File

@ -1,39 +0,0 @@
import cadquery as cq
# These can be modified rather than hardcoding values for each dimension.
width = 3.0 # The width of the plate
height = 4.0 # The height of the plate
thickness = 0.25 # The thickness of the plate
polygon_sides = 6 # The number of sides that the polygonal holes should have
polygon_dia = 1.0 # The diameter of the circle enclosing the polygon points
# Create a plate with two polygons cut through it
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the named plane orientation "front" to define the workplane, meaning
# that the positive Z direction is "up", and the negative Z direction
# is "down".
# 2. A 3D box is created in one box() operation to represent the plate.
# 2a. The box is centered around the origin, which creates a result that may
# be unituitive when the polygon cuts are made.
# 3. 2 points are pushed onto the stack and will be used as centers for the
# polygonal holes.
# 4. The two polygons are created, on for each point, with one call to
# polygon() using the number of sides and the circle that bounds the
# polygon.
# 5. The polygons are cut thru all objects that are in the line of extrusion.
# 5a. A face was not selected, and so the polygons are created on the
# workplane. Since the box was centered around the origin, the polygons end
# up being in the center of the box. This makes them cut from the center to
# the outside along the normal (positive direction).
# 6. The polygons are cut through all objects, starting at the center of the
# box/plate and going "downward" (opposite of normal) direction. Functions
# like cutBlind() assume a positive cut direction, but cutThruAll() assumes
# instead that the cut is made from a max direction and cuts downward from
# that max through all objects.
result = cq.Workplane("front").box(width, height, thickness) \
.pushPoints([(0, 0.75), (0, -0.75)]) \
.polygon(polygon_sides, polygon_dia) \
.cutThruAll()
# Displays the result of this script
show_object(result)

View File

@ -1,40 +0,0 @@
import cadquery as cq
# These can be modified rather than hardcoding values for each dimension.
# Define up our Length, Height, Width, and thickness of the beam
(L, H, W, t) = (100.0, 20.0, 20.0, 1.0)
# Define the points that the polyline will be drawn to/thru
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)
]
# We generate half of the I-beam outline and then mirror it to create the full
# I-beam.
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the named plane orientation "front" to define the workplane, meaning
# that the positive Z direction is "up", and the negative Z direction
# is "down".
# 2. moveTo() is used to move the first point from the origin (0, 0) to
# (0, 10.0), with 10.0 being half the height (H/2.0). If this is not done
# the first line will start from the origin, creating an extra segment that
# will cause the extrude to have an invalid shape.
# 3. The polyline function takes a list of points and generates the lines
# through all the points at once.
# 3. Only half of the I-beam profile has been drawn so far. That half is
# mirrored around the Y-axis to create the complete I-beam profile.
# 4. The I-beam profile is extruded to the final length of the beam.
result = cq.Workplane("front").moveTo(0, H/2.0) \
.polyline(pts) \
.mirrorY() \
.extrude(L)
# Displays the result of this script
show_object(result)

View File

@ -1,27 +0,0 @@
import cadquery as cq
# 1. Establishes a workplane to create the spline on to extrude.
# 1a. Uses the X and Y origins to define the workplane, meaning that the
# positive Z direction is "up", and the negative Z direction is "down".
s = cq.Workplane("XY")
# The points that the spline will pass through
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)
]
# 2. Generate our plate with the spline feature and make sure it is a
# closed entity
r = s.lineTo(3.0, 0).lineTo(3.0, 1.0).spline(sPnts).close()
# 3. Extrude to turn the wire into a plate
result = r.extrude(0.5)
# Displays the result of this script
show_object(result)

View File

@ -1,20 +0,0 @@
import cadquery as cq
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the named plane orientation "front" to define the workplane, meaning
# that the positive Z direction is "up", and the negative Z direction
# is "down".
# 2. A horizontal line is drawn on the workplane with the hLine function.
# 2a. 1.0 is the distance, not coordinate. hLineTo allows using xCoordinate
# not distance.
r = cq.Workplane("front").hLine(1.0)
# 3. Draw a series of vertical and horizontal lines with the vLine and hLine
# functions.
r = r.vLine(0.5).hLine(-0.25).vLine(-0.25).hLineTo(0.0)
# 4. Mirror the geometry about the Y axis and extrude it into a 3D object.
result = r.mirrorY().extrude(0.25)
# Displays the result of this script
show_object(result)

View File

@ -1,16 +0,0 @@
import cadquery as cq
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the named plane orientation "front" to define the workplane, meaning
# that the positive Z direction is "up", and the negative Z direction
# is "down".
# 2. Creates a 3D box that will have a hole placed in it later.
result = cq.Workplane("front").box(2, 3, 0.5)
# 3. Find the top-most face with the >Z max selector.
# 3a. Establish a new workplane to build geometry on.
# 3b. Create a hole down into the box.
result = result.faces(">Z").workplane().hole(0.5)
# Displays the result of this script
show_object(result)

View File

@ -1,21 +0,0 @@
import cadquery as cq
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the named plane orientation "front" to define the workplane, meaning
# that the positive Z direction is "up", and the negative Z direction
# is "down".
# 2. Creates a 3D box that will have a hole placed in it later.
result = cq.Workplane("front").box(3, 2, 0.5)
# 3. Select the lower left vertex and make a workplane.
# 3a. The top-most Z face is selected using the >Z selector.
# 3b. The lower-left vertex of the faces is selected with the <XY selector.
# 3c. A new workplane is created on the vertex to build future geometry on.
result = result.faces(">Z").vertices("<XY").workplane()
# 4. A circle is drawn with the selected vertex as its center.
# 4a. The circle is cut down through the box to cut the corner out.
result = result.circle(1.0).cutThruAll()
# Displays the result of this script
show_object(result)

View File

@ -1,20 +0,0 @@
import cadquery as cq
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the named plane orientation "front" to define the workplane, meaning
# that the positive Z direction is "up", and the negative Z direction
# is "down".
# 2. Creates a 3D box that will have geometry based off it later.
result = cq.Workplane("front").box(3, 2, 0.5)
# 3. The lowest face in the X direction is selected with the <X selector.
# 4. A new wokrplane is created
# 4a.The workplane is offset from the object surface so that it is not touching
# the original box.
result = result.faces("<X").workplane(offset=0.75)
# 5. Creates a thin disc on the offset workplane that is floating near the box.
result = result.circle(1.0).extrude(0.5)
# Displays the result of this script
show_object(result)

View File

@ -1,22 +0,0 @@
import cadquery as cq
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the named plane orientation "front" to define the workplane, meaning
# that the positive Z direction is "up", and the negative Z direction
# is "down".
# 2. Creates a plain box to base future geometry on with the box() function.
# 3. Selects the top-most Z face of the box.
# 4. Creates a new workplane and then moves and rotates it with the
# transformed function.
# 5. Creates a for-construction rectangle that only exists to use for placing
# other geometry.
# 6. Selects the vertices of the for-construction rectangle.
# 7. Places holes at the center of each selected vertex.
# 7a. Since the workplane is rotated, this results in angled holes in the face.
result = cq.Workplane("front").box(4.0, 4.0, 0.25).faces(">Z") \
.workplane() \
.transformed(offset=(0, -1.5, 1.0), rotate=(60, 0, 0)) \
.rect(1.5, 1.5, forConstruction=True).vertices().hole(0.25)
# Displays the result of this script
show_object(result)

View File

@ -1,21 +0,0 @@
import cadquery as cq
# Create a block with holes in each corner of a rectangle on that workplane.
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the named plane orientation "front" to define the workplane, meaning
# that the positive Z direction is "up", and the negative Z direction
# is "down".
# 2. Creates a plain box to base future geometry on with the box() function.
# 3. Selects the top-most Z face of the box.
# 4. Creates a new workplane to build new geometry on.
# 5. Creates a for-construction rectangle that only exists to use for placing
# other geometry.
# 6. Selects the vertices of the for-construction rectangle.
# 7. Places holes at the center of each selected vertex.
result = cq.Workplane("front").box(2, 2, 0.5)\
.faces(">Z").workplane() \
.rect(1.5, 1.5, forConstruction=True).vertices() \
.hole(0.125)
# Displays the result of this script
show_object(result)

View File

@ -1,14 +0,0 @@
import cadquery as cq
# Create a hollow box that's open on both ends with a thin wall.
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the named plane orientation "front" to define the workplane, meaning
# that the positive Z direction is "up", and the negative Z direction
# is "down".
# 2. Creates a plain box to base future geometry on with the box() function.
# 3. Selects faces with normal in +z direction.
# 4. Create a shell by cutting out the top-most Z face.
result = cq.Workplane("front").box(2, 2, 2).faces("+Z").shell(0.05)
# Displays the result of this script
show_object(result)

View File

@ -1,20 +0,0 @@
import cadquery as cq
# Create a lofted section between a rectangle and a circular section.
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the named plane orientation "front" to define the workplane, meaning
# that the positive Z direction is "up", and the negative Z direction
# is "down".
# 2. Creates a plain box to base future geometry on with the box() function.
# 3. Selects the top-most Z face of the box.
# 4. Draws a 2D circle at the center of the the top-most face of the box.
# 5. Creates a workplane 3 mm above the face the circle was drawn on.
# 6. Draws a 2D circle on the new, offset workplane.
# 7. Creates a loft between the circle and the rectangle.
result = cq.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)
# Displays the result of this script
show_object(result)

View File

@ -1,19 +0,0 @@
import cadquery as cq
# Create a plate with 4 counter-sunk holes in it.
# 1. Establishes a workplane using an XY object instead of a named plane.
# 2. Creates a plain box to base future geometry on with the box() function.
# 3. Selects the top-most face of the box and established a workplane on that.
# 4. Draws a for-construction rectangle on the workplane which only exists for
# placing other geometry.
# 5. Selects the corner vertices of the rectangle and places a counter-sink
# hole, using each vertex as the center of a hole using the cskHole()
# function.
# 5a. When the depth of the counter-sink hole is set to None, the hole will be
# cut through.
result = cq.Workplane(cq.Plane.XY()).box(4, 2, 0.5).faces(">Z") \
.workplane().rect(3.5, 1.5, forConstruction=True) \
.vertices().cskHole(0.125, 0.25, 82.0, depth=None)
# Displays the result of this script
show_object(result)

View File

@ -1,13 +0,0 @@
import cadquery as cq
# Create a plate with 4 rounded corners in the Z-axis.
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the X and Y origins to define the workplane, meaning that the
# positive Z direction is "up", and the negative Z direction is "down".
# 2. Creates a plain box to base future geometry on with the box() function.
# 3. Selects all edges that are parallel to the Z axis.
# 4. Creates fillets on each of the selected edges with the specified radius.
result = cq.Workplane("XY").box(3, 3, 0.5).edges("|Z").fillet(0.125)
# Displays the result of this script
show_object(result)

View File

@ -1,25 +0,0 @@
import cadquery as cq
# Create a simple block with a hole through it that we can split.
# 1. Establishes a workplane that an object can be built on.
# 1a. Uses the X and Y origins to define the workplane, meaning that the
# positive Z direction is "up", and the negative Z direction is "down".
# 2. Creates a plain box to base future geometry on with the box() function.
# 3. Selects the top-most face of the box and establishes a workplane on it
# that new geometry can be built on.
# 4. Draws a 2D circle on the new workplane and then uses it to cut a hole
# all the way through the box.
c = cq.Workplane("XY").box(1, 1, 1).faces(">Z").workplane() \
.circle(0.25).cutThruAll()
# 5. Selects the face furthest away from the origin in the +Y axis direction.
# 6. Creates an offset workplane that is set in the center of the object.
# 6a. One possible improvement to this script would be to make the dimensions
# of the box variables, and then divide the Y-axis dimension by 2.0 and
# use that to create the offset workplane.
# 7. Uses the embedded workplane to split the object, keeping only the "top"
# portion.
result = c.faces(">Y").workplane(-0.5).split(keepTop=True)
# Displays the result of this script
show_object(result)

View File

@ -1,19 +0,0 @@
import cadquery as cq
# Set up the length, width, and thickness
(L, w, t) = (20.0, 6.0, 3.0)
s = cq.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)
# Displays the result of this script
show_object(result)

View File

@ -1,77 +0,0 @@
import cadquery as cq
# 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
p_screwpostInset = 12.0 # How far in from the edges the screwposts should be
p_screwpostID = 4.0 # Inner diameter of the screwpost holes, should be roughly screw diameter not including threads
p_screwpostOD = 10.0 # Outer diameter of the screwposts. Determines 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_lipHeight = 1.0 # Height of lip on the underside of the lid. Sits inside the box body for a snug fit.
# Outer shell
oshell = cq.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) - (2.0 * 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()
# 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)
# Return the combined result
result = topOfLid.combineSolids(bottom)
# Displays the result of this script
show_object(result)

View File

@ -1,23 +0,0 @@
# This example is meant to be used from within the CadQuery module of FreeCAD.
import cadquery
import FreeCAD
# Create a new document that we can draw our model on
newDoc = FreeCAD.newDocument()
# Shows a 1x1x1 FreeCAD cube in the display
initialBox = newDoc.addObject("Part::Box", "initialBox")
newDoc.recompute()
# Make a CQ object
cqBox = cadquery.CQ(cadquery.Solid(initialBox.Shape))
# Extrude a peg
newThing = cqBox.faces(">Z").workplane().circle(0.5).extrude(0.25)
# Add a FreeCAD object to the tree and then store a CQ object in it
nextShape = newDoc.addObject("Part::Feature", "nextShape")
nextShape.Shape = newThing.val().wrapped
# Rerender the doc to see what the new solid looks like
newDoc.recompute()

View File

@ -1,21 +0,0 @@
import cadquery as cq
# The dimensions of the model. These can be modified rather than changing the
# shape's code directly.
rectangle_width = 10.0
rectangle_length = 10.0
angle_degrees = 360.0
# Revolve a cylinder from a rectangle
# Switch comments around in this section to try the revolve operation with different parameters
result = cq.Workplane("XY").rect(rectangle_width, rectangle_length, False).revolve()
#result = cadquery.Workplane("XY").rect(rectangle_width, rectangle_length, False).revolve(angle_degrees)
#result = cadquery.Workplane("XY").rect(rectangle_width, rectangle_length).revolve(angle_degrees,(-5,-5))
#result = cadquery.Workplane("XY").rect(rectangle_width, rectangle_length).revolve(angle_degrees,(-5, -5),(-5, 5))
#result = cadquery.Workplane("XY").rect(rectangle_width, rectangle_length).revolve(angle_degrees,(-5,-5),(-5,5), False)
# Revolve a donut with square walls
#result = cadquery.Workplane("XY").rect(rectangle_width, rectangle_length, True).revolve(angle_degrees, (20, 0), (20, 10))
# Displays the result of this script
show_object(result)

View File

@ -1,56 +0,0 @@
# This script can create any regular rectangular Lego(TM) Brick
import cadquery as cq
#####
# Inputs
######
lbumps = 1 # number of bumps long
wbumps = 1 # number of bumps wide
thin = True # True for thin, False for thick
#
# Lego Brick Constants-- these make a lego brick a lego :)
#
pitch = 8.0
clearance = 0.1
bumpDiam = 4.8
bumpHeight = 1.8
if thin:
height = 3.2
else:
height = 9.6
t = (pitch - (2 * clearance) - bumpDiam) / 2.0
postDiam = pitch - t # works out to 6.5
total_length = lbumps*pitch - 2.0*clearance
total_width = wbumps*pitch - 2.0*clearance
# make the base
s = cq.Workplane("XY").box(total_length, total_width, height)
# shell inwards not outwards
s = s.faces("<Z").shell(-1.0 * t)
# make the bumps on the top
s = s.faces(">Z").workplane(). \
rarray(pitch, pitch, lbumps, wbumps, True).circle(bumpDiam / 2.0) \
.extrude(bumpHeight)
# add posts on the bottom. posts are different diameter depending on geometry
# solid studs for 1 bump, tubes for multiple, none for 1x1
tmp = s.faces("<Z").workplane(invert=True)
if lbumps > 1 and wbumps > 1:
tmp = tmp.rarray(pitch, pitch, lbumps - 1, wbumps - 1, center=True). \
circle(postDiam / 2.0).circle(bumpDiam / 2.0).extrude(height - t)
elif lbumps > 1:
tmp = tmp.rarray(pitch, pitch, lbumps - 1, 1, center=True). \
circle(t).extrude(height - t)
elif wbumps > 1:
tmp = tmp.rarray(pitch, pitch, 1, wbumps - 1, center=True). \
circle(t).extrude(height - t)
else:
tmp = s
# Render the solid
show_object(tmp)

View File

@ -1,85 +0,0 @@
import cadquery as cq
exploded = False # when true, moves the base away from the top so we see
showTop = True # When true, the top is rendered.
showCover = True # When true, the cover is rendered
width = 2.2 # Nominal x dimension of the part
height = 0.5 # Height from bottom top to the top of the top :P
length = 1.5 # Nominal y dimension of the part
trapezoidFudge = 0.7 # ratio of trapezoid bases. set to 1.0 for cube
xHoleOffset = 0.500 # Holes are distributed symetrically about each axis
yHoleOffset = 0.500
zFilletRadius = 0.50 # Fillet radius of corners perp. to Z axis.
yFilletRadius = 0.250 # Fillet readius of the top edge of the case
lipHeight = 0.1 # The height of the lip on the inside of the cover
wallThickness = 0.06 # Wall thickness for the case
coverThickness = 0.2 # Thickness of the cover plate
holeRadius = 0.30 # Button hole radius
counterSyncAngle = 100 # Countersink angle.
xyplane = cq.Workplane("XY")
yzplane = cq.Workplane("YZ")
def trapezoid(b1, b2, h):
"Defines a symetrical trapezoid in the XY plane."
y = h / 2
x1 = b1 / 2
x2 = b2 / 2
return (xyplane.moveTo(-x1, y)
.polyline([(x1, y),
(x2, -y),
(-x2, -y)]).close())
# Defines our base shape: a box with fillets around the vertical edges.
# This has to be a function because we need to create multiple copies of
# the shape.
def base(h):
return (trapezoid(width, width * trapezoidFudge, length)
.extrude(h)
.translate((0, 0, height / 2))
.edges("Z")
.fillet(zFilletRadius))
# start with the base shape
top = (base(height)
# then fillet the top edge
.edges(">Z")
.fillet(yFilletRadius)
# shell the solid from the bottom face, with a .060" wall thickness
.faces("<Z")
.shell(-wallThickness)
# cut five button holes into the top face in a cross pattern.
.faces(">Z")
.workplane()
.pushPoints([(0, 0),
(-xHoleOffset, 0),
(0, -yHoleOffset),
(xHoleOffset, 0),
(0, yHoleOffset)])
.cskHole(diameter=holeRadius,
cskDiameter=holeRadius * 1.5,
cskAngle=counterSyncAngle))
# the bottom cover begins with the same basic shape as the top
cover = (base(coverThickness)
# we need to move it upwards into the parent solid slightly.
.translate((0, 0, -coverThickness + lipHeight))
# now we subtract the top from the cover. This produces a lip on the
# solid NOTE: that this does not account for mechanical tolerances.
# But it looks cool.
.cut(top)
# try to fillet the inner edge of the cover lip. Technically this
# fillets every edge perpendicular to the Z axis.
.edges("#Z")
.fillet(.020)
.translate((0, 0, -0.5 if exploded else 0)))
# Conditionally render the parts
if showTop:
show_object(top)
if showCover:
show_object(cover)

View File

@ -1,23 +0,0 @@
import numpy as np
import cadquery as cq
# Square side and offset in x and y.
side = 10
offset = 5
# Define the locations that the polyline will be drawn to/thru.
# The polyline is defined as numpy.array so that operations like translation
# of all points are simplified.
pts = np.array([
(side, 0),
(side, side),
(0, side),
(0, 0),
]) + [offset, offset]
result = cq.Workplane('XY') \
.polyline(pts).close().extrude(2) \
.faces('+Z').workplane().circle(side / 2).extrude(1)
# Render the solid
show_object(result)

View File

@ -1,182 +0,0 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, division
from collections import namedtuple
import cadquery as cq
# text_lines is a list of text lines.
# FreeCAD in braille (converted with braille-converter:
# https://github.com/jpaugh/braille-converter.git).
text_lines = ['⠠ ⠋ ⠗ ⠑ ⠑ ⠠ ⠉ ⠠ ⠁ ⠠ ⠙']
# See http://www.tiresias.org/research/reports/braille_cell.htm for examples
# of braille cell geometry.
horizontal_interdot = 2.5
vertical_interdot = 2.5
horizontal_intercell = 6
vertical_interline = 10
dot_height = 0.5
dot_diameter = 1.3
base_thickness = 1.5
# End of configuration.
BrailleCellGeometry = namedtuple('BrailleCellGeometry',
('horizontal_interdot',
'vertical_interdot',
'intercell',
'interline',
'dot_height',
'dot_diameter'))
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)
def __len__(self):
return 2
def __getitem__(self, index):
return (self.x, self.y)[index]
def __str__(self):
return '({}, {})'.format(self.x, self.y)
def brailleToPoints(text, cell_geometry):
# Unicode bit pattern (cf. https://en.wikipedia.org/wiki/Braille_Patterns).
mask1 = 0b00000001
mask2 = 0b00000010
mask3 = 0b00000100
mask4 = 0b00001000
mask5 = 0b00010000
mask6 = 0b00100000
mask7 = 0b01000000
mask8 = 0b10000000
masks = (mask1, mask2, mask3, mask4, mask5, mask6, mask7, mask8)
# Corresponding dot position
w = cell_geometry.horizontal_interdot
h = cell_geometry.vertical_interdot
pos1 = Point(0, 2 * h)
pos2 = Point(0, h)
pos3 = Point(0, 0)
pos4 = Point(w, 2 * h)
pos5 = Point(w, h)
pos6 = Point(w, 0)
pos7 = Point(0, -h)
pos8 = Point(w, -h)
pos = (pos1, pos2, pos3, pos4, pos5, pos6, pos7, pos8)
# Braille blank pattern (u'\u2800').
blank = ''
points = []
# Position of dot1 along the x-axis (horizontal).
character_origin = 0
for c in text:
for m, p in zip(masks, pos):
delta_to_blank = ord(c) - ord(blank)
if (m & delta_to_blank):
points.append(p + Point(character_origin, 0))
character_origin += cell_geometry.intercell
return points
def get_plate_height(text_lines, cell_geometry):
# cell_geometry.vertical_interdot is also used as space between base
# borders and characters.
return (2 * cell_geometry.vertical_interdot +
2 * cell_geometry.vertical_interdot +
(len(text_lines) - 1) * cell_geometry.interline)
def get_plate_width(text_lines, cell_geometry):
# cell_geometry.horizontal_interdot is also used as space between base
# borders and characters.
max_len = max([len(t) for t in text_lines])
return (2 * cell_geometry.horizontal_interdot +
cell_geometry.horizontal_interdot +
(max_len - 1) * cell_geometry.intercell)
def get_cylinder_radius(cell_geometry):
"""Return the radius the cylinder should have
The cylinder have the same radius as the half-sphere make the dots (the
hidden and the shown part of the dots).
The radius is such that the spherical cap with diameter
cell_geometry.dot_diameter has a height of cell_geometry.dot_height.
"""
h = cell_geometry.dot_height
r = cell_geometry.dot_diameter / 2
return (r ** 2 + h ** 2) / 2 / h
def get_base_plate_thickness(plate_thickness, cell_geometry):
"""Return the height on which the half spheres will sit"""
return (plate_thickness +
get_cylinder_radius(cell_geometry) -
cell_geometry.dot_height)
def make_base(text_lines, cell_geometry, plate_thickness):
base_width = get_plate_width(text_lines, cell_geometry)
base_height = get_plate_height(text_lines, cell_geometry)
base_thickness = get_base_plate_thickness(plate_thickness, cell_geometry)
base = cq.Workplane('XY').box(base_width, base_height, base_thickness,
centered=(False, False, False))
return base
def make_embossed_plate(text_lines, cell_geometry):
"""Make an embossed plate with dots as spherical caps
Method:
- make a thin plate on which sit cylinders
- fillet the upper edge of the cylinders so to get pseudo half-spheres
- make the union with a thicker plate so that only the sphere caps stay
"visible".
"""
base = make_base(text_lines, cell_geometry, base_thickness)
dot_pos = []
base_width = get_plate_width(text_lines, cell_geometry)
base_height = get_plate_height(text_lines, cell_geometry)
y = base_height - 3 * cell_geometry.vertical_interdot
line_start_pos = Point(cell_geometry.horizontal_interdot, y)
for text in text_lines:
dots = brailleToPoints(text, cell_geometry)
dots = [p + line_start_pos for p in dots]
dot_pos += dots
line_start_pos += Point(0, -cell_geometry.interline)
r = get_cylinder_radius(cell_geometry)
base = base.faces('>Z').vertices('<XY').workplane() \
.pushPoints(dot_pos).circle(r) \
.extrude(r)
# Make a fillet almost the same radius to get a pseudo spherical cap.
base = base.faces('>Z').edges() \
.fillet(r - 0.001)
hidding_box = cq.Workplane('XY').box(
base_width, base_height, base_thickness, centered=(False, False, False))
result = hidding_box.union(base)
return result
_cell_geometry = BrailleCellGeometry(
horizontal_interdot,
vertical_interdot,
horizontal_intercell,
vertical_interline,
dot_height,
dot_diameter)
if base_thickness < get_cylinder_radius(_cell_geometry):
raise ValueError('Base thickness should be at least {}'.format(dot_height))
show_object(make_embossed_plate(text_lines, _cell_geometry))

View File

@ -1,45 +0,0 @@
import cadquery as cq
# The dimensions of the model. These can be modified rather than changing the
# object's code directly.
width = 400
height = 500
thickness = 2
# Create a plate with two polygons cut through it
result = cq.Workplane("front").box(width, height, thickness)
h_sep = 60
for idx in range(4):
result = result.workplane(offset=1, centerOption='CenterOfBoundBox').center(157,210-idx*h_sep).moveTo(-23.5,0).circle(1.6).moveTo(23.5,0).circle(1.6).moveTo(-17.038896,-5.7).threePointArc((-19.44306,-4.70416),(-20.438896,-2.3)).lineTo(-21.25,2.3).threePointArc((-20.25416,4.70416),(-17.85,5.7)).lineTo(17.85,5.7).threePointArc((20.25416,4.70416),(21.25,2.3)).lineTo(20.438896,-2.3).threePointArc((19.44306,-4.70416),(17.038896,-5.7)).close().cutThruAll()
for idx in range(4):
result = result.workplane(offset=1, centerOption='CenterOfBoundBox').center(157,-30-idx*h_sep).moveTo(-16.65,0).circle(1.6).moveTo(16.65,0).circle(1.6).moveTo(-10.1889,-5.7).threePointArc((-12.59306,-4.70416),(-13.5889,-2.3)).lineTo(-14.4,2.3).threePointArc((-13.40416,4.70416),(-11,5.7)).lineTo(11,5.7).threePointArc((13.40416,4.70416),(14.4,2.3)).lineTo(13.5889,-2.3).threePointArc((12.59306,-4.70416),(10.1889,-5.7)).close().cutThruAll()
h_sep4DB9 = 30
for idx in range(8):
result = result.workplane(offset=1, centerOption='CenterOfBoundBox').center(91,225-idx*h_sep4DB9).moveTo(-12.5,0).circle(1.6).moveTo(12.5,0).circle(1.6).moveTo(-6.038896,-5.7).threePointArc((-8.44306,-4.70416),(-9.438896,-2.3)).lineTo(-10.25,2.3).threePointArc((-9.25416,4.70416),(-6.85,5.7)).lineTo(6.85,5.7).threePointArc((9.25416,4.70416),(10.25,2.3)).lineTo(9.438896,-2.3).threePointArc((8.44306,-4.70416),(6.038896,-5.7)).close().cutThruAll()
for idx in range(4):
result = result.workplane(offset=1, centerOption='CenterOfBoundBox').center(25,210-idx*h_sep).moveTo(-23.5,0).circle(1.6).moveTo(23.5,0).circle(1.6).moveTo(-17.038896,-5.7).threePointArc((-19.44306,-4.70416),(-20.438896,-2.3)).lineTo(-21.25,2.3).threePointArc((-20.25416,4.70416),(-17.85,5.7)).lineTo(17.85,5.7).threePointArc((20.25416,4.70416),(21.25,2.3)).lineTo(20.438896,-2.3).threePointArc((19.44306,-4.70416),(17.038896,-5.7)).close().cutThruAll()
for idx in range(4):
result = result.workplane(offset=1, centerOption='CenterOfBoundBox').center(25,-30-idx*h_sep).moveTo(-16.65,0).circle(1.6).moveTo(16.65,0).circle(1.6).moveTo(-10.1889,-5.7).threePointArc((-12.59306,-4.70416),(-13.5889,-2.3)).lineTo(-14.4,2.3).threePointArc((-13.40416,4.70416),(-11,5.7)).lineTo(11,5.7).threePointArc((13.40416,4.70416),(14.4,2.3)).lineTo(13.5889,-2.3).threePointArc((12.59306,-4.70416),(10.1889,-5.7)).close().cutThruAll()
for idx in range(8):
result = result.workplane(offset=1, centerOption='CenterOfBoundBox').center(-41,225-idx*h_sep4DB9).moveTo(-12.5,0).circle(1.6).moveTo(12.5,0).circle(1.6).moveTo(-6.038896,-5.7).threePointArc((-8.44306,-4.70416),(-9.438896,-2.3)).lineTo(-10.25,2.3).threePointArc((-9.25416,4.70416),(-6.85,5.7)).lineTo(6.85,5.7).threePointArc((9.25416,4.70416),(10.25,2.3)).lineTo(9.438896,-2.3).threePointArc((8.44306,-4.70416),(6.038896,-5.7)).close().cutThruAll()
for idx in range(4):
result = result.workplane(offset=1, centerOption='CenterOfBoundBox').center(-107,210-idx*h_sep).moveTo(-23.5,0).circle(1.6).moveTo(23.5,0).circle(1.6).moveTo(-17.038896,-5.7).threePointArc((-19.44306,-4.70416),(-20.438896,-2.3)).lineTo(-21.25,2.3).threePointArc((-20.25416,4.70416),(-17.85,5.7)).lineTo(17.85,5.7).threePointArc((20.25416,4.70416),(21.25,2.3)).lineTo(20.438896,-2.3).threePointArc((19.44306,-4.70416),(17.038896,-5.7)).close().cutThruAll()
for idx in range(4):
result = result.workplane(offset=1, centerOption='CenterOfBoundBox').center(-107,-30-idx*h_sep).circle(14).rect(24.7487,24.7487, forConstruction=True).vertices().hole(3.2).cutThruAll()
for idx in range(8):
result = result.workplane(offset=1, centerOption='CenterOfBoundBox').center(-173,225-idx*h_sep4DB9).moveTo(-12.5,0).circle(1.6).moveTo(12.5,0).circle(1.6).moveTo(-6.038896,-5.7).threePointArc((-8.44306,-4.70416),(-9.438896,-2.3)).lineTo(-10.25,2.3).threePointArc((-9.25416,4.70416),(-6.85,5.7)).lineTo(6.85,5.7).threePointArc((9.25416,4.70416),(10.25,2.3)).lineTo(9.438896,-2.3).threePointArc((8.44306,-4.70416),(6.038896,-5.7)).close().cutThruAll()
for idx in range(4):
result = result.workplane(offset=1, centerOption='CenterOfBoundBox').center(-173,-30-idx*h_sep).moveTo(-2.9176,-5.3).threePointArc((-6.05,0),(-2.9176,5.3)).lineTo(2.9176,5.3).threePointArc((6.05,0),(2.9176,-5.3)).close().cutThruAll()
# Render the solid
show_object(result)

View File

@ -1,40 +0,0 @@
import cadquery as cq
# Points we will use to create spline and polyline paths to sweep over
pts = [
(0, 1),
(1, 2),
(2, 4)
]
# Spline path generated from our list of points (tuples)
path = cq.Workplane("XZ").spline(pts)
# Sweep a circle with a diameter of 1.0 units along the spline path we just created
defaultSweep = cq.Workplane("XY").circle(1.0).sweep(path)
# Sweep defaults to making a solid and not generating a Frenet solid. Setting Frenet to True helps prevent creep in
# the orientation of the profile as it is being swept
frenetShell = cq.Workplane("XY").circle(1.0).sweep(path, makeSolid=False, isFrenet=True)
# We can sweep shapes other than circles
defaultRect = cq.Workplane("XY").rect(1.0, 1.0).sweep(path)
# Switch to a polyline path, but have it use the same points as the spline
path = cq.Workplane("XZ").polyline(pts)
# Using a polyline path leads to the resulting solid having segments rather than a single swept outer face
plineSweep = cq.Workplane("XY").circle(1.0).sweep(path)
# Switch to an arc for the path
path = cq.Workplane("XZ").threePointArc((1.0, 1.5), (0.0, 1.0))
# Use a smaller circle section so that the resulting solid looks a little nicer
arcSweep = cq.Workplane("XY").circle(0.5).sweep(path)
# Translate the resulting solids so that they do not overlap and display them left to right
show_object(defaultSweep)
show_object(frenetShell.translate((5, 0, 0)))
show_object(defaultRect.translate((10, 0, 0)))
show_object(plineSweep.translate((15, 0, 0)))
show_object(arcSweep.translate((20, 0, 0)))

View File

@ -1,215 +0,0 @@
# 3d printer for mounting hotend to X-carriage inspired by the P3steel Toolson
# edition - http://www.thingiverse.com/thing:1054909
import cadquery as cq
def move_to_center(cqObject, shape):
'''
Moves the origin of the current Workplane to the center of a given
geometry object
'''
# transform to workplane local coordinates
shape_center = shape.Center().sub(cqObject.plane.origin)
# project onto plane using dot product
x_offset = shape_center.dot(cqObject.plane.xDir)
y_offset = shape_center.dot(cqObject.plane.yDir)
return cqObject.center(x_offset, y_offset)
# Parameter definitions
main_plate_size_y = 67 # size of the main plate in y direction
main_plate_size_x = 50. # size of the main plate in x direction
main_plate_thickness = 10. # thickness of the main plate
wing_size_x = 10. # size of the side wing supporting the bridge in x direction
wing_size_y = 10. # size of the side wing supporting the bridge in y direction
bridge_depth = 35. # depth of the bridge
support_depth = 18. # depth of the bridge support
cutout_depth = 15. # depth of the hotend cutout
cutout_rad = 8. # radius of the cutout (cf groove mount sizes of E3D hotends)
cutout_offset = 2. # delta radius of the second cutout (cf groove mount sizes of E3D hotends)
extruder_hole_spacing = 50. # spacing of the extruder mounting holes (Wade's geared extruder)
m4_predrill = 3.7 # hole diameter for m4 tapping
m3_predrill = 2.5 # hole diameter for m3 tapping
m3_cbore = 5. # counterbore size for m3 socket screw
mounting_hole_spacing = 28. # spacing of the mounting holes for attaching to x-carriage
aux_hole_depth = 6. # depth of the auxiliary holes at the sides of the object
aux_hole_spacing = 5. # spacing of the auxiliary holes within a group
aux_hole_N = 2 # number of the auxiliary hole per group
# make the main plate
res = cq.Workplane('front').box(main_plate_size_x,
main_plate_size_y,
main_plate_thickness)
def add_wing(obj, sign=1):
'''
Adds a wing to the main plate, defined to keep the code DRY
'''
obj = obj.workplane()\
.hLine(sign*wing_size_x)\
.vLine(-wing_size_y)\
.line(-sign*wing_size_x, -2*wing_size_y)\
.close().extrude(main_plate_thickness)
return obj
# add wings
# add right wing
res = res.faces('<Z').vertices('>XY')
res = add_wing(res)
# store sides of the plate for further reuse, their area is used later on to calculate "optimum" spacing of the aux hole groups
face_right = res.faces('>X[1]').val()
face_left = res.faces('>X[-2]').val()
# add left wing
res = res.faces('<Z').vertices('>Y').vertices('<X')
res = add_wing(res, -1)
# make the bridge for extruder mounting
wp = res.faces('>Z') # select top face
e = wp.edges('>Y') # select most extreme edge in Y direction
bridge_length = e.val().Length() # the width of the bridge equals to the length of the selected edge
# draw the bridge x-section and extrude
res = e.vertices('<X'). \
workplane(). \
hLine(bridge_length). \
vLine(-10). \
hLine(-bridge_length). \
close().extrude(bridge_depth)
faces = res.faces('>Z[1]') # take all faces in Z direction and select the middle one; note the new selector syntax
edge = faces.edges('>Y') # select the top edge of this face...
res = move_to_center(faces.workplane(), edge.val()).\
transformed(rotate=(0, 90, 0)) # ...and make a workplane that is centered in this edge and oriented along X direction
res = res.vLine(-support_depth).\
line(-support_depth, support_depth).\
close() # draw a triangle
res = res.extrude(main_plate_size_x/2, both=True, clean=True) # extrude the triangle, now the bridge has a nice support making it much more stiff
# Start cutting out a slot for hotend mounting
face = res.faces('>Y') # select the most extreme face in Y direction, i.e. top ot the "bridge"
res = move_to_center(face.workplane(), face.edges('>Z').val()) # shift the workplane to the center of the most extreme edge of the bridge
def make_slot(obj, depth=None):
'''
Utility function that makes a slot for hotend mounting
'''
obj = obj.moveTo(cutout_rad, -cutout_depth).\
threePointArc((0, -cutout_depth-cutout_rad),
(-cutout_rad, -cutout_depth)).\
vLineTo(0).hLineTo(cutout_rad).close()
if depth is None:
obj = obj.cutThruAll()
else:
obj = obj.cutBlind(depth)
return obj
res = make_slot(res, None) # make the smaller slot
cutout_rad += cutout_offset # increase the cutout radius...
res = make_slot(res.end().end(), -main_plate_thickness/2) # ...and make a slightly larger slot
res = res.end().moveTo(0, 0) \
.pushPoints([(-extruder_hole_spacing/2, -cutout_depth), (extruder_hole_spacing/2, -cutout_depth)]) \
.hole(m4_predrill) # add extruder mounting holes at the top of the bridge
# make additional slot in the bridge support which allows the hotend's radiator to fit
cutout_rad += 3*cutout_offset
res = make_slot(res.end().moveTo(0, 0).workplane(offset=-main_plate_thickness))
# add reinforcement holes
cutout_rad -= 2*cutout_offset
res = res.faces('>Z').workplane().\
pushPoints([(-cutout_rad, -main_plate_thickness/4),
(cutout_rad, -main_plate_thickness/4)]).\
hole(m3_predrill)
# add aux holes on the front face
res = res.moveTo(-main_plate_size_x/2., 0).workplane().rarray(aux_hole_spacing, 1, aux_hole_N, 1) \
.hole(m3_predrill, depth=aux_hole_depth)
res = res.moveTo(main_plate_size_x, 0).workplane().rarray(aux_hole_spacing, 1, aux_hole_N, 1) \
.hole(m3_predrill, depth=aux_hole_depth)
# make a hexagonal cutout
res = res.faces('>Z[1]')
res = res.workplane(offset=bridge_depth). \
transformed(rotate=(0, 0, 90)). \
polygon(6, 30).cutThruAll()
# make 4 mounting holes with cbores
res = res.end().moveTo(0, 0). \
rect(mounting_hole_spacing,
mounting_hole_spacing, forConstruction=True)
res = res.vertices(). \
cboreHole(m3_predrill,
m3_cbore,
bridge_depth+m3_cbore/2)
# make cutout and holes for mounting of the fan
res = res.transformed(rotate=(0, 0, 45)). \
rect(35, 35).cutBlind(-bridge_depth).end(). \
rect(25, 25, forConstruction=True).vertices().hole(m3_predrill)
def make_aux_holes(workplane, holes_span, N_hole_groups=3):
'''
Utility function for creation of auxiliary mouting holes at the sides of the object
'''
res = workplane.moveTo(-holes_span/2).workplane().rarray(aux_hole_spacing, 1, aux_hole_N, 1) \
.hole(m3_predrill, depth=aux_hole_depth)
for i in range(N_hole_groups-1):
res = res.moveTo(holes_span/(N_hole_groups-1.)).workplane().rarray(aux_hole_spacing, 1, aux_hole_N, 1) \
.hole(m3_predrill, depth=aux_hole_depth)
return res
# make aux holes at the bottom
res = res.faces('<Y').workplane()
res = make_aux_holes(res, main_plate_size_x*2/3., 3)
# make aux holes at the side (@overhang)
res = res.faces('<X').workplane().transformed((90, 0, 0))
res = make_aux_holes(res, main_plate_size_x*2/3., 3)
res = res.faces('>X').workplane().transformed((90, 0, 0))
res = make_aux_holes(res, main_plate_size_x*2/3., 3)
# make aux holes at the side (@main plate)
res = res.faces('|X').edges('<Y').edges('>X')
res = res.workplane()
res = move_to_center(res, face_right)
res = res.transformed((90, 0, 0))
hole_sep = 0.5*face_right.Area()/main_plate_thickness
res = make_aux_holes(res, hole_sep, 2)
# make aux holes at the side (@main plate)
res = res.faces('|X').edges('<Y').edges('<X')
res = res.workplane()
res = move_to_center(res, face_left)
res = res.transformed((0, 180, 0))
hole_sep = 0.5*face_right.Area()/main_plate_thickness
res = make_aux_holes(res, hole_sep, 2)
# show the result
show_object(res)

View File

@ -1,10 +0,0 @@
# Example using advanced logical operators in string selectors to select only
# the inside edges on a shelled cube to chamfer.
import cadquery as cq
result = cq.Workplane("XY").box(2, 2, 2).\
faces(">Z").shell(-0.2).\
faces(">Z").edges("not(<X or >X or <Y or >Y)").\
chamfer(0.125)
show_object(result)

View File

@ -101,7 +101,7 @@ class CadQueryExecuteExample:
# Start off defaulting to the Examples directory
module_base_path = module_locator.module_path()
exs_dir_path = os.path.join(module_base_path, 'Examples')
exs_dir_path = os.path.join(module_base_path, 'Libs/cadquery/examples/FreeCAD')
# Append this script's directory to sys.path
sys.path.append(os.path.dirname(exs_dir_path))
@ -247,7 +247,7 @@ class CadQueryOpenScript:
if self.previousPath is None:
# Start off defaulting to the Examples directory
module_base_path = module_locator.module_path()
exs_dir_path = os.path.join(module_base_path, 'Examples')
exs_dir_path = os.path.join(module_base_path, 'Libs/cadquery/examples/FreeCAD')
self.previousPath = exs_dir_path
@ -288,7 +288,7 @@ class CadQuerySaveScript:
# If the code pane doesn't have a filename, we need to present the save as dialog
if len(cqCodePane.file.path) == 0 or os.path.basename(cqCodePane.file.path) == 'script_template.py' \
or os.path.split(cqCodePane.file.path)[-2].endswith('Examples'):
or os.path.split(cqCodePane.file.path)[0].endswith('FreeCAD'):
FreeCAD.Console.PrintError("You cannot save over a blank file, example file or template file.\r\n")
CadQuerySaveAsScript().Activated()

View File

@ -99,7 +99,7 @@ class CadQueryWorkbench (Workbench):
# List all of the example files in an order that makes sense
module_base_path = module_locator.module_path()
exs_dir_path = os.path.join(module_base_path, 'Examples')
exs_dir_path = os.path.join(module_base_path, 'Libs/cadquery/examples/FreeCAD')
dirs = os.listdir(exs_dir_path)
dirs.sort()

@ -1 +1 @@
Subproject commit 654f04c2e7e21fb1ebefcca519da86bcb342ee83
Subproject commit 0a107cf9350c779c20e87342213021811113e244