Originally posted by **pca006132** January 11, 2024
```js
const {cube, sphere} = Manifold;
const foo = cube(3, true).subtract(cube(1, true));
const parts = foo.decompose();
console.log(parts.length);
const result = parts[1];
```
It would be intuitive for negative volume meshes to be basically equivalent to a union becoming a difference, but we need to figure out if this is compatible with Julian Smith's algorithm.
@pca006132 After thinking about this for quite a while, I think it's going to be pretty difficult, algorithmically, to make negative objects work intuitively with Boolean operations. After all, they do work now (they're manifold), they're just surprising, as with overlapping manifolds. I think the better approach is to follow what we're already doing in 2D: make all Manifolds non-overlapping.
Of course, I haven't yet made an algorithm to remove overlaps from a Manifold, but I plan to. When that happens, negative volume objects will also be removed, due to the positive fill rule. So I think our best stepping-stone for now is to detect and remove negative-volume meshes as a Manifold is constructed. This leaves the question of how to handle Decompose.
We could remove the vugs from the output, which might be confusing. We could invert them, so they become positive volume objects in their own right. Or we could just ignore all of this and put in the documentation that negative volume meshes are not epsilon-valid, so it's up to you to avoid them, just like self-intersecting meshes.
So I think our best stepping-stone for now is to detect and remove negative-volume meshes as a Manifold is constructed. This leaves the question of how to handle Decompose.
Agreed. I am more inclined towards subtracting the vugs from the output volumes (which is just composing them if they intersect?), this matches my intuition about how the objects are defined (the holes are part of the enclosing object) and how Decompose should work (holes should be kept).
Btw, I'm thinking if we should just treat imported meshes with negative volumes as invalid meshes now. This seems to be a common issue that causes confusion to users:
Discussed in https://github.com/elalish/manifold/discussions/693
@pca006132 After thinking about this for quite a while, I think it's going to be pretty difficult, algorithmically, to make negative objects work intuitively with Boolean operations. After all, they do work now (they're manifold), they're just surprising, as with overlapping manifolds. I think the better approach is to follow what we're already doing in 2D: make all Manifolds non-overlapping.
Of course, I haven't yet made an algorithm to remove overlaps from a Manifold, but I plan to. When that happens, negative volume objects will also be removed, due to the positive fill rule. So I think our best stepping-stone for now is to detect and remove negative-volume meshes as a Manifold is constructed. This leaves the question of how to handle
Decompose
.We could remove the vugs from the output, which might be confusing. We could invert them, so they become positive volume objects in their own right. Or we could just ignore all of this and put in the documentation that negative volume meshes are not epsilon-valid, so it's up to you to avoid them, just like self-intersecting meshes.
What do you think?
Agreed. I am more inclined towards subtracting the vugs from the output volumes (which is just composing them if they intersect?), this matches my intuition about how the objects are defined (the holes are part of the enclosing object) and how
Decompose
should work (holes should be kept).That's a good point, and IIRC our 2D decompose already acts that way. Sounds like a good approach.
Btw, I'm thinking if we should just treat imported meshes with negative volumes as invalid meshes now. This seems to be a common issue that causes confusion to users:
https://github.com/openscad/openscad/issues/5381, https://github.com/elalish/manifold/discussions/995
Yeah, probably. The only trouble is it's not trivial to set a threshold for negative volume. Maybe volume < surface area * tolerance?
Yeah this makes sense