CadQuery / cadquery

A python parametric CAD scripting framework based on OCCT
https://cadquery.readthedocs.io
Other
2.95k stars 276 forks source link

How to select different edges? #1073

Closed 1knueller closed 2 years ago

1knueller commented 2 years ago

Hi!

I found i can find the top and the bottom with .edges(">Z") and .edges("<Z") (and probably of non cylindrical objects with other axis) but how do i get the middle ones?

import cadquery as cq
from cadquery import Workplane, Sketch, Vector, Location
from cadquery import exporters

r1 = 52.7/2
rbot = 20
hbot = 3
hmass =10
rgrip = 28.8/2
gripZStart = (hmass)/2

s2 = (
     Sketch()
     .circle(r1)
     )

s1 = (
     Sketch()
     .circle(rbot)
     )

wp1 = (
    Workplane()
    .placeSketch(s1, s2.moved(Location(Vector(0, 0, hbot))))
    .loft()
    )

wp2 = wp1.faces(">Z").first()
s1 = wp1.solids()

mass = wp2.circle(r1).extrude(hmass)

here how can i select the middle edge?

I tried indexing like [1]. The object gets more complicated and with holes. id like to be able to select different edges.

I also the (|(1,0,0)) instead of the Z> but i dont know where those magic strings could be defined. can you additionally help me. i cant find anything in the docs except for some examples being used sometimes.

jmwright commented 2 years ago

When faces are non-planar (along the axis you want to select on), you sometimes have to get creative with selectors. If the faces in the X and Y axes were planar, you could select .faces(">Y") and then .edges("<Z") to get the edge. Your case requires a different approach.

There are probably other ways of doing it, but the following will select and fillet that middle edge, and is relatively straight forward.

mass = mass.edges("(not >Z) and (not <Z)").fillet(2.0)

middle_fillet_screenshot

For specifying an axis to select on, you can do the following.

stand.faces('>Z').edges('|(1,1,0) or |(1,-1,0)')

You can also select based on edge or face type, and that can be useful for something like picking a circular edge out from among linear edges.

Selector reference in the docs

1knueller commented 2 years ago

thanks alot for the detailed description! this reference to the docs is perfect.

hastelloy commented 2 years ago

I have read through the selector reference but still not fully understand it. Could anyone help to explain below case for selecting the edges of ra and rb for fillet? Using item() works, but I don't know how is it indexed, i.e. why it is item(3)...

Screenshot 2022-05-04 214619

import cadquery as cq
from cadquery import exporters

DA = 25.4*13
A = 25.4*3
DB = 25.4*11
B = 25.4*2.75
DC = 25.4*9
L = 25.4*11.75
bore = 25.4*2

ra = 20
rb = 10
r = 2

result = (cq.Workplane('XY').circle(DA/2).extrude(A)
          .faces('>Z').workplane().circle(DC/2).tag('fa').extrude(L-A-B)
        # add fillet to the lower flange (A),
        .edges().item(3).fillet(ra)
        .faces('>Z').workplane().circle(DB/2).extrude(B)
        # add fillet to the upper flange (B)
        .edges().item(3).fillet(rb)
        .faces(">Z").workplane().hole(bore).fillet(r)

        )
jmwright commented 2 years ago

I would probably do something like this, which selects the face you want, and then selects the innermost circle (index 0). Notice also that I fillet at the end. If you can do this it will help avoid CAD kernel and selector issues. If you need to add them in place because the design requires it, that's fine too, I just try to minimize fillets until I'm ready to finish and manufacture the part.

import cadquery as cq
from cadquery import exporters

DA = 25.4*13
A = 25.4*3
DB = 25.4*11
B = 25.4*2.75
DC = 25.4*9
L = 25.4*11.75
bore = 25.4*2

ra = 20
rb = 10
r = 2

result = (cq.Workplane('XY').circle(DA/2).extrude(A)
          .faces('>Z').workplane().circle(DC/2).tag('fa').extrude(L-A-B)
        # add fillet to the lower flange (A),
        #.edges().item(3).fillet(ra)
        .faces('>Z').workplane().circle(DB/2).extrude(B)
        # add fillet to the upper flange (B)
        #.edges().item(3).fillet(rb)
        .faces(">Z").workplane().hole(bore)#.fillet(r)
        .faces(">Z[-2]").edges(cq.selectors.RadiusNthSelector(0)).fillet(ra)
        .faces("<Z[-2]").edges(cq.selectors.RadiusNthSelector(0)).fillet(ra)
        .fillet(r)
        )

show_object(result)
hastelloy commented 2 years ago

Thanks for the detailed explanation...