Open chaffra opened 7 months ago
The "Plane" constraint is stronger than "Axis" plus "PointInPlane", and it can make the first part's center meet the second part's center as close as possible. In your case, there are 25 faces for bumps.faces("<Z"), and CQ's assembly takes the first one (-16.0, -16.0)[the one enclosed by the green circle] as the object of "bumps@faces@<Z". So the constraint
assy.constrain("roic@faces@>Z", "bumps@faces@<Z", "Plane")
makes the bottom face center of enclosed cylinder by the green circle and the top face center of the box coincidence.
Using the following constraints can do the job. assy.constrain("roic@faces@>Z", "bumps@faces@<Z", "Axis") assy.constrain("roic@faces@>Z", "bumps@faces@<Z", "PointInPlane") assy.constrain("roic@faces@<Y", "bumps@faces@>Y", "Axis") assy.constrain("roic@faces@>Z", "bumps", "Point", param=(h/2))
Or the following constraints can also do the job. assy.constrain("roic@faces@>Z", "bumps@faces@<Z", "Axis") assy.constrain("roic@faces@>Z", "bumps@faces@<Z", "PointInPlane") assy.constrain("roic", "FixedRotation", (0, 0, 0)) assy.constrain("bumps", "FixedRotation", (0, 0, 0)) assy.constrain("roic@faces@>Z", "bumps", "Point", param=(h/2))
Change this: https://github.com/CadQuery/cadquery/blob/3451007f8eeb9d78e784ec8047ef69a5359ecb5e/cadquery/assembly.py#L271
to something like?:
if len(res.vals()) > 1:
if shapes:= _selectShapes(res.objects):
center = Shape.CombinedCenter(shapes)
res = getattr(res, query.selector_kind)(NearestToPointSelector(center.toTuple()))
val = res.val()
Then the original example posted here works as expected.
Otherwise can select and tag single object:
bumps.faces("<Z").faces(cq.selectors.NearestToPointSelector((0, 0, 0))).tag("centerface")
#...
assy.constrain("roic", "Fixed")
assy.constrain("roic@faces@>Z", "bumps?centerface", "Plane")
Thanks! Both solutions work. Maybe a deeper issue I was after is that you have to use assemblies to get colors. A simpler implementation would be like below but it's missing colors. It would be nice if the primitives could have colors when displaying. Should I file a feature request for that? Something like box(..., color=cq.Color('pink'))
would be useful.
rows = 8
cols = 8
pitch = 8
dx = cols*pitch
dy = rows*pitch
dz = 3*pitch
#roic
assy = cq.Workplane('XY').center(0,0).box(dx,dy,dz, centered=True)
#bumps
r = pitch/2/2
h = (2*r)*2
assy = assy.faces('>Z').workplane().rarray(pitch,pitch,cols,rows).cylinder(h,r)
display(assy)
Plus I think the aspect ratios are different between using assemblies and using the stack directly. The bumps look taller when using assemblies.
No need to use constraints, or modify cq:
rows = 8
cols = 8
pitch = 8
dx = cols*pitch
dy = rows*pitch
dz = 3*pitch
#roic
base = cq.Workplane('XY').center(0,0).box(dx,dy,dz, centered=True)
#bumps
r = pitch/2/2
h = (2*r)*2
top = base.faces('>Z').workplane().rarray(pitch,pitch,cols,rows).circle(r).extrude(h/2,combine=False)
assy = cq.Assembly().add(base, color=cq.Color('pink')).add(top, color=cq.Color('gray'))
show_object(assy)
Plus I think the aspect ratios are different between using assemblies and using the stack directly. The bumps look taller when using assemblies.
@chaffra The difference is expected. When using assembly, there are two individual objects, and the bumps are on the top of the face of the roic box. When using the stack directly, I remember there is an implicit concept that the object is symmetrical with respect to the workplane except for some operations, such as extrude.
If you want to get the same results, the code should be written as following (NB: offset=h/2).
assy.faces('>Z').workplane(offset=h/2).rarray(pitch,pitch,cols,rows).cylinder(h,r)
The code below allows me to stack 2 assemblies but I don't know how to center them, so that they have the same center in the XY plane.