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 · GCPnts_UniformAbscissa · GeomConvert CompCurveToBSplineCurve · Geom2dConvert CompCurveToBSplineCurve · Knot splitting, the deprecated v0.105.0 spellings · BndLib extras · GProp Torus · BRepTools_ReShape · BRepTools_Substitution · BRepLib_MakeVertex · BRepFill_PipeShell · OSD_Directory · IntAna Cone-Sphere extensions · XCAFPrs_DocumentExplorer extensions · Resource_Unicode · GProp weighted point sets · GeomLib_LogSample · GC_MakeConicalSurface · GC_MakeCylindricalSurface · GC_MakeTrimmedCone · GC_MakeTrimmedCylinder · BRepLib_MakeEdge2d extensions · ShapeAnalysis_Wire · ShapeAnalysis_Edge · OSD_DirectoryIterator · OSD_FileIterator · BRepFill_PipeShell extensions
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
Curve2Dwrapping aGeom2d_Parabola, ornilif 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
Curve2Dwrapping aGeom2d_Parabola, ornilon 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, elsenil. OCCT documents that precondition but enforces it with aRaise_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
nilif the edge is invalid or sampling fails. - OCCT:
GCPnts_UniformAbscissa(by number of points). The edge is read through aBRepAdaptor_Curve, whose constructor dereferences a null shape, so a null shape (fromShape.nullified) used to crash the process here; it answersnilnow (#1035, measured inScripts/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
nilon 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 (elsenil, see above);u1,u2, the parameter range on the underlying curve. - Returns: Array of parameter values, or
nilon failure. - OCCT:
GCPnts_UniformAbscissa(range variant, by count). A null shape (fromShape.nullified) used to crash the process in theBRepAdaptor_Curveconstructor; it answersnilnow (#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
nilon 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 boundedCurve3Dsegments;tolerance, continuity tolerance at join points. - Returns: A
Curve3Dwrapping aGeom_BSplineCurve, ornilif 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 boundedCurve2Dsegments;tolerance, continuity tolerance at join points. - Returns: A
Curve2Dwrapping aGeom2d_BSplineCurve, ornilif 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:
AnalyticBoundswithminandmaxcorners. - OCCT:
BndLib::Add, thegp_Elipsoverload (viaOCCTBndLibEllipse). The adaptor-drivenBndLib_Add3dCurveis whatBndLib.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 atcenter;vmin,vmax, axial parameter range;tolerance, optional inflation. - Returns:
AnalyticBounds. - OCCT:
BndLib::Add, thegp_Coneoverload takingvmin/vmax(viaOCCTBndLibCone). - 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, thegp_Circoverload takingu1/u2(viaOCCTBndLibCircleArc). - 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, thegp_Elipsoverload takingu1/u2(viaOCCTBndLibEllipseArc). - 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, thegp_Paraboverload (viaOCCTBndLibParabolaArc). - 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, thegp_Hyproverload (viaOCCTBndLibHyperbolaArc). - 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_SelGPropsover agp_Torusswept0...2πin both parameters (viaOCCTGPropTorusSurface). NotGProp_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_VelGPropsover agp_Torus(viaOCCTGPropTorusVolume).GProp_GPropsis 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:
trueif 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
nilon 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
nilif 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
Shapewith the substitution applied, ornilon 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:
trueif 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_Vertexwrapped asShape, ornilon 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 wireShapeused as the sweep path. - Returns:
nilifspineis 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,trueto 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_WireorTopoDS_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, aTopoDS_Vertexon 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, aLawFunctiondriving 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:
trueif 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
nilifbuild()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:
trueif 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:
truewhen 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:
trueon 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
nilon 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:
trueon 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
nilon error (e.g. identical surfaces). - OCCT:
IntAna_IntQuadQuadon anIntAna_Quadricbuilt from the sphere. The threeconeSphere*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 inconeSphere. - Returns: Array of up to
sampleCount3D 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:
trueif 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...lastparameter 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(viaDocument.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::SetFormatformat 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
nilon 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 into0...Sampling.maximumSampleCount(10,000,000); 0 or less returnsnil(#622). - Returns: String in the current encoding, or
nilon 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 aspoints). Every weight must be strictly positive. - Returns: Tuple of total mass (sum of weights) and the weighted centroid position, which is
nilwhen there is none to report. - A non-positive weight rejects the whole set.
GProp_PGProps::AddPointthrowsStandard_DomainErroron 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::AddPointpoint-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
nilfor 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 within1...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
nlogarithmically spaced values, or empty ifnis outside1...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 pastInt32.maxaborted 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 atcenter. - Returns: A
SurfacewrappingGeom_ConicalSurface, ornilon 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
SurfacewrappingGeom_ConicalSurface, ornilon 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
SurfacewrappingGeom_ConicalSurface, ornilon 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
SurfacewrappingGeom_CylindricalSurface, ornilon 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
SurfacewrappingGeom_CylindricalSurface, ornilon 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
SurfacewrappingGeom_CylindricalSurface, ornilon 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
SurfacewrappingGeom_CylindricalSurface, ornilon 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
SurfacewrappingGeom_CylindricalSurface, ornilon 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
SurfacewrappingGeom_ConicalSurface, ornilon 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
SurfacewrappingGeom_ConicalSurface, ornilon 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
SurfacewrappingGeom_CylindricalSurface, ornilon 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
SurfacewrappingGeom_CylindricalSurface, ornilon 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
SurfacewrappingGeom_CylindricalSurface, ornilon 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
Shapewrapping a closedTopoDS_Edgein 2D, ornilon 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 withminorRadius <= majorRadius. Equal radii are a circle and are valid. - Returns: A closed 2D edge, or
nilon failure or a degenerate ellipse.BRepLib_MakeEdge2ditself reportsIsDone()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 withminorRadius <= majorRadius;u1,u2: parameter range (radians). - Returns: A 2D edge arc, or
nilon 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 boundedCurve2D. - Returns: A
Shapewrapping a 2DTopoDS_Edge, ornilon 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, aCurve2D;u1,u2, parameter range to trim to. - Returns: A 2D edge, or
nilon 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:
trueif 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:
trueif 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:
trueif a problem is found,falseif none is,nilif the check could not be run. A face’s own outer wire returnsfalse; a hole wire on the same face returnstrue. - 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:
okistruewhen the edge is within tolerance;maxDeviationis 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:
trueif 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:
okwhen 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 toPrecision::Confusion(),1e-7). - Returns:
overlappingistruewhen the edges are withintoleranceof each other;toleranceechoes 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), ornilif 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,falsefor the start,truefor the end. - Returns: Tuple of 2D position and tangent, or
nilif 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:
trueif 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 forcount;index, 0-based index. - Returns: Directory name, or
nilif 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 into0...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
nilif 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 into0...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,trueto 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,trueto 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, ornilifbuild()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, ornilifbuild()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 */ }