Link Search Menu Expand Document

Document. Geometry Constructors & Pipe Shells

This page covers geometry construction and analysis utilities added across v0.105.0–v0.106.0 in Document.swift: 2D parabola constructors, uniform arc-length sampling, curve/surface concatenation and knot splitting, bounding-box extensions, geometric property helpers, shape reshaping, pipe-shell sweeping, directory/file access, quadric intersections, XCAF explorer queries, Unicode utilities, and shape-analysis diagnostics. For the core document lifecycle, shape tools, and STEP/IGES I/O see the main Document page.

Topics


GC_MakeParabola2d

Two-dimensional parabola constructors extending Curve2D via GC_MakeParabola2d.

Curve2D.gceParabola(center:direction:focalDistance:)

Create a 2D parabola from an axis (center + direction) and focal distance.

public static func gceParabola(center: SIMD2<Double>, direction: SIMD2<Double>,
                                focalDistance: Double) -> Curve2D?
  • Parameters: center, origin of the parabola axis; direction, X-direction of the axis; focalDistance, distance from vertex to focus.
  • Returns: A Curve2D wrapping a Geom2d_Parabola, or nil if construction fails.
  • OCCT: GC_MakeParabola2d
  • Example:
    if let p = Curve2D.gceParabola(center: .zero, direction: SIMD2(1, 0), focalDistance: 2.0) {
        // p represents y² = 8x in the local axis frame
    }
    

Curve2D.gceParabola(directrixPoint:directrixDirection:focus:)

Create a 2D parabola from a directrix line and a focus point.

public static func gceParabola(directrixPoint: SIMD2<Double>, directrixDirection: SIMD2<Double>,
                                focus: SIMD2<Double>) -> Curve2D?
  • Parameters: directrixPoint, a point on the directrix; directrixDirection, direction of the directrix; focus, the focus point.
  • Returns: A Curve2D wrapping a Geom2d_Parabola, or nil on failure.
  • OCCT: GC_MakeParabola2d (directrix-focus constructor)
  • Example:
    if let p = Curve2D.gceParabola(directrixPoint: SIMD2(-2, 0),
                                     directrixDirection: SIMD2(0, 1),
                                     focus: SIMD2(2, 0)) {
        // parabola with vertex at origin
    }
    

GCPnts_UniformAbscissa

Uniformly sample an edge by point count or arc distance. These are extensions on Shape (applied to edge shapes) wrapping GCPnts_UniformAbscissa.

Shape.uniformAbscissa(pointCount:)

Uniformly sample an edge by point count; returns parameter values.

public func uniformAbscissa(pointCount: Int) -> [Double]?
  • Parameters: pointCount, the number of sample points. Must be at least 2, else nil. OCCT documents that precondition but enforces it with a Raise_if, which the pinned Release kernel compiles out, so a request for zero used to come back with five parameters (#501).
  • Returns: Array of curve parameter values, or nil if the edge is invalid or sampling fails.
  • OCCT: GCPnts_UniformAbscissa (by number of points). The edge is read through a BRepAdaptor_Curve, whose constructor dereferences a null shape, so a null shape (from Shape.nullified) used to crash the process here; it answers nil now (#1035, measured in Scripts/repro/1035-unwrap-guard/).
  • Example:
    if let edge = Shape.makeVertex(at: .zero),
       let params = edge.uniformAbscissa(pointCount: 10) {
        print(params.count) // up to 10
    }
    

Shape.uniformAbscissa(distance:)

Uniformly sample an edge by arc distance; returns parameter values.

public func uniformAbscissa(distance: Double) -> [Double]?
  • Parameters: distance, arc-length step between consecutive sample points.
  • Returns: Array of curve parameter values, or nil on failure.
  • OCCT: GCPnts_UniformAbscissa (by chord/arc length)
  • Example:
    if let params = someEdgeShape.uniformAbscissa(distance: 1.0) {
        // params spaced 1.0 unit apart along the edge
    }
    

A null shape (from Shape.nullified) used to crash the process in the BRepAdaptor_Curve constructor behind this sampler; it answers nil now (#1035).


Shape.uniformAbscissa(pointCount:u1:u2:)

Uniformly sample an edge by point count within a parameter range.

public func uniformAbscissa(pointCount: Int, u1: Double, u2: Double) -> [Double]?
  • Parameters: pointCount, the number of points, at least 2 (else nil, see above); u1, u2, the parameter range on the underlying curve.
  • Returns: Array of parameter values, or nil on failure.
  • OCCT: GCPnts_UniformAbscissa (range variant, by count). A null shape (from Shape.nullified) used to crash the process in the BRepAdaptor_Curve constructor; it answers nil now (#1035).
  • Example:
    if let params = edge.uniformAbscissa(pointCount: 5, u1: 0.0, u2: .pi) {
        // 5 evenly-spaced parameters between 0 and π
    }
    

Shape.uniformAbscissa(distance:u1:u2:)

Uniformly sample an edge by arc distance within a parameter range.

public func uniformAbscissa(distance: Double, u1: Double, u2: Double) -> [Double]?
  • Parameters: distance, arc-length step; u1, u2, parameter range.
  • Returns: Array of parameter values, or nil on failure.
  • OCCT: GCPnts_UniformAbscissa (range variant, by distance)
  • Example:
    if let params = edge.uniformAbscissa(distance: 0.5, u1: 0.0, u2: 2.0) {
        // sampling at 0.5-unit intervals from u=0 to u=2
    }
    

A null shape (from Shape.nullified) used to crash the process in the BRepAdaptor_Curve constructor behind this sampler; it answers nil now (#1035).


GeomConvert CompCurveToBSplineCurve

Curve3D.concatenate(_:tolerance:)

Concatenate multiple bounded 3D curves into a single composite BSpline.

public static func concatenate(_ curves: [Curve3D], tolerance: Double = 1e-4) -> Curve3D?
  • Parameters: curves, ordered list of bounded Curve3D segments; tolerance, continuity tolerance at join points.
  • Returns: A Curve3D wrapping a Geom_BSplineCurve, or nil if the list is empty or concatenation fails.
  • OCCT: GeomConvert_CompCurveToBSplineCurve
  • Example:
    if let line = Curve3D.segment(from: SIMD3(0,0,0), to: SIMD3(1,0,0)),
       let arc  = Curve3D.arcOfCircle(start: SIMD3(1, 0, 0), interior: SIMD3(2, 1, 0), end: SIMD3(3, 0, 0)),
       let joined = Curve3D.concatenate([line, arc]) {
        // single BSpline spanning both segments
    }
    

Geom2dConvert CompCurveToBSplineCurve

Curve2D.concatenate(_:tolerance:)

Concatenate multiple bounded 2D curves into a single composite BSpline.

public static func concatenate(_ curves: [Curve2D], tolerance: Double = 1e-4) -> Curve2D?
  • Parameters: curves, ordered list of bounded Curve2D segments; tolerance, continuity tolerance at join points.
  • Returns: A Curve2D wrapping a Geom2d_BSplineCurve, or nil if the list is empty or concatenation fails.
  • OCCT: Geom2dConvert_CompCurveToBSplineCurve
  • Example:
    if let merged = Curve2D.concatenate([seg1, seg2], tolerance: 1e-5) {
        // one BSpline in 2D
    }
    

GeomConvert BSplineSurfaceKnotSplitting / Geom2dConvert BSplineCurveKnotSplitting

Five entry points documented here, Surface.bsplineKnotSplitsU(continuity:), Surface.bsplineKnotSplitsV(continuity:), Surface.bsplineKnotSplitValues(continuity:), Curve2D.bsplineKnotSplits(continuity:) and Curve2D.bsplineKnotSplitValues(continuity:), are deprecated as of #562. They were added in v0.105.0 over the same two analyzers that Surface.knotSplitting(uContinuity:vContinuity:) and Curve2D.splitIndicesAtDiscontinuities(continuity:) had already been wrapping for three releases, and each took one continuity for both parametric directions where the surface’s canonical call takes one per direction, so they could not ask a question the canonical call could not, only fewer of them.

Each now forwards to its canonical sibling; their own bridge functions are gone. The one thing they carried that the canonical calls did not, the raw 1-based knot-table indices, rather than the parameters those indices resolve to, is now KnotSplitResult.uSplitIndices / .vSplitIndices.

deprecated use
Surface.bsplineKnotSplitsU(continuity:) knotSplitting(uContinuity:vContinuity:).uSplitCount
Surface.bsplineKnotSplitsV(continuity:) knotSplitting(uContinuity:vContinuity:).vSplitCount
Surface.bsplineKnotSplitValues(continuity:) knotSplitting(uContinuity:vContinuity:).uSplitIndices / .vSplitIndices
Curve2D.bsplineKnotSplits(continuity:) splitIndicesAtDiscontinuities(continuity:)?.count
Curve2D.bsplineKnotSplitValues(continuity:) splitIndicesAtDiscontinuities(continuity:)
// Was: three analyzer constructions, one continuity for both directions.
let (uIdx, vIdx) = bsplineSurf.bsplineKnotSplitValues(continuity: .c3)

// Now: one construction, and U and V can be asked different questions.
let splits = bsplineSurf.knotSplitting(uContinuity: .c3, vContinuity: .c1)
let uIndices = splits.uSplitIndices               // the same 1-based knot indices
let uParams = splits.uSplitParams                 // and what they resolve to

BndLib extras

Analytic bounding-box extensions on BndLib covering conic curves and arcs.

BndLib.ellipse(center:normal:xDirection:majorRadius:minorRadius:tolerance:)

Axis-aligned bounding box of a full 3D ellipse.

public static func ellipse(center: SIMD3<Double>, normal: SIMD3<Double>, xDirection: SIMD3<Double>,
                            majorRadius: Double, minorRadius: Double, tolerance: Double = 0) -> AnalyticBounds
  • Parameters: center, ellipse center; normal, plane normal; xDirection, major-axis direction; majorRadius, minorRadius, semi-axes; tolerance, optional inflation.
  • Returns: AnalyticBounds with min and max corners.
  • OCCT: BndLib::Add, the gp_Elips overload (via OCCTBndLibEllipse). The adaptor-driven BndLib_Add3dCurve is what BndLib.edge(_:tolerance:) uses; nothing in this section reaches it.
  • Example:
    let b = BndLib.ellipse(center: .zero, normal: SIMD3(0,0,1), xDirection: SIMD3(1,0,0),
                            majorRadius: 3, minorRadius: 2)
    

BndLib.cone(center:axis:semiAngle:refRadius:vmin:vmax:tolerance:)

Axis-aligned bounding box of a cone segment.

public static func cone(center: SIMD3<Double>, axis: SIMD3<Double>,
                         semiAngle: Double, refRadius: Double,
                         vmin: Double, vmax: Double, tolerance: Double = 0) -> AnalyticBounds
  • Parameters: center, cone apex reference point; axis, cone axis direction; semiAngle, half-angle in radians; refRadius, radius at center; vmin, vmax, axial parameter range; tolerance, optional inflation.
  • Returns: AnalyticBounds.
  • OCCT: BndLib::Add, the gp_Cone overload taking vmin/vmax (via OCCTBndLibCone).
  • Example:
    let b = BndLib.cone(center: .zero, axis: SIMD3(0,0,1),
                         semiAngle: .pi/6, refRadius: 0, vmin: 0, vmax: 5)
    

BndLib.circleArc(center:normal:radius:u1:u2:tolerance:)

Axis-aligned bounding box of a circular arc.

public static func circleArc(center: SIMD3<Double>, normal: SIMD3<Double>,
                               radius: Double, u1: Double, u2: Double, tolerance: Double = 0) -> AnalyticBounds
  • Parameters: center, circle center; normal, plane normal; radius, circle radius; u1, u2, parameter range (radians); tolerance, optional inflation.
  • Returns: AnalyticBounds.
  • OCCT: BndLib::Add, the gp_Circ overload taking u1/u2 (via OCCTBndLibCircleArc).
  • Example:
    let b = BndLib.circleArc(center: .zero, normal: SIMD3(0,0,1),
                               radius: 5, u1: 0, u2: .pi)
    

BndLib.ellipseArc(center:normal:xDirection:majorRadius:minorRadius:u1:u2:tolerance:)

Axis-aligned bounding box of an ellipse arc.

public static func ellipseArc(center: SIMD3<Double>, normal: SIMD3<Double>, xDirection: SIMD3<Double>,
                               majorRadius: Double, minorRadius: Double,
                               u1: Double, u2: Double, tolerance: Double = 0) -> AnalyticBounds
  • Parameters: center, normal, xDirection, axis placement; majorRadius, minorRadius, semi-axes; u1, u2, parameter range (radians); tolerance, optional inflation.
  • Returns: AnalyticBounds.
  • OCCT: BndLib::Add, the gp_Elips overload taking u1/u2 (via OCCTBndLibEllipseArc).
  • Example:
    let b = BndLib.ellipseArc(center: .zero, normal: SIMD3(0,0,1), xDirection: SIMD3(1,0,0),
                                majorRadius: 4, minorRadius: 2, u1: 0, u2: .pi/2)
    

BndLib.parabolaArc(center:normal:xDirection:focalDistance:u1:u2:tolerance:)

Axis-aligned bounding box of a parabola arc.

public static func parabolaArc(center: SIMD3<Double>, normal: SIMD3<Double>, xDirection: SIMD3<Double>,
                                focalDistance: Double,
                                u1: Double, u2: Double, tolerance: Double = 0) -> AnalyticBounds
  • Parameters: center, normal, xDirection, axis placement; focalDistance, vertex-to-focus distance; u1, u2, parameter range; tolerance, optional inflation.
  • Returns: AnalyticBounds.
  • OCCT: BndLib::Add, the gp_Parab overload (via OCCTBndLibParabolaArc).
  • Example:
    let b = BndLib.parabolaArc(center: .zero, normal: SIMD3(0,0,1), xDirection: SIMD3(1,0,0),
                                 focalDistance: 2, u1: -2, u2: 2)
    

BndLib.hyperbolaArc(center:normal:xDirection:majorRadius:minorRadius:u1:u2:tolerance:)

Axis-aligned bounding box of a hyperbola arc.

public static func hyperbolaArc(center: SIMD3<Double>, normal: SIMD3<Double>, xDirection: SIMD3<Double>,
                                 majorRadius: Double, minorRadius: Double,
                                 u1: Double, u2: Double, tolerance: Double = 0) -> AnalyticBounds
  • Parameters: center, normal, xDirection, axis placement; majorRadius, minorRadius, semi-axes; u1, u2, parameter range; tolerance, optional inflation.
  • Returns: AnalyticBounds.
  • OCCT: BndLib::Add, the gp_Hypr overload (via OCCTBndLibHyperbolaArc).
  • Example:
    let b = BndLib.hyperbolaArc(center: .zero, normal: SIMD3(0,0,1), xDirection: SIMD3(1,0,0),
                                  majorRadius: 3, minorRadius: 2, u1: -1, u2: 1)
    

GProp Torus

Closed-form torus geometric properties on GeometryProperties.

GeometryProperties.torusSurfaceArea(majorRadius:minorRadius:)

Exact surface area of a full torus: 4π² R r.

public static func torusSurfaceArea(majorRadius: Double, minorRadius: Double) -> Double
  • Parameters: majorRadius, distance from torus center to tube center; minorRadius, tube radius.
  • Returns: Surface area in square units.
  • OCCT: GProp_SelGProps over a gp_Torus swept 0...2π in both parameters (via OCCTGPropTorusSurface). Not GProp_PEquation, which classifies a point cloud as coincident/collinear/coplanar and computes no areas.
  • Example:
    let area = GeometryProperties.torusSurfaceArea(majorRadius: 5, minorRadius: 1)
    // ≈ 197.39
    

GeometryProperties.torusVolume(majorRadius:minorRadius:)

Exact volume of a full torus: 2π² R r².

public static func torusVolume(majorRadius: Double, minorRadius: Double) -> Double
  • Parameters: majorRadius, major radius; minorRadius, tube radius.
  • Returns: Volume in cubic units.
  • OCCT: GProp_VelGProps over a gp_Torus (via OCCTGPropTorusVolume). GProp_GProps is the base class both inherit; it accumulates properties and computes none of its own.
  • Example:
    let vol = GeometryProperties.torusVolume(majorRadius: 5, minorRadius: 1)
    // ≈ 98.70
    

BRepTools_ReShape

ReShapeContext records removals and replacements of sub-shapes and then applies them in bulk to a target shape. Wraps BRepTools_ReShape.

ReShapeContext.init()

Create an empty reshape context.

public init()
  • OCCT: BRepTools_ReShape::BRepTools_ReShape
  • Example:
    let ctx = ReShapeContext()
    

ReShapeContext.clear()

Remove all recorded modifications.

public func clear()
  • OCCT: BRepTools_ReShape::Clear
  • Example:
    ctx.clear()
    

ReShapeContext.remove(_:)

Record removal of a shape from the result.

public func remove(_ shape: Shape)
  • Parameters: shape, the sub-shape to delete.
  • OCCT: BRepTools_ReShape::Remove
  • Example:
    ctx.remove(edgeToDelete)
    

ReShapeContext.replace(_:with:)

Record replacement of one shape with another.

public func replace(_ oldShape: Shape, with newShape: Shape)
  • Parameters: oldShape, shape to replace; newShape, the replacement.
  • OCCT: BRepTools_ReShape::Replace
  • Example:
    ctx.replace(oldEdge, with: newEdge)
    

ReShapeContext.isRecorded(_:)

Check whether a shape has been registered for removal or replacement.

public func isRecorded(_ shape: Shape) -> Bool
  • Parameters: shape, the shape to query.
  • Returns: true if the shape appears in the context.
  • OCCT: BRepTools_ReShape::IsRecorded
  • Example:
    if ctx.isRecorded(someEdge) { /* ... */ }
    

ReShapeContext.apply(to:)

Apply all recorded modifications and return the rebuilt shape.

public func apply(to shape: Shape) -> Shape?
  • Parameters: shape, the top-level shape to rebuild.
  • Returns: The reshaped result, or nil on failure.
  • OCCT: BRepTools_ReShape::Apply
  • Example:
    if let result = ctx.apply(to: solid) {
        // result has the recorded changes applied
    }
    

ReShapeContext.value(for:)

Retrieve the replacement value recorded for a specific shape.

public func value(for shape: Shape) -> Shape?
  • Parameters: shape, the original shape.
  • Returns: The recorded replacement, or nil if none.
  • OCCT: BRepTools_ReShape::Value
  • Example:
    if let replacement = ctx.value(for: oldEdge) {
        print("will replace with \(replacement)")
    }
    

BRepTools_Substitution

Sub-shape substitution on Shape, wrapping BRepTools_Substitution.

Shape.substitute(oldSubShape:newSubShapes:)

Replace a sub-shape with one or more new shapes. Pass an empty array to remove the sub-shape.

public func substitute(oldSubShape: Shape, newSubShapes: [Shape]) -> Shape?
  • Parameters: oldSubShape, the sub-shape to replace; newSubShapes, replacement shapes (empty = removal).
  • Returns: A new Shape with the substitution applied, or nil on failure.
  • OCCT: BRepTools_Substitution::Substitute + BRepTools_Substitution::Build
  • Example:
    if let rebuilt = solid.substitute(oldSubShape: oldFace, newSubShapes: [newFace]) {
        // rebuilt has oldFace replaced by newFace
    }
    

Shape.substitutionIsCopied(subshape:)

Check whether a sub-shape was copied (not merely referenced) during substitution.

public func substitutionIsCopied(subshape: Shape) -> Bool
  • Parameters: subshape, the sub-shape to query.
  • Returns: true if the sub-shape was copied.
  • OCCT: BRepTools_Substitution::IsCopied
  • Example:
    let copied = solid.substitutionIsCopied(subshape: anEdge)
    

BRepLib_MakeVertex

Shape.makeVertex(at:)

Create a vertex Shape at a given 3D point using BRepLib_MakeVertex.

public static func makeVertex(at point: SIMD3<Double>) -> Shape?
  • Parameters: point, 3D coordinates of the vertex.
  • Returns: A TopoDS_Vertex wrapped as Shape, or nil on failure.
  • OCCT: BRepLib_MakeVertex
  • Example:
    if let v = Shape.makeVertex(at: SIMD3(1, 2, 3)) {
        // v is a vertex shape
    }
    

BRepFill_PipeShell

PipeShellBuilder sweeps one or more profiles along a spine wire with fine-grained control over trihedron, tolerances, and transition mode. Wraps BRepFill_PipeShell.

PipeShellTransition

Transition mode between consecutive spine segments.

public enum PipeShellTransition: Int32, Sendable {
    case modified = 0
    case right = 1
    case round = 2
}
  • OCCT: BRepFill_TransitionStyle
Case Meaning
modified The two swept faces are extended/trimmed to meet exactly at the transition (the default OCCT behaviour).
right A sharp, square (“right-angle”) corner is built at the transition.
round A rounded (filleted) corner is built at the transition.

PipeShellTransition.round

A rounded (filleted) corner at the transition between spine segments.


PipeShellBuilder.init?(spine:)

Create a pipe-shell builder from a spine wire.

public init?(spine: Shape)
  • Parameters: spine, a wire Shape used as the sweep path.
  • Returns: nil if spine is not a valid wire or construction fails.
  • OCCT: BRepFill_PipeShell::BRepFill_PipeShell
  • Example:
    if let pipe = PipeShellBuilder(spine: spineWire) {
        pipe.add(profile: profileWire)
        pipe.build()
    }
    

PipeShellBuilder.setFrenet(_:)

Use the Frenet trihedron to orient the profile along the spine.

public func setFrenet(_ frenet: Bool = true)
  • Parameters: frenet, true to enable Frenet mode (default).
  • OCCT: BRepFill_PipeShell::Set(Standard_Boolean)
  • Example:
    guard let spineLine = Wire.line(from: .zero, to: SIMD3(0, 0, 50)),
          let spineWire = Shape.fromWire(spineLine),
          let pipe = PipeShellBuilder(spine: spineWire) else { return }
    pipe.setFrenet(true)
    

PipeShellBuilder.setDiscrete()

Use a discrete (piecewise constant) trihedron mode.

public func setDiscrete()
  • OCCT: BRepFill_PipeShell::SetDiscrete
  • Example:
    guard let spineLine = Wire.line(from: .zero, to: SIMD3(0, 0, 50)),
          let spineWire = Shape.fromWire(spineLine),
          let pipe = PipeShellBuilder(spine: spineWire) else { return }
    pipe.setDiscrete()
    

PipeShellBuilder.setFixed(binormal:)

Fix the binormal direction of the trihedron.

public func setFixed(binormal: SIMD3<Double>)
  • Parameters: binormal, world-space binormal direction.
  • OCCT: BRepFill_PipeShell::Set(gp_Dir)
  • Example:
    guard let spineLine = Wire.line(from: .zero, to: SIMD3(0, 0, 50)),
          let spineWire = Shape.fromWire(spineLine),
          let pipe = PipeShellBuilder(spine: spineWire) else { return }
    pipe.setFixed(binormal: SIMD3(0, 0, 1))
    

PipeShellBuilder.add(profile:)

Add a profile wire or vertex at the current (default) position on the spine.

public func add(profile: Shape)
  • Parameters: profile, the cross-sectional profile (TopoDS_Wire or TopoDS_Vertex).
  • OCCT: BRepFill_PipeShell::Add
  • Example:
    pipe.add(profile: circleWire)
    

PipeShellBuilder.add(profile:atVertex:)

Add a profile at a specific vertex on the spine.

public func add(profile: Shape, atVertex vertex: Shape)
  • Parameters: profile, the cross-sectional profile; vertex, a TopoDS_Vertex on the spine.
  • OCCT: BRepFill_PipeShell::Add (vertex-pinned overload)
  • Example:
    pipe.add(profile: smallCircle, atVertex: spineStart)
    pipe.add(profile: largeCircle, atVertex: spineEnd)
    

PipeShellBuilder.setLaw(profile:law:)

Attach a scaling law to a profile so the section varies along the spine.

public func setLaw(profile: Shape, law: LawFunction)
  • Parameters: profile, the cross-section profile; law, a LawFunction driving scale or parameter evolution.
  • OCCT: BRepFill_PipeShell::SetLaw
  • Example:
    pipe.setLaw(profile: profileWire, law: scalingLaw)
    

PipeShellBuilder.setTolerance(tol3d:boundTol:tolAngular:)

Set approximation tolerances.

public func setTolerance(tol3d: Double, boundTol: Double, tolAngular: Double)
  • Parameters: tol3d, 3D approximation tolerance; boundTol, boundary tolerance; tolAngular, angular tolerance (radians).
  • OCCT: BRepFill_PipeShell::SetTolerance
  • Example:
    guard let spineLine = Wire.line(from: .zero, to: SIMD3(0, 0, 50)),
          let spineWire = Shape.fromWire(spineLine),
          let pipe = PipeShellBuilder(spine: spineWire) else { return }
    pipe.setTolerance(tol3d: 1e-4, boundTol: 1e-4, tolAngular: 1e-3)
    

PipeShellBuilder.setTransition(_:)

Set the transition mode between consecutive spine segments.

public func setTransition(_ mode: PipeShellTransition)
  • Parameters: mode, .modified, .right, or .round.
  • OCCT: BRepFill_PipeShell::SetTransition
  • Example:
    guard let spineLine = Wire.line(from: .zero, to: SIMD3(0, 0, 50)),
          let spineWire = Shape.fromWire(spineLine),
          let pipe = PipeShellBuilder(spine: spineWire) else { return }
    pipe.setTransition(.round)
    

PipeShellBuilder.build()

Perform the sweep computation.

@discardableResult
public func build() -> Bool
  • Returns: true if the build succeeded.
  • OCCT: BRepFill_PipeShell::Build
  • Example:
    guard let spineLine = Wire.line(from: .zero, to: SIMD3(0, 0, 50)),
          let spineWire = Shape.fromWire(spineLine),
          let profileCircle = Wire.circle(radius: 5),
          let profile = Shape.fromWire(profileCircle),
          let pipe = PipeShellBuilder(spine: spineWire) else { return }
    pipe.add(profile: profile)
    guard pipe.build() else { return }  // handle the failure
    

PipeShellBuilder.shape

The resulting swept shape.

public var shape: Shape? { get }
  • Returns: The swept shell or solid, or nil if build() has not been called or failed.
  • OCCT: BRepFill_PipeShell::Shape
  • Example:
    guard let spineLine = Wire.line(from: .zero, to: SIMD3(0, 0, 50)),
          let spineWire = Shape.fromWire(spineLine),
          let profileCircle = Wire.circle(radius: 5),
          let profile = Shape.fromWire(profileCircle),
          let pipe = PipeShellBuilder(spine: spineWire) else { return }
    pipe.add(profile: profile)
    pipe.build()
    if let result = pipe.shape {
        // use result
    }
    

PipeShellBuilder.makeSolid()

Close the pipe shell into a solid by capping the open ends.

@discardableResult
public func makeSolid() -> Bool
  • Returns: true if solid construction succeeded.
  • OCCT: BRepFill_PipeShell::MakeSolid
  • Example:
    guard let spineLine = Wire.line(from: .zero, to: SIMD3(0, 0, 50)),
          let spineWire = Shape.fromWire(spineLine),
          let profileCircle = Wire.circle(radius: 5),
          let profile = Shape.fromWire(profileCircle),
          let pipe = PipeShellBuilder(spine: spineWire) else { return }
    pipe.add(profile: profile)
    pipe.build()
    pipe.makeSolid()
    

PipeShellBuilder.error

Approximation error of the swept surface.

public var error: Double { get }
  • Returns: Maximum deviation between the exact surface and the B-Spline approximation.
  • OCCT: BRepFill_PipeShell::ErrorOnSurface
  • Example:
    guard let spineLine = Wire.line(from: .zero, to: SIMD3(0, 0, 50)),
          let spineWire = Shape.fromWire(spineLine),
          let profileCircle = Wire.circle(radius: 5),
          let profile = Shape.fromWire(profileCircle),
          let pipe = PipeShellBuilder(spine: spineWire) else { return }
    pipe.add(profile: profile)
    pipe.build()
    print("error:", pipe.error)
    

PipeShellBuilder.isReady

Whether the builder has enough profiles to begin sweeping.

public var isReady: Bool { get }
  • Returns: true when at least one profile has been added and the builder is configured.
  • OCCT: BRepFill_PipeShell::IsReady
  • Example:
    guard let spineLine = Wire.line(from: .zero, to: SIMD3(0, 0, 50)),
          let spineWire = Shape.fromWire(spineLine),
          let profileCircle = Wire.circle(radius: 5),
          let profile = Shape.fromWire(profileCircle),
          let pipe = PipeShellBuilder(spine: spineWire) else { return }
    pipe.add(profile: profile)
    guard pipe.isReady else { return }  // not enough profiles yet
    

OSD_Directory

File-system directory operations via OSD_Directory. All members are on the DirectoryUtils enum.

DirectoryUtils.exists(_:)

Check whether a directory exists at the given path.

public static func exists(_ path: String) -> Bool
  • Parameters: path, file-system path.
  • OCCT: OSD_Directory::Exists
  • Example:
    if DirectoryUtils.exists("/tmp/mydir") { /* ... */ }
    

DirectoryUtils.create(_:)

Create a directory at the given path.

@discardableResult
public static func create(_ path: String) -> Bool
  • Parameters: path, file-system path to create.
  • Returns: true on success.
  • OCCT: OSD_Directory::Build
  • Example:
    DirectoryUtils.create("/tmp/output")
    

DirectoryUtils.buildTemporary()

Create a uniquely named temporary directory and return its path.

public static func buildTemporary() -> String?
  • Returns: The path of the created temporary directory, or nil on failure.
  • OCCT: OSD_Directory::BuildTemporary
  • Example:
    if let tmp = DirectoryUtils.buildTemporary() {
        print("temp dir:", tmp)
    }
    

DirectoryUtils.remove(_:)

Remove a directory at the given path.

@discardableResult
public static func remove(_ path: String) -> Bool
  • Parameters: path, file-system path.
  • Returns: true on success.
  • OCCT: OSD_Directory::Remove
  • Example:
    DirectoryUtils.remove("/tmp/mydir")
    

IntAna Cone-Sphere extensions

Analytical intersection of a Z-axis cone with a sphere, extending QuadricIntersection.

QuadricIntersection.coneSphere(semiAngle:refRadius:sphereCenter:sphereRadius:tolerance:)

Compute the number of intersection curves between a Z-axis cone and a sphere.

public static func coneSphere(semiAngle: Double, refRadius: Double,
                               sphereCenter: SIMD3<Double>, sphereRadius: Double,
                               tolerance: Double = 1e-6) -> Int?
  • Parameters: semiAngle, cone half-angle (radians); refRadius, cone radius at its reference plane; sphereCenter, sphereRadius, sphere definition; tolerance, intersection tolerance.
  • Returns: Number of intersection curves (0, 1, or 2), or nil on error (e.g. identical surfaces).
  • OCCT: IntAna_IntQuadQuad on an IntAna_Quadric built from the sphere. The three coneSphere* entries below read the curves it produces.
  • Example:
    if let n = QuadricIntersection.coneSphere(semiAngle: .pi/4, refRadius: 0,
                                               sphereCenter: SIMD3(0,0,5), sphereRadius: 3) {
        print("curves:", n)
    }
    

QuadricIntersection.coneSpherePoints(semiAngle:refRadius:sphereCenter:sphereRadius:tolerance:curveIndex:sampleCount:)

Sample points along a specific cone-sphere intersection curve.

public static func coneSpherePoints(semiAngle: Double, refRadius: Double,
                                     sphereCenter: SIMD3<Double>, sphereRadius: Double,
                                     tolerance: Double = 1e-6,
                                     curveIndex: Int, sampleCount: Int) -> [SIMD3<Double>]
  • Parameters: curveIndex, 0-based index of the intersection curve; sampleCount, number of points to evaluate; other parameters as in coneSphere.
  • Returns: Array of up to sampleCount 3D points on the intersection curve.
  • OCCT: IntAna_Curve::Value
  • Example:
    let pts = QuadricIntersection.coneSpherePoints(semiAngle: .pi/4, refRadius: 0,
                                                    sphereCenter: SIMD3(0,0,5), sphereRadius: 3,
                                                    curveIndex: 0, sampleCount: 32)
    

QuadricIntersection.coneSphereIsOpen(semiAngle:refRadius:sphereCenter:sphereRadius:tolerance:curveIndex:)

Check whether a cone-sphere intersection curve is open (has finite parameter domain).

public static func coneSphereIsOpen(semiAngle: Double, refRadius: Double,
                                     sphereCenter: SIMD3<Double>, sphereRadius: Double,
                                     tolerance: Double = 1e-6, curveIndex: Int) -> Bool
  • Parameters: Same geometry as coneSphere; curveIndex, 0-based curve index.
  • Returns: true if the intersection curve is open.
  • OCCT: IntAna_Curve::IsOpen
  • Example:
    let open = QuadricIntersection.coneSphereIsOpen(semiAngle: .pi/4, refRadius: 0,
                                                     sphereCenter: SIMD3(0,0,5), sphereRadius: 3,
                                                     curveIndex: 0)
    

QuadricIntersection.coneSphereDomain(semiAngle:refRadius:sphereCenter:sphereRadius:tolerance:curveIndex:)

Retrieve the valid parameter domain of a cone-sphere intersection curve.

public static func coneSphereDomain(semiAngle: Double, refRadius: Double,
                                     sphereCenter: SIMD3<Double>, sphereRadius: Double,
                                     tolerance: Double = 1e-6, curveIndex: Int) -> ClosedRange<Double>
  • Parameters: Same geometry as coneSphere; curveIndex, 0-based curve index.
  • Returns: first...last parameter range.
  • OCCT: IntAna_Curve::Domain
  • Example:
    let domain = QuadricIntersection.coneSphereDomain(semiAngle: .pi/4, refRadius: 0,
                                                       sphereCenter: SIMD3(0,0,5), sphereRadius: 3,
                                                       curveIndex: 0)
    print(domain) // e.g. 0.0...6.28
    

XCAFPrs_DocumentExplorer extensions

Per-node queries on the flat explorer index maintained by XCAFPrs_DocumentExplorer. These extend Document.

Document.explorerDepth(at:)

Nesting depth of an explorer node.

public func explorerDepth(at index: Int) -> Int
  • Parameters: index, 0-based node index in the flat explorer list.
  • Returns: Depth (0 = root).
  • OCCT: XCAFPrs_DocumentExplorer::Current().Depth
  • Example:
    let depth = doc.explorerDepth(at: 0)
    

Document.explorerIsAssembly(at:)

Whether an explorer node at index is itself an assembly node. It always returns false: this accessor shares the same flat index as explorerShape(at:)/explorerDepth(at:)/ explorerLocation(at:), built by walking XCAFPrs_DocumentExplorer with XCAFPrs_DocumentExplorerFlags_OnlyLeafNodes, which the flag’s own OCCT header comment documents as “skip assembly nodes”. No index into this explorer’s flat list can ever land on an assembly node, so explorerIsAssembly(at:) has nothing to report true for. This is by design, not a defect: every sibling accessor in this family (explorerNodeCount, explorerShape, explorerPathId, explorerDepth, explorerLocation) shares this same leaf-only index space, and changing just this one accessor’s walk would desynchronize it from the others sharing the same index.

public func explorerIsAssembly(at index: Int) -> Bool
  • Parameters: index, 0-based node index.
  • Returns: false, always: leaf nodes are never assembly nodes.
  • OCCT: XCAFPrs_DocumentExplorer::Current + XCAFDoc_ShapeTool::IsAssembly
  • To actually detect an assembly, use AssemblyNode.isAssembly (via Document.node(at:)), which walks the real free-shape/component label tree rather than this flat leaf-only list:
    if let node = doc.node(at: labelId), node.isAssembly { /* nested assembly */ }
    

Document.explorerLocation(at:)

Location matrix for an explorer node as a flat row-major 3×4 array.

public func explorerLocation(at index: Int) -> [Double]
  • Parameters: index, 0-based node index.
  • Returns: 12-element array representing the 3×4 affine transformation matrix (columns: 3 rotation columns + 1 translation column, row-major).
  • OCCT: XCAFPrs_DocumentExplorer::Current().Location
  • Example:
    let mat = doc.explorerLocation(at: 1)
    let tx = mat[9], ty = mat[10], tz = mat[11] // translation
    

Resource_Unicode

Global Unicode encoding format control and conversion utilities via Resource_Unicode.

UnicodeFormat

Encoding identifier used by UnicodeUtils.

public enum UnicodeFormat: Int32, Sendable {
    case sjis = 0
    case euc  = 1
    case gb   = 2
    case ansi = 3
}
  • OCCT: Resource_Unicode::SetFormat format constants
Case Meaning
sjis Shift-JIS multi-byte encoding (Japanese).
euc Extended Unix Code multi-byte encoding (CJK).
gb GB (GB2312-family) multi-byte encoding (Simplified Chinese).
ansi Single-byte ANSI/Western encoding; also the fallback UnicodeUtils.format returns when the underlying raw value doesn’t decode.

(Per-case anchors below, for cross-reference; the table above has the actual meaning of each.)

UnicodeFormat.sjis


UnicodeUtils.setFormat(_:)

Set the global multi-byte encoding format used for Resource_Unicode conversions.

public static func setFormat(_ format: UnicodeFormat)
  • Parameters: format, encoding to use (SJIS, EUC, GB, or ANSI).
  • OCCT: Resource_Unicode::SetFormat
  • Example:
    UnicodeUtils.setFormat(.sjis)
    

UnicodeUtils.format

Read the current global encoding format.

public static var format: UnicodeFormat { get }
  • Returns: The currently active UnicodeFormat.
  • OCCT: Resource_Unicode::GetFormat
  • Example:
    let fmt = UnicodeUtils.format
    

UnicodeUtils.convertToUnicode(_:)

Convert a multi-byte string (in the current format) to UTF-8.

public static func convertToUnicode(_ input: String) -> String?
  • Parameters: input, string in the current multi-byte encoding.
  • Returns: UTF-8 string, or nil on conversion failure.
  • OCCT: Resource_Unicode::ConvertUnicodeToSJIS / ConvertUnicodeToEUC / etc.
  • Example:
    if let utf8 = UnicodeUtils.convertToUnicode(sjisString) { /* ... */ }
    

UnicodeUtils.convertFromUnicode(_:maxSize:)

Convert a UTF-8 string to the current multi-byte encoding.

public static func convertFromUnicode(_ utf8Input: String, maxSize: Int = 4096) -> String?
  • Parameters: utf8Input, UTF-8 encoded source; maxSize, output buffer capacity in bytes, clamped into 0...Sampling.maximumSampleCount (10,000,000); 0 or less returns nil (#622).
  • Returns: String in the current encoding, or nil on failure.
  • OCCT: Resource_Unicode::ConvertSJISToUnicode / ConvertEUCToUnicode / etc. (inverse path)
  • Example:
    if let encoded = UnicodeUtils.convertFromUnicode("テスト") { /* ... */ }
    

GProp weighted point sets

Centroid and barycentre computation on discrete point sets, extending GeometryProperties.

GeometryProperties.weightedCentroid(points:weights:)

Compute the weighted centroid of a point set.

public static func weightedCentroid(points: [SIMD3<Double>], weights: [Double]) -> (mass: Double, centroid: SIMD3<Double>?)
  • Parameters: points, array of 3D points; weights, per-point scalar weights (must be same length as points). Every weight must be strictly positive.
  • Returns: Tuple of total mass (sum of weights) and the weighted centroid position, which is nil when there is none to report.
  • A non-positive weight rejects the whole set. GProp_PGProps::AddPoint throws Standard_DomainError on the first weight that is not strictly positive, and one bad weight discards every point rather than skipping that one. Before #609 that surfaced as mass 0 with a centroid of (0,0,0), which reads as success.
  • OCCT: GProp_PGProps::AddPoint point-set weighted mass properties
  • Example:
    let pts = [SIMD3<Double>(0,0,0), SIMD3(2,0,0)]
    let (mass, center) = GeometryProperties.weightedCentroid(points: pts, weights: [1.0, 3.0])
    // center?.x ≈ 1.5
    GeometryProperties.weightedCentroid(points: pts, weights: [1.0, 0.0]).centroid   // nil
    

GeometryProperties.barycentre(_:)

Compute the unweighted barycentre (arithmetic mean) of a point set.

public static func barycentre(_ points: [SIMD3<Double>]) -> SIMD3<Double>?
  • Parameters: points, array of 3D points.
  • Returns: The average position, or nil for an empty set, which has no barycentre. The (0,0,0) reported before #609 was indistinguishable from the barycentre of a set centred on the origin.
  • OCCT: GProp_PGProps::Barycentre
  • Example:
    let c = GeometryProperties.barycentre([SIMD3(0,0,0), SIMD3(4,0,0)])
    // c == SIMD3(2, 0, 0)
    GeometryProperties.barycentre([])   // nil
    

GeomLib_LogSample

LogSample.sample(from:to:count:)

Compute logarithmically spaced parameter values in [a, b].

public static func sample(from a: Double, to b: Double, count n: Int) -> [Double]
  • Parameters: a, start of interval; b, end of interval; n, a request for exactly this many sample points, honoured within 1...Sampling.maximumSampleCount (10,000,000). The bridge fills the buffer exactly, so this is not a capacity and is never clamped (#622).
  • Returns: Array of n logarithmically spaced values, or empty if n is outside 1...10,000,000: including above the ceiling, where it returns empty rather than a coarser sampling than was asked for (#622). Before #622 a count past Int32.max aborted the process.
  • OCCT: GeomLib_LogSample
  • Example:
    let params = LogSample.sample(from: 0.01, to: 10.0, count: 20)
    

GC_MakeConicalSurface

Conical Surface constructors wrapping GC_MakeConicalSurface.

Surface.gcConicalSurface(center:normal:semiAngle:radius:)

Create a conical surface from axis placement and cone parameters.

public static func gcConicalSurface(center: SIMD3<Double>, normal: SIMD3<Double>,
                                     semiAngle: Double, radius: Double) -> Surface?
  • Parameters: center, origin on the cone axis; normal, axis direction; semiAngle, half-angle in radians; radius, reference radius at center.
  • Returns: A Surface wrapping Geom_ConicalSurface, or nil on failure.
  • OCCT: GC_MakeConicalSurface
  • Example:
    if let cone = Surface.gcConicalSurface(center: .zero, normal: SIMD3(0,0,1),
                                            semiAngle: .pi/6, radius: 0) {
        // infinite conical surface
    }
    

Surface.gcConicalSurface2Pts(p1:p2:r1:r2:)

Create a conical surface through two circles defined by two points and radii.

public static func gcConicalSurface2Pts(p1: SIMD3<Double>, p2: SIMD3<Double>,
                                         r1: Double, r2: Double) -> Surface?
  • Parameters: p1, p2, axial positions of the two reference circles; r1, r2, respective radii.
  • Returns: A Surface wrapping Geom_ConicalSurface, or nil on failure.
  • OCCT: GC_MakeConicalSurface (two-point-two-radius constructor)
  • Example:
    if let cone = Surface.gcConicalSurface2Pts(p1: .zero, p2: SIMD3(0,0,5),
                                                r1: 1, r2: 3) { /* ... */ }
    

Surface.gcConicalSurface4Pts(p1:p2:p3:p4:)

Create a conical surface through four points (two on each base circle).

public static func gcConicalSurface4Pts(p1: SIMD3<Double>, p2: SIMD3<Double>,
                                         p3: SIMD3<Double>, p4: SIMD3<Double>) -> Surface?
  • Parameters: p1, p2, two points on the first circle; p3, p4, two points on the second circle.
  • Returns: A Surface wrapping Geom_ConicalSurface, or nil on failure.
  • OCCT: GC_MakeConicalSurface (four-point constructor)
  • Example:
    if let cone = Surface.gcConicalSurface4Pts(p1: SIMD3(1,0,0), p2: SIMD3(-1,0,0),
                                                p3: SIMD3(2,0,5), p4: SIMD3(-2,0,5)) { /* ... */ }
    

GC_MakeCylindricalSurface

Cylindrical Surface constructors wrapping GC_MakeCylindricalSurface.

Surface.gcCylindricalSurface(center:normal:radius:)

Create a cylindrical surface from an axis placement and radius.

public static func gcCylindricalSurface(center: SIMD3<Double>, normal: SIMD3<Double>,
                                          radius: Double) -> Surface?
  • Parameters: center, origin on the cylinder axis; normal, axis direction; radius, cylinder radius.
  • Returns: A Surface wrapping Geom_CylindricalSurface, or nil on failure.
  • OCCT: GC_MakeCylindricalSurface
  • Example:
    if let cyl = Surface.gcCylindricalSurface(center: .zero, normal: SIMD3(0,0,1), radius: 5) {
        // infinite cylinder
    }
    

Surface.gcCylindricalSurface3Pts(p1:p2:p3:)

Create a cylindrical surface through three points.

public static func gcCylindricalSurface3Pts(p1: SIMD3<Double>, p2: SIMD3<Double>,
                                              p3: SIMD3<Double>) -> Surface?
  • Parameters: p1, p2, p3, three points on the cylinder.
  • Returns: A Surface wrapping Geom_CylindricalSurface, or nil on failure.
  • OCCT: GC_MakeCylindricalSurface (three-point constructor)
  • Example:
    if let cyl = Surface.gcCylindricalSurface3Pts(p1: SIMD3(5,0,0),
                                                    p2: SIMD3(-5,0,0),
                                                    p3: SIMD3(0,5,3)) { /* ... */ }
    

Surface.gcCylindricalSurfaceFromCircle(center:normal:radius:)

Create a cylindrical surface from a circle definition (center, normal, radius).

public static func gcCylindricalSurfaceFromCircle(center: SIMD3<Double>, normal: SIMD3<Double>,
                                                   radius: Double) -> Surface?
  • Parameters: center, normal, radius, circle parameters that define the cylinder’s directrix.
  • Returns: A Surface wrapping Geom_CylindricalSurface, or nil on failure.
  • OCCT: GC_MakeCylindricalSurface (circle constructor)
  • Example:
    if let cyl = Surface.gcCylindricalSurfaceFromCircle(center: .zero,
                                                         normal: SIMD3(0,0,1), radius: 3) { /* ... */ }
    

Surface.gcCylindricalSurfaceParallel(center:normal:radius:distance:)

Create a cylindrical surface concentric with an existing one, offset by a distance.

public static func gcCylindricalSurfaceParallel(center: SIMD3<Double>, normal: SIMD3<Double>,
                                                  radius: Double, distance: Double) -> Surface?
  • Parameters: center, normal, radius, reference cylinder; distance, radial offset.
  • Returns: A Surface wrapping Geom_CylindricalSurface, or nil on failure.
  • OCCT: GC_MakeCylindricalSurface (parallel/offset constructor)
  • Example:
    if let outer = Surface.gcCylindricalSurfaceParallel(center: .zero, normal: SIMD3(0,0,1),
                                                         radius: 5, distance: 2) {
        // outer cylinder at r=7
    }
    

Surface.gcCylindricalSurfaceAxis(point:direction:radius:)

Create a cylindrical surface from an axis defined by a point and direction plus a radius.

public static func gcCylindricalSurfaceAxis(point: SIMD3<Double>, direction: SIMD3<Double>,
                                              radius: Double) -> Surface?
  • Parameters: point, any point on the axis; direction, axis direction; radius, cylinder radius.
  • Returns: A Surface wrapping Geom_CylindricalSurface, or nil on failure.
  • OCCT: GC_MakeCylindricalSurface (axis constructor)
  • Example:
    if let cyl = Surface.gcCylindricalSurfaceAxis(point: SIMD3(1,0,0),
                                                    direction: SIMD3(0,0,1), radius: 4) { /* ... */ }
    

GC_MakeTrimmedCone

Trimmed conical Surface constructors wrapping GC_MakeTrimmedCone.

Surface.gcTrimmedCone2Pts(p1:p2:r1:r2:)

Create a trimmed cone from two axial points and radii.

public static func gcTrimmedCone2Pts(p1: SIMD3<Double>, p2: SIMD3<Double>,
                                      r1: Double, r2: Double) -> Surface?
  • Parameters: p1, p2, positions of the base circles; r1, r2, respective radii.
  • Returns: A bounded Surface wrapping Geom_ConicalSurface, or nil on failure.
  • OCCT: GC_MakeTrimmedCone
  • Example:
    if let tc = Surface.gcTrimmedCone2Pts(p1: .zero, p2: SIMD3(0,0,10), r1: 2, r2: 5) { /* ... */ }
    

Surface.gcTrimmedCone4Pts(p1:p2:p3:p4:)

Create a trimmed cone through four points.

public static func gcTrimmedCone4Pts(p1: SIMD3<Double>, p2: SIMD3<Double>,
                                      p3: SIMD3<Double>, p4: SIMD3<Double>) -> Surface?
  • Parameters: p1, p2, two points on the first circle; p3, p4, two points on the second circle.
  • Returns: A bounded Surface wrapping Geom_ConicalSurface, or nil on failure.
  • OCCT: GC_MakeTrimmedCone (four-point constructor)
  • Example:
    if let tc = Surface.gcTrimmedCone4Pts(p1: SIMD3(2,0,0), p2: SIMD3(-2,0,0),
                                            p3: SIMD3(5,0,8), p4: SIMD3(-5,0,8)) { /* ... */ }
    

GC_MakeTrimmedCylinder

Trimmed cylindrical Surface constructors wrapping GC_MakeTrimmedCylinder.

Surface.gcTrimmedCylinderCircle(center:normal:radius:height:)

Create a trimmed cylinder from a circle definition and height.

public static func gcTrimmedCylinderCircle(center: SIMD3<Double>, normal: SIMD3<Double>,
                                            radius: Double, height: Double) -> Surface?
  • Parameters: center, normal, radius, directrix circle; height, axial extent.
  • Returns: A bounded Surface wrapping Geom_CylindricalSurface, or nil on failure.
  • OCCT: GC_MakeTrimmedCylinder
  • Example:
    if let tc = Surface.gcTrimmedCylinderCircle(center: .zero, normal: SIMD3(0,0,1),
                                                 radius: 5, height: 10) { /* ... */ }
    

Surface.gcTrimmedCylinderAxis(point:direction:radius:height:)

Create a trimmed cylinder from an axis, radius, and height.

public static func gcTrimmedCylinderAxis(point: SIMD3<Double>, direction: SIMD3<Double>,
                                          radius: Double, height: Double) -> Surface?
  • Parameters: point, origin on the axis; direction, axis direction; radius, cylinder radius; height, axial extent.
  • Returns: A bounded Surface wrapping Geom_CylindricalSurface, or nil on failure.
  • OCCT: GC_MakeTrimmedCylinder (axis constructor)
  • Example:
    if let tc = Surface.gcTrimmedCylinderAxis(point: .zero, direction: SIMD3(0,0,1),
                                                radius: 3, height: 8) { /* ... */ }
    

Surface.gcTrimmedCylinder3Pts(p1:p2:p3:)

Create a trimmed cylinder through three points.

public static func gcTrimmedCylinder3Pts(p1: SIMD3<Double>, p2: SIMD3<Double>,
                                          p3: SIMD3<Double>) -> Surface?
  • Parameters: p1, p2, p3, three points on the cylinder surface.
  • Returns: A bounded Surface wrapping Geom_CylindricalSurface, or nil on failure.
  • OCCT: GC_MakeTrimmedCylinder (three-point constructor)
  • Example:
    if let tc = Surface.gcTrimmedCylinder3Pts(p1: SIMD3(5,0,0),
                                                p2: SIMD3(-5,0,0),
                                                p3: SIMD3(0,5,4)) { /* ... */ }
    

BRepLib_MakeEdge2d extensions

2D edge construction from analytic curves, extending Shape.

Shape.edge2dFullCircle(center:direction:radius:)

Create a 2D edge from a full circle.

public static func edge2dFullCircle(center: SIMD2<Double>, direction: SIMD2<Double>,
                                     radius: Double) -> Shape?
  • Parameters: center: circle center in 2D; direction: X-axis direction; radius: radius, must be greater than zero.
  • Returns: A Shape wrapping a closed TopoDS_Edge in 2D, or nil on failure or a degenerate radius.
  • OCCT: BRepLib_MakeEdge2d (circle overload)
  • Example:
    if let e = Shape.edge2dFullCircle(center: .zero, direction: SIMD2(1,0), radius: 3) { /* ... */ }
    

Shape.edge2dEllipse(center:direction:majorRadius:minorRadius:)

Create a 2D edge from a full ellipse.

public static func edge2dEllipse(center: SIMD2<Double>, direction: SIMD2<Double>,
                                  majorRadius: Double, minorRadius: Double) -> Shape?
  • Parameters: center: center in 2D; direction: major-axis direction; majorRadius, minorRadius: semi-axes, both greater than zero with minorRadius <= majorRadius. Equal radii are a circle and are valid.
  • Returns: A closed 2D edge, or nil on failure or a degenerate ellipse. BRepLib_MakeEdge2d itself reports IsDone() for one: a zero-radius ellipse builds a zero-length edge with both vertices at the centre, and a zero minor radius builds a segment doubled back along the major axis (#514).
  • OCCT: BRepLib_MakeEdge2d (ellipse overload)
  • Example:
    if let e = Shape.edge2dEllipse(center: .zero, direction: SIMD2(1,0),
                                    majorRadius: 4, minorRadius: 2) { /* ... */ }
    

Shape.edge2dEllipseArc(center:direction:majorRadius:minorRadius:u1:u2:)

Create a 2D edge from an ellipse arc.

public static func edge2dEllipseArc(center: SIMD2<Double>, direction: SIMD2<Double>,
                                     majorRadius: Double, minorRadius: Double,
                                     u1: Double, u2: Double) -> Shape?
  • Parameters: center, direction, majorRadius, minorRadius: ellipse definition, both radii greater than zero with minorRadius <= majorRadius; u1, u2: parameter range (radians).
  • Returns: A 2D edge arc, or nil on failure or a degenerate ellipse.
  • OCCT: BRepLib_MakeEdge2d (ellipse-arc overload)
  • Example:
    if let e = Shape.edge2dEllipseArc(center: .zero, direction: SIMD2(1,0),
                                       majorRadius: 4, minorRadius: 2,
                                       u1: 0, u2: .pi/2) { /* ... */ }
    

Shape.edge2dFromCurve(_:)

Create a 2D edge spanning the full domain of a Curve2D.

public static func edge2dFromCurve(_ curve: Curve2D) -> Shape?
  • Parameters: curve, a bounded Curve2D.
  • Returns: A Shape wrapping a 2D TopoDS_Edge, or nil on failure.
  • OCCT: BRepLib_MakeEdge2d (curve overload)
  • Example:
    if let e = Shape.edge2dFromCurve(myParabola) { /* ... */ }
    

Shape.edge2dFromCurve(_:u1:u2:)

Create a 2D edge from a Curve2D with an explicit parameter range.

public static func edge2dFromCurve(_ curve: Curve2D, u1: Double, u2: Double) -> Shape?
  • Parameters: curve, a Curve2D; u1, u2, parameter range to trim to.
  • Returns: A 2D edge, or nil on failure.
  • OCCT: BRepLib_MakeEdge2d (curve + range overload)
  • Example:
    if let e = Shape.edge2dFromCurve(mySpline, u1: 0.2, u2: 0.8) { /* ... */ }
    

ShapeAnalysis_Wire

Wire quality checks using ShapeAnalysis_Wire. All members are static on the SAWireAnalysis enum. Each check returns true when a problem is detected. checkOuterBound(wire:face:) returns Bool? rather than Bool, so its refusal is not the same value as its clean verdict; see its own entry for what nil covers and why the other fourteen check members do not have it (#1058, tracked as #1074).

SAWireAnalysis.checkOrder(wire:face:precision:)

Check whether wire edges are correctly ordered on a face.

public static func checkOrder(wire: Shape, face: Shape, precision: Double = 1e-6) -> Bool
  • Parameters: wire, the wire to analyse; face, the supporting face; precision, tolerance.
  • Returns: true if the edge order is incorrect.
  • OCCT: ShapeAnalysis_Wire::CheckOrder
  • Example:
    if SAWireAnalysis.checkOrder(wire: w, face: f) { print("order problem") }
    

SAWireAnalysis.checkConnected(wire:face:precision:)

Check whether wire edges are topologically connected.

public static func checkConnected(wire: Shape, face: Shape, precision: Double = 1e-6) -> Bool
  • OCCT: ShapeAnalysis_Wire::CheckConnected

SAWireAnalysis.checkSmall(wire:face:precision:)

Check for edges shorter than precision (small/degenerate geometry).

public static func checkSmall(wire: Shape, face: Shape, precision: Double = 1e-6) -> Bool
  • OCCT: ShapeAnalysis_Wire::CheckSmall

SAWireAnalysis.checkDegenerated(wire:face:precision:)

Check for degenerate edges in the wire.

public static func checkDegenerated(wire: Shape, face: Shape, precision: Double = 1e-6) -> Bool
  • OCCT: ShapeAnalysis_Wire::CheckDegenerated

SAWireAnalysis.checkClosed(wire:face:precision:)

Check whether the wire is properly closed.

public static func checkClosed(wire: Shape, face: Shape, precision: Double = 1e-6) -> Bool
  • OCCT: ShapeAnalysis_Wire::CheckClosed

SAWireAnalysis.checkSelfIntersection(wire:face:precision:)

Check for self-intersecting edges or edge pairs.

public static func checkSelfIntersection(wire: Shape, face: Shape, precision: Double = 1e-6) -> Bool
  • OCCT: ShapeAnalysis_Wire::CheckSelfIntersection

SAWireAnalysis.checkGaps3d(wire:face:precision:)

Check for gaps between consecutive edge endpoints in 3D.

public static func checkGaps3d(wire: Shape, face: Shape, precision: Double = 1e-6) -> Bool
  • OCCT: ShapeAnalysis_Wire::CheckGaps3d

SAWireAnalysis.checkGaps2d(wire:face:precision:)

Check for gaps between consecutive edge endpoints in 2D (parametric space).

public static func checkGaps2d(wire: Shape, face: Shape, precision: Double = 1e-6) -> Bool
  • OCCT: ShapeAnalysis_Wire::CheckGaps2d

SAWireAnalysis.checkEdgeCurves(wire:face:precision:)

Check consistency between 3D curves and parametric curves for all edges.

public static func checkEdgeCurves(wire: Shape, face: Shape, precision: Double = 1e-6) -> Bool
  • OCCT: ShapeAnalysis_Wire::CheckEdgeCurves

SAWireAnalysis.checkLacking(wire:face:precision:)

Check for missing (lacking) edges that would be needed to close the wire.

public static func checkLacking(wire: Shape, face: Shape, precision: Double = 1e-6) -> Bool
  • OCCT: ShapeAnalysis_Wire::CheckLacking

SAWireAnalysis.edgeCount(wire:face:precision:)

Number of edges in the wire as seen by ShapeAnalysis_Wire.

public static func edgeCount(wire: Shape, face: Shape, precision: Double = 1e-6) -> Int
  • Returns: Edge count.
  • OCCT: ShapeAnalysis_Wire::NbEdges
  • Example:
    let n = SAWireAnalysis.edgeCount(wire: w, face: f)
    

SAWireAnalysis.minDistance3d(wire:face:precision:)

Minimum 3D gap distance between consecutive edges.

public static func minDistance3d(wire: Shape, face: Shape, precision: Double = 1e-6) -> Double
  • OCCT: ShapeAnalysis_Wire::MinDistance3d

SAWireAnalysis.maxDistance3d(wire:face:precision:)

Maximum 3D gap distance between consecutive edges.

public static func maxDistance3d(wire: Shape, face: Shape, precision: Double = 1e-6) -> Double
  • OCCT: ShapeAnalysis_Wire::MaxDistance3d

SAWireAnalysis.minDistance2d(wire:face:precision:)

Minimum 2D gap distance between consecutive edges in parametric space.

public static func minDistance2d(wire: Shape, face: Shape, precision: Double = 1e-6) -> Double
  • OCCT: ShapeAnalysis_Wire::MinDistance2d

SAWireAnalysis.maxDistance2d(wire:face:precision:)

Maximum 2D gap distance between consecutive edges in parametric space.

public static func maxDistance2d(wire: Shape, face: Shape, precision: Double = 1e-6) -> Double
  • OCCT: ShapeAnalysis_Wire::MaxDistance2d

SAWireAnalysis.checkConnectedEdge(wire:face:precision:edgeIndex:)

Check connectivity of a specific edge (1-based index).

public static func checkConnectedEdge(wire: Shape, face: Shape, precision: Double = 1e-6,
                                       edgeIndex: Int) -> Bool
  • Parameters: edgeIndex, 1-based edge index.
  • Returns: true if that edge has a connectivity problem.
  • OCCT: ShapeAnalysis_Wire::CheckConnected (per-edge)

SAWireAnalysis.checkSmallEdge(wire:face:precision:edgeIndex:)

Check whether a specific edge (1-based) is too small.

public static func checkSmallEdge(wire: Shape, face: Shape, precision: Double = 1e-6,
                                   edgeIndex: Int) -> Bool
  • OCCT: ShapeAnalysis_Wire::CheckSmall (per-edge)

SAWireAnalysis.checkDegeneratedEdge(wire:face:precision:edgeIndex:)

Check whether a specific edge (1-based) is degenerate.

public static func checkDegeneratedEdge(wire: Shape, face: Shape, precision: Double = 1e-6,
                                          edgeIndex: Int) -> Bool
  • OCCT: ShapeAnalysis_Wire::CheckDegenerated (per-edge)

SAWireAnalysis.checkGap3dEdge(wire:face:precision:edgeIndex:)

Check for a 3D gap at a specific edge (1-based).

public static func checkGap3dEdge(wire: Shape, face: Shape, precision: Double = 1e-6,
                                   edgeIndex: Int) -> Bool
  • OCCT: ShapeAnalysis_Wire::CheckGaps3d (per-edge)

SAWireAnalysis.checkOuterBound(wire:face:)

Check whether a wire fails to define an outer bound on a face, or report that the check could not be run.

public static func checkOuterBound(wire: Shape, face: Shape) -> Bool?

Takes the wire, like every sibling above, and takes no precision, unlike any of them: ShapeAnalysis_Wire::CheckOuterBound(APIMake) rebuilds the wire onto an empty copy of the face and asks ShapeAnalysis::IsOuterBound, consulting neither myPrecision nor anything derived from it. Measured across precisions from 1e-12 to 100 on three fixtures, the verdict never moved.

APIMake is likewise not exposed and stays at OCCT’s own default of true. It selects ShapeExtend_WireData::WireAPIMake over ::Wire, and gave the same verdict on all three fixtures, including one assembled with BRep_Builder from edges with unshared vertices, which is the case its own documentation distinguishes.

This is the only member of the family that returns an optional (#1058). The other fourteen check members, the ten whole-wire ones above and the four per-edge ones, answer a plain Bool, so a refused call and a clean verdict are the same value for them; here they are not. nil covers five inputs:

Input Why it cannot be answered
A Shape that is not a wire, or not a face, including a null shape The Swift signature takes two plain Shape values with no type constraint, so both are reachable. The bridge tests the type explicitly rather than letting the cast raise: TopoDS::Wire is written IsNull() ? false : ..., so it deliberately does not raise for a null shape and would pass one through to EmptyCopied(), which is CLAUDE.md’s #1035 note
A wire with no edges ShapeAnalysis_Wire::IsReady() is false, so OCCT never runs the check
A wire whose edges do not assemble ShapeExtend_WireData::WireAPIMake() returns a null wire whenever BRepBuilderAPI_MakeWire cannot join the loaded edges, two edges sharing no vertex being enough, and BRep_Builder::Add dereferences its component with no null test. That was an uncatchable SIGSEGV rather than a wrong answer, and ShapeAnalysis_Wire::CheckOuterBound builds the same wire, so it crashed before this fix too
A wire where any edge has no pcurve on the face ShapeAnalysis::TotCross2D skips every edge whose pcurve on the face is null, so it would sign an area only the pcurved subset contributed to, and with none left its accumulator is never written and the +0.0 it starts from signs as a positive area, reporting a foreign wire as the outer bound. The bridge walks every edge of the rebuilt probe face and refuses if BRep_Tool::CurveOnSurface returns null for one (#1073)
A wire whose signed area cancels to rounding The magnitude is tested against the face’s own UV area from ShapeAnalysis::GetFaceUVBounds, and anything under 1e-12 of it is refused rather than having its verdict decided by the sign of the noise (#1073)

The last two are OCCT’s behaviour, not the bridge’s, and neither announces itself: CheckOuterBound sets ShapeExtend_OK on entry and only raises it to ShapeExtend_DONE1 for the true verdict. The pcurve one needs a non-planar support face to show, because BRep_Tool::CurveOnSurface projects a 3D curve onto a plane when no pcurve is stored, so a foreign wire on a planar face is answered from the projection rather than refused. Both are refused by the bridge rather than passed on.

Both gaps #1073 named are closed, and the guard now says “the area means something”. Two cases used to sit past the original “nothing was consulted” guard. A wire where only some edges carried a pcurve on the face passed it, and TotCross2D then summed that subset. And a wire where every edge carried one but the contributions cancelled got its verdict from the sign of the rounding: a cylinder’s seam wire projected onto a plane measures -1.7802599672211983e-15, against +100 and +125.66 for the answerable fixtures, and checkOuterBound reported true off it. PR #1140 fixed both, and they are the last two rows of the table above: every edge must carry a pcurve on the probe face, and |TotCross2D| must exceed 1e-12 of the face’s own UV area, which ShapeAnalysis::GetFaceUVBounds supplies as the characteristic scale. The cancellation fixture is the cylinder's wire on the panel row in Scripts/repro/1058-outer-bound-refusal/. The partial-pcurve case is still read off TotCross2D’s own skip condition rather than observed: no fixture there produces a wire with some edges carrying a pcurve and some not, so the guard exists and the fixture proving it fires does not.

  • Parameters: wire, the wire to test; face, the face it should bound.
  • Returns: true if a problem is found, false if none is, nil if the check could not be run. A face’s own outer wire returns false; a hole wire on the same face returns true.
  • OCCT: ShapeAnalysis_Wire::CheckOuterBound
  • Example:
    for wire in panel.subShapes(ofType: .wire) {
        switch SAWireAnalysis.checkOuterBound(wire: wire, face: panel) {
        case true?: print("not the outer bound")
        case false?: print("the outer bound")
        case nil: print("not checkable against this face")
        }
    }
    

ShapeAnalysis_Edge

Per-edge analysis utilities using ShapeAnalysis_Edge. All members are static on the EdgeAnalysis enum.

EdgeAnalysis.hasCurve3d(_:)

Check whether an edge has a 3D curve representation.

public static func hasCurve3d(_ edge: Shape) -> Bool
  • OCCT: ShapeAnalysis_Edge::HasCurve3d
  • Example:
    if EdgeAnalysis.hasCurve3d(e) { /* ... */ }
    

EdgeAnalysis.isClosed3d(_:)

Check whether the edge’s 3D curve is closed.

public static func isClosed3d(_ edge: Shape) -> Bool
  • OCCT: ShapeAnalysis_Edge::IsClosed3d

EdgeAnalysis.hasPCurve(_:face:)

Check whether an edge has a parametric curve (PCurve) on a given face.

public static func hasPCurve(_ edge: Shape, face: Shape) -> Bool
  • Parameters: edge, the edge; face, the supporting face.
  • OCCT: ShapeAnalysis_Edge::HasPCurve

EdgeAnalysis.isSeam(_:face:)

Check whether an edge is a seam edge on the given face.

public static func isSeam(_ edge: Shape, face: Shape) -> Bool
  • OCCT: ShapeAnalysis_Edge::IsSeam

EdgeAnalysis.checkSameParameter(_:)

Verify the same-parameter property and report maximum deviation.

public static func checkSameParameter(_ edge: Shape) -> (ok: Bool, maxDeviation: Double)
  • Returns: ok is true when the edge is within tolerance; maxDeviation is the worst observed deviation.
  • OCCT: ShapeAnalysis_Edge::CheckSameParameter
  • Example:
    let (ok, dev) = EdgeAnalysis.checkSameParameter(e)
    

EdgeAnalysis.checkVerticesWithCurve3d(_:precision:)

Verify that vertex positions match the curve 3D endpoints.

public static func checkVerticesWithCurve3d(_ edge: Shape, precision: Double = -1.0) -> Bool
  • Returns: true if check passes.
  • OCCT: ShapeAnalysis_Edge::CheckVerticesWithCurve3d

EdgeAnalysis.checkVerticesWithPCurve(_:face:precision:)

Verify that vertex positions match the PCurve endpoints on a face.

public static func checkVerticesWithPCurve(_ edge: Shape, face: Shape,
                                            precision: Double = -1.0) -> Bool
  • OCCT: ShapeAnalysis_Edge::CheckVerticesWithPCurve

EdgeAnalysis.checkCurve3dWithPCurve(_:face:)

Verify consistency between the 3D curve and the PCurve on a face.

public static func checkCurve3dWithPCurve(_ edge: Shape, face: Shape) -> Bool
  • OCCT: ShapeAnalysis_Edge::CheckCurve3dWithPCurve

EdgeAnalysis.firstVertex(_:)

3D position of the edge’s first vertex.

public static func firstVertex(_ edge: Shape) -> SIMD3<Double>
  • OCCT: ShapeAnalysis_Edge::FirstVertex + BRep_Tool::Pnt
  • Example:
    let start = EdgeAnalysis.firstVertex(myEdge)
    

EdgeAnalysis.lastVertex(_:)

3D position of the edge’s last vertex.

public static func lastVertex(_ edge: Shape) -> SIMD3<Double>
  • OCCT: ShapeAnalysis_Edge::LastVertex + BRep_Tool::Pnt
  • Example:
    let end = EdgeAnalysis.lastVertex(myEdge)
    

EdgeAnalysis.checkVertexTolerance(_:face:)

Verify vertex tolerances on a face edge and return tolerance values.

public static func checkVertexTolerance(_ edge: Shape, face: Shape) -> (ok: Bool, toler1: Double, toler2: Double)
  • Returns: ok when within tolerance; toler1, toler2, first and last vertex tolerance values.
  • OCCT: ShapeAnalysis_Edge::CheckVertexTolerance
  • Example:
    let (ok, t1, t2) = EdgeAnalysis.checkVertexTolerance(e, face: f)
    

EdgeAnalysis.checkOverlapping(_:_:tolerance:)

Detect whether two edges overlap and report the overlap tolerance.

public static func checkOverlapping(_ edge1: Shape, _ edge2: Shape, tolerance: Double = 1e-7) -> (overlapping: Bool, tolerance: Double)
  • Parameters: tolerance, the overlap distance threshold (defaults to Precision::Confusion(), 1e-7).
  • Returns: overlapping is true when the edges are within tolerance of each other; tolerance echoes back the threshold used.
  • OCCT: ShapeAnalysis_Edge::CheckOverlapping
  • Example:
    let (over, tol) = EdgeAnalysis.checkOverlapping(e1, e2)
    

EdgeAnalysis.boundUV(_:face:)

UV bounds of an edge on a face in parametric space.

public static func boundUV(_ edge: Shape, face: Shape) -> (uFirst: Double, vFirst: Double, uLast: Double, vLast: Double)?
  • Returns: Tuple of (uFirst, vFirst, uLast, vLast), or nil if the edge has no PCurve on the face.
  • OCCT: ShapeAnalysis_Edge::BoundUV
  • Example:
    if let uv = EdgeAnalysis.boundUV(e, face: f) {
        print("u range:", uv.uFirst, "...", uv.uLast)
    }
    

EdgeAnalysis.endTangent2d(_:face:atEnd:)

2D endpoint and tangent direction of an edge in the face’s parametric space.

public static func endTangent2d(_ edge: Shape, face: Shape,
                                 atEnd: Bool) -> (point: SIMD2<Double>, tangent: SIMD2<Double>)?
  • Parameters: atEnd, false for the start, true for the end.
  • Returns: Tuple of 2D position and tangent, or nil if unavailable.
  • OCCT: ShapeAnalysis_Edge::GetEndTangent2d
  • Example:
    if let (pt, tan) = EdgeAnalysis.endTangent2d(e, face: f, atEnd: false) {
        // pt is the 2D start position
    }
    

EdgeAnalysis.checkPCurveRange(_:face:first:last:)

Verify that a PCurve parameter range is valid against the pcurve’s own underlying geometric domain.

public static func checkPCurveRange(_ edge: Shape, face: Shape,
                                     first: Double, last: Double) -> Bool
  • Parameters: first, last, the parameter range to check. Checked against the pcurve’s own domain (its full period, for a periodic pcurve), not against the edge’s current stored trim, so a range can be valid even when it extends past where the edge itself is trimmed.
  • Returns: true if the range is valid.
  • OCCT: ShapeAnalysis_Edge::CheckPCurveRange
  • Example:
    let ok = EdgeAnalysis.checkPCurveRange(e, face: f, first: 0, last: 1)
    

OSD_DirectoryIterator

Directory listing using OSD_DirectoryIterator. All members are static on the DirectoryIterator enum.

DirectoryIterator.count(path:mask:)

Count the directories matching mask inside path.

public static func count(path: String, mask: String = "*") -> Int
  • Parameters: path, directory to search; mask, glob-style name filter.
  • Returns: Number of matching sub-directories.
  • OCCT: OSD_DirectoryIterator
  • Example:
    let n = DirectoryIterator.count(path: "/tmp", mask: "occt*")
    

DirectoryIterator.name(path:mask:index:)

Name of the directory at a specific index in the filtered listing.

public static func name(path: String, mask: String = "*", index: Int) -> String?
  • Parameters: path, mask, as for count; index, 0-based index.
  • Returns: Directory name, or nil if the index is out of range.
  • OCCT: OSD_DirectoryIterator::Values
  • Example:
    if let first = DirectoryIterator.name(path: "/tmp", index: 0) {
        print(first)
    }
    

DirectoryIterator.list(path:mask:maxCount:)

List all directory names matching a mask (up to maxCount).

public static func list(path: String, mask: String = "*", maxCount: Int = 1000) -> [String]
  • Parameters: path, mask, search location and filter; maxCount, output capacity (default 1000), clamped into 0...Sampling.maximumSampleCount (10,000,000); 0 or less returns empty (#622).
  • Returns: Array of directory name strings.
  • OCCT: OSD_DirectoryIterator
  • Example:
    let dirs = DirectoryIterator.list(path: "/tmp")
    

OSD_FileIterator

File listing using OSD_FileIterator. All members are static on the FileIterator enum.

FileIterator.count(path:mask:)

Count files matching mask inside path.

public static func count(path: String, mask: String = "*") -> Int
  • Parameters: path, directory to search; mask, glob-style name filter.
  • Returns: Number of matching files.
  • OCCT: OSD_FileIterator
  • Example:
    let n = FileIterator.count(path: "/tmp", mask: "*.step")
    

FileIterator.name(path:mask:index:)

Name of the file at a specific index in the filtered listing.

public static func name(path: String, mask: String = "*", index: Int) -> String?
  • Parameters: path, mask, location and filter; index, 0-based index.
  • Returns: File name, or nil if out of range.
  • OCCT: OSD_FileIterator::Values
  • Example:
    if let f = FileIterator.name(path: "/tmp", mask: "*.step", index: 0) {
        print(f)
    }
    

FileIterator.list(path:mask:maxCount:)

List all file names matching a mask (up to maxCount).

public static func list(path: String, mask: String = "*", maxCount: Int = 1000) -> [String]
  • Parameters: path, mask, search location and filter; maxCount, output capacity (default 1000), clamped into 0...Sampling.maximumSampleCount (10,000,000); 0 or less returns empty (#622).
  • Returns: Array of file name strings.
  • OCCT: OSD_FileIterator
  • Example:
    let files = FileIterator.list(path: "/tmp", mask: "*.brep")
    

BRepFill_PipeShell extensions

Additional approximation controls and cap accessors added to PipeShellBuilder (v0.106.0 extensions).

PipeShellBuilder.setMaxDegree(_:)

Set the maximum polynomial degree for the BSpline approximation of the swept surface.

public func setMaxDegree(_ maxDeg: Int)
  • Parameters: maxDeg, maximum BSpline degree (OCCT default is 11).
  • OCCT: BRepFill_PipeShell::SetMaxDegree
  • Example:
    guard let spineLine = Wire.line(from: .zero, to: SIMD3(0, 0, 50)),
          let spineWire = Shape.fromWire(spineLine),
          let pipe = PipeShellBuilder(spine: spineWire) else { return }
    pipe.setMaxDegree(7)
    

PipeShellBuilder.setMaxSegments(_:)

Set the maximum number of BSpline segments in the swept surface approximation.

public func setMaxSegments(_ maxSeg: Int)
  • Parameters: maxSeg, maximum segment count.
  • OCCT: BRepFill_PipeShell::SetMaxSegments
  • Example:
    guard let spineLine = Wire.line(from: .zero, to: SIMD3(0, 0, 50)),
          let spineWire = Shape.fromWire(spineLine),
          let pipe = PipeShellBuilder(spine: spineWire) else { return }
    pipe.setMaxSegments(100)
    

PipeShellBuilder.setForceApproxC1(_:)

Force C1 continuity in the BSpline approximation.

public func setForceApproxC1(_ force: Bool)
  • Parameters: force, true to enforce C1 even at the cost of additional segments.
  • OCCT: BRepFill_PipeShell::SetForceApproxC1
  • Example:
    guard let spineLine = Wire.line(from: .zero, to: SIMD3(0, 0, 50)),
          let spineWire = Shape.fromWire(spineLine),
          let pipe = PipeShellBuilder(spine: spineWire) else { return }
    pipe.setForceApproxC1(true)
    

PipeShellBuilder.setBuildHistory(_:)

Enable or disable shape history tracking during the sweep.

public func setBuildHistory(_ enabled: Bool)

History is disabled by default to avoid a segfault in BRepFill_PipeShell::BuildHistory when using closed spine+profile combinations (OCCT bug). Enable only when generated/modified/isDeleted queries on the result are required.

  • Parameters: enabled, true to enable history.
  • OCCT: BRepFill_PipeShell::SetIsBuildHistory
  • Note: Enabling history on closed spine/profile geometries can trigger an OCCT segfault, use with caution.
  • Example:
    guard let spineLine = Wire.line(from: .zero, to: SIMD3(0, 0, 50)),
          let spineWire = Shape.fromWire(spineLine),
          let pipe = PipeShellBuilder(spine: spineWire) else { return }
    pipe.setBuildHistory(false) // safe default
    

PipeShellBuilder.errorOnSurface

Approximation error of the generated surface (distinct from error which covers the overall result).

public var errorOnSurface: Double { get }
  • OCCT: BRepFill_PipeShell::ErrorOnSurface
  • Example:
    guard let spineLine = Wire.line(from: .zero, to: SIMD3(0, 0, 50)),
          let spineWire = Shape.fromWire(spineLine),
          let profileCircle = Wire.circle(radius: 5),
          let profile = Shape.fromWire(profileCircle),
          let pipe = PipeShellBuilder(spine: spineWire) else { return }
    pipe.add(profile: profile)
    pipe.build()
    print("surface error:", pipe.errorOnSurface)
    

PipeShellBuilder.firstShape

The start-cap shape of the pipe shell (the face at the beginning of the spine).

public var firstShape: Shape? { get }
  • Returns: The first section Shape, or nil if build() has not succeeded.
  • OCCT: BRepFill_PipeShell::FirstShape
  • Example:
    guard let spineLine = Wire.line(from: .zero, to: SIMD3(0, 0, 50)),
          let spineWire = Shape.fromWire(spineLine),
          let profileCircle = Wire.circle(radius: 5),
          let profile = Shape.fromWire(profileCircle),
          let pipe = PipeShellBuilder(spine: spineWire) else { return }
    pipe.add(profile: profile)
    pipe.build()
    if let cap = pipe.firstShape { /* use start cap */ }
    

PipeShellBuilder.lastShape

The end-cap shape of the pipe shell (the face at the end of the spine).

public var lastShape: Shape? { get }
  • Returns: The last section Shape, or nil if build() has not succeeded.
  • OCCT: BRepFill_PipeShell::LastShape
  • Example:
    guard let spineLine = Wire.line(from: .zero, to: SIMD3(0, 0, 50)),
          let spineWire = Shape.fromWire(spineLine),
          let profileCircle = Wire.circle(radius: 5),
          let profile = Shape.fromWire(profileCircle),
          let pipe = PipeShellBuilder(spine: spineWire) else { return }
    pipe.add(profile: profile)
    pipe.build()
    if let cap = pipe.lastShape { /* use end cap */ }