STEP export: Fusion round-trip fixes (sense, analytic surfaces, horn torus)

- 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
This commit is contained in:
bherbruckandClaude Opus 5.5 committed 2026-10-08 04:23:46 +00:00
1 parent 178fc47ed7
commit 7382ebd6e8
12 files changed
+958 -85

No files matched your search

+4 -3
View File
@@ -21,9 +21,10 @@ Only the writer (`out`) is used; SolveCraft reads STEP with its own reader.
Changes:
- `out/geometry.rs`: an `INTERSECTION_CURVE`'s second surface was written at the first
surface's entity index, so every boolean-made edge produced duplicate entity ids.
- `out/geometry.rs`: surfaces of revolution carry the right `same_sense`: truck's revolution
has the same parameterisation and normal as ISO 10303-42 (the writer flipped it), and a
mirroring transform reverses the normal.
- `out/geometry.rs`: surfaces of revolution carry the right `same_sense` for inverted and
mirrored revolutions (ISO 10303-42 parameterises them by angle then profile, so their normal
is the opposite of truck's; a mirroring transform reverses it again), and the modeling-surface
wrapper passes the revolution's sense through instead of always `true`.
- `lib.rs`: compiler warnings no longer fail the build. Example and test targets are dropped
(their sources are not vendored).
+6 -5
View File
@@ -738,11 +738,11 @@ impl<C: ConstStepLength> ConstStepLength for RevolutedCurve<C> {
const LENGTH: usize = 4 + C::LENGTH;
}
// SolveCraft: truck revolves right-handed with u along the profile and v around the axis, the
// parameterisation of ISO 10303-42 surface_of_revolution, so the normals agree (was `false`).
// ISO 10303-42 parameterises surface_of_revolution by (angle, profile); truck by (profile,
// angle), so the normals are opposite.
impl<C> StepSurface for RevolutedCurve<C> {
#[inline(always)]
fn same_sense(&self) -> bool { true }
fn same_sense(&self) -> bool { false }
}
impl<C> DisplayByStep for Processor<RevolutedCurve<C>, Matrix4>
@@ -774,10 +774,11 @@ impl<C: StepLength> StepLength for Processor<RevolutedCurve<C>, Matrix4> {
}
// SolveCraft: the written surface revolves the transformed profile about the transformed
// axis; a mirroring transform reverses the turn, and with it the normal (was `!orientation`).
// axis; a mirroring transform reverses the turn, and with it the normal (was `!orientation`,
// right only without mirroring). The STEP normal is the opposite of truck's (see above).
impl<C> StepSurface for Processor<RevolutedCurve<C>, Matrix4> {
#[inline(always)]
fn same_sense(&self) -> bool { self.orientation() == (self.transform().determinant() >= 0.0) }
fn same_sense(&self) -> bool { self.orientation() != (self.transform().determinant() >= 0.0) }
}
impl DisplayByStep for ModelingSurface {