marcomusy / vedo

A python module for scientific analysis of 3D data based on VTK and Numpy
https://vedo.embl.es
MIT License
2.03k stars 265 forks source link

Placing a cylinder on top of a box so that the merged mesh is closed #1058

Closed christian-zydex closed 7 months ago

christian-zydex commented 7 months ago

I want to merge the cylinder and the box so that the area where the cylinder meets the box is cut out ( so that there are no extra faces left over from the bottom of the cylinder on the box) and so that the mesh is closed. How can I ensure this? Currently when I merge the two meshes it is not closed. I understand that this involves removing the base of the cylinder that is connected to the mesh and retriangulating the top of the box in some way, but not sure how to do this.

box = vedo.Box(pos=(0, 0, 0), length=1, width=1, height=1)
cylinder = Cylinder(pos=(0, 0, 1), r=0.5, height=1)
combined = vedo.merge(cylinder, box)

JeffreyWardman commented 7 months ago

Adding on to this as I work with Christian. We want to stick a cylinder on top of a rectangular prism and have the overlapping region removed. Similar to this image: e9kondnjpnp61

Essentially, the circle with 1 cm radius at the bottom of the cylinder lays at the same height as the rectangular prism's top surface. We want to cut out this circle from both the rectangular prism mesh and the cylinder mesh. However, cut_with_mesh and cut_with_cookiecutter will remove large faces in the rectangle surface. The intersection boolean operation provided with vedo gets the circle but we haven't been able to figure out how to then remove the circle from both the rectangular prism and cylinder.

We want to join the two in a way that the part can then be 3D printable with no internal compartments.

marcomusy commented 7 months ago

Hi @christian-zydex and @JeffreyWardman what about this

import vedo
box = vedo.Box(pos=(0, 0, 0), length=4, width=4, height=2).shift([0,0,1])
box.triangulate().subdivide(6, method=1).clean().flat().alpha(0.5)
cylinder = vedo.Circle(r=0.5, res=80).linewidth(1).extrude(7.5, res=120)
# add a small tolerance to avoid coincident edges
cylinder.shift([0.001,0.001,0.5]).reverse() 
union = box.boolean("+", cylinder).clean()
print(union.is_closed(), union.is_manifold())
vedo.show(cylinder+box, union, N=2, axes=1)
Screenshot 2024-02-22 at 14 15 23
JeffreyWardman commented 7 months ago

Not quite what we were aiming for. The goal is to not have the cylinder pass through the rectangle at all. We just want to remove the region where they overlap (the circle) and only that. We can gather the circle points and lines via cylinder.boundaries() but don't know how to progress from there.

For the trivial solution provided we could just recreate the rectangle from the cylinder but were wondering if there was essentially a 2D boolean subtraction/union-like method.

I assume for the trivial approach you would create a vedo.Rectangle(cap=False), remove the cylinder cap and then merge the rectangle with the cylinder.boundaries(), triangulate to create the triangles and then extrude downwards. If that wouldn't work then we'd have to figure this approach out as well.

marcomusy commented 7 months ago

We want to join the two in a way that the part can then be 3D printable with no internal compartments.

The goal is to not have the cylinder pass through the rectangle at all.

... that is what the mesh on the right does! (add some transparency to check)

JeffreyWardman commented 7 months ago

Amazing, thanks! I thought I plotted union.alpha(0.3) before replying but I must have forgotten to add a .close() before running it again.

Feel free to close the issue.