Skip to content

Cadova 0.9.0

Latest

Choose a tag to compare

@tomasf tomasf released this 04 Aug 09:50

This is meant to be the last 0.x release before 1.0, which is where the API settles down. If there's something you think should be fixed or reconsidered while breaking changes are still cheap, now is the time to file an issue.

Shape is now Geometry

Custom shapes now conform to Geometry2D and Geometry3D directly, so there's one geometry protocol instead of two parallel ones:

struct Bracket: Geometry3D {
    var body: any Geometry3D {
        Box([20, 10, 4])
            .aligned(at: .center)
    }
}

Shape2D and Shape3D still work, but are deprecated in favor of Geometry2D and Geometry3D. Existing shapes keep compiling; only the protocol name in the conformance changes. Conforming to Geometry2D/Geometry3D directly is something earlier compilers rejected, so Cadova now requires Swift 6.3 (Xcode 26).

Lofting along a path

Loft is no longer limited to stacking cross-sections along Z. It can now follow any curve, using the same framing as Sweep:

Loft(along: path, pointing: .down, toward: .direction(.negativeZ)) {
    Section(at: 0) { Circle(diameter: 12) }
    Section(at: 40) { Rectangle(8) }
    Section(at: 90) { Circle(diameter: 4) }
}
  • Section replaces Loft.Layer as the way to define a cross-section. Its position is a distance along the path, measured as arc length, and it also accepts a range or a atRelative: offset from the previous section.
  • layer(z:), layer(zOffset:) and Loft.Layer are deprecated in favor of Section. LayerTransition is now Loft.Transition.
  • Path-following initializers require an explicit pointing:/toward: pair. There's no default that works for both horizontal and vertical paths, so swept(along:) without them is deprecated.
  • The plain Loft { ... } initializer is unchanged and still produces an untwisted vertical stack.

Additions

  • twisted(by:per:) twists at a fixed rate per unit of height, independent of the geometry's bounding box, anchored at z = 0. The existing twisted(by:) still spreads a total angle over the full height.
  • Evaluate is a standalone version of evaluating(_:) for reads that aren't anchored to a receiver, such as geometry captured from an outer scope, or several unrelated geometries at once.

Documentation

  • New guides: Transformations, Cutting & Splitting, Bending & Deforming, Extrusion & Revolution, Measuring, Repetition & Patterns, Curves & Paths, Designing for 3D Printing, and Anchors & Tags. Several existing pages were revised and illustrated.

Bug fixes

  • Arc with a negative radius produced a mirrored sector with a real area instead of empty geometry.
  • 2D shapes with degenerate sizes now report an area of zero rather than a bogus value.
  • Fixed an inverted emptiness check on curve subcurves.
  • Empty items in a Stack no longer consume spacing as if they had size.
  • Decomposing geometry no longer reports empty pieces as components.
  • Trimming empty geometry no longer goes through mesh evaluation.

Renames

  • readPoints, readSamples and readMetrics are now readingPoints, readingSamples and readingMetrics.
  • resizing and extending are now resized and extended.
  • readTolerance and readOperation are deprecated. Use @Environment(\.tolerance) and @Environment(\.operation) instead.
  • filled(), deprecated since 0.4.3, has been removed. Use fillingHoles().