|
| 1 | +# Examples |
| 2 | + |
| 3 | +A collection of example models demonstrating Cadova's features. |
| 4 | + |
| 5 | +## Chamfer |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | +```swift |
| 10 | +await Model("chamfer") { |
| 11 | + Circle(diameter: 12) |
| 12 | + .clonedAt(x: 8) |
| 13 | + .rounded(insideRadius: 2) |
| 14 | + .extruded(height: 7, topEdge: .chamfer(depth: 2)) |
| 15 | +} |
| 16 | +``` |
| 17 | + |
| 18 | +## Colors and materials |
| 19 | + |
| 20 | + |
| 21 | + |
| 22 | +```swift |
| 23 | +await Model("stack-materials") { |
| 24 | + Stack(.x, spacing: 2, alignment: .center, .bottom) { |
| 25 | + Sphere(diameter: 10) |
| 26 | + .colored(.darkOrange) |
| 27 | + Cylinder(diameter: 8, height: 12) |
| 28 | + .withMaterial(.glossyPlastic(.mediumSeaGreen)) |
| 29 | + Box(x: 12, y: 8, z: 15) |
| 30 | + .withMaterial(.steel) |
| 31 | + } |
| 32 | +} |
| 33 | +``` |
| 34 | + |
| 35 | +## Swept text |
| 36 | + |
| 37 | + |
| 38 | + |
| 39 | +```swift |
| 40 | +await Model("swept-text") { |
| 41 | + Text("Cadova") |
| 42 | + .withFont("Futura", style: "Condensed Medium", size: 10) |
| 43 | + .wrappedAroundCircle(spanning: 230°..<310°) |
| 44 | + .aligned(at: .centerX, .bottom) |
| 45 | + .swept(along: BezierPath { |
| 46 | + curve( |
| 47 | + controlX: 20, controlY: 10, controlZ: 3, |
| 48 | + endX: 20, endY: 30, endZ: 12 |
| 49 | + ) |
| 50 | + }) |
| 51 | +} |
| 52 | +``` |
| 53 | + |
| 54 | +## Loft |
| 55 | + |
| 56 | + |
| 57 | + |
| 58 | +```swift |
| 59 | +await Model("loft") { |
| 60 | + Loft(interpolation: .easeInOut) { |
| 61 | + layer(z: 0) { |
| 62 | + Ring(outerDiameter: 20, innerDiameter: 12) |
| 63 | + } |
| 64 | + layer(z: 30) { |
| 65 | + Rectangle(x: 25, y: 6) |
| 66 | + .aligned(at: .center) |
| 67 | + .cloned { $0.rotated(90°) } |
| 68 | + .subtracting { |
| 69 | + RegularPolygon(sideCount: 8, circumradius: 2) |
| 70 | + } |
| 71 | + } |
| 72 | + layer(z: 35) { |
| 73 | + Ring(outerDiameter: 12, innerDiameter: 10) |
| 74 | + } |
| 75 | + } |
| 76 | +} |
| 77 | +``` |
| 78 | + |
| 79 | +## Circular overhang |
| 80 | + |
| 81 | + |
| 82 | + |
| 83 | +```swift |
| 84 | +await Model("circular-overhang") { |
| 85 | + Stack(.x, spacing: 5) { |
| 86 | + Box(20) |
| 87 | + .aligned(at: .centerXY) |
| 88 | + .subtracting { |
| 89 | + Cylinder(diameter: 10, height: 20) |
| 90 | + .overhangSafe(.teardrop) |
| 91 | + } |
| 92 | + .rotated(x: -90°) |
| 93 | + |
| 94 | + Circle(diameter: 20) |
| 95 | + .overhangSafe(.bridge) |
| 96 | + .extruded(height: 20) |
| 97 | + .rotated(x: -90°) |
| 98 | + } |
| 99 | + .aligned(at: .minZ) |
| 100 | +} |
| 101 | +``` |
| 102 | + |
| 103 | +Using `overhangSafe(_:)` makes a circle or cylinder extend its shape to work better with FDM 3D printing. The shapes are extended in the right direction automatically, using the geometry's world transform, pointing downward for additive geometry and upward for subtractive geometry (holes). |
| 104 | + |
| 105 | +## Table |
| 106 | + |
| 107 | + |
| 108 | + |
| 109 | +```swift |
| 110 | +await Model("table") { |
| 111 | + let height = 7.0 |
| 112 | + let footDiameter = 2.0 |
| 113 | + let footHeight = 2.0 |
| 114 | + let legDiameter = 1.0 |
| 115 | + let topThickness = 1.0 |
| 116 | + let size = Vector2D(5, 7) |
| 117 | + |
| 118 | + Loft(interpolation: .smootherstep) { |
| 119 | + layer(z: 0) { Circle(diameter: footDiameter) } |
| 120 | + layer(z: footHeight) { Circle(diameter: legDiameter) } |
| 121 | + layer(z: height) { Circle(diameter: legDiameter) } |
| 122 | + } |
| 123 | + .translated(size / 2, z: 0) |
| 124 | + .symmetry(over: .xy) |
| 125 | + .sliced(atZ: height - 1e-6) { base, slice in |
| 126 | + base |
| 127 | + slice.extruded(height: topThickness) |
| 128 | + .convexHull() |
| 129 | + .translated(z: height) |
| 130 | + } |
| 131 | +} |
| 132 | +``` |
0 commit comments