Projecting Holes

209 views
Skip to first unread message

Anthony Sokolowski

unread,
Nov 25, 2021, 11:11:57 PM11/25/21
to CadQuery
Looking for some advise to project holes from one part onto another in an assembly to created bolted connections?

See example code below:

import cadquery as cq

plate = cq.Workplane().box(100,100,1)
bolted_part = (
    cq.Workplane()
    .box(10,10,1)
    .pushPoints([(3,3), (-3, -3)])
    .circle(1)
    .cutThruAll())

assembly = (
    cq.Assembly()
    .add(plate,
         name="plate")
    .add(
        bolted_part,
        name='part',
        loc=cq.Location(cq.Vector(25, 0, 1)))
    )

show_object(assembly)

bolted-connection.PNG

How would you guys project the holes on the top plate to the bottom plate?

Roger Maitland

unread,
Nov 26, 2021, 12:20:29 PM11/26/21
to Anthony Sokolowski, CadQuery
Here is how you can do this with cq_warehouse and get the screws too:
import cadquery as cq
from cq_warehouse.fastener import SocketHeadCapScrew

# Create the screws that will fasten the plates together
cap_screw = SocketHeadCapScrew(
size="M2-0.4", length=5, fastener_type="iso4762", simple=False
)

# Two assemblies are required - the top will contain the screws
top_plate_assembly = cq.Assembly(None, name="top_plate_assembly")
base_plate_assembly = cq.Assembly(None, name="base_plate_assembly")

# Create the top plate and add clearance holes for the screws
top_plate = (
cq.Workplane()
.box(10, 10, 1, centered=(True, True, False))
.faces(">Z")
.workplane()
.pushPoints([(3, 3), (-3, -3)])
.clearanceHole(
fastener=cap_screw, counterSunk=False, baseAssembly=top_plate_assembly
)
)
# Define the location of the top plate relative to the base plate
top_plate_location = cq.Vector(25, 0, 1)

# Extract the bolt locations that will be used to create holes in the base plate
base_bolt_hole_locations = [
cq.Vector(screw.loc.toTuple()[0]) + top_plate_location
for screw in top_plate_assembly.children
]
# Add the top plate to the top assembly so it can be placed with the screws
top_plate_assembly.add(top_plate)
# Add the top plate and screws to the base assembly
base_plate_assembly.add(
top_plate_assembly, name="top_plate_assembly", loc=cq.Location(top_plate_location)
)

# Create the base plate with tap holes that align with the top plate
base_plate = (
cq.Workplane()
.box(65, 100, 1, centered=(True, True, False))
.faces(">Z")
.workplane()
.pushPoints(base_bolt_hole_locations)
.tapHole(fastener=cap_screw, counterSunk=False)
)
# Complete the base plate assembly by adding the top assembly and base plate
base_plate_assembly.add(base_plate, name="base_plate")

if "show_object" in locals():
show_object(top_plate, name="top_plate")
show_object(base_plate, name="base_plate")
show_object(base_plate_assembly, name="plate_assembly")

The result looks like this:
align_fastener_holes.py.png
Would a cq_warehouse.fastener method that returns the locations of fasteners be useful?

Cheers,
Roger

--
cadquery home: https://github.com/CadQuery/cadquery
post issues at https://github.com/CadQuery/cadquery/issues
run it at home at : https://github.com/CadQuery/CQ-editor
---
You received this message because you are subscribed to the Google Groups "CadQuery" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cadquery/67731228-c611-412b-ba96-48dbc1f46a1an%40googlegroups.com.

Adam Urbanczyk

unread,
Nov 27, 2021, 2:25:04 PM11/27/21
to CadQuery
Not exactly projecting, but since recently you can define on sketch (cq.Sketch) with the hole pattern, place it on both parts, cut and then assemble them. Take a look here:  https://cadquery.readthedocs.io/en/latest/sketch.html#workplane-integration

Anthony Sokolowski

unread,
Nov 29, 2021, 4:18:53 PM11/29/21
to CadQuery
Using Cq Warehouse is a great solution as I can model the bolts and holes in the connection at the same time.
I think a method that returns all the locations of fasteners may work well as I can loop through each one and cut out matching holes in each corresponding part. This would allow one to build the model without fasteners and then add them in as an afterthought and easily make the holes as required.
Using sketches is the solution that I was originally looking for but it seems that cq warehouse option will work better for me.

Thanks for the replies.

Roger Maitland

unread,
Dec 17, 2021, 4:29:51 PM12/17/21
to Anthony Sokolowski, CadQuery
I've updated cq_warehouse with a couple new methods to address this hole alignment question.  Consider the following example:
import cadquery as cq
from cq_warehouse.fastener import SocketHeadCapScrew

# Create the screws that will fasten the plates together
cap_screw = SocketHeadCapScrew(
size="M2-0.4", length=6, fastener_type="iso4762", simple=False
)

# Two assemblies are required - the top will contain the screws
bracket_assembly = cq.Assembly(None, name="top_plate_assembly")
square_tube_assembly = cq.Assembly(None, name="base_plate_assembly")

# --- Angle Bracket ---

# Create an angle bracket and add clearance holes for the screws
angle_bracket = (
cq.Workplane("YZ")
.moveTo(-9, 1)
.hLine(10)
.vLine(-10)
.offset2D(1)
.extrude(10, both=True)
.faces(">Z")
.workplane()
.pushPoints([(5, -5), (-5, -5)])
.clearanceHole(fastener=cap_screw, counterSunk=False, baseAssembly=bracket_assembly)
.faces(">Y")
.workplane()
.pushPoints([(0, -7)])
.clearanceHole(fastener=cap_screw, counterSunk=False, baseAssembly=bracket_assembly)
)
# Add the top plate to the top assembly so it can be placed with the screws
bracket_assembly.add(angle_bracket, name="angle_bracket")
# Add the top plate and screws to the base assembly
square_tube_assembly.add(
bracket_assembly,
name="top_plate_assembly",
loc=cq.Location(cq.Vector(20, 10, 10)),
)

# --- Square Tube ---

# Create the square tube
square_tube = (
cq.Workplane("YZ").rect(18, 18).rect(14, 14).offset2D(1).extrude(30, both=True)
)
# Complete the square tube assembly by adding the square tube
square_tube_assembly.add(square_tube, name="square_tube")
# Add tap holes to the square tube that align with the angle bracket
square_tube = square_tube.pushFastenerLocations(
cap_screw, square_tube_assembly
).tapHole(fastener=cap_screw, counterSunk=False, depth=10)


# Where are the cap screw holes in the square tube?
for loc in square_tube_assembly.fastenerLocations(cap_screw):
print(loc)

# How many fasteners are used in the square_tube_assembly and all sub-assemblies
print(square_tube_assembly.fastenerQuantities())

if "show_object" in locals():
show_object(angle_bracket.translate((0, -40, 0)), name="angle_bracket")
show_object(square_tube.translate((0, -25, 0)), name="square_tube")
show_object(square_tube_assembly, name="square_tube_assembly")

This example shows how the holes made in the top and side of the `angle_bracket` are extracted by the `pushFastenerLocations()` method for use in creating `tapHole` (or any other feature) in the `square_tube`. This results in the following:
fastenerLocations.png

This cq_warehouse feature is dependent on a very recent change in CadQuery so be sure to update to the latest version of master.

Cheers,
Roger

--
cadquery home: https://github.com/CadQuery/cadquery
post issues at https://github.com/CadQuery/cadquery/issues
run it at home at : https://github.com/CadQuery/CQ-editor
---
You received this message because you are subscribed to the Google Groups "CadQuery" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+u...@googlegroups.com.

Anthony Sokolowski

unread,
Dec 17, 2021, 11:03:34 PM12/17/21
to CadQuery
This is a great feature.
Thank you.
Reply all
Reply to author
Forward
0 new messages