cadquery
cadquery copied to clipboard
Selected faces must be co-planar
Hi, I have the following code snippet:
def perFace(face: cq.Workplane):
return (
face.box(2, 2, 2)
)
part = (
cq.Workplane("XY")
.polygon(6, (radius + wall + shift)*2, circumscribed=True)
.extrude(-partHeight)
)
part = (
part.faces("#Z")
.workplane()
.each(perFace)
)
I am trying to apply the box to each side face of the polygon, but I get the error ValueError: Selected faces must be co-planar
How can I repeat the operation in the function perFace for each selected face? faces("#Z").workplane().each(perFace) seems not to work 🤔
I got it running now, but very ugly. Is there a better way?
faceCenters: list[cq.Vector] = []
def perFace(face: cq.Face):
faceCenters.append(face.CenterOfBoundBox())
return face
part = (
cq.Workplane("XY")
.polygon(6, (radius + wall + shift)*2, circumscribed=True)
.extrude(-partHeight)
)
part = (
part.faces("#Z")
.each(perFace, combine=False)
)
for faceCenter in faceCenters:
part = (
part
.faces(cq.NearestToPointSelector((faceCenter.x, faceCenter.y, faceCenter.z)))
.workplane(centerOption="CenterOfBoundBox")
.box(2, 2, 2)
)
And why .faces(cq.NearestToPointSelector(faceCenter)) throws the error TypeError: cadquery.occ_impl.geom.Vector() argument after * must be an iterable, not Vector?
There's a plugin for this. Even if you don't use it, maybe it's got some code you could reuse. https://github.com/CadQuery/cadquery-plugins/tree/main/plugins/apply_to_each_face
Ah cool, thank you 👍🏻
@jniclas note that each requires callables with the following signature:
Callable[[Union[cadquery.occ_impl.geom.Vector, cadquery.occ_impl.geom.Location, cadquery.occ_impl.shapes.Shape, cadquery.sketch.Sketch]], cadquery.occ_impl.shapes.Shape]
Yours was returning a Workplane and not a Shape.
@adam-urbanczyk I can not figure out how to add shapes with the each method, when the argument is a Face, and without using the plugin.
Could you give me a hint on that sinppet?:
def perFace(face: cq.Face):
return (
...?
.box(2, 2, 2)
)
part = (
cq.Workplane("XY")
.polygon(6, 10, circumscribed=True)
.extrude(50)
.faces("#Z")
.each(perFace)
)
The point was that you need to return a Shape and not a Workplane. So if you insist on using cq.Workplane, it could be:
def perFace(face: cq.Face):
return cq.Workplane(origin=face.Center()).box(1,1,1).val()
But I don't know if this is what you actually want.