Skip to content

recipe 03 revolves a wire, so the flange is a shell rather than a solid #100

Description

@gsdali

Found while diagnosing the Route B failure in #86.

The defect

recipes/03-pipe-flange/main.swift:45 builds the flange by revolving a wire:

let section = Wire.polygon([...])!
var flange = Shape.revolve(profile: section, axisOrigin: .zero,
                           axisDirection: SIMD3(0, 1, 0), angle: 2 * .pi)!

Shape.revolve(profile:) revolves a curve, so it correctly returns a shell, not a solid. This
is standard BRepPrimAPI_MakeRevol behaviour and not an OCCTSwift bug. Rebuilt and measured:

recipe03 flange: type=shell  valid=true  vol=228707.95  faces=6

The recipe then chamfers it and cuts a bolt circle, treating it as a solid throughout. Its README
describes the output as a solid body.

Why CI does not catch it

Scripts/recipe-check.sh asserts the emitted volume is greater than zero. A closed shell
returns a correct positive volume from volumeInertia, so the check passes. Nothing currently
asserts the result is a solid.

The committed recipes/03-pipe-flange/output.brep reports shapeType: compound with volume
241242.9, which looks healthy by every metric the recipe suite measures.

Why it matters

A shell is a surface model. It will not fillet reliably, exports to STEP as surfaces rather than a
solid body, and misbehaves as a boolean operand. In #86 the same pattern produced disconnected
surface patches once real cuts were attempted against it, with Shape.volume returning nil and
the written BREP giving a negative volume. Recipe 03 gets away with it because its bolt-circle cut
happens to leave a closed shell, but it is the same latent error and it is being shipped as a
reference example.

Fix

Revolve a face:

guard let section = Wire.polygon([...]),
      let face = Shape.face(from: section),
      let flange = face.revolved(axisOrigin: .zero, axisDirection: SIMD3(0, 1, 0)) else { ... }

Verified on the #86 blank: Shape.face(from: wire).revolved(...) yields type=solid with the
same volume, and downstream booleans then behave correctly.

Suggested follow-up

Two things worth doing alongside the fix:

  1. Audit the other recipes for the same pattern. Any Shape.revolve(profile:) or
    Shape.extrude(profile:) whose result is treated as a solid should be checked.
  2. Strengthen recipe-check.sh to assert the emitted body is a solid, not merely that its
    volume is positive. That is the assertion which would have caught this, and it is the same
    class of gap as a check that cannot fail.

Metadata

Metadata

Assignees

No one assigned

    Labels

    type:bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions