[World] Boolean Surface Geometry
Daniel Phillips
phillips at phunq.net
Thu Jun 21 18:49:30 PDT 2012
The general case of sectioning meshes along arcs (step 4 of 5) now appears to
work, including nontrivial combinations of open and closed surfaces and
multiple intersections per surface. Solid16.png shows a tetrahedron subtracted
from the middle of an open mesh.
In the process of doing the tricky arc cutting I discovered a wonderful new
Euler operator (an operator that always takes a mesh from one valid state to
another) called "pivot":
pivot(a, b, c, d) {
swap(next(a), next(c))
swap(next(a), next(b))
swap(next(a), next(d))
}
where a, b, c, and d are half edges. Wow, how can that do anything
interesting, it is just three swaps!? But in fact it does something very
interesting: it reroutes two pairs of oppositely oriented edges (a ring edge
and its twin or two paired half edges) where all edges are incident on the
same vertex, so that each edge "turns left" at the vertex instead of going
straight through. So to cut a mesh by an arc, I first create a ring going all
around the (closed) arc, then twin it. This creates exactly the right
conditions to apply the pivot operator at each vertex, leaving a cleanly split
mesh with boundary rings at its edges. I used to do this in a far more complex
way that was nigh on impossible to read let alone debug. This new way is tiny
code that is blindingly fast. Look at it, just three swaps. One nanosecond per
vertex or thereabouts.
Well, it is not quite so simple because pivot has an additional annoying
property: if you provide the edge parameters in the wrong order, instead of
splitting the mesh it tangles it. And trust me, it is way easier to tangle a
mesh than split it. The right order to give the parameters depends on arcane
details of the essentially random order in which edge intersections are
detected. In the end, the correct logic was simple, efficient and easy to prove,
but getting there required some serious head scratching.
How do you debug this stuff? With great difficulty. Soild17.png shows how I did
it this time, a schematic view augmented to show the mesh topology details so
I don't have to go crazy staring at tables of halfedge link numbers. In this
case, all the links point exactly where they should. Of course there were
other situations along the way where the links appear as a big tangled
hairball instead of the nice consistent counterclockwise faces we see here.
This enhanced schematic allowed me to track down bugs about a hundred times
faster than previously, no exaggeration.
Notice that one of the faces in the sectioned mesh has six sides. There is
actually no limit to the complexity of the polygons of a mesh intersection.
Though most non-triangular faces will be convex and therefore easy to
triangulate, the general case requires the services of a full polygon
triangulator. Which fortunately we have, otherwise that would be a reason to
stop right here and spend weeks getting one.
Intersected polygons do have some helpful properties: 1) they always lie in
the plane and within the bounds of exactly one original face; 2) each result
edge is a segment of some original edge; 3) edges never cross. The last point
is important because my triangulator fails if edges cross (and something needs
to be done about that). Anyway, I should probably add a new step to the full
algorithm: retriangulate, which comes right after sectioning and before the
last step, reassembly.
Solid18.png and solid19.png are exploded renderings I made to clarify how this
all works. The first image shows a tetrahedron/surface intersection yielding
five separate mesh parts. One result part is a small, zero volume ring that
puzzled me for a while until I realized that it really belongs to the green
tetrahedron. It is the small slit where the other surface penetrates the back
face.
The other interesting thing about the green tetrahedron is the zero-area slit
on the front. It is not immediately obvious what this might be useful for.
Well, it provides an attachment point to which one or two of the other
fragments can be glued exactly, if that is what we want. And if we do that,
the result will all make sense and be a consistent mesh, but it is definitely
not something you could do with traditional constructive solid geometry. As I
may have mentioned earlier, this new algorithm includes all of traditional
constructive solid geometry as a subset. So actually, this is pretty exciting,
if you are the kind of person who gets excited by things like this.
I made a quick survey of the literature, and as far as I know, this new
approach to boolean combination is unique, and nothing similar has been
published. So on the assumption that I actually discovered it, I get to name
it. Tentatively, this will be called "Boolean Surface Geometry" (BSG), a
superset of constructive boolean geometry (CSG). In BSG, we dispense with any
notion of inside and outside, and instead rely only on adjacency, boundaries
and local orientation. For some constructions (any closed manifold) it is
indeed possible to define inside and outside precisely in BSG, but the general
case also has open manifolds as in these images, which do not have inside and
outside, only front and back.
In CSG parlance, such volume-less structures are called "non-manifold" and can
result from various CSG operations. They must be removed by some separate
algorithm in a "clean up" step before further CSG operations can take place.
So CSG is incomplete in the sense that the result of a CSG operation may not
have a well defined inside. But "BSG" (boolean surface geometry) is complete,
because the result of any boolean operation on a collection of open or closed
manifolds is always a collection of open or closed manifolds. Or in other
words, the group of boolean operations on open meshes form a mathematical
"ring" while those of CSG do not. Or in other words, BSG is well defined for
open manifolds while CSG is not. So this is not just a nice new algorithm, but
a (seemingly obvious) extension of a significant part of computational
geometry.
The last attached image is a simpler alignment that produces three result
surfaces instead of five. But it is actually the most computationally complex
example so far, because there are multiple edges of each original mesh part
interpenetrating multiple faces of the other. This, and many other examples,
are now working reliably. So pretty soon it will be on to the final step: re-
triangulate and recombine the segmented surfaces to create some shiny demo
images. And shortly after that, I hope to use this new tool to model a nice
solid catapult, which is after all, the whole point of this effort.
Regards,
Daniel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://phunq.net/pipermail/world/attachments/20120621/56823e55/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: solid16.png
Type: image/png
Size: 28608 bytes
Desc: not available
URL: <http://phunq.net/pipermail/world/attachments/20120621/56823e55/attachment-0004.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: solid17.png
Type: image/png
Size: 26118 bytes
Desc: not available
URL: <http://phunq.net/pipermail/world/attachments/20120621/56823e55/attachment-0005.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: solid18.png
Type: image/png
Size: 41348 bytes
Desc: not available
URL: <http://phunq.net/pipermail/world/attachments/20120621/56823e55/attachment-0006.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: solid19.png
Type: image/png
Size: 34509 bytes
Desc: not available
URL: <http://phunq.net/pipermail/world/attachments/20120621/56823e55/attachment-0007.png>
More information about the World
mailing list