CadQuery / CadQuery/cadquery

Proper way to extrude a planar face along its normal?

Open
#1,043 2 comments 1 reaction 0 assignees View on GitHub
question
Dominant language
Python
Stars
5.8k
Forks
541
Avg merge
3d 2h
Merged PRs (30d)
5

Description

Hello, I've seen this snippet given as the way to extrude a planar face:

```python
cq.Workplane().box(10, 20, 30).faces('>Z').wires().toPending().extrude(10, taper=15)
```

However, it does not work for all planar faces. For example, changing `>Z` to `>Y` causes a "ValueError: Null TopoDS_Shape object" error, even though fundamentally there should be no reason for it, I think.

The reason seems to be that Workplane's `extrude` method hardcodes the direction of extrusion as `self.plane.zDir` ([source](https://github.com/CadQuery/cadquery/blob/3f6da6d8b528d1556382e691b92b70a8e6c5d1b6/cadquery/cq.py#L3607-L3610)), and I guess selecting `.faces()` does not affect `self.plane`.

When extruding a face, I would expect extrude direction to default to the selected face's normal, not `self.plane` normal. I guess the same would apply to extruding any supported wire, although perhaps there isn't enough information in the wire to know which of the two sides the normal is pointing to (if that makes sense).

Perhaps CadQuery could let users provide a custom extrusion direction to `extrude`, and also default to the selected face's normal when using this (currently unsupported) syntax: `.faces('>Z').extrude(10, taper=15)`? That would be backwards-compatible, although I don't know if that's actually possible.

I found an old suggestion to just force-override `self.plane.zDir` along with a warning not to do that. So, building on that idea, the following appears to work:

```python
def extrudeFaces(wp: Workplane, selector: str, until: float, taper: float = 0):
originalNormal = wp.plane.zDir
faceWp = wp.faces(selector)
faceNormal = faceWp.val().normalAt()
faceWp.plane.zDir = faceNormal
result = faceWp.wires().toPending().extrude(until, taper = taper)
faceWp.plane.zDir = originalNormal
return result

extrudeFaces(cq.Workplane("XY").box(10, 20, 30), '>Y', until = 5, taper = 15)
```

I'm not sure what are the risks of messing with `plane.zDir` this way. Is the above a good / safe approach to the problem? If yes, maybe CadQuery could have something like that built-in?

It's entirely possible that I've missed some obvious feature / mechanic of CadQuery, but the above is the best I got at the moment.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.