cadquery icon indicating copy to clipboard operation
cadquery copied to clipboard

Cutting or splitting assemblies/compounds produces wrong result

Open qwelyt opened this issue 3 years ago • 1 comments

Sample code

import cadquery as cq

space = 19.05
cherryCutOutSize=14.05
cherrySize=14.58
cols = 2
rows = 4

width = cols * space
depth = rows * space
lip=3
height = 10
plateThickness=3

bottom = (cq.Workplane("XY")
          .box(width,depth,height)
          .faces("+Z")
          .shell(lip)
          .faces(">Z")
          .wires(cq.selectors.AreaNthSelector(-1))
          .toPending()
          .workplane()
          .extrude(1)
          .faces(">Z")
          .wires()
          .item(0)
          .toPending()
          .workplane()
          .offset2D(-lip/2)
          .cutBlind(-plateThickness)
          )

cherryCut = (cq.Workplane()
             .box(cherryCutOutSize, cherryCutOutSize, plateThickness+2)
             
             # Side cuts
             .faces(">Z")
             .edges("|Y")
             .rect(1,4)
             .cutThruAll()
             
             # Potrusions
             .faces(">Y or <Y")
             .edges("<Z")
             .rect(4,1)
             .extrude(plateThickness+1)
             
             # Add chamfer to potrusions
             .faces(">Y or <Y")
             .edges(">Z")
             .chamfer(0.2,0.4)
             )

plate = (cq.Workplane("XY")
    .box(width,depth,plateThickness)
    .faces(">Z")
    .workplane()
    .rarray(space,space,cols,rows,True)
    .cutEach(lambda loc: cherryCut.val().moved(loc).translate((0,0,-2)))
    )


top = (cq.Workplane("XY")
          .box(width,depth,height/2)
          .faces("-Z")
          .shell(lip)
          .faces(">Z")
          .rect(width-lip,depth-lip)
          .cutThruAll()
           .faces("<Z")
           .wires(cq.selectors.AreaNthSelector(-1))
           .toPending()
           .workplane()
           .extrude(1)
           .faces("<Z")
           .wires()
           .item(0)
           .toPending()
           .workplane()
           .offset2D(-lip/2)
           .cutBlind(-plateThickness)
          )
cherry = cq.Workplane("XY").box(15.6,15.6,3.6+11.6+3.3)
switches = (cq.Workplane()
            .rect(width,depth, forConstruction=True)
            .rarray(space,space,cols,rows,True)
            .eachpoint(lambda loc: cherry.val().moved(loc))
            .combine(glue=True)
          )

dsa1u = cq.Workplane("XY").box(15.6,15.6,10)
caps = (cq.Workplane()
            .rect(width,depth, forConstruction=True)
            .rarray(space,space,cols,rows,True)
            .eachpoint(lambda loc: dsa1u.val().moved(loc))
            .combine(glue=True)
          )

keyboard = (cq.Assembly()
    .add(bottom, name="bottom", color=cq.Color(0, 0, 1, 1))
    .add(plate, name="plate", color=cq.Color(1,1,0,1))
    .add(switches, name="switches", color=cq.Color(0,1,0,1))
    .add(caps, name="caps", color=cq.Color(1,0,1,1))
    .add(top, name="top", color=cq.Color(0,1,1,1))
    )

switches.faces("<X").edges(">Y").vertices(">Z").tag("refpoint")
bottom.faces("<X[-4]").tag("xface")
bottom.faces(">Y[-4]").tag("yface")
(keyboard
 .constrain("bottom@faces@>Z", "plate@faces@<Z", "PointInPlane", param=-1.5)
 .constrain("plate@faces@>Z", "switches@faces@<Z", "PointInPlane", param=-7.7)
  .constrain("switches@faces@>Z", "caps@faces@<Z", "PointInPlane", param=-3)
 .constrain("plate@faces@>Z", "top@faces@<Z", "PointInPlane", param=-1.5)
 
.constrain("plate@faces@<X", "bottom@faces@<X", "Axis")
.constrain("plate@faces@<Y", "bottom@faces@<Y", "Axis")
.constrain("plate@faces@<X", "switches@faces@<X", "Axis")
.constrain("plate@faces@<Y", "switches@faces@<Y", "Axis")
.constrain("plate@faces@<X", "top@faces@<X", "Axis")
.constrain("plate@faces@<Y", "top@faces@<Y", "Axis")
.constrain("plate@faces@<X", "caps@faces@<X", "Axis")
.constrain("plate@faces@<Y", "caps@faces@<Y", "Axis")
)

keyboard.solve()
print(keyboard.toCompound().isValid())
kwp = cq.Workplane(keyboard.toCompound())
half = (kwp
        .faces("<Z")
        .workplane()
        .hole(20)
)

half2 = (kwp
         .faces("<Z")
         .workplane()
         .rect(20,20)
         .cutThruAll()
         .translate((80,0,0))
) 

cutBox = cq.Workplane("XY").box(20,200,50)
half3 = (kwp
         .faces("<Z")
         .workplane()
         .cut(cutBox)
         .translate((-80,0,0))
)

half4 = (kwp
         .faces("<Y")
         .workplane(offset=-30)
         .split(keepTop=True)
         .translate((0,-100,0))
         )
show_object(half)
show_object(half2)
show_object(half3)
show_object(half4)
debug(cutBox.translate((-80,0,0)))

Running this code should give this result image

Neither of which is expected. It seems like cq is unable to properly split or cut compounds here. I would expect split to work just like on any other solid. Giving me the the split object, not this result. And I would expect cut and cutThruAll to cut thru the entire piece, not just some layers of it.

qwelyt avatar Jan 22 '22 10:01 qwelyt

I have the same issue with this code (the cone cannot be cut completely).

import cadquery as cq
from math import cos, sin, sqrt, pi, ceil
from cadquery import Vector

export_flag = True
cone_angle = 20
angle_rad = cone_angle/180 * pi
thickness = 10
base_width = 300
base_rad = base_width/2
radius = base_rad/cos(cone_angle/360 * 2 * pi)
min_height = 2
max_height = 30
med_height = min_height+(min_height+max_height)/2
frame_thickness = 4
cone_thickness = 4
insert_diam = 286
diffuser_margin = 5.5
screw_holes_rad = 4.5
nut_holes_rad = screw_holes_rad * 2
screw_holes_depth = 80
nut_holes_depth = 80
screw_holes_height = -56.596

cone_pts = [[0,0],[0, -cone_thickness],[base_rad-base_rad*cone_thickness/(sin(angle_rad)*radius),-sin(angle_rad)*radius],[base_rad,-sin(angle_rad)*radius],[0,0]]

cone = cq.Workplane("XZ")
cone = cone.polyline(cone_pts)
cone = cone.faces("+Z")
cone = cone.wire()
cone = cone.toPending()
cone = cone.revolve(360, (0, 0, 0), (0, 1, 0))

diffuser_holes_pts  = [[sin(i/4 * 2 * pi + pi/8) * (insert_diam/2+diffuser_margin), cos(i/4 * 2 * pi + pi/8) * (insert_diam/2+diffuser_margin)] for i in range(4)]

screw_holes = cq.Workplane("XY", origin = (0,0,screw_holes_height-10))
screw_holes = screw_holes.pushPoints(diffuser_holes_pts).circle(screw_holes_rad).rotate((0,0,-1), (0,0,1), 45)
screw_holes = screw_holes.extrude(screw_holes_depth)
nut_holes = cq.Workplane("XY", origin = (0,0,screw_holes_height+6))
nut_holes = nut_holes.pushPoints(diffuser_holes_pts).circle(nut_holes_rad).rotate((0,0,-1), (0,0,1), 45)
nut_holes = nut_holes.extrude(nut_holes_depth)
main_holes = cq.Assembly()
main_holes = main_holes.add(screw_holes)
main_holes = main_holes.add(nut_holes)
main_holes = main_holes.toCompound()
cone = cone.cut(screw_holes)
show_object(main_holes, options = {"alpha":0.9, "color": (255, 0, 255)})
show_object(cone, options = {"alpha":0., "color": (255, 63, 0)})

nesdnuma avatar Jun 17 '22 12:06 nesdnuma