Compact circle packing on complex surface

To give a bit more explanation - in a compact circle packing, the size of the circles is completely determined by the connectivity of the mesh and I believe 2 parameters for where they touch the boundary (essentially you can slide them along the boundary and choose how ‘bunched up’ they are - easiest to see on a circle as shown here).
So apart from these 2 degrees of freedom, once you’ve got your mesh with which vertex connects to which defined, you really can’t control the relative sizes without breaking the circle packing. There’s no way to just pick one circle and make it a bit bigger or smaller, because that would introduce gaps in all the surrounding ones.

Given a mesh, Kangaroo adjusts the edge lengths to meet a specific condition which allows it to be converted to a circle packing. To make the circles also tangent to some boundary there is a slightly different condition required on the lengths, and that is what the script part in the definition above does.

Because the final circles are centred on the vertices of the optimised mesh, to get them tangent to the boundary curve, the mesh needs to stop a particular distance away from this curve. The offsetting of the curve on the surface before remeshing in the above definition helps it start closer to this condition to avoid them popping onto the wrong side. I’ll have another look at that boundary tangency code though - I think it should be possible to adjust it to consider the target surface direction and always pull to the interior side to prevent this more robustly.

If the input mesh to this relaxation is nice enough, the relaxation for the circle packing property generally wont change it very much, so you don’t get big changes in the circle sizes after optimization. The TriRemesh component in Rhino 7 gives meshes with good connectivity, usually with only valence 5/6/7. This helps, as the occasional valence 4 or 8 vertices you often get with other remeshing tools will lead to larger variation in the circle sizes, as seen in the square in your second image.

The iterations of the remeshing are a sequence of topology updates (changing the number of vertices and which vertex connects to which), and vertex relocation - typically some form of smoothing and reprojection to keep them on the target surface, respecting sharp features and so on. Repeated application of these steps leads to a ‘nice’ mesh.
Here’s a post I wrote on it when I was first working on remeshing tools.

Now for the compact circle packing, what can sometimes be an even better way to go about it is instead of treating the 2 steps separately like above - remeshing then relaxing the resulting mesh for circle packing - to actually do both together in the same loop. So the optimisation for circle packing is part of the relocation step in the remeshing. That way, if the circle packing relaxation causes them to slide around and change size a lot, the mesh can update itself, which gets around the restriction I mentioned earlier about the connectivity determining the sizes.
I have actually coded versions of this combined remeshing and circle packing optimisation several years ago, but with older versions of both kangaroo and the remesher.
see here

At some point I will make an updated version of this combined version, possibly as part of TriRemesh.

6 Likes