Link Search Menu Expand Document

Shape. Builders & Boolean Internals II

Continuation of the low-level builder and algorithm wrappers on Shape, covering GeomFill sweep/evolved-section, projection, offset, iso-curve evaluation, parameter transfer, boolean section/feature removal, shape build/extend/upgrade utilities, 2D vector math, topological transition analysis, GeomFill trihedrons, 2D polygon interference, analytical 2D circle construction, IntTools intersection, BOPAlgo builders, BRepFeat split/hole/glue, LocOpe split/glue, and 2D chamfer/fillet APIs.

See also: Shape (index).

Topics


GeomFill_Sweep

Shape.geomFillSweep(path:section:)

Sweep a section edge along a path edge to create a surface face.

public static func geomFillSweep(path: Shape, section: Shape) -> Shape?
  • Parameters: path, edge defining the sweep path. section, edge defining the cross-section profile.
  • Returns: A Shape wrapping the swept face, or nil on failure, including when GeomFill_Sweep fits the surface but misses its own 1e-4 tolerance (ErrorOnSurface()); a surface reported IsDone() is not necessarily within the tolerance it was built at, so this is checked rather than assumed (#597).
  • OCCT: GeomFill_Sweep
  • Example:
    if let face = Shape.geomFillSweep(path: pathEdge, section: sectionEdge) {
        // face is a swept surface
    }
    

GeomFill_EvolvedSection

evolvedSectionInfo()

Get evolved section info for an edge curve.

public func evolvedSectionInfo() -> EvolvedSectionInfo
  • Returns: EvolvedSectionInfo with nbPoles, nbKnots, degree, and isRational.
  • OCCT: GeomFill_EvolvedSection
  • Example:
    let info = edge.evolvedSectionInfo()
    print(info.degree, info.isRational)
    

EvolvedSectionInfo.nbPoles

Number of BSpline control poles in the evolved section curve.

EvolvedSectionInfo.nbKnots

Number of BSpline knots in the evolved section curve.


ProjLib_ComputeApprox

projectOntoSurface(_:tolerance:)

Project this edge’s 3D curve onto a face’s surface, returning an edge-on-surface.

public func projectOntoSurface(_ face: Shape, tolerance: Double = 1e-3) -> Shape?
  • Parameters: face, target face. tolerance, approximation tolerance.
  • Returns: Projected edge as shape, or nil on failure.
  • OCCT: ProjLib_ComputeApprox
  • Example:
    if let proj = edge.projectOntoSurface(face) { }
    

projectOntoPolarSurface(_:tolerance:)

Project this edge’s 3D curve onto a polar surface (sphere, torus).

public func projectOntoPolarSurface(_ face: Shape, tolerance: Double = 1e-3) -> Shape?
  • Parameters: face, polar face. tolerance, approximation tolerance.
  • Returns: Projected edge as shape, or nil on failure.
  • OCCT: ProjLib_ComputeApproxOnPolarSurface
  • Example:
    if let proj = edge.projectOntoPolarSurface(sphereFace) { }
    

BRepOffset_Offset

offsetFace(distance:)

Offset a face by a distance, creating a new offset face.

public func offsetFace(distance: Double) -> Shape?
  • Parameters: distance, signed offset amount; positive moves along the face normal.
  • Returns: Offset face, or nil on failure.
  • OCCT: BRepOffset_Offset
  • Example:
    if let off = face.offsetFace(distance: 2.0) { }
    

Adaptor3d_IsoCurve

uIsoCurvePoints(u:count:)

Evaluate sample points along a U-iso curve on a face.

public func uIsoCurvePoints(u: Double, count: Int = 20) -> [SIMD3<Double>]
  • Parameters: u, U parameter value. count, number of sample points, a request honoured within 1...Sampling.maximumSampleCount (10,000,000); outside that range the result is empty (#558).
  • Returns: Array of 3D points along the iso curve.
  • OCCT: Adaptor3d_IsoCurve, selected with GeomAbs_IsoU/GeomAbs_IsoV (iso kind 0 = U)
  • Note: The samples are spread evenly over the iso curve’s own parameter range, clamped to -1e6...1e6 when the surface is infinite in that direction (a plane, or a cylinder’s V), so on an unbounded face the points span that clamp rather than anything derived from the face’s own extent. When the shape is not a face, or its surface cannot be read, the bridge writes nothing and the array comes back as count points at the origin rather than empty.
  • Example:
    let pts = face.uIsoCurvePoints(u: 0.5, count: 50)
    

vIsoCurvePoints(v:count:)

Evaluate sample points along a V-iso curve on a face.

public func vIsoCurvePoints(v: Double, count: Int = 20) -> [SIMD3<Double>]
  • Parameters: v, V parameter value. count, number of sample points, a request honoured within 1...Sampling.maximumSampleCount (10,000,000); outside that range the result is empty (#558).
  • Returns: Array of 3D points along the iso curve.
  • OCCT: Adaptor3d_IsoCurve, selected with GeomAbs_IsoU/GeomAbs_IsoV (iso kind 1 = V)
  • Note: The samples are spread evenly over the iso curve’s own parameter range, clamped to -1e6...1e6 when the surface is infinite in that direction (a plane, or a cylinder’s V), so on an unbounded face the points span that clamp rather than anything derived from the face’s own extent. When the shape is not a face, or its surface cannot be read, the bridge writes nothing and the array comes back as count points at the origin rather than empty.
  • Example:
    let pts = face.vIsoCurvePoints(v: 0.25)
    

uIsoCurveEdge(u:vMin:vMax:)

Extract a U-iso curve from a face as an edge.

public func uIsoCurveEdge(u: Double, vMin: Double, vMax: Double) -> Shape?
  • Parameters: u, U parameter. vMin/vMax, V parameter range for the edge.
  • Returns: Edge shape representing the iso curve, or nil on failure.
  • OCCT: Geom_Surface::UIso / VIso turned into an edge by BRepBuilderAPI_MakeEdge (no Adaptor3d_IsoCurve, unlike the point samplers above)
  • Example:
    if let e = face.uIsoCurveEdge(u: 0.5, vMin: 0, vMax: 1) { }
    

vIsoCurveEdge(v:uMin:uMax:)

Extract a V-iso curve from a face as an edge.

public func vIsoCurveEdge(v: Double, uMin: Double, uMax: Double) -> Shape?
  • Parameters: v, V parameter. uMin/uMax, U parameter range for the edge.
  • Returns: Edge shape representing the iso curve, or nil on failure.
  • OCCT: Geom_Surface::UIso / VIso turned into an edge by BRepBuilderAPI_MakeEdge (no Adaptor3d_IsoCurve, unlike the point samplers above)
  • Example:
    if let e = face.vIsoCurveEdge(v: 0.5, uMin: 0, uMax: 1) { }
    

ShapeAnalysis_TransferParametersProj

transferParameterToFace(_:face:)

Transfer a parameter from edge to face coordinate system via projection.

public func transferParameterToFace(_ param: Double, face: Shape) -> Double
  • Parameters: param, edge parameter. face, face to transfer into.
  • Returns: Corresponding parameter in the face’s coordinate system.
  • OCCT: ShapeAnalysis_TransferParametersProj (toFace = true)
  • Example:
    let faceParam = edge.transferParameterToFace(0.5, face: face)
    

transferParameterFromFace(_:face:)

Transfer a parameter from face to edge coordinate system via projection.

public func transferParameterFromFace(_ param: Double, face: Shape) -> Double
  • Parameters: param, face parameter. face, face to transfer from.
  • Returns: Corresponding parameter in the edge’s coordinate system.
  • OCCT: ShapeAnalysis_TransferParametersProj (toFace = false)
  • Example:
    let edgeParam = edge.transferParameterFromFace(0.5, face: face)
    

BOPAlgo_RemoveFeatures

removeFeatures(faces:) was defeature(faces:) under a second name: BRepAlgoAPI_Defeaturing, which defeature(faces:) drives, is an API wrapper over BOPAlgo_RemoveFeatures, and both spellings drove one algorithm object with identical defaults, measured byte-for-byte identical on every case including the refusals (see Scripts/repro/536-defeature-removefeatures-unify/). Deprecated as a forward to defeature(faces:) in #536, removeFeatures(faces:) was removed at v2.0.0 (#784); use defeature(faces:).

let faces = solid.subShapes(ofType: .face)
if let cleaned = solid.defeature(faces: [faces[2]]) { }

BOPAlgo_Section

section(with:)

Compute section (intersection curves/vertices) between this shape and tools.

public func section(with tools: [Shape]) -> Shape?
  • Parameters: tools, tool shapes to intersect with this shape.
  • Returns: Compound of intersection edges and vertices, or nil on failure.
  • OCCT: BOPAlgo_Section
  • Example:
    if let sect = solid.section(with: [plane]) { }
    

Shape.section(shapes:)

Compute section between multiple shapes (static variant).

public static func section(shapes: [Shape]) -> Shape?
  • Parameters: shapes, at least 2 shapes; all are treated as equal arguments.
  • Returns: Compound of intersection edges and vertices, or nil on failure (requires ≥ 2 shapes).
  • OCCT: BOPAlgo_Section
  • Example:
    if let sect = Shape.section(shapes: [box, sphere]) { }
    

ShapeBuild_Edge

copyEdge(sharePCurves:)

Copy an edge, optionally sharing its PCurves with the original.

public func copyEdge(sharePCurves: Bool = true) -> Shape?
  • Parameters: sharePCurves, if true, the copy shares PCurves with the original edge.
  • Returns: Copied edge as shape, or nil on failure.
  • OCCT: ShapeBuild_Edge::Copy
  • Example:
    if let copy = edge.copyEdge() { }
    

copyEdgeReplacingVertices(startVertex:endVertex:)

Copy an edge, replacing its start and/or end vertices.

public func copyEdgeReplacingVertices(startVertex: Shape?, endVertex: Shape?) -> Shape?
  • Parameters: startVertex, new start vertex, or nil to keep original. endVertex, new end vertex, or nil to keep original.
  • Returns: Edge with replaced vertices, or nil on failure.
  • OCCT: ShapeBuild_Edge::CopyReplaceVertices
  • Example:
    if let e = edge.copyEdgeReplacingVertices(startVertex: v1, endVertex: nil) { }
    

setEdgeRange3d(first:last:)

Set the 3D parameter range on this edge shape.

public func setEdgeRange3d(first: Double, last: Double)
  • Parameters: first, start parameter. last, end parameter.
  • OCCT: ShapeBuild_Edge::SetRange3d
  • Example:
    edge.setEdgeRange3d(first: 0, last: 1)
    

buildEdgeCurve3d()

Rebuild the 3D curve of an edge from its PCurves.

@discardableResult
public func buildEdgeCurve3d() -> Bool
  • Returns: true if the curve was rebuilt successfully.
  • OCCT: ShapeBuild_Edge::BuildCurve3d
  • Example:
    edge.buildEdgeCurve3d()
    

removeEdgeCurve3d()

Remove the 3D curve from this edge.

public func removeEdgeCurve3d()
  • OCCT: ShapeBuild_Edge::RemoveCurve3d
  • Example:
    edge.removeEdgeCurve3d()
    

copyEdgeRanges(from:)

Copy parameter ranges from another edge to this edge.

public func copyEdgeRanges(from source: Shape)
  • Parameters: source, edge from which to copy ranges.
  • OCCT: ShapeBuild_Edge::CopyRanges
  • Example:
    edge.copyEdgeRanges(from: sourceEdge)
    

copyEdgePCurves(from:)

Copy PCurves from another edge to this edge.

public func copyEdgePCurves(from source: Shape)
  • Parameters: source, edge from which to copy PCurves.
  • OCCT: ShapeBuild_Edge::CopyPCurves
  • Example:
    edge.copyEdgePCurves(from: sourceEdge)
    

removeEdgePCurve(onFace:)

Remove the PCurve from this edge for a given face.

public func removeEdgePCurve(onFace face: Shape)
  • Parameters: face, the face whose PCurve should be removed from this edge.
  • OCCT: ShapeBuild_Edge::RemovePCurve
  • Example:
    edge.removeEdgePCurve(onFace: face)
    

reassignEdgePCurve(from:to:)

Reassign a PCurve from one face to another.

@discardableResult
public func reassignEdgePCurve(from oldFace: Shape, to newFace: Shape) -> Bool
  • Parameters: oldFace, face that currently holds the PCurve. newFace, destination face.
  • Returns: true if reassignment succeeded.
  • OCCT: ShapeBuild_Edge::ReassignPCurve
  • Example:
    edge.reassignEdgePCurve(from: oldFace, to: newFace)
    

ShapeBuild_Vertex

combineVertex(with:tolFactor:)

Combine this vertex shape with another at their average position.

public func combineVertex(with other: Shape, tolFactor: Double = 1.0001) -> Shape?
  • Parameters: other, vertex to combine with. tolFactor, tolerance scale factor.
  • Returns: Combined vertex as shape, or nil on failure.
  • OCCT: ShapeBuild_Vertex::CombineVertex
  • Example:
    if let v = v1.combineVertex(with: v2) { }
    

Shape.combineVertices(point1:tol1:point2:tol2:tolFactor:)

Create a vertex by combining two 3D points with tolerances.

public static func combineVertices(
    point1: SIMD3<Double>, tol1: Double,
    point2: SIMD3<Double>, tol2: Double,
    tolFactor: Double = 1.0001
) -> Shape?
  • Parameters: point1/tol1, first point and its tolerance. point2/tol2, second point and its tolerance. tolFactor, scale factor applied to the combined tolerance.
  • Returns: Combined vertex, or nil on failure.
  • OCCT: ShapeBuild_Vertex::CombineVertex (from points)
  • Example:
    if let v = Shape.combineVertices(point1: .zero, tol1: 1e-7, point2: SIMD3(0,0,0.001), tol2: 1e-7) { }
    

ShapeExtend_Explorer

ShapeFilterType

Shape type enum for filtering compounds.

public typealias ShapeFilterType = ShapeType

A typealias for the canonical ShapeType (see “Shape-Features”), this used to be an independent local mirror of the same TopAbs_ShapeEnum ordinals, with its own, differently-cased compsolid case (ShapeType spells it compSolid). ShapeExtend_Explorer uses the identical ordinal convention every other sub-shape-type API in this package does, so there was no reason for a second declaration once the casing was reconciled (#844).


sortedCompound(type:explore:)

Filter this compound, extracting only sub-shapes of the specified type.

public func sortedCompound(type: ShapeFilterType, explore: Bool = true) -> Shape?
  • Parameters: type, target shape type. explore, if true, recurse into sub-compounds.
  • Returns: Compound of matching sub-shapes, or nil on failure.
  • OCCT: ShapeExtend_Explorer::SortedCompound
  • Example:
    if let faces = compound.sortedCompound(type: .face) { }
    

predominantShapeType(lookInsideCompounds:)

Get the predominant shape type in this compound.

public func predominantShapeType(lookInsideCompounds: Bool = true) -> ShapeFilterType
  • Parameters: lookInsideCompounds, if true, inspect sub-compounds.
  • Returns: The most-common ShapeFilterType found, or .unknown if the underlying OCCT walk throws (PR #870 aggregate review, this used to decode as .vertex, a real, legitimate case, indistinguishable from an actual vertex-dominated shape).
  • OCCT: ShapeExtend_Explorer::ShapeType
  • Example:
    let t = compound.predominantShapeType()
    

ShapeUpgrade_FaceDivide

divideFace()

Divide a face using surface segmentation.

public func divideFace() -> Shape?
  • Returns: Divided shape, or nil on failure.
  • OCCT: ShapeUpgrade_FaceDivide
  • Example:
    if let divided = face.divideFace() { }
    

ShapeUpgrade_WireDivide

divideWire(onFace:)

Divide a wire on a face.

public func divideWire(onFace face: Shape) -> Shape?
  • Parameters: face, face the wire lies on.
  • Returns: Divided wire as shape, or nil on failure.
  • OCCT: ShapeUpgrade_WireDivide
  • Example:
    if let w = wire.divideWire(onFace: face) { }
    

ShapeUpgrade_EdgeDivide

EdgeDivideResult

Result of an edge divide analysis.

public struct EdgeDivideResult: Sendable {
    public let hasCurve2d: Bool
    public let hasCurve3d: Bool
}
Field Meaning
hasCurve2d true if the edge carries a 2D (pcurve) representation on the analysed face.
hasCurve3d true if the edge carries a 3D curve representation.

Shape.EdgeDivideResult.hasCurve2d


analyzeEdgeDivide(onFace:)

Analyze an edge for potential division on a face.

public func analyzeEdgeDivide(onFace face: Shape) -> EdgeDivideResult?
  • Parameters: face, face context for the edge.
  • Returns: Analysis result indicating 2D/3D curve presence, or nil on failure.
  • OCCT: ShapeUpgrade_EdgeDivide::Compute
  • Example:
    if let r = edge.analyzeEdgeDivide(onFace: face) {
        print(r.hasCurve3d)
    }
    

ShapeUpgrade_ClosedEdgeDivide

canDivideClosedEdge(onFace:)

Check if a closed (seam) edge can be divided on a face.

public func canDivideClosedEdge(onFace face: Shape) -> Bool
  • Parameters: face, face context.
  • Returns: true if the edge is closed and divisible.
  • OCCT: ShapeUpgrade_ClosedEdgeDivide::Compute
  • Example:
    if edge.canDivideClosedEdge(onFace: face) { }
    

ShapeUpgrade_ConvertCurve3dToBezier

convertCurves3dToBezier(lineMode:circleMode:conicMode:)

Convert 3D curves in this shape to Bezier representation.

public func convertCurves3dToBezier(lineMode: Bool = true, circleMode: Bool = true,
                                     conicMode: Bool = true) -> Shape?
  • Parameters: lineMode, convert line segments. circleMode, convert circles. conicMode, convert other conics.
  • Returns: Shape with Bezier curves, or nil on failure.
  • OCCT: ShapeUpgrade_ShapeConvertToBezier with 3D-curve conversion enabled
  • Example:
    if let bez = shape.convertCurves3dToBezier(lineMode: false) { }
    

ShapeUpgrade_ConvertSurfaceToBezierBasis

convertSurfacesToBezier(planeMode:revolutionMode:extrusionMode:bsplineMode:)

Convert surfaces in this shape to Bezier patches.

public func convertSurfacesToBezier(planeMode: Bool = true, revolutionMode: Bool = true,
                                     extrusionMode: Bool = true, bsplineMode: Bool = true) -> Shape?
  • Parameters: planeMode, convert planes. revolutionMode, convert revolution surfaces. extrusionMode, convert extrusions. bsplineMode, convert BSpline surfaces.
  • Returns: Shape with Bezier surfaces, or nil on failure.
  • OCCT: ShapeUpgrade_ShapeConvertToBezier with surface conversion enabled
  • Example:
    if let bez = shape.convertSurfacesToBezier(bsplineMode: false) { }
    

2D Vector/Direction Utilities & LProp

Shape.vector2DAngle(a:b:)

Signed angle between two 2D vectors, in radians (range −π to π).

public static func vector2DAngle(a: SIMD2<Double>, b: SIMD2<Double>) -> Double
  • OCCT: gp_Vec2d::Angle
  • Example:
    let angle = Shape.vector2DAngle(a: SIMD2(1, 0), b: SIMD2(0, 1))  // π/2
    

Shape.vector2DCross(a:b:)

Cross product of two 2D vectors (scalar Z component).

public static func vector2DCross(a: SIMD2<Double>, b: SIMD2<Double>) -> Double
  • OCCT: Inline arithmetic ax * by - ay * bx via OCCTVector2DCross (no gp_Vec2d constructed).
  • Example:
    let z = Shape.vector2DCross(a: SIMD2(1, 0), b: SIMD2(0, 1))  // 1.0
    

Shape.vector2DDot(a:b:)

Dot product of two 2D vectors.

public static func vector2DDot(a: SIMD2<Double>, b: SIMD2<Double>) -> Double
  • OCCT: Inline arithmetic ax * bx + ay * by via OCCTVector2DDot (no gp_Vec2d constructed).
  • Example:
    let d = Shape.vector2DDot(a: SIMD2(1, 0), b: SIMD2(0.5, 0.5))
    

Shape.vector2DMagnitude(_:)

Magnitude of a 2D vector.

public static func vector2DMagnitude(_ v: SIMD2<Double>) -> Double
  • OCCT: inline arithmetic sqrt(x * x + y * y) (no gp_Vec2d constructed)
  • Example:
    let m = Shape.vector2DMagnitude(SIMD2(3, 4))  // 5.0
    

Shape.vector2DNormalized(_:)

Return a normalized copy of a 2D vector.

public static func vector2DNormalized(_ v: SIMD2<Double>) -> SIMD2<Double>
  • OCCT: inline arithmetic dividing each component by the magnitude (no gp_Vec2d constructed)
  • Example:
    let n = Shape.vector2DNormalized(SIMD2(3, 4))
    

Shape.direction2DNormalized(_:)

Create a normalized 2D direction from components.

public static func direction2DNormalized(_ v: SIMD2<Double>) -> SIMD2<Double>
  • OCCT: gp_Dir2d constructor (normalizes on construction)
  • Example:
    let d = Shape.direction2DNormalized(SIMD2(1, 1))
    

Shape.direction2DAngle(a:b:)

Signed angle between two 2D directions, in radians.

public static func direction2DAngle(a: SIMD2<Double>, b: SIMD2<Double>) -> Double
  • OCCT: gp_Dir2d::Angle
  • Example:
    let angle = Shape.direction2DAngle(a: SIMD2(1, 0), b: SIMD2(0, 1))
    

Shape.direction2DCross(a:b:)

Cross product of two 2D directions.

public static func direction2DCross(a: SIMD2<Double>, b: SIMD2<Double>) -> Double
  • OCCT: gp_Dir2d::Crossed
  • Example:
    let z = Shape.direction2DCross(a: SIMD2(1, 0), b: SIMD2(0, 1))
    

CurvaturePointType

Type of a special curvature point found by LProp analysis.

public enum CurvaturePointType: Int32 {
    case inflection = 0
    case minimumCurvature = 1
    case maximumCurvature = 2
}
case meaning
.inflection Parameter where curvature changes sign.
.minimumCurvature Parameter at a local minimum of curvature.
.maximumCurvature Parameter at a local maximum of curvature.

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

maximumCurvature


CurvatureSpecialPoint

A special point on a curve at a given parameter.

public struct CurvatureSpecialPoint {
    public let parameter: Double
    public let type: CurvaturePointType
}

Shape.analyticCurvaturePoints(curveType:first:last:)

Compute the curvature extrema of an analytic curve type, as parameter/kind pairs.

Only curveType: 2 (ellipse) ever produces a point: a line has zero curvature, a circle constant curvature, and a parabola and a hyperbola monotonic curvature, so none of them has an extremum, and every other value returns an empty array. An ellipse reports the four axis vertices that fall inside first...last, classified the way LProp_CurAndInf classifies them, by radius of curvature rather than by curvature: the major-axis vertices at 0 and π are .minimumCurvature (minimum radius) and the minor-axis vertices at π/2 and 3π/2 are .maximumCurvature. CurvaturePointType.inflection is declared but never returned; an analytic conic has no inflection.

public static func analyticCurvaturePoints(curveType: Int32, first: Double,
                                            last: Double) -> [CurvatureSpecialPoint]
  • Parameters: curveType, the GeomAbs_CurveType ordinal: 0=Line, 1=Circle, 2=Ellipse, 3=Hyperbola, 4=Parabola. first/last, parameter domain.
  • Returns: Array of curvature extrema; empty for every curveType but 2, and for an ellipse whose domain excludes all four vertices.
  • OCCT: LProp_CurAndInf (the result container) and LProp_CIType (the kind enum). The extrema themselves are computed in the bridge rather than by an OCCT algorithm, since the closed form for a conic is four fixed parameters; OCCTLPropAnalyticCurInf fills the container with AddExtCur and reads it back with Parameter/Type.
  • Example:
    let pts = Shape.analyticCurvaturePoints(curveType: 2, first: 0, last: .pi)
    

TopTrans Surface Transition

TopologicalState

OCCT TopAbs_State mapping.

public enum TopologicalState: Int32, Sendable {
    case `in` = 0, out = 1, on = 2, unknown = 3
}

The point or curve lies strictly inside the boundary for `in` (TopAbs_IN, not independently documented below since `-escaped keyword case names aren’t headings this project’s own tooling resolves).

TopologicalState.out

The point or curve lies strictly outside the boundary (TopAbs_OUT).

case out = 1

TopologicalState.on

The point or curve lies exactly on the boundary element itself (TopAbs_ON).

case on = 2

TopologicalState.unknown

The transition analysis could not determine a state (TopAbs_UNKNOWN).

case unknown = 3

SurfaceTransitionResult

Result of a surface or curve transition analysis.

public struct SurfaceTransitionResult: Sendable {
    public let stateBefore: TopologicalState
    public let stateAfter: TopologicalState
}

SurfaceTransitionResult.stateBefore

The TopologicalState immediately before the curve crosses the surface or boundary element.

public let stateBefore: TopologicalState

SurfaceTransitionResult.stateAfter

The TopologicalState immediately after the curve crosses the surface or boundary element.

public let stateAfter: TopologicalState

Shape.surfaceTransition(tangent:normal:surfaceNormal:tolerance:surfaceOrientation:boundaryOrientation:)

Analyze topological state before and after a curve crosses a surface boundary.

public static func surfaceTransition(
    tangent: SIMD3<Double>, normal: SIMD3<Double>,
    surfaceNormal: SIMD3<Double>, tolerance: Double = 1e-6,
    surfaceOrientation: Int = 0, boundaryOrientation: Int = 0
) -> SurfaceTransitionResult
  • Parameters: tangent, curve tangent at crossing. normal, boundary normal. surfaceNormal, normal of the crossed surface. tolerance, angular tolerance. surfaceOrientation/boundaryOrientation, 0=FORWARD, 1=REVERSED.
  • Returns: States before and after the surface crossing.
  • OCCT: TopTrans_SurfaceTransition
  • Example:
    let r = Shape.surfaceTransition(tangent: t, normal: n, surfaceNormal: sn)
    

Shape.surfaceTransitionWithCurvature(...)

Extended surface transition analysis that accounts for surface curvature.

public static func surfaceTransitionWithCurvature(
    tangent: SIMD3<Double>, normal: SIMD3<Double>,
    maxDirection: SIMD3<Double>, minDirection: SIMD3<Double>,
    maxCurvature: Double, minCurvature: Double,
    surfaceNormal: SIMD3<Double>,
    surfaceMaxDirection: SIMD3<Double>, surfaceMinDirection: SIMD3<Double>,
    surfaceMaxCurvature: Double, surfaceMinCurvature: Double,
    tolerance: Double = 1e-6,
    surfaceOrientation: Int = 0, boundaryOrientation: Int = 0
) -> SurfaceTransitionResult
  • Parameters: Principal curvature directions and magnitudes for both the boundary and the surface at the crossing point, plus tangent and normals.
  • Returns: States before and after.
  • OCCT: TopTrans_SurfaceTransition (with curvature)
  • Example:
    let r = Shape.surfaceTransitionWithCurvature(
        tangent: t, normal: n,
        maxDirection: md, minDirection: nd,
        maxCurvature: k1, minCurvature: k2,
        surfaceNormal: sn,
        surfaceMaxDirection: smd, surfaceMinDirection: snd,
        surfaceMaxCurvature: sk1, surfaceMinCurvature: sk2)
    

TopTrans Curve Transition

Shape.curveTransition(tangent:boundaryTangent:boundaryNormal:curvature:tolerance:surfaceOrientation:boundaryOrientation:)

Analyze topological state before and after a curve crosses a boundary element.

public static func curveTransition(
    tangent: SIMD3<Double>,
    boundaryTangent: SIMD3<Double>, boundaryNormal: SIMD3<Double>,
    curvature: Double = 0.0, tolerance: Double = 1e-6,
    surfaceOrientation: Int = 0, boundaryOrientation: Int = 0
) -> SurfaceTransitionResult
  • Parameters: tangent, curve tangent. boundaryTangent/boundaryNormal, boundary element geometry. curvature, boundary curvature (0 for straight boundary).
  • Returns: SurfaceTransitionResult with before/after states.
  • OCCT: TopTrans_CurveTransition
  • Example:
    let r = Shape.curveTransition(tangent: t, boundaryTangent: bt, boundaryNormal: bn)
    

Shape.curveTransitionWithCurvature(tangent:curveNormal:curveCurvature:boundaryTangent:boundaryNormal:surfaceCurvature:tolerance:surfaceOrientation:boundaryOrientation:)

Curve transition analysis accounting for boundary curve curvature.

public static func curveTransitionWithCurvature(
    tangent: SIMD3<Double>,
    curveNormal: SIMD3<Double>, curveCurvature: Double,
    boundaryTangent: SIMD3<Double>, boundaryNormal: SIMD3<Double>,
    surfaceCurvature: Double, tolerance: Double = 1e-6,
    surfaceOrientation: Int = 0, boundaryOrientation: Int = 0
) -> SurfaceTransitionResult
  • Returns: SurfaceTransitionResult with before/after states.
  • OCCT: TopTrans_CurveTransition (with curvature)
  • Example:
    let r = Shape.curveTransitionWithCurvature(
        tangent: t, curveNormal: cn, curveCurvature: kc,
        boundaryTangent: bt, boundaryNormal: bn, surfaceCurvature: ks)
    

GeomFill Trihedrons

frenetTrihedron(at:)

Evaluate a Frenet trihedron on an edge at a parameter.

public func frenetTrihedron(at param: Double) -> (tangent: SIMD3<Double>, normal: SIMD3<Double>, binormal: SIMD3<Double>)?
  • Parameters: param, curve parameter.
  • Returns: Tuple of tangent, normal, binormal, or nil if the trihedron cannot be computed (e.g. inflection point).
  • OCCT: GeomFill_Frenet
  • Example:
    if let f = edge.frenetTrihedron(at: 0.5) {
        print(f.tangent, f.normal, f.binormal)
    }
    

constantBiNormalTrihedron(at:biNormal:)

Evaluate a constant-binormal trihedron on an edge at a parameter.

public func constantBiNormalTrihedron(at param: Double, biNormal: SIMD3<Double>) -> (tangent: SIMD3<Double>, normal: SIMD3<Double>, binormal: SIMD3<Double>)?
  • Parameters: param, curve parameter. biNormal, fixed binormal direction.
  • Returns: Trihedron tuple, or nil on failure.
  • OCCT: GeomFill_ConstantBiNormal
  • Example:
    if let f = edge.constantBiNormalTrihedron(at: 0.5, biNormal: SIMD3(0, 0, 1)) { }
    

Shape.fixedTrihedron(tangent:normal:at:)

Evaluate a fixed (constant) trihedron at any parameter.

public static func fixedTrihedron(tangent: SIMD3<Double>, normal: SIMD3<Double>, at param: Double = 0) -> (tangent: SIMD3<Double>, normal: SIMD3<Double>, binormal: SIMD3<Double>)
  • Parameters: tangent/normal, fixed trihedron directions. param, parameter (unused geometrically; for API consistency).
  • Returns: Trihedron tuple (binormal = tangent × normal).
  • OCCT: GeomFill_Fixed
  • Example:
    let f = Shape.fixedTrihedron(tangent: SIMD3(1,0,0), normal: SIMD3(0,1,0))
    

darbouxTrihedron(onFace:at:)

Evaluate a Darboux trihedron on an edge lying on a face.

public func darbouxTrihedron(onFace face: Shape, at param: Double) -> (tangent: SIMD3<Double>, normal: SIMD3<Double>, binormal: SIMD3<Double>)?
  • Parameters: face, the supporting face. param, curve parameter.
  • Returns: Darboux frame (tangent, surface normal, binormal), or nil on failure.
  • OCCT: GeomFill_Darboux
  • Example:
    if let f = edge.darbouxTrihedron(onFace: face, at: 0.5) { }
    

Polygon Interference

PolygonIntersection

Result of 2D polygon interference computation.

public struct PolygonIntersection: Sendable {
    public let points: [SIMD2<Double>]
}

points is capped at 100 entries, and the truncation is silent: both entry points below size a fixed 100-element buffer and pass its length to Intf_InterferencePolygon2d as the maximum. A polyline pair with more than 100 crossings loses the rest with no signal (#1399).


Shape.polygonInterference(poly1:poly2:)

Compute intersection points between two 2D polylines.

public static func polygonInterference(
    poly1: [SIMD2<Double>], poly2: [SIMD2<Double>]
) -> PolygonIntersection
  • Parameters: poly1/poly2, ordered arrays of 2D vertices defining each polyline.
  • Returns: PolygonIntersection with intersection points (may be empty).
  • OCCT: Intf_InterferencePolygon2d
  • Example:
    let result = Shape.polygonInterference(poly1: pts1, poly2: pts2)
    

Shape.polygonSelfInterference(polygon:)

Compute self-intersection points of a 2D polyline.

public static func polygonSelfInterference(
    polygon: [SIMD2<Double>]
) -> PolygonIntersection
  • Parameters: polygon, ordered 2D vertices.
  • Returns: Self-intersection points.
  • OCCT: Intf_InterferencePolygon2d (self-interference mode)
  • Example:
    let result = Shape.polygonSelfInterference(polygon: pts)
    

GccAna_Circ2d3Tan

Circle2DSolution

A circle solution from a GccAna tangency solver.

public struct Circle2DSolution: Sendable {
    public let centerX: Double
    public let centerY: Double
    public let radius: Double
}

Circle2DSolution.centerX

X coordinate of the solution circle’s center.

public let centerX: Double

Circle2DSolution.centerY

Y coordinate of the solution circle’s center.

public let centerY: Double

Circle2DSolution.radius

Radius of the solution circle.

public let radius: Double

Shape.circleThrough3Points(p1:p2:p3:tolerance:)

Find circles through 3 points (circumscribed circle).

public static func circleThrough3Points(
    p1: SIMD2<Double>, p2: SIMD2<Double>, p3: SIMD2<Double>,
    tolerance: Double = 1e-6
) -> [Circle2DSolution]
  • Returns: Array of circle solutions (typically 0 or 1).
  • OCCT: GccAna_Circ2d3Tan (3 points)
  • Example:
    let sols = Shape.circleThrough3Points(p1: SIMD2(0,0), p2: SIMD2(1,0), p3: SIMD2(0,1))
    

Shape.circleTangent3Lines(l1Point:l1Dir:l2Point:l2Dir:l3Point:l3Dir:tolerance:)

Find circles tangent to 3 lines.

public static func circleTangent3Lines(
    l1Point: SIMD2<Double>, l1Dir: SIMD2<Double>,
    l2Point: SIMD2<Double>, l2Dir: SIMD2<Double>,
    l3Point: SIMD2<Double>, l3Dir: SIMD2<Double>,
    tolerance: Double = 1e-6
) -> [Circle2DSolution]
  • Returns: Array of up to 8 tangent circles.
  • OCCT: GccAna_Circ2d3Tan (3 lines)
  • Example:
    let sols = Shape.circleTangent3Lines(
        l1Point: .zero, l1Dir: SIMD2(1,0),
        l2Point: SIMD2(0,1), l2Dir: SIMD2(1,0),
        l3Point: .zero, l3Dir: SIMD2(0,1))
    

Shape.circleTangent3Circles(c1Center:c1Radius:c2Center:c2Radius:c3Center:c3Radius:tolerance:)

Find circles tangent to 3 circles (Apollonius problem).

public static func circleTangent3Circles(
    c1Center: SIMD2<Double>, c1Radius: Double,
    c2Center: SIMD2<Double>, c2Radius: Double,
    c3Center: SIMD2<Double>, c3Radius: Double,
    tolerance: Double = 1e-6
) -> [Circle2DSolution]
  • Returns: Array of up to 8 solution circles.
  • OCCT: GccAna_Circ2d3Tan (3 circles)
  • Note: every radius must be positive (#553). A zero-radius argument is a point, and the solver does not answer the point question when it is given one: measured, it returns each solution twice, because tangency to a circle of radius zero satisfies the enclosing and the outside qualifier at once. Use circleTangent2CirclesPoint, circleTangentCircle2Points or circleThrough3Points to name a point as a point. A non-positive radius returns an empty array.
  • Example:
    let sols = Shape.circleTangent3Circles(
        c1Center: SIMD2(-2,0), c1Radius: 1,
        c2Center: SIMD2(2,0), c2Radius: 1,
        c3Center: SIMD2(0,2), c3Radius: 1)
    

Shape.circleTangent2CirclesPoint(c1Center:c1Radius:c2Center:c2Radius:point:tolerance:)

Find circles tangent to 2 circles and passing through 1 point.

public static func circleTangent2CirclesPoint(
    c1Center: SIMD2<Double>, c1Radius: Double,
    c2Center: SIMD2<Double>, c2Radius: Double,
    point: SIMD2<Double>, tolerance: Double = 1e-6
) -> [Circle2DSolution]
  • OCCT: GccAna_Circ2d3Tan (2 circles + point)
  • Note: both radii must be positive (#553). With a zero radius the solution set comes back padded with repeats: measured, four solutions holding two distinct circles.
  • Example:
    let sols = Shape.circleTangent2CirclesPoint(
        c1Center: .zero, c1Radius: 1,
        c2Center: SIMD2(3,0), c2Radius: 1,
        point: SIMD2(1.5, 2))
    

Shape.circleTangentCircle2Points(circleCenter:circleRadius:p1:p2:tolerance:)

Find circles tangent to 1 circle and passing through 2 points.

public static func circleTangentCircle2Points(
    circleCenter: SIMD2<Double>, circleRadius: Double,
    p1: SIMD2<Double>, p2: SIMD2<Double>, tolerance: Double = 1e-6
) -> [Circle2DSolution]
  • OCCT: GccAna_Circ2d3Tan (circle + 2 points)
  • Note: circleRadius must be positive (#553). This is the case where reading a zero-radius circle as a point fails outright: measured, the solver finds nothing at all, where circleThrough3Points on the same three positions finds the circle through them.
  • Example:
    let sols = Shape.circleTangentCircle2Points(
        circleCenter: .zero, circleRadius: 1,
        p1: SIMD2(3,0), p2: SIMD2(0,3))
    

Shape.circleTangent2LinesPoint(l1Point:l1Dir:l2Point:l2Dir:point:tolerance:)

Find circles tangent to 2 lines and passing through 1 point.

public static func circleTangent2LinesPoint(
    l1Point: SIMD2<Double>, l1Dir: SIMD2<Double>,
    l2Point: SIMD2<Double>, l2Dir: SIMD2<Double>,
    point: SIMD2<Double>, tolerance: Double = 1e-6
) -> [Circle2DSolution]
  • OCCT: GccAna_Circ2d3Tan (2 lines + point)
  • Example:
    let sols = Shape.circleTangent2LinesPoint(
        l1Point: .zero, l1Dir: SIMD2(1,0),
        l2Point: .zero, l2Dir: SIMD2(0,1),
        point: SIMD2(2,2))
    

IntTools

CommonPartType

Type of an edge-edge or edge-face intersection common part.

public enum CommonPartType: Int32, Sendable {
    case vertex = 0
    case edge = 1
}

CommonPart

A single intersection common part from IntTools.

public struct CommonPart: Sendable {
    public let type: CommonPartType
    public let param1Range: (first: Double, last: Double)
    public let param2Range: (first: Double, last: Double)
    public let point: SIMD3<Double>
}
field meaning
type .vertex or .edge: the kind of intersection found.
param1Range Parameter range (first, last) on the first edge; equal endpoints for a vertex intersection.
param2Range Parameter range (first, last) on the second edge; equal endpoints for a vertex intersection. Only edgeEdgeIntersection(with:) has a second edge, see below.
point Representative 3D point of the intersection.

param2Range is always (0, 0) from edgeFaceIntersection(with:). A face is not an edge, and IntTools_EdgeFace reflects that: IntTools_EdgeFace.cxx never calls AppendRange2 or SetVertexParameter2, so IntTools_CommonPrt::Ranges2() comes back empty and VertexParameter2() comes back as the 0.0 its default constructor set (IntTools_CommonPrt.cxx:33). The bridge reads those and passes them on, so the pair reads as a measurement and is not one. Measured in Scripts/repro/1399-refman-coverage-unlaned/probe-transcript.txt (#1399). Read param1Range, the range on the edge, and point.

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

param2Range


edgeEdgeIntersection(with:)

Intersect two edges to find common vertices and edge overlaps.

public func edgeEdgeIntersection(with other: Shape) -> [CommonPart]?
  • Parameters: other, second edge.
  • Returns: Array of common parts, or nil if intersection failed.
  • OCCT: IntTools_EdgeEdge
  • Example:
    if let parts = e1.edgeEdgeIntersection(with: e2) {
        for p in parts { print(p.type, p.point) }
    }
    

edgeFaceIntersection(with:)

Intersect an edge with a face to find common vertices and edge overlaps.

public func edgeFaceIntersection(with face: Shape) -> [CommonPart]?
  • Parameters: face, face to intersect with.
  • Returns: Array of common parts, or nil on failure.
  • Warning: this currently returns an empty array for every input, including an edge that genuinely crosses the face. OCCTIntToolsEdgeFace never calls IntTools_EdgeFace::SetRange, and IntTools_Range’s default is (0, 0), so the search window is degenerate. #1631 has the measurement and the fix.
  • Note: CommonPart.param2Range is (0, 0) on this path whatever the result, see the CommonPart entry above.
  • OCCT: IntTools_EdgeFace
  • Example:
    if let parts = edge.edgeFaceIntersection(with: face) { }
    

FaceFaceCurve

An intersection curve from a face-face intersection.

public struct FaceFaceCurve: Sendable {
    public let start: SIMD3<Double>?
    public let end: SIMD3<Double>?
}

FaceFaceCurve.start

Start point of the intersection curve, or nil if the curve is unbounded.

public let start: SIMD3<Double>?

FaceFaceCurve.end

End point of the intersection curve, or nil if the curve is unbounded.

public let end: SIMD3<Double>?

FaceFacePoint

An intersection point from a face-face intersection.

public struct FaceFacePoint: Sendable {
    public let pointOnFace1: SIMD3<Double>
    public let pointOnFace2: SIMD3<Double>
}

FaceFacePoint.pointOnFace1

The coincident point’s coordinates as evaluated on the first face.

public let pointOnFace1: SIMD3<Double>

FaceFacePoint.pointOnFace2

The coincident point’s coordinates as evaluated on the second face.

public let pointOnFace2: SIMD3<Double>

FaceFaceResult

Result of a face-face intersection.

public struct FaceFaceResult: Sendable {
    public let curves: [FaceFaceCurve]
    public let points: [FaceFacePoint]
    public let isTangent: Bool
}
Field Meaning
curves Intersection curves between the two faces.
isTangent true if the two faces are tangent at the intersection rather than transversally crossing.

Shape.FaceFaceResult.isTangent


faceFaceIntersection(with:tolerance:)

Intersect two faces to find intersection curves and points.

public func faceFaceIntersection(with other: Shape, tolerance: Double = 1e-7) -> FaceFaceResult?
  • Parameters: other, second face. tolerance, approximation tolerance.
  • Returns: FaceFaceResult, or nil on failure.
  • OCCT: IntTools_FaceFace
  • Example:
    if let r = f1.faceFaceIntersection(with: f2) {
        print(r.curves.count, r.isTangent)
    }
    

classifyPoint2d(u:v:tolerance:)

Classify a UV point relative to a face boundary in parameter space.

public func classifyPoint2d(u: Double, v: Double, tolerance: Double = 1e-6) -> OCCTSwift.PointClassification

Answers the same “in/on/out of the face boundary” question as Face.classify(u:v:tolerance:) (see “Shape-Healing”) and Shape.classifyPoint2D(faceIndex:u:v:tolerance:) (see “Document-Math-Bounds”), both backed by BRepClass_FaceClassifier/BRepClass_FClassifier. This method’s default used to be 1e-7, an order of magnitude tighter than the other two’s 1e-6; aligned to 1e-6 (#840). isHole(tolerance:) below, this method’s own IntTools_FClass2d file-neighbor, keeps its 1e-7 default deliberately, it answers a different question.

  • Parameters: u/v, UV coordinates. tolerance, classification tolerance (default 1e-6).
  • Returns: .inside, .onBoundary, .outside, or .unknown.
  • OCCT: IntTools_FClass2d::Perform
  • Example:
    let c = face.classifyPoint2d(u: 0.5, v: 0.5)
    

isHole(tolerance:)

Check if a face represents a hole (inner-wire orientation).

public func isHole(tolerance: Double = 1e-7) -> Bool
  • Returns: true if the face is classified as a hole.
  • OCCT: IntTools_FClass2d (IsHole query)
  • Example:
    if face.isHole() { }
    

BOPAlgo Builder

buildFaces(from:)

Build faces from edges that lie on this face’s surface.

public func buildFaces(from edges: [Shape]) -> [Shape]?
  • Parameters: edges, edge shapes on this face’s surface.
  • Returns: Array of result face shapes, or nil on failure.
  • OCCT: BOPAlgo_BuilderFace
  • Example:
    if let faces = face.buildFaces(from: edges) { }
    

Shape.buildSolids(from:)

Build solids from a closed set of faces.

public static func buildSolids(from faces: [Shape]) -> [Shape]?
  • Parameters: faces, face shapes forming closed volumes.
  • Returns: Array of result solid shapes, or nil on failure.
  • OCCT: BOPAlgo_BuilderSolid
  • Example:
    if let solids = Shape.buildSolids(from: faces) { }
    

splitShell()

Split a shell into connected components.

public func splitShell() -> [Shape]?
  • Returns: Array of shell shapes (one per connected component), or nil on failure.
  • OCCT: BOPAlgo_ShellSplitter
  • Example:
    if let shells = shell.splitShell() { }
    

edgesToWires(tolerance:)

Connect a compound of edges into wires.

public func edgesToWires(tolerance: Double = 1e-7) -> Shape?
  • Parameters: tolerance, edge connection tolerance.
  • Returns: Compound of wires, or nil on failure.
  • OCCT: BOPAlgo_Tools::EdgesToWires
  • Example:
    if let wires = edgeCompound.edgesToWires() { }
    

wiresToFaces(tolerance:)

Build planar faces from a compound of wires.

public func wiresToFaces(tolerance: Double = 1e-7) -> Shape?
  • Parameters: tolerance, face building tolerance.
  • Returns: Compound of faces, or nil on failure.
  • OCCT: BOPAlgo_Tools::WiresToFaces
  • Example:
    if let faces = wireCompound.wiresToFaces() { }
    

BOPTools

Shape.normalOnEdge(edge:face:)

Get the normal to a face at an edge location.

public static func normalOnEdge(edge: Shape, face: Shape) -> SIMD3<Double>?
  • Parameters: edge, edge on the face. face, containing face.
  • Returns: Unit normal direction, or nil on failure.
  • OCCT: BOPTools_AlgoTools3D::GetNormalToFaceOnEdge
  • Example:
    if let n = Shape.normalOnEdge(edge: e, face: f) { }
    

pointInFace()

Find a point strictly inside this face.

public func pointInFace() -> SIMD3<Double>?
  • Returns: A 3D point in the interior of this face, or nil on failure.
  • OCCT: BOPTools_AlgoTools3D::PointInFace
  • Example:
    if let pt = face.pointInFace() { }
    

isEmpty

Check if this shape has no sub-shapes.

public var isEmpty: Bool { get }
  • OCCT: BOPTools_AlgoTools3D::IsEmptyShape
  • Example:
    if shape.isEmpty { }
    

isOpenShell

Check if this shell is open (not all edges shared by two faces).

public var isOpenShell: Bool { get }
  • OCCT: BOPTools_AlgoTools::IsOpenShell
  • Example:
    if shell.isOpenShell { }
    

IntTools_BeanFaceIntersector

BeanFaceIntersection

Result of an edge-face coincidence check.

public struct BeanFaceIntersection: Sendable {
    public let ranges: [(first: Double, last: Double)]
    public let minSquareDistance: Double
}
field meaning
ranges Coincident (first, last) parameter ranges on the edge curve where it lies on the face.
minSquareDistance Minimum squared distance between the edge curve and the face surface.

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

minSquareDistance


Shape.beanFaceIntersect(edge:face:)

Find coincident parameter ranges where an edge lies on a face surface.

public static func beanFaceIntersect(edge: Shape, face: Shape) -> BeanFaceIntersection?
  • Parameters: edge, edge curve to test. face, face surface to test against.
  • Returns: Ranges of coincidence and minimum squared distance, or nil on failure.
  • OCCT: IntTools_BeanFaceIntersector
  • Example:
    if let r = Shape.beanFaceIntersect(edge: e, face: f) {
        print(r.ranges.count, r.minSquareDistance)
    }
    

BOPAlgo_WireSplitter

Shape.makeWire(from:)

Assemble edges into a connected wire using BOPAlgo_WireSplitter.

public static func makeWire(from edges: [Shape]) -> Shape?
  • Parameters: edges, array of edge shapes to connect.
  • Returns: Result wire as shape, or nil on failure.
  • OCCT: BOPAlgo_WireSplitter::MakeWire
  • Example:
    if let wire = Shape.makeWire(from: [e1, e2, e3]) { }
    

BRepFeat_SplitShape

splitByEdge(_:onFace:)

Split this shape by adding an edge to a face.

public func splitByEdge(_ edge: Shape, onFace face: Shape) -> Shape?
  • Parameters: edge, edge to add as a split line. face, face the edge lies on.
  • Returns: Result shape with the split face, or nil on failure.
  • OCCT: BRepFeat_SplitShape
  • Example:
    if let split = solid.splitByEdge(e, onFace: face) { }
    

splitByWire(_:onFace:)

Split this shape by adding a wire to a face.

public func splitByWire(_ wire: Shape, onFace face: Shape) -> Shape?
  • Parameters: wire, wire to split along. face, face the wire lies on.
  • Returns: Result shape with split face, or nil on failure.
  • OCCT: BRepFeat_SplitShape
  • Example:
    if let split = solid.splitByWire(w, onFace: face) { }
    

SplitShapeResult

Result of a multi-pair split-shape operation.

public struct SplitShapeResult: Sendable {
    public let shape: Shape
    public let leftFaces: [Shape]
    public let rightFaces: [Shape]
}

SplitShapeResult.shape

The resulting shape after all edge-on-face pairs have been split in.

public let shape: Shape

SplitShapeResult.leftFaces

The faces BRepFeat_SplitShape::Left() classified as lying on the left side of the splitting edges.

public let leftFaces: [Shape]

SplitShapeResult.rightFaces

The faces BRepFeat_SplitShape::Right() classified as lying on the right side of the splitting edges.

public let rightFaces: [Shape]

splitWithSides(edgesOnFaces:)

Split this shape with multiple edge-on-face pairs, returning left/right face classifications.

public func splitWithSides(edgesOnFaces: [(edge: Shape, face: Shape)]) -> SplitShapeResult?
  • Parameters: edgesOnFaces, array of (edge, face) pairs; each edge is added to the corresponding face.
  • Returns: Split result with the resulting shape and left/right face arrays, or nil on failure.
  • OCCT: BRepFeat_SplitShape with Left()/Right() queries
  • Example:
    if let r = solid.splitWithSides(edgesOnFaces: [(edge: e, face: f)]) {
        print(r.leftFaces.count, r.rightFaces.count)
    }
    

BRepFeat_MakeCylindricalHole

OCCT’s dedicated feature-drilling operator. It wants a solid: every extent but .throughAll reports .invalidPlacement for a shell or a face.

This is a different contract from drilled(at:direction:radius:depth:), not a better one, #496 measured six requests where the two disagree. Reach for this family when the solid’s own faces should bound the hole, or when you need a diagnosis of why a drill is impossible; reach for drilled when the hole starts where you say it starts, when the input is not a solid, or when an over-long depth should simply drill through. Full measurements: Scripts/repro/496-drill-hole-contracts/.

radius must exceed Precision::Confusion (1e-7) for every spelling below. Under that, OCCT reports BRepFeat_NoError and hands back the undrilled input, so the bridge rejects it (#496).

CylindricalHoleExtent

How a feature-drilled hole is bounded. The five modes are not interchangeable.

public enum CylindricalHoleExtent: Sendable, Equatable {
    case throughAll
    case untilEnd
    case thruNext
    case blind(depth: Double)
    case range(from: Double, to: Double)
}
case OCCT bounded by
.throughAll Perform(R) nothing, an infinite cylinder, both ways along the axis. The origin anchors the axis; it is not where the hole starts. The only extent that tolerates a non-solid input.
.untilEnd PerformUntilEnd(R) the stock’s own first and last faces along the axis. The forward-bounded through hole most callers reach for .throughAll expecting.
.thruNext PerformThruNext(R) the next face after the origin.
.blind(depth:) PerformBlind(R, depth) depth, measured from the axis origin. The only extent that can report .holeTooLong: a depth that would leave the far side of the stock is refused rather than drilled through.
.range(from:to:) Perform(R, PFrom, PTo) the entry/exit face pair the parameter window selects.

.range is the subtle one: the window chooses a face pair, it does not trim the cut. A window lying strictly inside one body still drills all the way through that body; a window naming no face pair (the gap between two plates) is .invalidPlacement. Its use is picking which body to drill in a stack, a window over one plate drills that plate, one spanning several drills all of them.

On a stack, every extent that bounds the hole by the stock’s own faces drills every body the axis crosses: .untilEnd, a spanning .range, .throughAll and drilled(at:…) all agree. Until the kernel patch carried for #532 they did not, .untilEnd, .range and .blind(depth:) reported .noError while removing no material at all, because OCCT selected which piece of its drilling tool to keep from the cut result rather than from the split tool.

The three cases the table above covers are .thruNext, .untilEnd, .range(from:to:) and .blind(depth:); .blind bores to a fixed depth from the placement, and .range is the one whose two parameters are measured along the axis rather than from the face.

bridgeParameters (var bridgeParameters: (mode: Int32, p0: Double, p1: Double)) is internal, not public API: it is the (mode, p0, p1) triple the bridge call reads, one row per case above.


cylindricalHole(axisOrigin:axisDirection:radius:extent:)

Drill a cylindrical hole bounded by extent.

public func cylindricalHole(axisOrigin: SIMD3<Double>, axisDirection: SIMD3<Double>,
                            radius: Double, extent: CylindricalHoleExtent) -> Shape?
  • Parameters: axisOrigin, hole axis origin. axisDirection, hole axis direction, any non-zero vector. radius, hole radius, above Precision::Confusion. extent, where the hole stops.
  • Returns: Shape with hole, or nil on failure. Ask cylindricalHoleStatus(…extent:) when you need to know why; nil collapses every reason into one.
  • OCCT: BRepFeat_MakeCylindricalHole::Perform / PerformUntilEnd / PerformThruNext / PerformBlind, per extent
  • Example:
    let plate = Shape.box(width: 50, height: 50, depth: 20)!
    let origin = SIMD3<Double>(0, 0, 15)   // 5mm above the top face
    let axis = SIMD3<Double>(0, 0, -1)
    
    // Bounded by the plate's own entry and exit faces:
    let through = plate.cylindricalHole(axisOrigin: origin, axisDirection: axis,
                                        radius: 5, extent: .untilEnd)
    
    // A 6mm-deep blind hole, measured from the origin, so 1mm into the plate:
    let blind = plate.cylindricalHole(axisOrigin: origin, axisDirection: axis,
                                      radius: 5, extent: .blind(depth: 6))
    

cylindricalHoleStatus(axisOrigin:axisDirection:radius:extent:)

Ask what the matching drill would report, without building the result.

public func cylindricalHoleStatus(axisOrigin: SIMD3<Double>, axisDirection: SIMD3<Double>,
                                  radius: Double,
                                  extent: CylindricalHoleExtent) -> CylindricalHoleStatus

The extent is part of the question, because the answer depends on it: a radius wider than the whole solid is .noError for .throughAll and .invalidPlacement for .thruNext, and .holeTooLong exists only under .blind(depth:).

  • Returns: .noError if and only if cylindricalHole(…extent:) would return a shape for the same request.
  • OCCT: BRepFeat_MakeCylindricalHole::Status after the matching Perform*
  • Example:
    let origin = SIMD3<Double>(0, 0, 11), axis = SIMD3<Double>(0, 0, -1)
    if plate.cylindricalHoleStatus(axisOrigin: origin, axisDirection: axis,
                                   radius: 5, extent: .blind(depth: 100)) == .holeTooLong {
        // too deep for this stock, drill it through instead
    }
    

CylindricalHoleStatus

Status result for a cylindrical hole operation.

public enum CylindricalHoleStatus: Int32, Sendable {
    case noError = 0
    case invalidPlacement = 1
    case holeTooLong = 2
    case unknown = 3
}
  • .invalidPlacement also covers a request with no axis direction, or a radius at or below Precision::Confusion.
  • .holeTooLong is reachable only through .blind(depth:).

CylindricalHoleStatus.noError

The request is drillable.

case noError = 0

CylindricalHoleStatus.invalidPlacement

The axis does not meet the shape in a way this extent can use, including a request with no axis direction, or a radius at or below Precision::Confusion.

case invalidPlacement = 1

CylindricalHoleStatus.holeTooLong

A .blind(depth:) depth that would leave the far side of the stock. Only that extent produces this status.

case holeTooLong = 2

CylindricalHoleStatus.unknown

OCCT raised something the bridge does not recognise.

case unknown = 3

cylindricalHole(axisOrigin:axisDirection:radius:)

Drill a through cylindrical hole in this shape. Convenience for extent: .throughAll.

public func cylindricalHole(axisOrigin: SIMD3<Double>, axisDirection: SIMD3<Double>, radius: Double) -> Shape?
  • Parameters: axisOrigin, hole axis origin. axisDirection, hole axis direction. radius, hole radius.
  • Returns: Shape with hole, or nil on failure.
  • OCCT: BRepFeat_MakeCylindricalHole::Perform, an infinite cylinder both ways along the axis. For a hole bounded by the stock’s own faces, use extent: .untilEnd.
  • Example:
    if let holed = solid.cylindricalHole(axisOrigin: .zero, axisDirection: SIMD3(0,0,1), radius: 5) { }
    

cylindricalHoleBlind(axisOrigin:axisDirection:radius:depth:)

Drill a blind cylindrical hole to a specified depth. Convenience for extent: .blind(depth:).

public func cylindricalHoleBlind(axisOrigin: SIMD3<Double>, axisDirection: SIMD3<Double>, radius: Double, depth: Double) -> Shape?
  • Parameters: depth, hole depth, measured from the axis origin.
  • Returns: Shape with blind hole, or nil on failure, including a depth that would leave the far side of the stock, which is refused rather than drilled through (.holeTooLong).
  • OCCT: BRepFeat_MakeCylindricalHole::PerformBlind
  • Example:
    if let holed = solid.cylindricalHoleBlind(axisOrigin: .zero, axisDirection: SIMD3(0,0,1), radius: 5, depth: 10) { }
    

cylindricalHoleThruNext(axisOrigin:axisDirection:radius:)

Drill a cylindrical hole through to the next face encountered. Convenience for extent: .thruNext.

public func cylindricalHoleThruNext(axisOrigin: SIMD3<Double>, axisDirection: SIMD3<Double>, radius: Double) -> Shape?
  • Returns: Shape with hole stopping at the first inner face, or nil on failure.
  • OCCT: BRepFeat_MakeCylindricalHole::PerformThruNext
  • Example:
    if let holed = solid.cylindricalHoleThruNext(axisOrigin: .zero, axisDirection: SIMD3(0,1,0), radius: 3) { }
    

cylindricalHoleStatus(axisOrigin:axisDirection:radius:)

Check whether a through-all cylindrical hole can be drilled, without modifying the shape.

public func cylindricalHoleStatus(axisOrigin: SIMD3<Double>, axisDirection: SIMD3<Double>, radius: Double) -> CylindricalHoleStatus

Answers for .throughAll only. Pass the extent you are actually about to drill to cylindricalHoleStatus(…extent:): this spelling reports .noError for requests that cylindricalHoleThruNext and cylindricalHoleBlind then refuse.

  • Returns: A CylindricalHoleStatus indicating through-all feasibility.
  • OCCT: BRepFeat_MakeCylindricalHole (status query)
  • Example:
    let s = solid.cylindricalHoleStatus(axisOrigin: .zero, axisDirection: SIMD3(0,0,1), radius: 5)
    if s == .noError { }
    

BRepFeat_Gluer

glue(_:facePairs:)

Glue another shape onto this shape by binding matching face pairs.

public func glue(_ gluedShape: Shape, facePairs: [(base: Shape, glued: Shape)]) -> Shape?
  • Parameters: gluedShape, shape to merge onto this one. facePairs, matching face pairs: base from this shape, glued from gluedShape.
  • Returns: Glued result shape, or nil on failure.
  • OCCT: BRepFeat_Gluer
  • Example:
    if let r = base.glue(toAttach, facePairs: [(base: bf, glued: gf)]) { }
    

LocOpe_WiresOnShape + LocOpe_Spliter

LocOpeSplitResult

Result of a LocOpe_Spliter operation.

public struct LocOpeSplitResult: Sendable {
    public let shape: Shape
    public let directLeftFaces: [Shape]
}

LocOpeSplitResult.shape

The resulting shape after all wire-on-face pairs have been split in.

public let shape: Shape

LocOpeSplitResult.directLeftFaces

The faces LocOpe_Spliter::DirectLeft() classified as lying directly to the left of the splitting wires.

public let directLeftFaces: [Shape]

locOpeSplit(wiresOnFaces:)

Split this shape by projecting wires onto specific faces using LocOpe_Spliter.

public func locOpeSplit(wiresOnFaces: [(wire: Shape, face: Shape)]) -> LocOpeSplitResult?
  • Parameters: wiresOnFaces, pairs binding each wire to the face it lies on.
  • Returns: Split result with direct-left faces, or nil on failure.
  • OCCT: LocOpe_WiresOnShape + LocOpe_Spliter
  • Note: Each pair contributes only the first wire of its wire shape. A pair whose shape holds several wires binds one of them and ignores the rest; give each wire its own pair. A pair whose shape holds no wire at all is skipped silently. (#443 audit)
  • Example:
    if let r = solid.locOpeSplit(wiresOnFaces: [(wire: w, face: f)]) {
        print(r.directLeftFaces.count)
    }
    

locOpeSplitAuto(wires:)

Split this shape by automatically projecting wires onto faces.

public func locOpeSplitAuto(wires: [Shape]) -> Shape?
  • Parameters: wires, wires to project and split by; faces are determined automatically.
  • Returns: Result shape, or nil on failure.
  • OCCT: LocOpe_WiresOnShape::BindAll + LocOpe_Spliter
  • Example:
    if let r = solid.locOpeSplitAuto(wires: [w]) { }
    

LocOpe_Gluer

locOpeGlue(_:facePairs:edgePairs:)

Glue another shape onto this shape using LocOpe_Gluer with optional edge binding.

public func locOpeGlue(_ gluedShape: Shape,
                       facePairs: [(base: Shape, glued: Shape)],
                       edgePairs: [(base: Shape, glued: Shape)] = []) -> Shape?
  • Parameters: gluedShape, shape to glue. facePairs, at least one required matching face pair. edgePairs, optional edge pairs for precise alignment.
  • Returns: Result shape, or nil on failure (including empty facePairs).
  • OCCT: LocOpe_Gluer
  • Example:
    if let r = base.locOpeGlue(toGlue, facePairs: [(base: bf, glued: gf)]) { }
    

ChFi2d_Builder

All ChFi2d_Builder methods operate exclusively on planar faces, not solids. Extract the target face first if working from a solid.

addFillet2d(vertexIndex:radius:)

Add a 2D fillet at a vertex on a planar face.

public func addFillet2d(vertexIndex: Int, radius: Double) -> Shape?
  • Parameters: vertexIndex, 0-based vertex index. radius, fillet radius.
  • Returns: Result face with fillet, or nil if the shape is not a planar face.
  • OCCT: ChFi2d_Builder::AddFillet
  • Example:
    let face = solid.subShapes(ofType: .face)[0]
    if let filleted = face.addFillet2d(vertexIndex: 0, radius: 1.0) { }
    

addChamfer2d(edge1Index:edge2Index:d1:d2:)

Add a 2D chamfer between two edges on a planar face.

public func addChamfer2d(edge1Index: Int, edge2Index: Int, d1: Double, d2: Double) -> Shape?
  • Parameters: edge1Index/edge2Index, 0-based edge indices. d1/d2, chamfer distances on each edge.
  • Returns: Result face with chamfer, or nil on failure.
  • OCCT: ChFi2d_Builder::AddChamfer
  • Example:
    if let ch = face.addChamfer2d(edge1Index: 0, edge2Index: 1, d1: 1.0, d2: 1.0) { }
    

addChamfer2dAngle(edgeIndex:vertexIndex:distance:angle:)

Add a 2D chamfer defined by distance and angle on a planar face.

public func addChamfer2dAngle(edgeIndex: Int, vertexIndex: Int, distance: Double, angle: Double) -> Shape?
  • Parameters: edgeIndex, reference edge. vertexIndex, vertex to chamfer. distance, distance on the edge. angle, chamfer angle in radians.
  • Returns: Result face with chamfer, or nil on failure.
  • OCCT: ChFi2d_Builder::AddChamfer (distance + angle)
  • Example:
    if let ch = face.addChamfer2dAngle(edgeIndex: 0, vertexIndex: 1, distance: 1.0, angle: .pi/4) { }
    

modifyFillet2d(originalFace:filletEdgeIndex:newRadius:)

Modify an existing fillet radius on a face.

public func modifyFillet2d(originalFace: Shape, filletEdgeIndex: Int, newRadius: Double) -> Shape?
  • Parameters: originalFace, face before the fillet was added. filletEdgeIndex, 0-based index of the fillet edge in self. newRadius, new fillet radius.
  • Returns: Result face with modified fillet, or nil on failure.
  • OCCT: ChFi2d_Builder::ModifyFillet
  • Example:
    if let modified = filletedFace.modifyFillet2d(originalFace: original, filletEdgeIndex: 0, newRadius: 2.0) { }
    

removeFillet2d(originalFace:filletEdgeIndex:)

Remove a fillet from a face, restoring the original corner.

public func removeFillet2d(originalFace: Shape, filletEdgeIndex: Int) -> Shape?
  • Parameters: originalFace, face before the fillet. filletEdgeIndex, 0-based fillet edge index in self.
  • Returns: Face with fillet removed, or nil on failure.
  • OCCT: ChFi2d_Builder::RemoveFillet
  • Example:
    if let r = filletedFace.removeFillet2d(originalFace: original, filletEdgeIndex: 0) { }
    

removeChamfer2d(originalFace:chamferEdgeIndex:)

Remove a chamfer from a face.

public func removeChamfer2d(originalFace: Shape, chamferEdgeIndex: Int) -> Shape?
  • Parameters: originalFace, face before the chamfer. chamferEdgeIndex, 0-based chamfer edge index in self.
  • Returns: Face with chamfer removed, or nil on failure.
  • OCCT: ChFi2d_Builder::RemoveChamfer
  • Example:
    if let r = chamferedFace.removeChamfer2d(originalFace: original, chamferEdgeIndex: 0) { }
    

ChFi2d_ChamferAPI

Chamfer2DEdgeResult

Result of a standalone 2D chamfer between two edges.

public struct Chamfer2DEdgeResult: Sendable {
    public let chamferEdge: Shape
    public let modifiedEdge1: Shape
    public let modifiedEdge2: Shape
}

Chamfer2DEdgeResult.chamferEdge

The new chamfer edge connecting the two trimmed originals.

public let chamferEdge: Shape

Chamfer2DEdgeResult.modifiedEdge1

edge1, trimmed back by d1 to meet the chamfer edge.

public let modifiedEdge1: Shape

Chamfer2DEdgeResult.modifiedEdge2

edge2, trimmed back by d2 to meet the chamfer edge.

public let modifiedEdge2: Shape

Shape.chamfer2dEdges(edge1:edge2:d1:d2:)

Create a chamfer between two linear edges using ChFi2d_ChamferAPI.

public static func chamfer2dEdges(edge1: Shape, edge2: Shape, d1: Double, d2: Double) -> Chamfer2DEdgeResult?
  • Parameters: edge1/edge2, linear edges sharing a vertex. d1/d2, chamfer distances on each edge.
  • Returns: Chamfer2DEdgeResult with chamfer edge and trimmed originals, or nil on failure.
  • OCCT: ChFi2d_ChamferAPI
  • Example:
    if let r = Shape.chamfer2dEdges(edge1: e1, edge2: e2, d1: 1.0, d2: 1.0) {
        let chamfer = r.chamferEdge
    }
    

ChFi2d_FilletAPI

Fillet2DEdgeResult

Result of a standalone 2D fillet between two edges.

public struct Fillet2DEdgeResult: Sendable {
    public let filletEdge: Shape
    public let modifiedEdge1: Shape
    public let modifiedEdge2: Shape
    public let solutionCount: Int
}
Field Meaning
filletEdge The new fillet arc edge.
modifiedEdge1 edge1, trimmed to meet the fillet arc.
modifiedEdge2 edge2, trimmed to meet the fillet arc.

Shape.Fillet2DEdgeResult.modifiedEdge2


Shape.fillet2dEdges(edge1:edge2:planeOrigin:planeNormal:radius:nearPoint:)

Create a fillet between two edges in a plane using ChFi2d_FilletAPI.

public static func fillet2dEdges(edge1: Shape, edge2: Shape,
                                 planeOrigin: SIMD3<Double> = .zero,
                                 planeNormal: SIMD3<Double>,
                                 radius: Double,
                                 nearPoint: SIMD3<Double>) -> Fillet2DEdgeResult?
  • Parameters: edge1/edge2, edges to fillet. planeOrigin, a point on the plane containing the edges (defaults to the world origin; must match the edges’ actual plane for edges not passing through (0,0,0), #1459). planeNormal, normal of the plane containing the edges. radius, fillet radius. nearPoint, point near the desired fillet location, used to select among multiple solutions.
  • Returns: Fillet2DEdgeResult with the fillet arc, trimmed edges, and solution count, or nil on failure.
  • OCCT: ChFi2d_FilletAPI (selects analytical or iterative algorithm automatically)
  • Example:
    if let r = Shape.fillet2dEdges(
        edge1: e1, edge2: e2,
        planeOrigin: SIMD3(0, 0, 0),
        planeNormal: SIMD3(0, 0, 1),
        radius: 2.0,
        nearPoint: SIMD3(1, 1, 0)) {
        print(r.solutionCount)
    }
    

FilletSurf_Builder

FilletSurfaceInfo

Geometry information for one computed fillet surface.

public struct FilletSurfaceInfo: Sendable {
    public let surface: Surface
    public let supportFace1: Shape
    public let supportFace2: Shape
    public let tolerance: Double
    public let firstParameter: Double
    public let lastParameter: Double
    public let startStatus: Int
    public let endStatus: Int
}
Field Meaning
supportFace1 The first of the two original faces this fillet surface blends between.
supportFace2 The second of the two original faces this fillet surface blends between.
tolerance Geometric tolerance achieved for this fillet surface.
firstParameter The fillet’s parameter on the first edge of the whole request, not a per-surface value; see the note below.
lastParameter The fillet’s parameter on the last edge of the whole request; per request, not per surface, for the same reason.
startStatus Where the fillet’s start section sits relative to the edge it was built on: both extremities on the edge (0), one extremity on the edge (1), or neither (2); see the note below.
endStatus The same scale at the fillet’s end section.

firstParameter and lastParameter come from FilletSurf_Builder::FirstParameter() and LastParameter(), which take no surface index. They are the fillet’s parameters on the first and last edge of the whole request, and this struct repeats the same pair into every element rather than measuring one per surface.

startStatus/endStatus come from FilletSurf_Builder::StartSectionStatus() and EndSectionStatus(), whose enum is FilletSurf_StatusType (0 = FilletSurf_TwoExtremityOnEdge, 1 = FilletSurf_OneExtremityOnEdge, 2 = FilletSurf_NoExtremityOnEdge). They are not on FilletSurfaceResult.status’s scale, and reading them as if they were is a silent misread rather than an error: that field carries FilletSurf_StatusDone (0 = ok, 1 = not ok, 2 = partial). The two enums are unrelated and share the ordinals 0...2. This table described both as the ok/not-ok/partial scale until #1399 measured the ordinals against the pinned FilletSurf_StatusType.hxx (Scripts/repro/1399-refman-coverage-unlaned/probe-transcript.txt).

Shape.FilletSurfaceInfo.endStatus


FilletSurfaceResult

Result of FilletSurf_Builder computation.

public struct FilletSurfaceResult: Sendable {
    public let surfaces: [FilletSurfaceInfo]
    public let status: Int  // 0=ok, 1=notOk, 2=partial
}
Field Meaning
surfaces One FilletSurfaceInfo per requested edge that produced a fillet surface.
status Overall outcome of the whole computation: 0 = ok, 1 = not ok, 2 = partial.

That is FilletSurf_Builder::IsDone()’s FilletSurf_StatusDone, and it is unrelated to FilletSurfaceInfo.startStatus/endStatus, which carry FilletSurf_StatusType on the same ordinals.

Shape.FilletSurfaceResult.surfaces


filletSurfaces(edges:radius:)

Compute fillet surface geometry on this shape without modifying its topology.

public func filletSurfaces(edges: [Shape], radius: Double) -> FilletSurfaceResult?
  • Parameters: edges, edges to fillet. radius, fillet radius.
  • Returns: FilletSurfaceResult with NURBS fillet surfaces and support faces, or nil on total failure. status == 1 with an empty surfaces array also maps to nil.
  • OCCT: FilletSurf_Builder
  • Note: Returns raw surface geometry only; does not produce a new solid. Use Shape.filleted(edges:radius:) to produce a filleted solid.
  • Example:
    if let r = solid.filletSurfaces(edges: [e1, e2], radius: 1.0) {
        for info in r.surfaces {
            print(info.surface, info.tolerance)
        }
    }