Motivation
Both Voronoi generators are currently hand-rolled, with documented complexity / scale ceilings:
voronoi_generator_2d (include/rvegen/generators/voronoi_generator_2d.h): Sutherland–Hodgman half-plane clipping. Each cell starts as the bounding rectangle and is clipped against the bisector of every other seed — O(N²) per build, fine for hundreds of seeds, no external dep.
voronoi_generator_3d (include/rvegen/generators/voronoi_generator_3d.h): brute-force half-space-triplet vertex enumeration with Eigen PartialPivLU for the 3×3 solves. O(N⁵) — caps out around ~50 seeds. The header explicitly flags this: "beyond that, switch to a real Voronoi library (Voro++, CGAL)."
This sits in tension with our general preference for established geometry libraries over re-inventing primitives. The current code is correct (partition-of-unity invariant is tested in 2D and 3D), but it's a known scaling cliff and a maintenance burden when more sophisticated cases come up (weighted Voronoi / power diagrams, anisotropic seeds, periodic Voronoi on a torus, Laguerre cells for polydisperse grain packing, etc.).
Options
| Library |
2D |
3D |
Bounded cells |
License |
Notes |
| CGAL |
✅ Voronoi_diagram_2 |
✅ via Periodic_3_regular_triangulation_3 + dual |
✅ |
GPL / commercial dual |
Industrial-strength; periodic-3D support is the standout feature for RVE workflows. Heavyweight build dep. |
| Voro++ |
— |
✅ native |
✅ native (this is its whole point) |
BSD-3 |
Header + small .cc; designed for exactly this use case; supports walls, periodicity, polydisperse (radical) cells. No 2D. |
| boost::polygon |
✅ voronoi_diagram |
— |
Requires our own clipping |
Boost (already in tree) |
Drop-in for 2D, integer-coord flavored — needs a small wrapper for double-precision unit-box coords. No 3D. |
| GTE (already vendored) |
Delaunay only (Delaunay2/3) |
Delaunay only |
— |
Boost-like |
Would still leave us implementing the dual + clipping ourselves. Not a real fit. |
Proposed scope
Not a single PR. Suggest splitting:
- 3D first (highest payoff — replaces the O(N⁵) ceiling). Most likely Voro++ for the BSD license and surgical scope. CGAL's periodic 3D Voronoi is the alternative if we want periodic polycrystal RVEs.
- 2D as a follow-up. Lower priority since current Sutherland–Hodgman is correct and scales fine for typical RVE sizes.
boost::polygon is the obvious swap since Boost is already a tree dep.
- Keep the current implementations behind a compile-time / runtime knob for the first round so we can A/B them and confirm the new backends reproduce the partition-of-unity tests bit-for-bit before deleting the in-house code.
Acceptance criteria
- Existing 2D and 3D partition-of-unity tests pass against the new backend.
- New regression test exercising N = 200+ seeds in 3D in under a second (validates we actually escaped the O(N⁵) cliff).
voronoi_to_shapes(gen) / convex_polygon output shape stays the same — downstream svg_writer / vtk_legacy_writer paths don't change.
- The dep choice doesn't break the header-only contract for non-polycrystal users — gate the new generator behind a CMake option (e.g.
RVEGEN_WITH_VORO_PP=ON) so consumers who only need circles/spheres don't pay the dep cost.
Out of scope here
- Weighted / Laguerre / periodic Voronoi — separate follow-up once the library is in.
- Migration of the test suite to a different convex-polytope representation — keep
voronoi_cell / convex_polygon as the public shape.
Motivation
Both Voronoi generators are currently hand-rolled, with documented complexity / scale ceilings:
voronoi_generator_2d(include/rvegen/generators/voronoi_generator_2d.h): Sutherland–Hodgman half-plane clipping. Each cell starts as the bounding rectangle and is clipped against the bisector of every other seed — O(N²) per build, fine for hundreds of seeds, no external dep.voronoi_generator_3d(include/rvegen/generators/voronoi_generator_3d.h): brute-force half-space-triplet vertex enumeration with EigenPartialPivLUfor the 3×3 solves. O(N⁵) — caps out around ~50 seeds. The header explicitly flags this: "beyond that, switch to a real Voronoi library (Voro++, CGAL)."This sits in tension with our general preference for established geometry libraries over re-inventing primitives. The current code is correct (partition-of-unity invariant is tested in 2D and 3D), but it's a known scaling cliff and a maintenance burden when more sophisticated cases come up (weighted Voronoi / power diagrams, anisotropic seeds, periodic Voronoi on a torus, Laguerre cells for polydisperse grain packing, etc.).
Options
Voronoi_diagram_2Periodic_3_regular_triangulation_3+ dual.cc; designed for exactly this use case; supports walls, periodicity, polydisperse (radical) cells. No 2D.voronoi_diagramDelaunay2/3)Proposed scope
Not a single PR. Suggest splitting:
boost::polygonis the obvious swap since Boost is already a tree dep.Acceptance criteria
voronoi_to_shapes(gen)/convex_polygonoutput shape stays the same — downstreamsvg_writer/vtk_legacy_writerpaths don't change.RVEGEN_WITH_VORO_PP=ON) so consumers who only need circles/spheres don't pay the dep cost.Out of scope here
voronoi_cell/convex_polygonas the public shape.