Skip to content

Releases: SecondMouseAU/OCCTSwift

v1.8.2 — smooth multi-start threadedShaft direct build (#257)

21 Jun 22:07
240ad38

Choose a tag to compare

Feature. Multi-start threads (threadedShaft(starts: N), N > 1) now build via the smooth, boolean-free direct path instead of falling to the faceted boolean cut (which produced disconnected notches, #254).

The single-start cam-slice loft (#213) is generalised to N teeth tiling the turn at lead = N·pitch, giving a continuous interleaved multi-helix — a low-face-count, BRepCheck-valid solid with the crest exactly at the nominal major radius. Partial-length multi-start (thread + plain shank) closes via per-start shoulder faces.

starts faces mesh crest (nominal 5.0)
1 7 5.000
2 12 5.000
3 17 5.000

Scope: piecewise-linear forms (ISO/Unified, trapezoidal/ACME, square, buttress). Rounded (knuckle / rounded Whitworth), tapered (NPT/BSPT), and non-cylinder targets still use the cut path. Single-start behaviour unchanged.

Key detail: the loft samples per pitch, not per lead — sampling per turn under-samples each tooth at N > 1 and the ruled:false loft balloons the crest radially past nominal.

Swift-only — no xcframework rebuild. Full thread suite (54 tests) green. Closes #257.

v1.8.1 — fix: single-start threadedShaft always smooth; deprecate .boolean (#254)

21 Jun 11:33
ed33088

Choose a tag to compare

Fix. threadedShaft(build: .boolean) produced a faceted, disconnected thread — a helical scatter of rectangular notches instead of a continuous groove — because it forced the screw-loft boolean cut path, whose tightly-wound helical cutter is the classic OCCT BOP failure (cf. #213/#225). The solid was isValid with ~the right volume, so only rendering exposed it.

.boolean only existed to clamp a supposed crest "overshoot" (#222) — but #232 established that overshoot is a Bnd_Box control-hull artifact. Verified here: the direct build's crest measures exactly nominal by both boundingBoxOptimal() and mesh vertices, while .bounds over-reads +14–21%.

With no remaining reason to prefer it, single-start coaxial-cylinder threads now take the smooth, boolean-free direct build (#213) for every build mode, and ThreadBuild.boolean is deprecated (treated as .auto). Use .auto or .direct.

.auto/.direct single-start behaviour is unchanged. Swift-only — no xcframework rebuild.

Known limitation: multi-start (starts > 1) and non-cylinder targets still use the faceted cut path (no direct alternative yet) — tracked separately.

Full thread suite (49 tests) green. Closes #254.

Note: the separately-reported helical-flank "ridges" (#255) are a renderer normals artifact, not a geometry bug — see OCCTSwiftViewport#81.

v1.8.0 — Exporter.writeBREP(allowInvalid:)

19 Jun 23:59
94eea64

Choose a tag to compare

Feature (additive). Exporter.writeBREP (and the Shape.writeBREP instance wrapper) gain allowInvalid: Bool = false. When true, the shape.isValid pre-check is skipped and the shape is serialized as-is — BREP is OCCT's lossless native format and BRepTools::Write does not require a valid shape, and loadBREP already doesn't gate on read. Lets an in-progress reconstruction (a compound of loose analytic faces) be persisted and reloaded for measurement / diagnostics.

Default false preserves the existing gate; other exporters unchanged. Enables OCCTMCP #41. No xcframework change.

PR #248.

v1.7.11 — fromPointGrid degree clamp prevents a BRepMesh hang (#244)

19 Jun 22:35

Choose a tag to compare

Bug fix. No new operations; no xcframework change (same v1.7.1 binary).

Surface.fromPointGrid now clamps the B-spline fit degree to min(uCount, vCount) − 1. Passing a degMax higher than the grid supports (the default degMax: 8 on a 7×7 grid) over-parameterised the fit: a degree-8 surface from only 7 samples/direction oscillates (Runge phenomenon) and can self-overlap in 3D. The resulting face is topologically valid (BRepCheck passes) but geometrically rippling, so BRepMesh's adaptive refinement never converged — an in-process, uninterruptible hang (the OCCTReconstruct blocker). The clamp keeps the fit well-posed; the 7×7 case now meshes in ~40 ms.

Why not an interruptible mesh? A watchdog-based bounded mesh was prototyped and rejected — BRepMesh doesn't poll UserBreak during heavy meshing (verified: a fine sphere ran ~13 min / 5 GB ignoring a 0.01s deadline), so an in-process time bound can't be made both reliable and safe. Prevention (well-posed surfaces) is the robust fix.

📖 Docs & cookbook: https://gsdali.github.io/OCCTSwift/

v1.7.10 — degenerate-hole crash fix (#234)

19 Jun 19:59

Choose a tag to compare

Bug fix + docs. No new operations; no xcframework change (same v1.7.1 binary).

  • #234faceAddHole rejects degenerate hole wires. A 2-vertex / zero-area / collinear hole wire was accepted, producing an invalid face whose extruded prism SIGSEGV'd OCCT's ShapeFix (Shape.healed()) — an uncatchable OS signal. faceAddHole now returns nil for a hole wire with < 3 distinct vertices or all-collinear points, breaking the crash chain at the source.
  • #178 — loft polar-iterator fix is upstream. The BRepFill_CompatibleWires guard (#176) shipped in OCCT 8.0.0p1; the carried local patch was dropped. Stale CLAUDE.md / test references corrected (the #176 regression passes against the unpatched p1 xcframework).
  • #210 — context7. Runnable-snippet doc comments on the core ops + a CLAUDE.md doc-standards rule. The Swift API is now indexed and queryable on context7 (/gsdali/occtswift).

📖 Docs & cookbook: https://gsdali.github.io/OCCTSwift/

v1.7.9 — face from surface bounded by a wire / UV polygon

19 Jun 19:17

Choose a tag to compare

Additive, source-compatible. Trim a curved analytic surface (cylinder / cone / sphere / B-spline) to a non-rectangular region — closes #233.

  • Surface.toFace(uvBoundary: [SIMD2<Double>]) — a closed UV-space boundary polygon → 2D edges with pcurves on the surface → BRepBuilderAPI_MakeFace(surface, wire) + BuildCurves3d. (Ground-truthed: a cylinder region trims to 39.75 vs 60 for the full UV box.)
  • Shape.face(from: Surface, boundary: Wire) — a 3D boundary wire: exact MakeFace + ShapeFix_Face when the wire lies on the surface, else a fallback that projects the wire's ordered points to UV and trims by that polygon (handles sampled boundary polylines — the reconstruction case; seam-crossing boundaries not handled by the fallback).

Surfaces 86→88, total 4,290 operations. No xcframework change (same v1.7.1 binary).

Also lands the #232 investigation (doc + tests, no behavior change): Shape.bounds over-reports for B-spline/faceted geometry — threaded solids are bounded exactly to length/depth; Issue232BoundsTests asserts the true (mesh-vertex) extent.

📖 Docs & cookbook: https://gsdali.github.io/OCCTSwift/

v1.7.8 — cookbook: surfaces from points + working with meshes

19 Jun 11:57

Choose a tag to compare

Documentation-only release. No code, API, or xcframework change — SPM consumers get the same v1.7.1 binary; only the tag and docs advance.

Two new cookbook pages (snippets compile-checked against the shipped API):

  • Surfaces from Points (#230) — fit a B-spline Surface through 3D points: a regular grid via Surface.fromPointGrid (GeomAPI_PointsToBSplineSurface), a scattered cloud via Surface.plateThrough (GeomPlate), and deform-to-targets via nlPlateDeformed (NLPlate).
  • Working with Meshes (#231) — operating on the Mesh type: build from vertex/index arrays, inspect, triangle ↔ B-Rep face picking, mesh-level booleans, toShape, and SceneKit / RealityKit / Metal interop.

The cookbook now spans twelve pages: Booleans · Threads · Helices · Lofting & Sweeps · Helical Sweeps · Healing & Validity · Meshing & Export · XCAF Assemblies · Topology Graph · Gordon Surfaces · Surfaces from Points · Working with Meshes.

📖 Docs & cookbook: https://gsdali.github.io/OCCTSwift/

v1.7.7 — cookbook: Gordon surfaces

19 Jun 09:43

Choose a tag to compare

Documentation-only release. No code, API, or xcframework change — SPM consumers get the same v1.7.1 binary; only the tag and docs advance.

New cookbook page on Gordon surfaces (#229) — skinning a surface through a network of crossing profile + guide curves via Surface.gordon / Surface.gordonReport (GeomFill_Gordon):

  • The grid-closure requirement (≥2 profiles × ≥2 guides, shared corners) and surface.toFace().
  • Build diagnostics — gordonReport returns status + isApproximate instead of bare nil; allowApproximateFallback for a sampled fallback.
  • The lower-level networkSurface (GeomFill_NetworkSurface) and its knot-alignment caveat.
  • A Gordon-vs-loft-vs-fill decision table.

Snippets compile-checked; figure rendered from the same network the page shows.

The cookbook now spans ten pages: Booleans · Threads · Helices · Lofting & Sweeps · Helical Sweeps · Healing & Validity · Meshing & Export · XCAF Assemblies · Topology Graph · Gordon Surfaces.

📖 Docs & cookbook: https://gsdali.github.io/OCCTSwift/

v1.7.6 — cookbook complete: healing, meshing, XCAF, topology

19 Jun 09:36

Choose a tag to compare

Documentation-only release. No code, API, or xcframework change — SPM consumers get the same v1.7.1 binary; only the tag and docs advance.

Completes the issue #210 cookbook area list — the Swift-API counterpart to OCCT's own user guides — with the final four areas (#228). Every snippet was compile- and run-checked against the shipped API.

  • Healing & Validity — checks (isValid / isValidSolid / isSelfIntersecting / analyze), orientation (signedVolume / orientedForward), and repair (healed / fixed / unified / upgraded / sew / free-bounds).
  • Meshing & Exportmesh + MeshParameters, the Mesh type, toShape, a deflection table, and STL / OBJ / PLY / STEP / IGES / BREP / glTF export + import.
  • XCAF AssembliesDocument trees, components & instancing, colors & materials, structured STEP / GLB round-trip (with a rendered two-colour assembly figure).
  • Topology Graph — node counts, adjacency / shared edges / sameDomainFaces, durable UIDs, and history tracking.

The cookbook now covers Booleans, Threads, Helices, Lofting & Sweeps, Helical Sweeps, Healing & Validity, Meshing & Export, XCAF Assemblies, and Topology Graph.

📖 Docs & cookbook: https://gsdali.github.io/OCCTSwift/

v1.7.5 — threadedRod from a custom profile (#225)

19 Jun 09:14
0671425

Choose a tag to compare

Additive, source-compatible. Builds a smooth worm/screw from a custom radial tooth profile directly — no boolean — closing the actionable part of #225.

Why

helicalSweep a profile then union/subtract it with a coaxial cylinder is invalid (union) or collapses to zero (subtract), and no fuzzyValue / heal pass recovers it — OCCT's BOP can't resolve the coincident/tangent helicoid faces (consistent with #213, #181). The boolean compose path was never the way; the direct build is.

New API

  • Shape.threadedRod(customProfile:nominalDiameter:pitch:cutDepth:length:axisOrigin:axisDirection:leftHanded:) — composes a custom tooth profile with the core by sewing (no boolean) → BRepCheck-valid, analytic (handful of B-spline faces → sub-MB STEP). Returns nil rather than silently producing an invalid boolean.
  • ThreadProfile.supportsSmoothRodBuild — public predicate (real crest flat, ≤ 2 flanks).
  • Shape.helicalSweep(…) doc now warns against the boolean-compose anti-pattern and points to threadedRod.

The issue's worm (root r3, crest r6) via threadedRod: valid, 9 faces, ~0.74 MB STEP (vs the ~6.8 MB faceted fallback).

Docs

New Helical Sweeps cookbook page (helicalSweep helicoids vs. threadedRod worms, and why the boolean compose fails), with rendered figures.

No xcframework change — same binary as v1.7.1. Thread Features 22→23, total 4,288 operations.

📖 Docs & cookbook: https://gsdali.github.io/OCCTSwift/