diff --git a/Sources/SwiftSCAD/Operations/Extrude/Edge Profiles/ApplyEdgeProfile.swift b/Sources/SwiftSCAD/Operations/Extrude/Edge Profiles/ApplyEdgeProfile.swift new file mode 100644 index 0000000..380894e --- /dev/null +++ b/Sources/SwiftSCAD/Operations/Extrude/Edge Profiles/ApplyEdgeProfile.swift @@ -0,0 +1,40 @@ +import Foundation + +internal extension Geometry3D { + func applyingTopEdgeProfile(profile: EdgeProfile, at z: Double, shape: (any Geometry2D)?, method: EdgeProfile.Method) -> any Geometry3D { + let slice = shape ?? projection(slicingAtZ: z - 0.01) + let subtraction = profile.negativeMask(shape: slice, method: method) + .translated(z: z) + return subtracting(subtraction) + } + + func applyingBottomEdgeProfile(profile: EdgeProfile, at z: Double, shape: (any Geometry2D)?, method: EdgeProfile.Method) -> any Geometry3D { + let slice = shape ?? projection(slicingAtZ: z + 0.01) + let subtraction = profile.negativeMask(shape: slice, method: method) + .flipped(along: .z) + .translated(z: z) + return subtracting(subtraction) + } +} + +public extension Geometry3D { + func applyingTopEdgeProfile(_ profile: EdgeProfile, at z: Double? = nil, shape: (any Geometry2D)? = nil, method: EdgeProfile.Method) -> any Geometry3D { + if let z { + return applyingTopEdgeProfile(profile: profile, at: z, shape: shape, method: method) + } else { + return measuringBounds { _, box in + return applyingTopEdgeProfile(profile: profile, at: box.maximum.z, shape: shape, method: method) + } + } + } + + func applyingBottomEdgeProfile(_ profile: EdgeProfile, at z: Double? = nil, shape: (any Geometry2D)? = nil, method: EdgeProfile.Method) -> any Geometry3D { + if let z { + return applyingBottomEdgeProfile(profile: profile, at: z, shape: shape, method: method) + } else { + return measuringBounds { _, box in + return applyingBottomEdgeProfile(profile: profile, at: box.minimum.z, shape: shape, method: method) + } + } + } +} diff --git a/Sources/SwiftSCAD/Operations/Extrude/Edge Profiles/EdgeProfile.swift b/Sources/SwiftSCAD/Operations/Extrude/Edge Profiles/EdgeProfile.swift index 10bde26..76a8d2c 100644 --- a/Sources/SwiftSCAD/Operations/Extrude/Edge Profiles/EdgeProfile.swift +++ b/Sources/SwiftSCAD/Operations/Extrude/Edge Profiles/EdgeProfile.swift @@ -70,4 +70,15 @@ internal extension EdgeProfile { func mask(shape: any Geometry2D, extrusionHeight: Double, method: EdgeProfile.Method) -> any Geometry3D { profileShape.mask(shape: shape, extrusionHeight: extrusionHeight, method: method) } + + func negativeMask(shape: any Geometry2D, method: EdgeProfile.Method) -> any Geometry3D { + let height = profileShape.height + return shape + .offset(amount: 0.01, style: .round) + .extruded(height: height + 0.01) + .subtracting { + profileShape.mask(shape: shape, extrusionHeight: height, method: method) + } + .translated(z: -height) + } }