Link Search Menu Expand Document

Cross-Section Types

Planar slicing of a mesh into closed contours — the perimeter step a 3D-printer slicer performs. CutPlane describes the cut; MeshContour is one classified closed loop; MeshCrossSection is the whole slice (plane basis + every loop). The entry points are the Mesh.crossSection(plane:) and Mesh.crossSections(axis:through:spacing:) extension methods. Pure geometry over Mesh.vertices / Mesh.indices (no OCCT kernel calls), so it stays robust on open / unwelded scan meshes. All three value types are Sendable.

Topics


CutPlane

An oriented cut plane: a point on the plane and its normal. The normal need not be unit length — Mesh.crossSection normalizes it.

public struct CutPlane: Sendable {
    public var point: SIMD3<Double>    // a point that lies on the plane
    public var normal: SIMD3<Double>   // the plane normal (any non-zero length)
}

CutPlane.init(point:normal:)

Creates a cut plane from a point and a (not-necessarily-unit) normal.

public init(point: SIMD3<Double>, normal: SIMD3<Double>)
  • Parameters:
    • point — a point that lies on the plane.
    • normal — the plane normal; any non-zero length (normalized on use).
  • Example:
    let plane = CutPlane(point: SIMD3(0, 0, 5), normal: SIMD3(0, 0, 1))
    

CutPlane.perpendicular(to:offset:)

A plane perpendicular to axis, positioned offset along it from the origin.

public static func perpendicular(to axis: SIMD3<Double>, offset: Double) -> CutPlane
  • Parameters:
    • axis — the direction the plane is perpendicular to (normalized internally).
    • offset — signed distance along the normalized axis from the origin.
  • Returns: the CutPlane.
  • Example:
    let z5 = CutPlane.perpendicular(to: SIMD3(0, 0, 1), offset: 5)   // the z = 5 plane
    

MeshContour

One closed loop of a cross-section, expressed in the plane’s 2D (u, v) basis. Loops are implicitly closed (the last point connects back to the first; the first point is not repeated). depth / isHole come from nesting, so they are reliable even on meshes with inconsistent triangle winding.

public struct MeshContour: Sendable {
    public var points: [SIMD2<Double>]
    public var signedArea: Double
    public var depth: Int
    public var parent: Int?
}

points

Ordered loop points in the section plane’s (u, v) coordinates (millimetres). Implicitly closed.

public var points: [SIMD2<Double>]

signedArea

Shoelace signed area in plane coordinates (CCW positive). After crossSection returns, orientation is normalized so an even depth (solid boundary) is CCW (> 0) and an odd depth (hole) is CW (< 0).

public var signedArea: Double

depth

Nesting depth: 0 = outermost solid boundary, 1 = a hole inside it (inner wall / window), 2 = a solid island inside that hole, etc.

public var depth: Int

parent

Index (into the section’s contours) of the immediately enclosing loop, or nil for an outermost loop.

public var parent: Int?

isHole

true when this loop bounds empty space inside a solid (odd nesting depth).

public var isHole: Bool { get }   // depth % 2 == 1
  • Example:
    for c in section.contours where c.isHole {
        print("hole of area \(c.area)")
    }
    

area

Unsigned enclosed area.

public var area: Double { get }   // abs(signedArea)

perimeter

Total perimeter length of the loop (sum of edge lengths, including the implicit closing edge).

public var perimeter: Double { get }

bounds

Axis-aligned bounds in plane coordinates: (min, max).

public var bounds: (min: SIMD2<Double>, max: SIMD2<Double>) { get }

MeshCrossSection

A planar cross-section of a mesh: the plane basis plus every closed loop the plane cuts. Map 2D loop points back to 3D with worldPoint(_:).

public struct MeshCrossSection: Sendable {
    public var origin: SIMD3<Double>
    public var normal: SIMD3<Double>
    public var uAxis: SIMD3<Double>
    public var vAxis: SIMD3<Double>
    public var contours: [MeshContour]
    public var openPaths: [[SIMD2<Double>]]
}

origin / normal / uAxis / vAxis

The plane basis. origin is the (u, v) = (0, 0) point in world space; normal is the unit plane normal; uAxis and vAxis are the unit in-plane basis vectors (vAxis = normal × uAxis).

public var origin: SIMD3<Double>
public var normal: SIMD3<Double>
public var uAxis: SIMD3<Double>
public var vAxis: SIMD3<Double>

contours

The closed loops cut by the plane, each classified by nesting depth.

public var contours: [MeshContour]

openPaths

Open polylines (in (u, v) coordinates) produced where the plane exits the mesh through a boundary edge — e.g. cutting across an open end or a window rim. Empty for a clean section between features.

public var openPaths: [[SIMD2<Double>]]

outerContours

The outermost loops (nesting depth 0) — the solid’s outer boundary.

public var outerContours: [MeshContour] { get }
  • Example:
    print("\(section.outerContours.count) outer wall(s)")
    

worldPoint(_:)

Map a plane (u, v) coordinate back to a world-space point.

public func worldPoint(_ uv: SIMD2<Double>) -> SIMD3<Double>
  • Parameters:
    • uv — a point in the plane’s (u, v) basis (e.g. an element of a contour’s points).
  • Returns: the corresponding world-space SIMD3<Double>.
  • Example:
    guard let loop = section.contours.first else { return }
    let worldRing = loop.points.map { section.worldPoint($0) }
    

Mesh.crossSection(plane:minLoopArea:weld:)

Slice the mesh with a plane and return the closed contours where the plane cuts the surface — a 3D-printer slicer’s perimeter step. Intersection points are welded by quantized world position, so the two triangles sharing an edge chain without tolerance fuzz; inner walls and pockets come back as separate loops, classified by nesting.

func crossSection(plane: CutPlane, minLoopArea: Double = 0, weld: Double = 0) -> MeshCrossSection?
  • Parameters:
    • plane — the cut plane (normal need not be unit length).
    • minLoopArea — loops with unsigned area below this are discarded as slivers (default 0, keep everything).
    • weld — spatial tolerance for welding coincident intersection points (handles unwelded STL). 0 (default) auto-derives 1e-6 × the mesh’s bounding-box diagonal.
  • Returns: the MeshCrossSection, or nil if the plane misses the mesh entirely.
  • Example:
    import OCCTSwift
    import OCCTSwiftMesh
    
    guard let section = mesh.crossSection(
        plane: CutPlane(point: SIMD3(0, 0, 5), normal: SIMD3(0, 0, 1)),
        minLoopArea: 0.01
    ) else { return }
    
    for c in section.contours {
        print("depth \(c.depth)\(c.isHole ? " (hole)" : ""): area \(c.area)")
    }
    

Mesh.crossSections(axis:through:spacing:margin:)

A stack of evenly-spaced cross-sections along an axis — a slicer’s layer stack. Sections that miss the mesh are skipped.

func crossSections(axis: SIMD3<Double>, through point: SIMD3<Double>,
                   spacing: Double, margin: Double? = nil) -> [MeshCrossSection]
  • Parameters:
    • axis — slicing direction (normalized internally).
    • point — a point the axis passes through (the stack is measured from here).
    • spacing — distance between successive section planes. Must be > 0 (otherwise returns []).
    • margin — inset from each end of the mesh’s extent along the axis, so the first/last slice doesn’t sit exactly on an end cap (default spacing / 2).
  • Returns: an array of MeshCrossSection, one per plane that hit the mesh.
  • Example:
    let layers = mesh.crossSections(
        axis: SIMD3(0, 0, 1),
        through: SIMD3(0, 0, 0),
        spacing: 0.2            // 0.2 mm layers
    )
    print("\(layers.count) layers")