Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ suite into these targets (each `Tests/OCCT<Domain>Tests/`, declared in `Package.
- `ShapeFix_Face::FixPeriodicDegenerated` (invoked from `Shape.face(from:boundary:)`/`face(from:boundary:innerWires:)` and the `FaceFixer` API whenever a face's sole boundary wire is a single closed edge belting a `Surface.cone`'s full period, apex outside the wire's V range — e.g. a rivet/boss-rim seam fit as one periodic curve) used to SIGSEGV (uncatchable) on the ordinary `ShapeFix_Face fixer(face); fixer.Perform();` construction — a null-Context dereference at the function's final `Context()->Replace(myFace, myResult)`, the only one of twelve such call sites in the file missing the `if (!Context().IsNull())` guard every sibling uses. A standalone circle repro is negative (`wireFromEdges` alone never reaches `FixPeriodicDegenerated`); the minimal repro needs the wire trimmed to a periodic conical surface via `face(from:boundary:)`. **Fixed in v1.12.7**: bridge now calls `fixer.SetContext(new ShapeBuild_ReShape)` before `Perform()` at all three `ShapeFix_Face` call sites (immediate fix, any xcframework); kernel patch also carried (`Scripts/patches/0005-*`, xcframework rebuilt) and filed upstream as [OCCT#1378](https://github.com/Open-Cascade-SAS/OCCT/issues/1378) (repro) / [OCCT#1380](https://github.com/Open-Cascade-SAS/OCCT/pull/1380) (fix). #317.
- `BRepGProp_EdgeTool::IntegrationOrder` (invoked from `BRepGProp::LinearProperties`, which backs `Shape.analyze(tolerance:)`'s small-edge scan) used to SIGSEGV (uncatchable) on an edge whose sole geometry is a Bezier/BSpline-type curve-on-surface pcurve (no 3D curve) — the common shape of a degenerate edge `BRepBuilderAPI_Sewing` produces reconciling near-coincident vertices between two faces that don't share an edge outright (surfaced sewing two real mesh-derived candidate faces from `kof_ii_engine_cover.stl`). `IntegrationOrder` correctly reads the pcurve's type via `BAC.GetType()` (the curve-on-surface-aware virtual dispatch) but then re-derives the pole count by hand from `BAC.Curve().Curve()` — a completely different, non-virtual accessor that's null whenever there's no 3D curve; down-casting that null handle and calling `->NbPoles()` on it crashes. A from-scratch synthetic degenerate edge (`BRep_Builder` + a hand-built `Geom2d_BSplineCurve` pcurve on a plane, no 3D curve) reproduces the identical crash trace — no real fixture needed to pin the mechanism. **Fixed in v1.12.8**: bridge's small-edge scan now skips degenerate edges outright (`OCCTShapeAnalyze`, immediate fix, any xcframework — a degenerate edge's zero 3D extent isn't a "small edge" defect to flag); kernel patch also carried (`Scripts/patches/0006-*`, xcframework rebuilt): `IntegrationOrder` now calls the adaptor's own (correctly-dispatching) `BAC.NbPoles()` instead. Filed upstream as [OCCT#1381](https://github.com/Open-Cascade-SAS/OCCT/issues/1381) (repro) / [OCCT#1382](https://github.com/Open-Cascade-SAS/OCCT/pull/1382) (fix). #318.
- Three more upstream crash/hang fixes carried proactively (audit of OCCT PRs since our p1 baseline, not discovered via our own crashes — #323, v1.12.9): (1) `ShapeAnalysis_FreeBounds::connectWiresToWiresImpl` (the same helper as the #310 fix above) left a stale `lwire` index when a skipped-loop candidate wire had zero edges (e.g. a wire wrapping a single internal-orientation edge), so the outer loop's termination check never fired and it read invalid memory — `Scripts/patches/0007-*`, backports open third-party [OCCT#1331](https://github.com/Open-Cascade-SAS/OCCT/pull/1331) (fixes OCCT#1330, the "still open" sibling bug noted above). (2) `Geom_BSplineCurve::PeriodicNormalization` used an O(N) `while`-loop to bring an out-of-range parameter back into a periodic curve's range, and could infinite-loop outright once the parameter's magnitude vastly exceeded the period (floating-point no-op on `Parameter -= Period`) — hung `BRepAlgoAPI_Section` on cylindrical shapes; `Scripts/patches/0008-*`, backports merged [OCCT#1329](https://github.com/Open-Cascade-SAS/OCCT/pull/1329) (rewritten to O(1)). (3) `StepData_StepWriter::AddString` looped forever writing a single unbroken raw string longer than the 72-char line buffer (`StepLong`) — no amount of flushing ever made room; `Scripts/patches/0009-*`, backports open [OCCT#1318](https://github.com/Open-Cascade-SAS/OCCT/pull/1318) (splits the token across lines instead), regression test `STEPWriterOversizedNameTests` (`OCCTIOTests`) via `Shape.writeSTEP(to:name:)` with a >72-char name.
- `BOPAlgo_ArgumentAnalyzer`'s self-interference phase (backs `Shape.isSelfIntersecting(hardTimeout:)`) could run unboundedly past its `hardTimeout:` deadline on a pathological artifact — 619s+ CPU against a 30s deadline, never returning. Two compounding causes: (1) `Intf_Interference::Insert` called `Intf_TangentZone::GetPoint(Index)` inside a nested comparison loop; `GetPoint` is O(n) per call (the backing `NCollection_Sequence` has no O(1) indexed access), so every comparison paid that cost again — profiling attributed ~80% of runtime to `NCollection_BaseSequence::Find`. (2) the phase never polled its cooperative progress indicator below `BOPAlgo_CheckerSI::CheckFaceSelfIntersection`, so a caller's timeout could only fire between whole-face checks, not within one — exactly where the artifact got stuck. **Fixed in v1.15.1** (`Scripts/patches/0010-*`, xcframework rebuilt): `Intf_TangentZone::Points()` caches a true random-access array per zone (O(1) lookup); `Intf_Interference::SetBreaker` (thread-local, RAII-scoped via `Intf_InterferenceBreakerScope`) lets `Insert()` poll every 256 calls and abort by throwing `Standard_Failure`, wired up in `BOPAlgo_CheckerSI`'s self-intersect functor only when single-threaded (an exception from an `OSD_Parallel::For` worker thread would risk `std::terminate()`). Verified: a 0.5s deadline now returns in 0.547s and a 30s deadline in 30.1s, correct results throughout. Reproducer at [`Scripts/repro/319-selfintersection`](https://github.com/SecondMouseAU/OCCTSwift/tree/main/Scripts/repro/319-selfintersection); filed upstream as [OCCT#1385](https://github.com/Open-Cascade-SAS/OCCT/issues/1385) (repro) / [OCCT#1386](https://github.com/Open-Cascade-SAS/OCCT/pull/1386) (fix, CI green on all 3 platforms). #319.

### Carrying OCCT source patches

Expand Down
9 changes: 5 additions & 4 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,19 @@ let occtTarget: Target = useLocalBinary
name: "OCCT",
path: "Libraries/OCCT.xcframework"
)
// v1.12.9 rebuild: OCCT 8.0.0p1 + our carried patches — 0001 (ShapeFix_Face guard, #263),
// v1.15.1 rebuild: OCCT 8.0.0p1 + our carried patches — 0001 (ShapeFix_Face guard, #263),
// 0002 (backport of upstream OCCT#1334, #280), 0003 (fillet TopOpeBRep thread_local, #298),
// 0004 (ShapeAnalysis_FreeBounds owires init, #310), 0005 (ShapeFix_Face null-Context guard
// in FixPeriodicDegenerated, #317), 0006 (BRepGProp_EdgeTool adaptor NbPoles, #318), 0007
// (ShapeAnalysis_FreeBounds lwire reset, #323), 0008 (Geom_BSplineCurve O(1)
// PeriodicNormalization, #323), and 0009 (StepData_StepWriter split oversized string, #323).
// PeriodicNormalization, #323), 0009 (StepData_StepWriter split oversized string, #323), and
// 0010 (Intf_Interference O(1) tangent-zone lookup + checkpointed breaker, #319).
// Bump BOTH url and checksum whenever the xcframework is rebuilt, or URL-resolving consumers
// silently keep the previous kernel while local sibling builds get the new one.
: .binaryTarget(
name: "OCCT",
url: "https://github.com/SecondMouseAU/OCCTSwift/releases/download/v1.12.9/OCCT.xcframework.zip",
checksum: "52282c923321fbef5d6ff09ad2a3f4e664da2a37a236b0d1c4de48cbc73f00bb"
url: "https://github.com/SecondMouseAU/OCCTSwift/releases/download/v1.15.1/OCCT.xcframework.zip",
checksum: "b1c967f90ea45a74ba97893ce78297d8c2dee516024f9c79f80b16b388ece2c1"
)

let package = Package(
Expand Down
Loading