Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using fillet() and cutThruAll() interact poorly #716

Open
wcraigtrader opened this issue Apr 5, 2021 · 5 comments
Open

Using fillet() and cutThruAll() interact poorly #716

wcraigtrader opened this issue Apr 5, 2021 · 5 comments

Comments

@wcraigtrader
Copy link

wcraigtrader commented Apr 5, 2021

If I build a part using a fillet() on the bottom-inside edges of a section removed from a larger part, and then try to use cutThruAll() to cut some vertical through holes, the holes turn into columns, or holes, or disappear entirely.

Code that fails:

part = (cq.Workplane().rect(142.875,213.360)
        .workplane(offset=-30.1625).rect(142.875,213.260)
        .loft()
        .cut(cq.Workplane().rect(128.99127,195.66627)
             .workplane(offset=-9.535).rect(127.0,193.675)
             .loft()
             .edges('<Z').fillet(0.4)
             .translate((0,0,0.01)).translate((0,0,0))
        )
        .faces('>Z')
        .moveTo(-62.8625,-96.2).circle(0.875).cutThruAll()
        .moveTo(-62.8625, 96.2).circle(0.875).cutThruAll()
        .moveTo( 62.8625,-96.2).circle(0.875).cutThruAll()
        .moveTo( 62.8625, 96.2).circle(0.875).cutThruAll()        
   )

Code that succeeds:

part = (cq.Workplane().rect(142.875,213.360)
        .workplane(offset=-30.1625).rect(142.875,213.260)
        .loft()
        .cut(cq.Workplane().rect(128.99127,195.66627)
             .workplane(offset=-9.535).rect(127.0,193.675)
             .loft()
             .translate((0,0,0.01)).translate((0,0,0))
        )
        .faces('>Z')
        .moveTo(-62.8625,-96.2).circle(0.875).cutThruAll()
        .moveTo(-62.8625, 96.2).circle(0.875).cutThruAll()
        .moveTo( 62.8625,-96.2).circle(0.875).cutThruAll()
        .moveTo( 62.8625, 96.2).circle(0.875).cutThruAll()        
   )

Other ways of cutting the holes also fail if fillet() is called, though they fail in different fashions.

@jmwright
Copy link
Member

jmwright commented Apr 5, 2021

I usually try to leave filleting to the end if possible since the CAD kernel can do some weird things with filleted objects. You can also simplify the moveTo() calls with pushPoints().

import cadquery as cq

part = (cq.Workplane().rect(142.875,213.360)
        .workplane(offset=-30.1625).rect(142.875,213.260)
        .loft()
        .cut(cq.Workplane().rect(128.99127,195.66627)
             .workplane(offset=-9.535).rect(127.0,193.675)
             .loft()
             .translate((0,0,0.01)).translate((0,0,0))
        )
        .faces('>Z').workplane()
        .pushPoints([(-62.8625,-96.2), (-62.8625, 96.2), ( 62.8625,-96.2), ( 62.8625, 96.2)]).circle(0.875).cutThruAll()
   )

part = part.edges('<Z').fillet(0.4)

show_object(part)

@wcraigtrader
Copy link
Author

Thanks for the suggestion on pushPoints(); that simplifies my code in several places and cuts the number of steps in the model from ~570 to ~230.

Moving the fillet() action isn't that easy in practice; in a large model the fillets are scattered all over the place. This was a 30-step section of an almost 600-step model.

@adam-urbanczyk
Copy link
Member

I think it is a combination of lofting/fillets that makes it more difficult for the kernel. Would this kind of modeling approach work?

W = 300
D = 200
H = 50

o = 20
alpha = 2

res = (
    cq.Workplane().rect(W,D).extrude(H,taper=alpha)
    .faces('>Z').workplane().rect(W-o,D-o).cutBlind(-H/2, taper=alpha)
    .faces('>Z[-2]').fillet(1)
    .faces('<Z').rect(W-1.15*o,D-1.15*o,forConstruction=True)
    .vertices().circle(1).cutThruAll()
)

@wcraigtrader
Copy link
Author

I went to using loft()/fillet() on your advice because extrude()/fillet() was unreliable, depending on the taper. See our conversation from the CadQuery group here: https://groups.google.com/g/cadquery/c/qEAMOFQkeD8

I looked at your solution, and I don't think it will work for me because it depends on knowing exactly how many vertical faces are in play faces('>Z[-2]'). Given the way I'm assembling my models (data-driven with layout managers), all of the CQ steps are scattered about and called as needed, with each section of the model knowing how to render itself, but knowing little to nothing about the rest of the model -- the layout managers do that. The sample that failed was originally built something like this:

class TestTray3(Tray):

    def contents(self):
        well = Well( x=4.875*inch, y=7.500*inch, z=3/8*inch, radius=0, pad=0.5*mm, draft=6 )
        return RowLayout( well )

tray = TestTray3( z=30, padding=2, vents=True )
part = tray.render()

In this case, Tray handles building the exterior box (aka buck) automatically (though you can specify the buck manually) from the size of the well, renders all of the components, and then optionally drills all of the vent holes. Well only knows how to render a box with appropriate draft angle, corner radius and where to place vent holes.

@wcraigtrader
Copy link
Author

wcraigtrader commented Apr 27, 2021

Here's another example without cutThruAll() that may help characterize the problems with fillet(). Again, the function is creating a truncated pyramid (the buck) and removing another truncated pyramid from the top (the well).

def test( r1, h1, f1 ):
    r2 = int( r1 )
    r3 = r1 + 10
    r4 = r3 + 1.5
    h2 = 5.00
    
    well = ( 
        cq.Workplane().rect(r1, r1).workplane(-h1).rect( r2, r2 )
        .loft()
        .edges('not(|X or |Y)').fillet(f1)
        .translate((0,0,0.01))
    )
    buck = (
        cq.Workplane().rect(r3, r3).workplane(-h2).rect(r4, r4)
        .loft()
        .cut( well )
    )
    return buck

This function fails to produce the correct result depending on all 3 parameters; altering any one of them will cause the function to succeed:

test( 26.418, 2.01, 3.175 ) # Fails
test( 26.410, 2.01, 3.175 ) # Succeeds
test( 26.418, 2.11, 3.175 ) # Succeeds
test( 26.418, 2.01, 3.150 ) # Succeeds

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants