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 · GeomFill_EvolvedSection · ProjLib_ComputeApprox · BRepOffset_Offset · Adaptor3d_IsoCurve · ShapeAnalysis_TransferParametersProj · BOPAlgo_RemoveFeatures · BOPAlgo_Section · ShapeBuild_Edge · ShapeBuild_Vertex · ShapeExtend_Explorer · ShapeUpgrade_FaceDivide · ShapeUpgrade_WireDivide · ShapeUpgrade_EdgeDivide · ShapeUpgrade_ClosedEdgeDivide · ShapeUpgrade_FixSmallCurves · ShapeUpgrade_FixSmallBezierCurves · ShapeUpgrade_ConvertCurve3dToBezier · ShapeUpgrade_ConvertSurfaceToBezierBasis · 2D Vector/Direction Utilities & LProp · TopTrans Surface Transition · TopTrans Curve Transition · GeomFill Trihedrons · Polygon Interference · GccAna_Circ2d3Tan · IntTools · BOPAlgo Builder · BOPTools · IntTools_BeanFaceIntersector · BOPAlgo_WireSplitter · BRepFeat_SplitShape · BRepFeat_MakeCylindricalHole · BRepFeat_Gluer · LocOpe_WiresOnShape + LocOpe_Spliter · LocOpe_Gluer · ChFi2d_Builder · ChFi2d_ChamferAPI · ChFi2d_FilletAPI · FilletSurf_Builder
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
Shapewrapping the swept face, ornilon failure, including whenGeomFill_Sweepfits the surface but misses its own 1e-4 tolerance (ErrorOnSurface()); a surface reportedIsDone()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:
EvolvedSectionInfowithnbPoles,nbKnots,degree, andisRational. - 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
nilon 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
nilon 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
nilon 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 within1...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(iso kind 0 = U) - 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 within1...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(iso kind 1 = V) - 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
nilon failure. - OCCT:
Adaptor3d_IsoCurve - 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
nilon failure. - OCCT:
Adaptor3d_IsoCurve - 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
nilon 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
nilon 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— iftrue, the copy shares PCurves with the original edge. - Returns: Copied edge as shape, or
nilon 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, ornilto keep original.endVertex— new end vertex, ornilto keep original. - Returns: Edge with replaced vertices, or
nilon 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:
trueif 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:
trueif 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
nilon 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
nilon 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 enum ShapeFilterType: Int32, Sendable {
case compound = 0, compsolid = 1, solid = 2, shell = 3
case face = 4, wire = 5, edge = 6, vertex = 7
}
Matches TopAbs_ShapeEnum values used by ShapeExtend_Explorer.
ShapeFilterType.compsolid
A compound solid: several solids sharing faces, treated as a single connected shape (TopAbs_COMPSOLID).
case compsolid = 1
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— iftrue, recurse into sub-compounds. - Returns: Compound of matching sub-shapes, or
nilon 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— iftrue, inspect sub-compounds. - Returns: The most-common
ShapeFilterTypefound. - 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
nilon 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
nilon 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
nilon 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:
trueif the edge is closed and divisible. - OCCT:
ShapeUpgrade_ClosedEdgeDivide::Compute - Example:
if edge.canDivideClosedEdge(onFace: face) { }
ShapeUpgrade_FixSmallCurves
fixSmallCurves(tolerance:)
Fix small curves in this shape.
public func fixSmallCurves(tolerance: Double = 1e-6) -> Shape?
- Parameters:
tolerance— threshold below which curves are considered small. - Returns: Fixed shape, or
nilon failure. - OCCT:
ShapeUpgrade_FixSmallCurves - Example:
if let fixed = shape.fixSmallCurves() { }
ShapeUpgrade_FixSmallBezierCurves
fixSmallBezierCurves(tolerance:)
Fix small Bezier curves in this shape.
public func fixSmallBezierCurves(tolerance: Double = 1e-6) -> Shape?
- Parameters:
tolerance— detection threshold. - Returns: Fixed shape, or
nilon failure. - OCCT:
ShapeUpgrade_FixSmallBezierCurves - Example:
if let fixed = shape.fixSmallBezierCurves() { }
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
nilon failure. - OCCT:
ShapeUpgrade_ConvertCurve3dToBezier - 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
nilon failure. - OCCT:
ShapeUpgrade_ConvertSurfaceToBezierBasis - 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:
gp_Vec2d::Crossed - 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:
gp_Vec2d::Dot - 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:
gp_Vec2d::Magnitude - 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:
gp_Vec2d::Normalized - 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_Dir2dconstructor (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 curvature special points (inflections, min/max curvature) for an analytic curve type.
public static func analyticCurvaturePoints(curveType: Int32, first: Double,
last: Double) -> [CurvatureSpecialPoint]
- Parameters:
curveType— 0=Line, 1=Circle, 2=Ellipse, 3=Hyperbola, 4=Parabola.first/last— parameter domain. - Returns: Array of special points; empty if none found.
- OCCT:
LProp_AnalyticCurInf - 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:
SurfaceTransitionResultwith 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:
SurfaceTransitionResultwith 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
nilif 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
nilon 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
nilon 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>]
}
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:
PolygonIntersectionwith 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,circleTangentCircle2PointsorcircleThrough3Pointsto 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:
circleRadiusmust 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, wherecircleThrough3Pointson 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. |
point | Representative 3D point of the intersection. |
(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
nilif 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
nilon failure. - 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, ornilon 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-7) -> OCCTSwift.PointClassification
- Parameters:
u/v— UV coordinates.tolerance— classification tolerance. - 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:
trueif 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
nilon 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
nilon 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
nilon 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
nilon 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
nilon 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
nilon 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
nilon 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
nilon 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
nilon 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
nilon 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
nilon 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
nilon failure. - OCCT:
BRepFeat_SplitShapewithLeft()/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, abovePrecision::Confusion.extent— where the hole stops. - Returns: Shape with hole, or
nilon failure. AskcylindricalHoleStatus(…extent:)when you need to know why;nilcollapses every reason into one. - OCCT:
BRepFeat_MakeCylindricalHole::Perform/PerformUntilEnd/PerformThruNext/PerformBlind, perextent - 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:
.noErrorif and only ifcylindricalHole(…extent:)would return a shape for the same request. - OCCT:
BRepFeat_MakeCylindricalHole::Statusafter the matchingPerform* - 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
}
.invalidPlacementalso covers a request with no axis direction, or a radius at or belowPrecision::Confusion..holeTooLongis 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
nilon failure. - OCCT:
BRepFeat_MakeCylindricalHole::Perform— an infinite cylinder both ways along the axis. For a hole bounded by the stock’s own faces, useextent: .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
nilon failure — including adepththat 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
nilon 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
CylindricalHoleStatusindicating 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:basefrom this shape,gluedfromgluedShape. - Returns: Glued result shape, or
nilon 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
nilon failure. - OCCT:
LocOpe_WiresOnShape+LocOpe_Spliter - Note: Each pair contributes only the first wire of its
wireshape. 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
nilon 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
nilon failure (including emptyfacePairs). - 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
nilif 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
nilon 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
nilon 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 inself.newRadius— new fillet radius. - Returns: Result face with modified fillet, or
nilon 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 inself. - Returns: Face with fillet removed, or
nilon 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 inself. - Returns: Face with chamfer removed, or
nilon 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:
Chamfer2DEdgeResultwith chamfer edge and trimmed originals, ornilon 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:planeNormal:radius:nearPoint:)
Create a fillet between two edges in a plane using ChFi2d_FilletAPI.
public static func fillet2dEdges(edge1: Shape, edge2: Shape,
planeNormal: SIMD3<Double>,
radius: Double,
nearPoint: SIMD3<Double>) -> Fillet2DEdgeResult?
- Parameters:
edge1/edge2— edges to fillet.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:
Fillet2DEdgeResultwith the fillet arc, trimmed edges, and solution count, ornilon failure. - OCCT:
ChFi2d_FilletAPI(selects analytical or iterative algorithm automatically) - Example:
if let r = Shape.fillet2dEdges( edge1: e1, edge2: e2, 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. |
startStatus | FilletSurf_Builder status code at the fillet’s start extremity (0 = ok, 1 = not ok, 2 = partial). |
endStatus | FilletSurf_Builder status code at the fillet’s end extremity (0 = ok, 1 = not ok, 2 = partial). |
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. |
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:
FilletSurfaceResultwith NURBS fillet surfaces and support faces, ornilon total failure.status == 1with an emptysurfacesarray also maps tonil. - 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) } }