Trying to revolve an ellipse into a head

289 views
Skip to first unread message

Dan Christian

unread,
Aug 29, 2022, 7:48:34 PM8/29/22
to CadQuery
I'm new to cq and am likely doing something dumb...

I'm trying to model a head in CQ, or at least half of one (the back doesn't matter).  The plan is to just build half a head and mirror it at the end.  I'm not trying for realism here.  It's really an enclosure that's very much like a head...

I don't see a way to create a 3D ellipse.  So I just do a 2D ellipse and revolve, right?

If I try the ellipse, I get the dreaded "command not done" on the revolve.  Does an ellipse not count as a wire?

So I try a polygon for the ellipse.  This makes the revolve work (yielding a kind of radiation symbol), but cutting away the negative half does nothing (I expected to retain just one lobe).  So I'm pretty confused on why the cut didn't remove anything.

I'm using cadquery and cq-editor from master (updated today).  All in mini-conda on Linux 64bit (Ubuntu 22.04).

Any help would be appreciated.
Thanks,
Dan

#!/usr/bin/env python3
import cadquery as cq
head_height = 120                        # distance from top to bottom
head_width2 = 50                         # half the width
head_depth = 50                          # front of forehead to base

obj = cq.Workplane("XY")
#obj = obj.ellipse(head_height/2, head_width2)
obj = obj.polygon(180, head_width2)
obj = obj.revolve(90, (0,0,0), (1,0,0))

# Box to subtract the negative half
neg = cq.Workplane("XY").box(head_height, head_width2, head_depth*2)
neg = neg.translate([0, -head_width2 / 2, 0])
obj = obj.cut(neg)

if "show_object" in locals():
    show_object(obj)

Dan Christian

unread,
Aug 29, 2022, 8:19:07 PM8/29/22
to CadQuery
This seems to have fixed the ellipse case.  If I use ellipseArc, then I can force it to be wire (ellipse doesn't have the option), and I can get the right hemisphere (no cut required).
 
        obj = obj.ellipseArc(head_height/2, head_width2,
                             0, 180, makeWire=True)
        obj = obj.revolve(90, (0, 0, 0), (1, 0, 0))
        obj = obj.translate((head_height/2, 0, 0))

I'd still like to understand the original problems if someone is willing to comment.

Lorenz Neureuter

unread,
Aug 29, 2022, 8:46:35 PM8/29/22
to Dan Christian, CadQuery
Hi Dan,

Here is an example that revolves a half-circle.

da = 180  # fails when da > 180
obj = cq.Workplane().sketch().arc((0, 0), 10, 0, da).close().assemble().finalize()

obj = obj.revolve(90, (0, 0, 0), (1, 0, 0))

Note that this fails when da > 180.  The face to revolve must not cross the axis of rotation.

--
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/CAEcGQ%2BNxk2e5OTHSZRcj%3D1jTZxmffy-ApqOKiy%2Bwwv3C8NoWrw%40mail.gmail.com.

Dan Christian

unread,
Aug 30, 2022, 6:15:08 PM8/30/22
to Lorenz Neureuter, CadQuery
I thought that I had this working, but the object is marked invalid.

Here is the current code:
import cadquery as cq

head_height = 120
head_width2 = 50
head_depth = 50


obj = cq.Workplane("XY")
obj = obj.ellipseArc(head_height/2, head_width2, 0, 180, makeWire=True)
obj = obj.revolve(90, (0, 0, 0), (1, 0, 0))
obj = obj.translate((head_height/2, 0, 0))
if not obj.findSolid().isValid():
    print("object isn't valid")

show_object(obj)

This renders what I expect, but shows object isn't valid.  Later operations on the object fail in weird ways.

I see there is a fix() call, but I'm not sure how to use it (or what it can fix).
I tried:
obj.findSolid().fix()
But that returns a new object, which I don't know how to re-insert into the workplane ('cause I'm a newbie).

Dan
halfhead.png

Roger Maitland

unread,
Aug 30, 2022, 6:30:12 PM8/30/22
to Dan Christian, Lorenz Neureuter, CadQuery
Try this:
import cadquery as cq

head_height = 120
head_width2 = 50
head_depth = 50
eye_height = 20
eye_offset = 40
eye_depth = 20


def eyesocket():
obj = cq.Workplane("XY").box(eye_height, head_width2, eye_depth)
obj = obj.translate([eye_height / 2, -head_width2 / 2, eye_depth / 2])
obj = obj.rotate((0, 0, 0), (1, 0, 0), 180)
obj = obj.translate([-eye_offset, 0, head_depth])
return obj

sock = eyesocket()

head = (
cq.Workplane("XZ")
.lineTo(head_width2, 0)
.ellipseArc(head_width2, head_height, angle1=0, angle2=90)
.close()
.revolve(360, axisStart=(0, 0, 0), axisEnd=(0, 1, 0))
.cut(sock)
.cut(sock.translate((1.5 * eye_offset, 0, 0)))
)

show_object(head)
image.png
Objects that are revolved can't cross the axis of revolution which might be why revolved objects aren't valid.

Cheers,
Roger

Dan Christian

unread,
Aug 30, 2022, 7:40:25 PM8/30/22
to CadQuery
I may be missing what you're suggesting.  Creating a different shape isn't helping me at all.

The ellipseArc is not crossing the axis of revolution in either 2D or 3D.  It goes right to it, but does not cross.

I wondered if the ellipseArc wasn't closed, I tried adding .close() to the end of the 2D line.  However, this gave me an error about not being able to convert the wire to a vector (which doesn't make sense to me).

Dan

Lorenz Neureuter

unread,
Aug 30, 2022, 8:21:38 PM8/30/22
to Dan Christian, CadQuery
> I wondered if the ellipseArc wasn't closed, I tried adding .close() to the end of the 2D line. 
Yes, that is the problem.  The wire is not closed.  You can set makeWire=False, then close() will build the wire.

    obj = obj.ellipseArc(head_height/2, head_width2, 0, 180, makeWire=False)
    obj = obj.close()


Dan Christian

unread,
Aug 30, 2022, 8:34:47 PM8/30/22
to CadQuery
Yes, that works perfectly.
Thank you,
Dan
Reply all
Reply to author
Forward
0 new messages