Each of these asks the allocator for tens of gigabytes, or runs for hours, from
a file of a few kilobytes to a few megabytes. An allocation failure is an abort,
so no panic guard can report it and the user's unsaved work is gone.
- IGES composite curves (102) name their children by pointer, and a tree whose
every node names the same child twice fans out to 2^30 leaf visits under the
depth cap. Count the entities visited and the segments produced against one
budget, since a node that yields no segment trips no bound on the output, and
refuse a composite curve that contains itself.
- IGES directory entries could all name the same parameter range, each
materialising it as its own string and token list. Keep the total text
proportional to the parameter section the file carries.
- STEP knot multiplicities were expanded into one value each before the knot
count was compared with the control points: 20 million knots of multiplicity
64 built a 10 GB vector only to be rejected. Check the sum first.
- One STEP face could list any number of boundary loops, each cloning its edge
handles into a new wire that the face extent then samples. Cap the loops and
the edges they hold; 100,000 bounds went from 2.1 GB to an immediate error.
Also guard the IGES translation, which was the one importer stage outside every
panic guard, keep the vertex-sewing bucket key clear of the overflow its
neighbour lookup caused for coordinates near f64's range, and count how often a
loop passes each vertex once instead of once per edge.
Fixes#146
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit c32792b71c76d74348ad5002d8d2da870937e58e)
split_body(body, tool) divides every face where the tool meets it and
closes each side with the piece of the tool surface inside the body.
- Patches have outer loops and holes.
- Bands go round a cylinder or another surface of revolution.
- Each side falls apart into its connected parts.
- A body the tool misses comes back whole.
Faces that are B-spline sheets but really planes or circular cylinders
(extruded faces) split as the whole plane or cylinder: the tool is
extended, and the field is exact and cheap.
Tests (volumes): a box split by a plane (2400/3600); a holed plate split
through its hole into two equal halves; a box split by a cylinder's side
into the core (pi*16*30) and the rest; a plane that misses.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
Fusion round trip WARNs on face counts:
- 48: the pulley's annular end faces arrived as 240° and 120° sectors.
- 54: the side faces and holes of a body glued to its mirror image came
in halves.
Changes:
- Planes merge: PLANE faces and flat B-spline sheets, as well as revolved
planes. A plane keeps several loops (an annulus, a face with holes), no
seam. Flat B-spline sheets are written as PLANE.
- Pieces of an extruded cylinder (B-spline sheets) merge when their edges
are circles square to the axis. The merged face is written as a
CYLINDRICAL_SURFACE, with its parameter seam on the face's seam edge.
- A full turn's loop is built explicitly: ring, seam, other ring (or the
apex on the axis), seam back. Before, it depended on edge order, and
after 81c85b5 the pulley's last pieces no longer merged.
- The read-back check moved to the whole file. If the merged file reads
with warnings and the unmerged one does not, the unmerged one is
written.
Results: 48 has 12 faces (Fusion 12), 54 has 12 (Fusion 12). Oracle
results are unchanged (73 PASS) and the STEP corpus passes 76/76. New
test: a plate with a hole glued to its mirror exports 8 faces, all
planes and cylinders, and round-trips.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
- Surfaces of revolution follow ISO 10303-42 strictly in reader and writer: the
normal is d/d(angle) x d/d(profile), the opposite of truck's revolution, as
Fusion reads it (fixes Fusion inverting fillet sphere corners and the dimple).
step_orientation_errors flags faces whose loop runs clockwise round their
normal; engine, oracle and kernel round trips assert it.
- Revolved faces with analytic profiles are written as native PLANE,
CYLINDRICAL/CONICAL/SPHERICAL/TOROIDAL surfaces, and the pieces truck splits
a revolution into are merged back into one face per surface (with a seam
edge for full turns), so face counts match other systems.
- A horn torus (tight sweep: tube touching its axis) is written as one rational
B-spline face whose loop passes the pole twice, with truck's zero-length pole
edges collapsed, instead of a degenerate surface of revolution; the reader
starts such figure-eight loops off the pole (Fusion's own part 50 now imports
with the right volume).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
Meshing (vendored truck-meshalgo) works within a budget so hostile files
cannot hang: bounded edge and surface divisions (point caps, depth and
round limits, NaN-safe), and a grid budget per face shared out per shell.
Surface grids refine only the direction that bends; rulings left undivided
get cells comparable to the other direction, so trimmed cylinders (holes,
tee joints) no longer lose volume to long triangles. The helical sweep
imports in 12 s instead of 7 minutes.
Small sphere patches get poles away from them even when the file runs a
seam through the patch (a pyramid's corner blend). Faces the mesher cannot
mesh are reported as import warnings. Test: wild B-spline and far-off
boundaries import in bounded time.
STEP corpus 65/66 (50-sweep-tight-bend: a horn-torus bend whose inner side
collapses to a point; Fusion's own area for it is also off).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
Vendored truck-stepio (writer only): an intersection curve's second surface
was written at the first one's id (duplicate ids for every boolean edge),
and revolved surfaces lost their orientation (the modeling-surface sense was
always true; inverted or mirrored revolutions came out inside out). Export
now writes intersection edges as C1 cubic B-splines through exact points,
so files carry plain 3D curves and no redundant surfaces.
Vendored truck-meshalgo: hinted parameter searches that run off a B-spline's
domain are rejected or clamped (meshing their grid never finished).
STEP import: straight revolution profiles are bounded in the meridian plane
and stop at the axis; loops on revolutions start away from the axis; face
extents include edge end points. Edges between pieces of one split surface
draw as seams.
kernel::step_validate checks a STEP file (duplicate ids, dangling
references, dense numbering); the oracle replay now exports every rebuilt
part, validates it and re-imports it with no warnings and the same volume
(all 32 rebuildable cases pass).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
Own ISO 10303-21 parser and AP203/AP214/AP242 geometry reader in the kernel
(step_import): planes, cylinders, cones, spheres, tori, B-spline and rational
surfaces, surfaces of revolution/extrusion; lines, conics, B-spline curves;
breps with voids, faceted breps, shell models; units (SI prefixes, conversion
based), product names, colours, assemblies (NAUO + item-defined
transformations, mapped items). Hostile input is capped and guarded; faces
that cannot be read are left out and reported. Faces that wrap around a
closed non-periodic direction (pipe tori, revolved B-spline bands) are split
for truck's mesher. Bodies are meshed per shell so open imports never panic.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL