Skip to content

Commit 34ef572

Browse files
committed
Merge branch 'dev'
2 parents b9ce092 + d566036 commit 34ef572

39 files changed

+1006
-24
lines changed

Sources/Cadova/Abstract Layer/3D/Mesh.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,10 @@ public extension Mesh {
143143
/// any variable inputs that affect the resulting geometry so Cadova can safely reuse cached
144144
/// results without returning stale meshes.
145145
///
146-
/// - Parameter faces: A sequence of polygonal faces, where each face is a sequence of `Vector3D` points.
146+
/// - Parameters:
147+
/// - faces: A sequence of polygonal faces, where each face is a sequence of `Vector3D` points.
148+
/// - name: A name used for caching the mesh.
149+
/// - cacheParameters: Additional hashable parameters that uniquely identify this mesh for caching purposes.
147150
///
148151
/// - Important: All faces must contain at least 3 points. The combined set of faces must define a closed and manifold solid.
149152
init<Face: Sequence<Vector3D>, FaceList: Sequence<Face>>(

Sources/Cadova/Abstract Layer/Geometry/References/Anchors+Public.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import Foundation
88
/// at specific locations.
99
///
1010
/// You create an anchor once (optionally with a human-readable label for debugging) and then define
11-
/// it on geometry using ``Geometry3D/definingAnchor(_:at:offset:pointing:rotated:)``. Later, you can
12-
/// use ``Geometry3D/anchored(to:)`` to place other geometry at the recorded transforms.
11+
/// it on geometry using `definingAnchor(_:at:offset:pointing:rotated:)`. Later, you can
12+
/// use `anchored(to:)` to place other geometry at the recorded transforms.
1313
///
1414
/// - Multiple definitions:
1515
/// - An anchor can be defined multiple times across a geometry tree. Each definition records a

Sources/Cadova/Abstract Layer/Geometry/ResultElement/ResultElement.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public protocol ResultElement: Sendable {
3030
/// is present. Implementations should define a stable, deterministic merge policy
3131
/// (such as last-wins, union, intersection, or accumulation) appropriate to the element’s meaning.
3232
///
33-
/// - Parameter elements: The instances to be combined.
33+
/// - Parameter combining: The instances to be combined.
3434
init(combining: [Self])
3535
}
3636

Sources/Cadova/Abstract Layer/Operations/Follow3D.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public extension Geometry3D {
3434
/// - Parameter path: A 2D parametric curve interpreted in the XY plane that the geometry should follow.
3535
/// - Returns: A warped version of the geometry that follows the 2D path.
3636
///
37-
/// - SeeAlso: ``following(path:pointing:toward:)``, ``Geometry2D/swept(along:pointing:toward:)``, ``Geometry3D/deformed(by:)``
37+
/// - SeeAlso: ``following(path:pointing:toward:)``, `swept(along:pointing:toward:)`, `deformed(by:)`
3838
func following<Path: ParametricCurve<Vector2D>>(path: Path) -> any Geometry3D {
3939
rotated(y: -90°)
4040
.following(path: path.curve3D, pointing: .positiveX, toward: .direction(.negativeZ))

Sources/Cadova/Abstract Layer/Operations/Loft/Loft.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ public struct Loft: Geometry {
118118
/// A single cross-section in a lofted shape.
119119
///
120120
/// Each layer defines a 2D shape at a specific Z height. Layers are created using the
121-
/// ``layer(z:interpolation:shape:)`` function within a ``Loft`` builder.
121+
/// `layer(z:interpolation:shape:)` function within a ``Loft`` builder.
122122
///
123123
public struct Layer: Sendable {
124124
internal let z: Double

Sources/Cadova/Abstract Layer/Operations/Measure.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public extension Geometry {
6464
/// only the main geometry, `.solidParts` (default) to include solid/printable parts, or
6565
/// `.allParts` to include every part (solid, context, and visual).
6666
/// - builder: A closure that receives the geometry and its bounding box, and returns a new geometry.
67-
/// - empty: A closure that provides fallback geometry when the original geometry is empty. Defaults to `Empty()`.
67+
/// - emptyBuilder: A closure that provides fallback geometry when the original geometry is empty. Defaults to `Empty()`.
6868
/// - Returns: A modified geometry based on the bounding box, or the result of `empty` if no bounds exist.
6969
///
7070
func measuringBounds<Output: Dimensionality>(

Sources/Cadova/Abstract Layer/Operations/Transformations/RotateAround.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ public extension Geometry2D {
1111
///
1212
/// - Parameters:
1313
/// - angle: The angle to rotate the geometry. Defaults to `0°`.
14-
/// - pivot: A list of alignment options that specify the pivot point for the rotation. For example, `.center`
14+
/// - pivot: An alignment option that specifies the pivot point for the rotation. For example, `.center`
1515
/// can be used to rotate the geometry around its center, while `.top` can rotate it around the top boundary.
16+
/// - more: Additional alignment options for the pivot point.
1617
///
1718
/// - Returns: A new geometry that is the result of applying the specified rotation and pivot adjustments.
1819
///
@@ -22,7 +23,7 @@ public extension Geometry2D {
2223
/// .rotated(45°, around: .center)
2324
/// ```
2425
/// This example rotates the square 45 degrees around its center.
25-
///
26+
///
2627
func rotated(
2728
_ angle: Angle = 0°,
2829
around pivot: GeometryAlignment2D,
@@ -50,8 +51,9 @@ public extension Geometry3D {
5051
/// - x: The angle to rotate around the X-axis. Defaults to `0°`.
5152
/// - y: The angle to rotate around the Y-axis. Defaults to `0°`.
5253
/// - z: The angle to rotate around the Z-axis. Defaults to `0°`.
53-
/// - pivot: A list of alignment options that specify the pivot point for the rotation. For example, `.center`
54+
/// - pivot: An alignment option that specifies the pivot point for the rotation. For example, `.center`
5455
/// can be used to rotate the geometry around its center, while `.top` can rotate it around the top boundary.
56+
/// - more: Additional alignment options for the pivot point.
5557
///
5658
/// - Returns: A new geometry that is the result of applying the specified rotation and pivot adjustments.
5759
///
@@ -61,7 +63,7 @@ public extension Geometry3D {
6163
/// .rotated(x: 90°, around: .center)
6264
/// ```
6365
/// This example rotates the box 90 degrees around its center.
64-
///
66+
///
6567
func rotated(
6668
x: Angle = 0°,
6769
y: Angle = 0°,

Sources/Cadova/Abstract Layer/Visualization/BoundingBoxVisualization.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public extension Geometry3D {
1919
/// Overlays the geometry's bounding box as a thin 3D frame for debugging.
2020
///
2121
/// This is useful for visualizing the region affected by range-based spatial APIs
22-
/// like ``within(x:y:z:)`` or ``EdgeCriteria/within(x:y:z:)``.
22+
/// like `within(x:y:z:)` or `EdgeCriteria.within(x:y:z:)`.
2323
///
2424
/// ```swift
2525
/// // Visualize the entire bounding box
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Alignment and Stacking
2+
3+
Position geometry relative to the origin and arrange shapes along an axis.
4+
5+
## Overview
6+
7+
In Cadova, alignment is a way to control how geometry is positioned relative to the coordinate system's origin. Since different shapes are defined differently, some centered, some corner-based, aligning them explicitly is often the easiest way to place them where you want.
8+
9+
For example, a `Circle(radius: 10)` is centered at the origin by default, but a `Rectangle([20, 10])` extends from the origin toward the top right. Using alignment helps you standardize and simplify placement:
10+
11+
```swift
12+
Rectangle([20, 10])
13+
.aligned(at: .centerX, .bottom)
14+
```
15+
16+
This centers the rectangle along the X-axis and aligns its bottom edge with Y = 0.
17+
18+
## How `.aligned(at:)` works
19+
20+
The `.aligned(at:)` method repositions geometry by translating it so that parts of its *bounding box* align to the coordinate system origin, based on the criteria you provide. The geometry isn't clipped, resized, or modified, just moved so it aligns as requested. You can align any geometry, including complex compositions, boolean operations, or custom components.
21+
22+
You align along one or more axes:
23+
24+
```swift
25+
Box([30, 40, 50])
26+
.aligned(at: .centerX, .maxY, .bottom)
27+
```
28+
29+
This centers the box in X, moves the back to Y = 0, and aligns the bottom of the Z axis to Z = 0. If you provide multiple alignments for the same axis, the last one wins.
30+
31+
## Alignment Presets
32+
33+
Cadova provides a set of readable alignment constants so you don't need to manually calculate anything. These include:
34+
35+
- `.minX`, `.centerX`, `.maxX`, `.left`, `.right`
36+
- `.minY`, `.centerY`, `.maxY`
37+
- `.minZ`, `.centerZ`, `.maxZ`
38+
- `.top`, `.bottom` (Y axis in 2D, Z axis in 3D)
39+
- `.center` (all axes), `.centerXY`
40+
41+
## Practical Examples
42+
43+
### Center a rectangle
44+
45+
```swift
46+
Rectangle([20, 10])
47+
.aligned(at: .center)
48+
```
49+
50+
### Align the bottom (min Y) of a circle to the origin
51+
52+
```swift
53+
Circle(radius: 10)
54+
.aligned(at: .bottom)
55+
```
56+
57+
### Center a shape horizontally and align to the top
58+
59+
```swift
60+
Rectangle([50, 20])
61+
.aligned(at: .centerX, .top)
62+
```
63+
64+
## Stack
65+
66+
``Stack`` is a container that arranges its contents one after another along a given axis like `.x`, `.y`, or `.z`. It avoids overlap by using bounding boxes, and positions items relative to the origin using alignment on the *non-stacking* axes.
67+
68+
### Basic Usage
69+
70+
```swift
71+
Stack(.z, spacing: 2, alignment: .centerX) {
72+
Cylinder(radius: 5, height: 1)
73+
Box([10, 10, 3])
74+
}
75+
```
76+
77+
This stacks a cylinder and a box vertically. Each item is spaced 2 mm apart, centered in X, and Y positioning is left unchanged.
78+
79+
### Axis and Alignment
80+
81+
- `axis` determines the direction of stacking.
82+
- `spacing` is `0` by default, meaning items touch edge-to-edge. Positive values add space between them.
83+
- `alignment` applies only to *non-stacking axes you explicitly specify*. Unspecified axes are left unchanged and the stacking axis is ignored. You can use `.center`, `.left`, `.bottom`, etc., just like with `.aligned(at:)`.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# ``Cadova``
2+
3+
A Swift DSL for creating precise, parametric 3D models for 3D printing.
4+
5+
@Metadata {
6+
@DisplayName("Cadova")
7+
}
8+
9+
## Overview
10+
11+
Cadova is a Swift library for constructing 3D models programmatically — with a focus on 3D printing. It builds on the ideas of OpenSCAD, but replaces its limited language with the power and elegance of Swift. Inspired by SwiftUI and designed for developers who want a better way to build models through code, Cadova is cross-platform and works on macOS, Linux, and Windows.
12+
13+
![A 3D model created with Cadova](home-hero)
14+
15+
## Topics
16+
17+
### Essentials
18+
19+
- <doc:GettingStarted>
20+
- <doc:WhatIsCadova>
21+
22+
### Core Concepts
23+
24+
- <doc:Geometry>
25+
- <doc:VectorsAndAngles>
26+
- <doc:AlignmentAndStacking>
27+
- <doc:Environment>
28+
- <doc:ModelAndProject>
29+
30+
### Guides
31+
32+
- <doc:WorkingWithParts>
33+
- <doc:Examples>
34+
35+
### Under the Hood
36+
37+
- <doc:Internals>
38+
- <doc:Troubleshooting>

0 commit comments

Comments
 (0)