SwiftSCAD 是一个允许您在 Swift 中创建 3D 和 2D CAD 模型的库。它充当 OpenSCAD 的预处理器,生成可以使用 OpenSCAD 应用程序预览和渲染的 .scad 文件。这提供了一个更方便的 API,打破了 OpenSCAD 语言的限制。
SwiftSCAD 在 macOS、Windows 和 Linux 上运行。
概要:创建一个新的可执行 Swift 包,将 SwiftSCAD 添加为依赖项,在您的代码中导入它,创建几何体并使用
save(to:)
方法将其保存到磁盘作为 OpenSCAD 文件。
安装 OpenSCAD 以便预览和渲染您的模型。使用开发快照版本,因为稳定版本通常非常旧。
如果您使用的是 macOS,最简单的方法是安装最新版本的 Xcode。
对于 Windows 和 Linux,直接安装 Swift。我还建议安装 VS Code 以及 Swift 扩展,以使开发更轻松。
$ mkdir thingamajig
$ cd thingamajig
$ swift package init --type executable
let package = Package( name: "thingamajig", dependencies: [ .package(url: "https://github.com/tomasf/SwiftSCAD.git", upToNextMinor(from: "0.9.0")), ], targets: [ .executableTarget(name: "thingamajig", dependencies: ["SwiftSCAD"]) ] )
在 main.swift
中,导入 SwiftSCAD,创建几何体并保存它
import SwiftSCAD
Box([10, 10, 5])
.subtracting {
Sphere(diameter: 10)
.translated(z: 5)
}
.save(to: "gadget.scad")
使用 swift run
(或使用 Xcode/VS Code)运行您的代码以生成 .scad
文件。默认情况下,文件保存在当前工作目录中。完整路径将打印在控制台中。
在 OpenSCAD 中打开它以预览您的模型。为了获得最佳体验,使用视图 > 隐藏编辑器隐藏编辑器视图,并启用设计 > 自动重新加载和预览。这样设置后,每次您在更改模型后运行代码时,OpenSCAD 都会自动重新加载。
Box(x: 10, y: 20, z: 5)
.aligned(at: .centerY)
.rotated(y: -20°, z: 45°)
.save(to: "example1.scad")
Circle(diameter: 10)
.withFacets(count: 3)
.translated(x: 2)
.scaled(x: 2)
.repeated(in: 0°..<360°, count: 5)
.rounded(amount: 1)
.extruded(height: 5, twist: -20°)
.subtracting {
Cylinder(bottomDiameter: 1, topDiameter: 5, height: 20)
.translated(y: 2, z: -7)
.rotated(x: 20°)
.highlighted()
}
.save(to: "example2")
struct Star: Shape2D {
let pointCount: Int
let radius: Double
let pointRadius: Double
let centerSize: Double
var body: any Geometry2D {
Circle(diameter: centerSize)
.adding {
Circle(radius: max(pointRadius, 0.001))
.translated(x: radius)
}
.convexHull()
.repeated(in: 0°..<360°, count: pointCount)
}
}
save {
Stack(.x, spacing: 1, alignment: .centerY) {
Star(pointCount: 5, radius: 10, pointRadius: 1, centerSize: 4)
Star(pointCount: 6, radius: 8, pointRadius: 0, centerSize: 2)
}
.named("example3")
}
let path = BezierPath2D(startPoint: .zero)
.addingCubicCurve(
controlPoint1: [10, 65],
controlPoint2: [55, -20],
end: [60, 40]
)
save {
Star(pointCount: 5, radius: 10, pointRadius: 1, centerSize: 4)
.usingDefaultFacets()
.extruded(along: path)
.withPreviewConvexity(4)
.usingFacets(minAngle: 5°, minSize: 1)
.named("example4")
}