Edge
An Edge is a bounded curve in 3D space — the Swift analog of OCCT’s TopoDS_Edge. Edges are the one-dimensional elements of B-Rep topology: each edge carries a Geom_Curve trimmed to a parameter range, and connects two vertices. Obtain edges by calling shape.edges(), shape.edge(at:), or by constructing a Wire and extracting via wire.edges().
Topics
- Initializers · Properties · 3D Curve Properties · Sampling · Shape Extension for Edge Access · Edge Analysis · Curve Approximation · Edge Splitting · PCurve / BRepAdaptor_Curve2d
Initializers
Edge.init?(_ shape:)
Constructs an Edge by extracting the edge topology from a Shape. Returns nil if shape is null or wraps a non-edge topology type.
public convenience init?(_ shape: Shape)
Use when you have an edge-typed Shape (e.g. from sub-shape iteration) and need the typed Edge object.
- Parameters:
shape— aShapewrapping aTopoDS_Edge. - Returns:
nilifshapeis null or its topology type is notTopAbs_EDGE. - OCCT:
TopoDS::Edge— casts the underlyingTopoDS_Shapeafter checkingShapeType() == TopAbs_EDGE. - Example:
let shapes = box.subShapes(ofType: .edge) if let edge = Edge(shapes[0]) { print(edge.length) }
Properties
index
The index of this edge within the parent shape, or -1 if the edge was created standalone.
public let index: Int
Reflects the 0-based position at which shape.edge(at:) returned this edge. Set to -1 for edges obtained via Edge(_ shape:).
- Example:
let edge = box.edge(at: 3)! print(edge.index) // 3
length
The arc length of the edge.
public var length: Double { get }
- Returns: Length in model units. Returns
0for degenerate or null edges. - OCCT:
BRepGProp::LinearProperties— computes linear mass (= arc length) of the edge. - Example:
let box = Shape.box(width: 10, height: 10, depth: 10)! let edge = box.edge(at: 0)! print(edge.length) // 10.0
bounds
The axis-aligned bounding box of the edge.
public var bounds: (min: SIMD3<Double>, max: SIMD3<Double>) { get }
- Returns: Tuple of the AABB min and max corners. Returns
(.zero, .zero)on failure. - OCCT:
BRepBndLib::Add+Bnd_Box::Get. - Example:
let b = box.edge(at: 0)!.bounds // b.min and b.max define the bounding box of that edge
isLine
Whether this edge’s underlying curve is a straight line.
public var isLine: Bool { get }
- OCCT:
BRepAdaptor_Curve::GetType()compared toGeomAbs_Line. - Example:
let box = Shape.box(width: 10, height: 10, depth: 10)! let hasLines = box.edges().contains(where: \.isLine)
isCircle
Whether this edge’s underlying curve is a full or partial circle.
public var isCircle: Bool { get }
- OCCT:
BRepAdaptor_Curve::GetType()compared toGeomAbs_Circle. - Example:
let cyl = Shape.cylinder(radius: 5, height: 10)! let circEdge = cyl.edges().first(where: \.isCircle)
endpoints
The start and end 3D points of the edge (its bounding vertices).
public var endpoints: (start: SIMD3<Double>, end: SIMD3<Double>) { get }
Extracts the vertex positions using TopExp::Vertices. Returns (.zero, .zero) on failure (e.g. degenerate edge with no vertices).
- Returns: Tuple of the edge’s start and end vertex positions.
- OCCT:
TopExp::Vertices+BRep_Tool::Pnt. - Example:
let ep = box.edge(at: 0)!.endpoints print(ep.start, ep.end)
3D Curve Properties
Properties and methods in this section provide parametric access to the edge’s underlying Geom_Curve. Parameters are native OCCT curve parameters (not normalised to [0, 1]); query parameterBounds first.
CurveType
Curve type classification for an edge’s underlying geometry.
public enum CurveType: Int32, Sendable {
case line = 0, circle = 1, ellipse = 2, hyperbola = 3, parabola = 4
case bezierCurve = 5, bsplineCurve = 6, offsetCurve = 7, other = 8
}
Matches GeomAbs_CurveType values from BRepAdaptor_Curve. Use curveType to distinguish geometric type before calling type-specific accessors.
| case | meaning |
|---|---|
.line | Geom_Line, a straight line. |
.circle | Geom_Circle, a circular arc. |
.ellipse | Geom_Ellipse. |
.hyperbola | Geom_Hyperbola. |
.parabola | Geom_Parabola. |
.bezierCurve | Geom_BezierCurve. |
.bsplineCurve | Geom_BSplineCurve. |
.offsetCurve | Geom_OffsetCurve. |
.other | Unrecognised or null curve. |
(Per-case anchors below, for cross-reference; the table above has the actual meaning of each.)
other
CurveProjection
Result of projecting a point onto an edge’s curve.
public struct CurveProjection: Sendable {
public let point: SIMD3<Double>
public let parameter: Double
public let distance: Double
}
point— closest point on the curve.parameter— native curve parameter at the closest point.distance— Euclidean distance from the query point topoint.
parameterBounds
The native OCCT parameter range [first, last] for this edge’s underlying curve.
public var parameterBounds: (first: Double, last: Double)? { get }
Required before calling any at parameter: method — OCCT parameters are not normalised. For a line of length 10 starting at the origin, first ≈ 0 and last ≈ 10.
- Returns:
(first, last)parameter tuple, ornilif the edge has no 3D curve. - OCCT:
BRep_Tool::Curve— returns the handle and its parameter range. - Example:
let box = Shape.box(width: 10, height: 10, depth: 10)! let edge = box.edge(at: 0)! if let b = edge.parameterBounds { let mid = (b.first + b.last) / 2.0 let pt = edge.point(at: mid) }
curveType
The geometric type of this edge’s curve.
public var curveType: CurveType { get }
- Returns: One of
CurveType’s cases. Returns.otherfor unknown or null curves. - OCCT:
BRepAdaptor_Curve::GetType(). - Example:
for edge in shape.edges() { if edge.curveType == .circle { // handle circular edges } }
point(at:)
Returns the 3D position on the edge’s curve at a native OCCT parameter.
public func point(at parameter: Double) -> SIMD3<Double>?
- Parameters:
parameter— a value in[parameterBounds.first, parameterBounds.last]. - Returns: 3D point, or
nilif the edge has no curve or the parameter is out of domain. - OCCT:
BRep_Tool::Curve→Geom_Curve::D0. - Example:
let edge = cyl.edges().first(where: \.isCircle)! if let b = edge.parameterBounds { let mid = (b.first + b.last) / 2.0 let pt = edge.point(at: mid) }
curvature(at:)
Returns the curvature (1/radius) of the edge’s curve at a native parameter.
public func curvature(at parameter: Double) -> Double?
A straight line has curvature 0; a circle of radius R has curvature 1/R.
- Parameters:
parameter— native curve parameter. - Returns: Curvature ≥ 0, or
nilif the tangent is undefined or the edge has no curve. - OCCT:
BRep_Tool::Curve→GeomLProp_CLProps::Curvature. - Example:
let radius = 5.0 let cyl = Shape.cylinder(radius: radius, height: 10)! if let edge = cyl.edges().first(where: \.isCircle), let b = edge.parameterBounds { let curv = edge.curvature(at: (b.first + b.last) / 2.0) // curv ≈ 0.2 (1/5) }
tangent(at:)
Returns the unit tangent vector at a native curve parameter.
public func tangent(at parameter: Double) -> SIMD3<Double>?
- Parameters:
parameter— native curve parameter. - Returns: Unit tangent vector in the direction of increasing parameter, or
nilif undefined. - OCCT:
BRep_Tool::Curve→GeomLProp_CLProps::Tangent. - Example:
let box = Shape.box(width: 10, height: 10, depth: 10)! if let edge = box.edges().first(where: \.isLine), let b = edge.parameterBounds { let t = edge.tangent(at: (b.first + b.last) / 2.0) }
normal(at:)
Returns the principal normal direction at a native curve parameter.
public func normal(at parameter: Double) -> SIMD3<Double>?
The principal normal points toward the centre of curvature. For straight edges, curvature is zero and the normal is undefined.
- Parameters:
parameter— native curve parameter. - Returns: Unit normal vector, or
nilif the curvature is zero or the tangent is undefined. - OCCT:
BRep_Tool::Curve→GeomLProp_CLProps::Normal. - Example:
if let edge = cyl.edges().first(where: \.isCircle), let b = edge.parameterBounds { let n = edge.normal(at: (b.first + b.last) / 2.0) }
centerOfCurvature(at:)
Returns the centre of curvature at a native curve parameter.
public func centerOfCurvature(at parameter: Double) -> SIMD3<Double>?
The centre of curvature lies on the principal normal at distance 1/κ from the curve point. Undefined (returns nil) for zero-curvature (straight) segments.
- Parameters:
parameter— native curve parameter. - Returns: 3D centre of curvature, or
nilif curvature is zero or computation fails. - OCCT:
BRep_Tool::Curve→GeomLProp_CLProps::CentreOfCurvature. - Example:
if let edge = cyl.edges().first(where: \.isCircle), let b = edge.parameterBounds { let cc = edge.centerOfCurvature(at: b.first) // cc is the circle centre }
torsion(at:)
Returns the torsion of the edge’s curve at a native parameter.
public func torsion(at parameter: Double) -> Double?
Torsion measures the rate at which the osculating plane twists. Zero for planar curves (lines, circles, arcs). Non-zero for space curves (helices, general B-splines).
- Parameters:
parameter— native curve parameter. - Returns: Torsion value (can be negative), or
nilif computation fails. Returns0.0for degenerate (zero-curvature cross-product) configurations. -
OCCT: Geom_Curve::D3— uses the formula τ = (d1 × d2) · d3 /d1 × d2 ². - Example:
// A helix has non-zero torsion if let helix = Wire.helix(radius: 5, pitch: 2, turns: 3), let shape = Shape.fromWire(helix) { let edges = shape.edges() if let edge = edges.first, let b = edge.parameterBounds { let tau = edge.torsion(at: b.first) } }
project(point:)
Projects a 3D point onto this edge’s curve, returning the closest point.
public func project(point: SIMD3<Double>) -> CurveProjection?
The answer is always inside the edge’s own parameter range (parameterBounds), and always the true nearest point. Where the query point has no perpendicular foot on the edge, the nearest point is one of its ends, and that is what comes back.
- Parameters:
point— query point in 3D space. - Returns:
CurveProjectionwith the closest point, its parameter, and the distance; ornilonly for an edge with no 3D curve to project onto. - OCCT:
BRep_Tool::Curve, thenShapeAnalysis_Curve::ProjectandGeomAPI_ProjectPointOnCurveminimised together with the range’s ends — no one of the three is correct alone (#539). SharesCurve3D.projectPoint(_:precision:)’s implementation. - Example:
let box = Shape.box(width: 10, height: 10, depth: 10)! if let edge = box.edges().first(where: \.isLine) { let ep = edge.endpoints let mid = (ep.start + ep.end) / 2.0 if let proj = edge.project(point: mid + SIMD3(1, 1, 1)) { print(proj.distance) // ≈ √3 } } // Past the end: the end of the edge, rather than nil. let edge = Wire.line(from: SIMD3(3, 0, 0), to: SIMD3(8, 0, 0))!.edges()[0] if let proj = edge.project(point: SIMD3(100, 0, 0)) { print(proj.point) // SIMD3(8, 0, 0) print(proj.distance) // 92.0 }
Before #539 the bare
GeomAPI_ProjectPointOnCurvebehind this returned extrema rather than minima, which cost it two ways: it returnednilwhenever the nearest point was an end rather than a perpendicular foot (the case above), and on an arc it could report the far side as the nearest point — 11 for a query whose nearest point on a half circle is 7.81 away.
distance(to:)
The shortest distance from a 3D point to this edge.
public func distance(to point: SIMD3<Double>) -> Double?
Pure-Swift convenience — delegates to project(point:)?.distance, so it measures to the same nearest point: over the edge’s own parameter range, ends included.
- Parameters:
point— query point. - Returns: Distance to the nearest point on the edge, or
nilonly for an edge with no 3D curve. - OCCT: Delegates to
project(point:), and inherits its #539 fix. - Example:
if let d = edge.distance(to: SIMD3(5, 5, 5)) { print("Distance to edge: \(d)") }
curve3D
The 3D curve underlying this edge as a standalone Curve3D.
public var curve3D: Curve3D? { get }
Returns a Geom_TrimmedCurve wrapping the edge’s geometry, trimmed to the edge’s parameter range. Returns nil for edges with no 3D curve representation (rare — typically pcurve-only edges before BuildCurves3d).
Use cases include extracting CircleProperties from a circular edge, emitting native DXF entities, or feeding edge geometry into parametric analysis pipelines.
- Returns:
Curve3Dwrapping aGeom_TrimmedCurve, ornilif no 3D curve exists. - OCCT:
BRepLib::BuildCurves3d+BRep_Tool::Curve. - Example:
if let edge = cyl.edges().first(where: \.isCircle), let curve = edge.curve3D { let props = curve.circleProperties }
Sampling
points(count:)
Returns uniformly-sampled points along the edge curve.
public func points(count: Int? = nil) -> [SIMD3<Double>]
When count is nil, automatically computes a point count at approximately 0.5 model-unit spacing (max(2, Int(length / 0.5) + 1)). Points are evenly spaced in the OCCT parameter domain (not arc-length).
- Parameters:
count— number of points to generate;nil= automatic (~0.5 mm spacing). A request: honoured within2...Sampling.maximumSampleCount(10,000,000); outside that range the result is empty (#558). The automatic default is bounded the same way, since a long enough edge implies more points at 0.5 mm than the ceiling can serve. - Returns: Array of 3D points; empty on failure or for degenerate edges.
- OCCT:
BRepAdaptor_Curve::Value— samples at uniformly-spaced parameter values. - Example:
let cyl = Shape.cylinder(radius: 5, height: 10)! if let circEdge = cyl.edges().first(where: \.isCircle) { let pts = circEdge.points(count: 32) // pts has 32 points around the circle }
Shape Extension for Edge Access
These members are declared on Shape in Edge.swift and provide indexed access to all edges in a shape.
edgeCount
The number of distinct edges in the shape: the same TopExp::MapShapes enumeration edges()/edge(at:) walk.
public var edgeCount: Int { get }
An edge reachable from two adjacent faces is counted once, not once per face. See edges() below for the identity rule and why it needs no orientation-preserving counterpart.
- OCCT:
TopExp::MapShapes(shape, TopAbs_EDGE, map)→map.Extent()viaTopTools_IndexedMapOfShape. - Example:
let box = Shape.box(width: 10, height: 10, depth: 10)! print(box.edgeCount) // 12 - Former second spelling:
Shape.nbEdgesasked this same question, backed by a bareTopExp_Exploreroccurrence count (24 on this same box) instead of this deduplicated one; deprecated as a forward here in #651 and removed at v2.0.0 (#784).
edge(at:)
Returns the edge at a given 0-based index.
public func edge(at index: Int) -> Edge?
- Parameters:
index— 0-based edge index. - Returns:
Edgeat the given index, ornilif the index is out of range. - OCCT:
TopExp::MapShapes+TopoDS::Edge— extracts fromTopTools_IndexedMapOfShape(1-based internally; index is adjusted). - Example:
let box = Shape.box(width: 10, height: 10, depth: 10)! if let edge = box.edge(at: 0) { print(edge.length) }
edges()
Returns all edges from the shape as typed Edge objects.
public func edges() -> [Edge]
Iterates edge(at:) from 0 to edgeCount - 1. The order matches edgeCount / edge(at:), i.e., TopTools_IndexedMapOfShape traversal order, which can vary between runs.
Identity, not orientation. Edges are distinguished the way OCCT distinguishes them for an index: by TopoDS_Shape::IsSame, which compares the underlying curve and placement and ignores orientation. An edge reachable from two owners, the ordinary case of any two adjacent faces on one solid, collapses to a single entry here, carrying whichever orientation was reached first:
let box = Shape.box(width: 10, height: 10, depth: 10)!
print(box.edges().count) // 12: the distinct, addressable edges
print(box.contents.edges) // 24: one per (face, edge) visit, ShapeAnalysis_ShapeContents
Unlike Shape.faces(), this collapse is not a defect (#638). #614 made faces()’s equivalent collapse a bug because Face.normal(atU:v:) reverses on TopAbs_REVERSED, so a face’s stored orientation changes the answer it returns. Edge has no such consumer: it exposes no .orientation accessor at all, and every geometric query on it (tangent(at:), point(at:), parameterBounds, curvature(at:)) reads the edge’s underlying Geom_Curve through BRep_Tool::Curve, which is defined independently of TopAbs_Orientation. A bridge-wide audit (grep -rn "\.Orientation() ==" across Sources/OCCTBridge/src/*.mm) found 14 branching sites: 13 are face-normal logic faces()/orientedFaces() already cover, and the fourteenth (occtSampleWirePoints, OCCTBridge_Modeling.mm) reads orientation fresh off a BRepTools_WireExplorer walk of the wire it samples, not from an edge this method returns. So there is currently no orientedEdges() counterpart to edges(): nothing needs one. See Scripts/repro/cluster-a-subshape-enumeration/ for the full census this rests on.
- Returns: Array of all
Edgeobjects; empty if the shape has no edges. - OCCT:
TopExp::MapShapes(shape, TopAbs_EDGE), collects all edges via indexed map. - Example:
let box = Shape.box(width: 10, height: 10, depth: 10)! let edges = box.edges() // edges.count == 12 for edge in edges { if edge.isLine { print(edge.length) } } - Note: Edge indices may vary across runs — iterate edges to find a specific one rather than relying on a fixed index.
Edge Analysis
hasCurve3D
Whether this edge has an underlying 3D curve.
public var hasCurve3D: Bool { get }
- OCCT:
ShapeAnalysis_Edge::HasCurve3d. - Example:
for edge in shape.edges() { if edge.hasCurve3D { let curve = edge.curve3D } }
isClosed3D
Whether this edge is closed — i.e., its start and end vertices coincide.
public var isClosed3D: Bool { get }
Closed edges appear as the single circular edge of a cylinder face.
- OCCT:
ShapeAnalysis_Edge::IsClosed3d. - Example:
let cyl = Shape.cylinder(radius: 5, height: 10)! let hasClosedEdge = cyl.edges().contains(where: \.isClosed3D) // hasClosedEdge == true (the circular top/bottom edges)
isSeam(on:)
Whether this edge is a seam edge on the given face.
public func isSeam(on face: Face) -> Bool
A seam edge appears twice on a face with different orientations — e.g., the seam line on a cylindrical face where the surface wraps around. Relevant for surface parameterisation and UV-space computations.
- Parameters:
face— the face to test against. - Returns:
trueif the edge is a seam onface. - OCCT:
ShapeAnalysis_Edge::IsSeam. - Example:
let cyl = Shape.cylinder(radius: 5, height: 10)! let faces = cyl.faces() for edge in cyl.edges() { if edge.isSeam(on: faces[0]) { print("found seam edge") } }
adjacentFaces(in:)
Returns the faces adjacent to this edge within a parent shape.
public func adjacentFaces(in shape: Shape) -> (Face, Face?)?
Most interior edges have exactly two adjacent faces (manifold solid). Boundary edges (on open shells) have only one. The shape must be the same solid from which this edge was extracted.
- Parameters:
shape— the parent shape containing this edge. - Returns: Tuple
(face1, face2)whereface2isnilfor boundary edges; ornilif the edge has no adjacent faces inshape. - OCCT:
TopExp::MapShapesAndAncestors(shape, TopAbs_EDGE, TopAbs_FACE, map). - Example:
let box = Shape.box(width: 10, height: 10, depth: 10)! if let edge = box.edge(at: 0), let (f1, f2) = edge.adjacentFaces(in: box) { print("face1, face2:", f1, f2 as Any) }
dihedralAngle(between:and:at:)
Computes the dihedral angle between two faces at this edge.
public func dihedralAngle(between face1: Face, and face2: Face, at parameter: Double = 0.5) -> Double?
The dihedral angle is measured between the face normals evaluated at a point along the edge. A value of π (180°) indicates tangent (smooth) faces; less than π is convex; greater than π is concave.
- Parameters:
face1— first adjacent face.face2— second adjacent face.parameter— normalised position along the edge in[0.0, 1.0]where to measure (default: midpoint).
- Returns: Dihedral angle in radians
[0, 2π], ornilon error (e.g. degenerate normals or missing PCurves). - OCCT:
BRepAdaptor_Curve+BRep_Tool::CurveOnSurface+BRepAdaptor_Surface::D1— computes face normals from first derivatives at the UV parameter. - Example:
let box = Shape.box(width: 10, height: 10, depth: 10)! for edge in box.edges() { if let (f1, f2) = edge.adjacentFaces(in: box), let f2 { if let angle = edge.dihedralAngle(between: f1, and: f2) { // angle ≈ π/2 for all edges of a box print(angle) } } }
Curve Approximation
CurveApproximation
Result of B-spline approximation of an edge’s curve.
public struct CurveApproximation: Sendable {
public let maxError: Double
public let degree: Int
public let poleCount: Int
}
maxError— maximum deviation between the original curve and the B-spline approximation.degree— B-spline degree of the result.poleCount— number of B-spline control points (poles) in the result.
approximatedCurve(tolerance:maxSegments:maxDegree:)
Approximates this edge’s curve as a B-spline Curve3D.
public func approximatedCurve(tolerance: Double = 1e-3,
maxSegments: Int = 100,
maxDegree: Int = 8) -> Curve3D?
Uses Approx_Curve3d with C² continuity to convert any curve type (line, circle, ellipse, etc.) into a B-spline representation. Useful for normalising geometry before export or downstream processing.
- Parameters:
tolerance— maximum allowed approximation error (default1e-3).maxSegments— maximum number of B-spline segments (default100).maxDegree— maximum B-spline degree (default8).
- Returns: Approximated B-spline as a
Curve3D, ornilon failure. - OCCT:
BRepAdaptor_Curve+Approx_Curve3d(GeomAbs_C2). - Example:
let cyl = Shape.cylinder(radius: 5, height: 10)! if let edge = cyl.edges().first(where: \.isCircle), let bspline = edge.approximatedCurve(tolerance: 1e-4) { let dom = bspline.domain }
curveApproximationInfo(tolerance:maxSegments:maxDegree:)
Returns information about B-spline approximation without creating the curve object.
public func curveApproximationInfo(tolerance: Double = 1e-3,
maxSegments: Int = 100,
maxDegree: Int = 8) -> CurveApproximation?
Runs the same Approx_Curve3d computation as approximatedCurve(tolerance:maxSegments:maxDegree:) but returns only the metadata — error, degree, and pole count — without allocating a full Curve3D.
- Parameters:
tolerance— maximum allowed approximation error (default1e-3).maxSegments— maximum number of B-spline segments (default100).maxDegree— maximum B-spline degree (default8).
- Returns:
CurveApproximationstruct, ornilon failure. - OCCT:
BRepAdaptor_Curve+Approx_Curve3d(GeomAbs_C2) — readsMaxError(),Degree(),NbPoles(). - Example:
let cyl = Shape.cylinder(radius: 5, height: 10)! if let edge = cyl.edges().first(where: \.isCircle), let info = edge.curveApproximationInfo() { print(info.maxError, info.degree, info.poleCount) }
Edge Splitting
split(at:vertex:)
Splits this edge into two new edges at the specified parameter value.
public func split(at parameter: Double, vertex: SIMD3<Double>) -> (Edge, Edge)?
Divides the edge at parameter, placing a new vertex at vertex. The two result edges share the new vertex. The original edge is not modified.
- Parameters:
parameter— native OCCT curve parameter at which to split (must be withinparameterBounds).vertex— 3D position for the split vertex (should lie on the curve atparameter).
- Returns: Tuple
(edge1, edge2)representing the two halves, ornilif splitting fails. - OCCT:
ShapeFix_SplitTool::SplitEdgewith a synthetic planar face context. - Example:
let box = Shape.box(width: 10, height: 10, depth: 10)! for edge in box.edges() where edge.isLine { if let b = edge.parameterBounds, let midPt = edge.point(at: (b.first + b.last) / 2.0) { let midParam = (b.first + b.last) / 2.0 if let (e1, e2) = edge.split(at: midParam, vertex: midPt) { print(e1.length, e2.length) } } break } - Note: The synthetic planar face used internally (
gp_Plnthrough the curve midpoint with Z normal) may causeSplitEdgeto fail for space curves not lying near Z=0. Provide a curve midpoint asvertexfor best results.
PCurve / BRepAdaptor_Curve2d
Members in this section access the 2D parametric curve (PCurve) of an edge on a specific face — the Geom2d_Curve that maps the edge into the face’s UV parameter space.
pcurveParams(on:)
Returns the 2D parametric curve parameter range for this edge on a face.
public func pcurveParams(on face: Face) -> (first: Double, last: Double)?
- Parameters:
face— the face on which this edge lies. - Returns:
(first, last)parameter range for the PCurve, ornilif no PCurve exists for this edge onface. - OCCT:
BRepAdaptor_Curve2d— adaptor over the edge’s PCurve on the face’s surface. - Example:
let box = Shape.box(width: 10, height: 20, depth: 30)! let faces = box.faces() let edges = box.edges() for edge in edges { if let params = edge.pcurveParams(on: faces[0]) { print(params.first, params.last) break } }
pcurveValue(at:on:)
Evaluates the 2D parametric curve of this edge on a face at the given parameter.
public func pcurveValue(at parameter: Double, on face: Face) -> SIMD2<Double>?
Returns the UV coordinate on the face’s surface corresponding to the given curve parameter.
- Parameters:
parameter— curve parameter (within the range frompcurveParams(on:)).face— the face on which the edge lies.
- Returns: UV point on the face surface, or
nilon failure. - OCCT:
BRepAdaptor_Curve2d::Value. - Example:
let box = Shape.box(width: 10, height: 20, depth: 30)! let faces = box.faces() for edge in box.edges() { if let params = edge.pcurveParams(on: faces[0]) { let mid = (params.first + params.last) / 2.0 if let uv = edge.pcurveValue(at: mid, on: faces[0]) { print("UV:", uv) break } } }
approxCurveOnSurface(face:tolerance:maxSegments:maxDegree:)
Approximates the 3D curve of this edge on a face from its PCurve.
public func approxCurveOnSurface(face: Face, tolerance: Double = 1e-4,
maxSegments: Int = 10, maxDegree: Int = 8) -> Shape?
Uses Approx_CurveOnSurface to compute a 3D B-spline from the edge’s 2D parametric curve on the given face’s surface. Returns the result as a Shape wrapping a new TopoDS_Edge with the approximated 3D curve.
- Parameters:
face— the face whose surface defines the PCurve-to-3D mapping.tolerance— approximation tolerance (default1e-4).maxSegments— maximum B-spline segments (default10).maxDegree— maximum B-spline degree (default8).
- Returns:
Shapewrapping the new edge with approximated 3D curve, ornilon failure (e.g. no PCurve found). - OCCT:
BRep_Tool::CurveOnSurface+Approx_CurveOnSurface(GeomAbs_C2) +BRepBuilderAPI_MakeEdge. - Example:
let cyl = Shape.cylinder(radius: 5, height: 10)! let faces = cyl.faces() let edges = cyl.edges() if faces.count > 0 { if let approxShape = edges[0].approxCurveOnSurface(face: faces[0]) { // approxShape wraps an edge with a B-spline 3D curve } }