Files
turtle/turtle-lib/examples/bezier.rs
T
dietrich 68593ba64d Builder Pattern Trait Hierarchy Refactoring
We refactored the builder pattern in
[`turtle-lib`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib)
to eliminate inherent method asymmetry and organize all turtle
capabilities into six cohesive traits.

[`builders.rs`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/builders.rs)

The legacy traits (`DirectionalMovement`, `Turnable`, `CurvedMovement`)
and orphaned inherent methods have been reorganized into six
domain-focused traits:

-
  **[`Movement`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/builders.rs#L14)**:
  - `forward()`
  - `backward()`
  - `go_to()`
  - `circle_left()`
  - `circle_right()`
-
  **[`Rotation`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/builders.rs#L191)**:
  - `left()`
  - `right()`
  - `set_heading()`
-
  **[`Pen`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/builders.rs#L279)**:
  - `pen_up()`
  - `pen_down()`
  - `set_pen_color()`
  - `set_pen_width()`
-
  **[`Fill`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/builders.rs#L393)**:
  - `begin_fill()`
  - `end_fill()`
  - `set_fill_color()`
-
  **[`Cursor`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/builders.rs#L481)**:
  - `hide()`
  - `show()`
  - `shape()`
  - `set_shape()`
  - `set_speed()`
  - `reset()`
-
  **[`Text`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/builders.rs#L646)**:
  - `write_text()`

[`TurtlePlan`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/builders.rs#L688)

`TurtlePlan`'s inherent methods are now strictly builder lifecycle
controls:
- `new() -> Self`
- `build(self) -> CommandQueue`

`TurtlePlan` implements `WithCommands`, `Movement`, `Rotation`, `Pen`,
`Fill`, `Cursor`, and `Text`.

-
  **[`lib.rs`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/lib.rs#L62-L65)**:
  Re-exports `Cursor`, `Fill`, `Movement`, `Pen`, `Rotation`, `Text`,
  `TurtlePlan`, `WithCommands`.
- **Examples**: Updated
  [`clock.rs`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/examples/clock.rs#L8),
  [`clock_threaded.rs`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/examples/clock_threaded.rs#L9),
  [`dashed_circle.rs`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/examples/dashed_circle.rs#L4),
  and
  [`bezier.rs`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/examples/bezier.rs#L4)
  to use `use turtle_lib::*;`.
-
  **[`README.md`](file:///home/dietrich/Projekte/Source/turtlers/README.md#L344)**:
  Updated trait references in the architecture outline.

---

- **Unit & Doc Tests**:
  ```bash
  cargo test --package turtle-lib
  ```
  Result: 17 unit tests passed; 34 doc-tests passed (0 failed).
- **All Examples**:
  ```bash
  cargo check --package turtle-lib --examples
  ```
  Result: Successfully compiled all 30 examples.
- **Clippy**:
  ```bash
  cargo clippy --package turtle-lib -- -Wclippy::pedantic \
  -Aclippy::cast_precision_loss -Aclippy::cast_sign_loss
  -Aclippy::cast_possible_truncation
  ```
  Result: 0 warnings in `builders.rs`.
2026-09-19 11:45:57 +02:00

57 lines
1.5 KiB
Rust

//! Cubic Bézier curve example
//! <https://en.wikipedia.org/wiki/B%C3%A9zier_curve>
use turtle_lib::*;
struct CubicBezier {
point0: (f32, f32),
point1: (f32, f32),
point2: (f32, f32),
point3: (f32, f32),
}
impl CubicBezier {
/// Returns the value of this curve at the given parameter t (0.0 to 1.0)
pub fn at(&self, t: f64) -> (f32, f32) {
let t = t as f32;
let mt = 1.0 - t; // (1 - t)
// Cubic Bézier formula from Wikipedia
let p0_weight = mt.powi(3);
let p1_weight = 3.0 * mt.powi(2) * t;
let p2_weight = 3.0 * mt * t.powi(2);
let p3_weight = t.powi(3);
(
self.point0.0 * p0_weight
+ self.point1.0 * p1_weight
+ self.point2.0 * p2_weight
+ self.point3.0 * p3_weight,
self.point0.1 * p0_weight
+ self.point1.1 * p1_weight
+ self.point2.1 * p2_weight
+ self.point3.1 * p3_weight,
)
}
}
#[turtle_main("Bézier Curve")]
fn draw(turtle: &mut TurtlePlan) {
let curve = CubicBezier {
point0: (-200.0, -100.0),
point1: (-100.0, 400.0),
point2: (100.0, -500.0),
point3: (300.0, 200.0),
};
let start = curve.at(0.0);
turtle.pen_up().go_to(vec2(start.0, start.1)).pen_down();
let samples = 100;
for i in 0..samples {
let t = f64::from(i) / f64::from(samples);
let point = curve.at(t);
turtle.go_to(vec2(point.0, point.1));
}
}