forked from 1b-agent/fieldcraft-upstream
* Structured hex meshing: multi-level extrude and revolve, one-to-one sweep, mapped blocks (M5) modelcraft_mesh::hex::hex_mesh meshes a face-tagged boundary surface with hexahedra by the first structured method that fits: a straight or rotational multi-level sweep (imprinted cross-section arrangement, cuts at reflex corners, mapped/annulus/free regions), a one-to-one sweep through rings of linking faces (least-squares affine layers with residual correction), or a mapped logical cube (trivariate transfinite interpolation). Interval assignment couples shared curves; boundary quads carry B-rep face tags; the certified validity gate, a tiling check and a fidelity check guard the output; hex20 mid-edge nodes go onto the faces. Shape::face_surfaces exposes the analytic face surfaces; the corpus runner gets a structured hex column. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * mesh.hex.generate: structured hex meshing as a command Meshes one body, every body of the open design or an imported surface, replaces the mesh, tags element faces with the B-rep faces (so sets by geometry resolve) and reports per body the method, counts and quality. The quality pass certifies each element once and feeds the validity gate (quality::validity_gate_checks). Shape::size gives the cached body size for defaults instead of a full measure. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Hex: disk O-grids, convex interval cost, early size guard, hex20 corpus column Smooth single-loop sections (cylinders, tori, vases) get a butterfly O-grid instead of the free mesher; interval assignment raises counts by the squared relative error so equal sides share increments evenly; a mesh far beyond the element limit is refused before any work and mapped limits are no longer swallowed. The corpus reports hex8 and hex20 quality. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Catalogue: structured hex commands ready (mesh.hex.sweep, mesh.hex.mapped, mesh.hex.generate) mesh.hex.sweep and mesh.hex.mapped run mesh.hex.generate with the sweeping methods or the mapped one; mesh.hex.generate is the sweep entry's related command. The planned M6 octree entry moves to mesh.hex.octree (its icon renamed with it). docs/features.md regenerated. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Docs: structured hex literature (B8), architecture, roadmap, parity; corpus hex column Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Hex: simplify review fixes Prepare each sweep frame's cross-section once (arrangement, cuts, fill) and reuse it across refinement retries; candidate frames come from one setup pass. Edge triangles come from the feature edges, layer counts go through size::edge_divisions, sweep residual weights are computed once per node, flux shape functions live on the stack, and the arrangement's exact side test and distances serve the region probe. The engine takes the boundary options mesh.tet.generate takes and names unnamed faces by index like it; the corpus hex20 run reuses the winning method; the mapped entry lists mesh.hex.generate too; the octree icon is redrawn under its new id. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Regenerate docs/features.md and docs/meshing/corpus.md after rebasing Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Regenerate docs/features.md and docs/meshing/corpus.md after rebasing onto main Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Regenerate docs/features.md and docs/meshing/corpus.md after rebasing onto main Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Regenerate docs/features.md and docs/meshing/corpus.md after rebasing onto main Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Regenerate docs/features.md after rebasing onto main Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Regenerate docs/features.md after rebasing onto main Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Regenerate docs/features.md after rebasing onto main Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm --------- Co-authored-by: jyviko <[email protected]> Co-authored-by: Claude Opus 5.5 <[email protected]>
10 KiB
10 KiB
Meshing test corpus
Generated by cargo xtask corpus; do not edit. The parts are our own: SolidCraft recipes in
tests/corpus/<name>/recipe.json and analytic shapes generated in code
(crates/testkit/src/corpus.rs). Each run rebuilds every part, tessellates it at a chordal
tolerance of 1e-3 of its bounding-box diagonal and runs every stage on it. Times are wall
clock on the machine that ran it; every other column is deterministic.
Results
| part | categories | bodies | faces | triangles | tol. mm | build ms | enclosed mm³ | SolidCraft mm³ | rel. diff | exact mm³ | boundary | genus | feature edges | check ms | CDT tets | Steiner | cavities | tet gate | CDT ms | hex | hex elements | hex8 min SJ | hex20 min SJ | hex ms |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| bent-tube | sweepable, thin-wall, genus | 1 | 18 | 4296 | 0.121 | 454 | 4213.1 | 4159.4 | 1.3e-2 | 4159.8 | ok, 2148 vertices | 1 | 268 | 11.5 | 15550 | 2338 | 0 | pass | 606 | sweep | 192 | 0.859 | 0.997 | 63 |
| bolted-assembly | assembly, blocky | 3 | 22 | 284 | 0.117 | 206 | 33004.7 | 32999.0 | 1.7e-4 | 32998.9 | ok, 144 vertices | 0, 1, 1 | 104 | 0.7 | 690 | 181 | 0 | pass | 34 | extrude | 357 | 0.398 | 0.222 | 40 |
| cross-cylinders | boolean, sharp | 1 | 10 | 1395 | 0.087 | 7920 | 32197.4 | 32357.8 | -5.0e-3 | 32365.8 | error: Cross: invalid boundary surface: 28 defects; triangles 142 and 184 are oriented inconsistently across edge 0–396 at (-15.488656021315903, 4.577998041166734, 7.853092194999726); triangles 184 and 239 are oriented inconsistently across edge 0–554 at (-18.75000000000002, 5.634596901641276, 7.632255089815496); edge 103–108 at (-0.16007784063084018, 0.03984236936862052, 9.998639270596865) is shared by 3 triangles; … | error: Cross: invalid boundary surface: 28 defects; triangles 142 and 184 are oriented inconsistently across edge 0–396 at (-15.488656021315903, 4.577998041166734, 7.853092194999726); triangles 184 and 239 are oriented inconsistently across edge 0–554 at (-18.75000000000002, 5.634596901641276, 7.632255089815496); edge 103–108 at (-0.16007784063084018, 0.03984236936862052, 9.998639270596865) is shared by 3 triangles; … | error: Cross: invalid boundary surface: 28 defects; triangles 142 and 184 are oriented inconsistently across edge 0–396 at (-15.488656021315903, 4.577998041166734, 7.853092194999726); triangles 184 and 239 are oriented inconsistently across edge 0–554 at (-18.75000000000002, 5.634596901641276, 7.632255089815496); edge 103–108 at (-0.16007784063084018, 0.03984236936862052, 9.998639270596865) is shared by 3 triangles; … | |||||||||||
| filleted-bracket | fillet, genus, sweepable | 1 | 13 | 540 | 0.088 | 388 | 32162.3 | 32145.0 | 5.4e-4 | 32144.8 | ok, 268 vertices | 2 | 135 | 1.4 | 5582 | 1613 | 0 | pass | 208 | no: Bracket: not supported yet: no structured hex method fits this body (extrude: cylindrical face 8 is not parallel to the direction; sweep: from face 1: linking face 6 has 2 boundary loops (periodic or holed linking faces are not swept); from face 6: | 5 | |||
| i-beam | sweepable, thin-wall | 1 | 14 | 44 | 0.208 | 3 | 61600.0 | 61600.0 | 0.0e0 | 61600.0 | ok, 24 vertices | 0 | 36 | 0.1 | 94 | 24 | 0 | pass | 4 | extrude | 336 | 0.707 | 0.707 | 34 |
| loft-transition | organic | 1 | 6 | 292 | 0.075 | 57 | 56390.2 | 56450.6 | -1.1e-3 | – | ok, 148 vertices | 0 | 40 | 0.7 | 1329 | 256 | 1 | pass | 38 | sweep | 2873 | 0.189 | 0.189 | 328 |
| perforated-plate | genus, thin-wall, sweepable | 1 | 54 | 1644 | 0.144 | 273 | 26822.2 | 26764.6 | 2.2e-3 | 26764.2 | ok, 776 vertices | 24 | 828 | 4.8 | 33611 | 9798 | 0 | pass | 1345 | extrude | 467 | 0.304 | 0.033 | 98 |
| pinhole-block | small-feature, genus | 1 | 38 | 4044 | 0.073 | 201 | 49919.4 | 49909.6 | 2.0e-4 | 49909.5 | ok, 1992 vertices | 16 | 1548 | 12.9 | 96411 | 30221 | 0 | pass | 8142 | extrude | 5236 | 0.408 | 0.392 | 735 |
| rounded-box | fillet | 1 | 26 | 2540 | 0.054 | 235 | 23325.7 | 23340.5 | -6.3e-4 | 23340.8 | ok, 1272 vertices | 0 | 216 | 8.4 | 11663 | 1916 | 0 | pass | 469 | no: Box: not supported yet: no structured hex method fits this body (extrude: cylindrical face 8 is not parallel to the direction; sweep: from face 0: 12 faces are not on the sweep path; from face 5: 12 faces are not on the sweep path; revolve: plan | 15 | |||
| shallow-groove | near-tangent, boolean | 1 | 8 | 62 | 0.075 | 11 | 47795.2 | 47782.3 | 2.7e-4 | 47781.5 | ok, 33 vertices | 0 | 24 | 0.2 | 267 | 87 | 0 | pass | 13 | extrude | 1960 | 0.991 | 0.986 | 201 |
| sharp-wedge | sharp, thin-wall, sweepable | 1 | 5 | 8 | 0.083 | 2 | 3200.0 | 3200.0 | 0.0e0 | 3200.0 | ok, 6 vertices | 0 | 9 | 0.0 | 11 | 3 | 0 | pass | 0 | extrude | 294 | 0.050 | 0.050 | 30 |
| sphere-on-plate | near-tangent, boolean | 1 | 12 | 2826 | 0.098 | 974 | 69353.3 | 69509.0 | -2.2e-3 | 69509.7 | ok, 1415 vertices | 0 | 124 | 7.2 | 4898 | 309 | 9 | pass | 260 | no: Plate: not supported yet: no structured hex method fits this body (extrude: face 6 is curved across the direction; sweep: from face 0: 6 faces are not on the sweep path; from face 5: linking face 11 has 2 boundary loops (periodic or holed linking | 11 | |||
| spline-vase | organic | 1 | 11 | 3890 | 0.106 | 226 | 94891.2 | 94948.5 | -6.0e-4 | – | ok, 1947 vertices | 0 | 243 | 9.0 | 12461 | 1512 | 0 | pass | 456 | sweep | 4554 | 0.649 | 0.649 | 547 |
| stepped-block | blocky, sharp | 1 | 14 | 96 | 0.078 | 264 | 47000.0 | 47000.0 | 0.0e0 | 47000.0 | ok, 48 vertices | 1 | 60 | 0.4 | 223 | 41 | 0 | pass | 7 | extrude | 1416 | 0.999 | 0.999 | 142 |
| thin-ribs | thin-wall, blocky | 1 | 26 | 92 | 0.119 | 1004 | 32000.0 | 32000.0 | -4.5e-16 | 32000.0 | ok, 48 vertices | 0 | 72 | 0.6 | 171 | 33 | 0 | pass | 8 | extrude | 777 | 0.844 | 0.844 | 100 |
| thin-wall-enclosure | thin-wall, blocky | 1 | 11 | 36 | 0.108 | 340 | 15564.0 | 15564.0 | 0.0e0 | 15564.0 | ok, 20 vertices | 0 | 28 | 0.2 | 191 | 47 | 2 | pass | 11 | extrude | 894 | 0.297 | 0.297 | 112 |
| analytic-sphere | analytic | 1 | 6 | 2784 | 0.069 | 719 | 33353.4 | 33507.9 | -4.6e-3 | 33510.3 | ok, 1394 vertices | 0 | 96 | 12.6 | 4211 | 58 | 0 | pass | 440 | no: Sphere: not supported yet: no structured hex method fits this body (extrude: no direction to try; sweep: no planar face to sweep from; revolve: no axis to try; mapped: meshing failed: meshing failed: mesh validity gate: 8 inverted or degenerate ele | 31 | |||
| analytic-torus | analytic, genus | 1 | 6 | 7230 | 0.109 | 944 | 37644.1 | 37893.7 | -6.6e-3 | 37899.3 | ok, 3615 vertices | 1 | 180 | 25.6 | 19790 | 466 | 0 | pass | 1412 | revolve | 1134 | 0.706 | 0.706 | 280 |
| analytic-cylinder | analytic, sweepable | 1 | 4 | 1004 | 0.049 | 190 | 12533.1 | 12564.7 | -2.5e-3 | 12566.4 | ok, 504 vertices | 0 | 106 | 3.4 | 7437 | 1568 | 0 | pass | 452 | extrude | 3200 | 0.707 | 0.707 | 585 |
| analytic-pipe | analytic, genus, sweepable | 1 | 6 | 1448 | 0.104 | 336 | 94150.9 | 94238.0 | -9.3e-4 | 94247.8 | ok, 724 vertices | 1 | 220 | 9.0 | 6238 | 1340 | 0 | pass | 479 | extrude | 1288 | 0.998 | 0.998 | 290 |
| analytic-plate-hole | analytic, genus, sweepable | 1 | 8 | 112 | 0.224 | 231 | 98449.1 | 98429.5 | 2.0e-4 | 98429.2 | ok, 56 vertices | 1 | 62 | 0.9 | 1868 | 543 | 0 | pass | 72 | extrude | 321 | 0.320 | 0.142 | 55 |
Categories
| category | stresses | parts |
|---|---|---|
| thin-wall | walls thin against the part's size | 6 |
| small-feature | features much smaller than the part | 1 |
| fillet | blends between faces | 2 |
| genus | through holes (genus > 0) | 7 |
| sharp | sharp edges and acute dihedral angles | 3 |
| near-tangent | faces meeting at a shallow angle | 2 |
| boolean | intersection curves from booleans | 3 |
| sweepable | extrusions and sweeps (one-to-one sweep meshing) | 8 |
| blocky | axis-aligned blocks (polycube-friendly) | 4 |
| organic | free-form, lofted or revolved spline surfaces | 2 |
| assembly | several bodies placed by component transforms | 1 |
| analytic | closed-form geometry for solver verification | 5 |
Parts
bent-tube: A 10 mm tube with a 1 mm wall, bent through R30: a thin-walled sweep along a line-arc-line path.bolted-assembly: A base plate with a clamp block component placed twice, once turned 90 degrees: bodies placed by component transforms.cross-cylinders: Two orthogonal R10 cylinders joined: equal radii, so the intersection curves cross at two singular points.filleted-bracket: An 8 mm L-bracket with an R6 inside fillet and a hole through each leg: a blend beside holes.i-beam: A 200 mm I-beam with 3 mm flanges and a 2 mm web: a long sweepable prism with thin walls.loft-transition: A 40 mm square lofted to an R15 circle 50 mm above: a ruled free-form surface between unlike sections.perforated-plate: A 3 mm plate perforated by a 6 x 4 grid of 6 mm holes: genus 24 in a thin sheet.pinhole-block: A 50 mm block drilled through by sixteen 0.6 mm pinholes: features 80 times smaller than the part, genus 16.rounded-box: A 40 x 30 x 20 box with every edge rounded R3: cylinder and sphere blends meeting at the corners.shallow-groove: A block with a 0.5 mm deep groove cut by an R30 cylinder: groove walls 10 degrees off the top face.sharp-wedge: A wedge whose faces meet at under 3 degrees: a sharp edge with a needle-thin cross-section.sphere-on-plate: A sphere sunk 0.1 mm into a plate: the faces meet at under 6 degrees around a 2 mm circle.spline-vase: A vase revolved from a spline profile: doubly curved faces of varying curvature around a closed axis.stepped-block: Three stacked blocks with a slot cut through the base: axis-aligned steps for polycube and octree meshers.thin-ribs: A 4 mm plate carrying five 0.8 mm ribs 20 mm tall: thin walls standing on a thicker base.thin-wall-enclosure: An 80 x 60 x 40 box shelled to 1 mm walls, open on top: thin walls over a large span.analytic-sphere: Sphere r 20: curvature everywhere, no edges.analytic-torus: Torus 30/8: genus 1 with doubly curved faces and no edges.analytic-cylinder: Cylinder r 10, h 40: the round bar of beam and torsion checks.analytic-pipe: Thick-walled pipe 20/30, length 60: the Lamé cylinder.analytic-plate-hole: Plate 200 x 100 x 5 with a 20 mm hole: the Kirsch plate.