svg text size and orientation
This commit is contained in:
parent
5e0e0e5be3
commit
bc925ffe26
102
turtle-lib/examples/breadboard.rs
Normal file
102
turtle-lib/examples/breadboard.rs
Normal file
@ -0,0 +1,102 @@
|
||||
use turtle_lib::*;
|
||||
#[cfg(feature = "svg")]
|
||||
#[macroquad::main("Export SVG")]
|
||||
|
||||
async fn main() {
|
||||
// Create turtle plan
|
||||
let mut turtle = create_turtle_plan();
|
||||
|
||||
// Set instant mode so commands execute imqmediately
|
||||
turtle.set_speed(1200).set_pen_width(0.5);
|
||||
|
||||
breadboard(&mut turtle, 65);
|
||||
|
||||
turtle.hide();
|
||||
let mut app = TurtleApp::new().with_commands(turtle.build());
|
||||
use macroquad::{
|
||||
input::{is_key_pressed, KeyCode},
|
||||
text::draw_text,
|
||||
window::{clear_background, next_frame},
|
||||
};
|
||||
|
||||
loop {
|
||||
clear_background(WHITE);
|
||||
app.update();
|
||||
app.render();
|
||||
|
||||
draw_text("Drücke E für SVG-Export", 20.0, 40.0, 32.0, BLACK);
|
||||
|
||||
if is_key_pressed(KeyCode::E) {
|
||||
match app.export_drawing("test.svg", export::DrawingFormat::Svg) {
|
||||
Ok(_) => println!("SVG exportiert nach test.svg"),
|
||||
Err(e) => println!("Fehler beim Export: {:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
next_frame().await;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "svg"))]
|
||||
fn main() {
|
||||
println!("SVG-Export ist nicht aktiviert. Baue mit --features svg");
|
||||
}
|
||||
|
||||
fn pin(t: &mut TurtlePlan, size: f32) {
|
||||
t.left(90.0).forward(size / 2.0);
|
||||
for _ in 0..5 {
|
||||
t.right(90.0).forward(size);
|
||||
}
|
||||
t.right(90.0).forward(size / 2.0).left(90.0);
|
||||
}
|
||||
|
||||
fn pin_reihe(t: &mut TurtlePlan, anzahl: usize) {
|
||||
for x in 0..anzahl {
|
||||
pin(t, 5.0);
|
||||
if x < anzahl - 1 {
|
||||
t.forward(5.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn pin_spalte(t: &mut TurtlePlan, anzahl: usize, x_coord: f32) {
|
||||
for x in 0..anzahl {
|
||||
t.pen_up().go_to(vec2(x_coord, x as f32 * 10.0)).pen_down();
|
||||
pin_reihe(t, 5);
|
||||
}
|
||||
}
|
||||
|
||||
fn pin_seite(t: &mut TurtlePlan, anzahl: usize, x_coord: f32, color: Color) {
|
||||
t.pen_up()
|
||||
.go_to(vec2(x_coord, -2.5))
|
||||
.pen_down()
|
||||
.set_pen_color(color)
|
||||
.set_heading(90.0);
|
||||
for x in 0..anzahl {
|
||||
pin(t, 5.0);
|
||||
if x < anzahl - 1 {
|
||||
t.forward(5.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn breadboard(t: &mut TurtlePlan, anzahl_reihen: usize) {
|
||||
pin_spalte(t, anzahl_reihen, 0.0);
|
||||
pin_spalte(t, anzahl_reihen, 65.0);
|
||||
pin_seite(t, anzahl_reihen, -15.0, BLUE);
|
||||
pin_seite(t, anzahl_reihen, -25.0, RED);
|
||||
pin_seite(t, anzahl_reihen, 125.0, BLUE);
|
||||
pin_seite(t, anzahl_reihen, 135.0, RED);
|
||||
|
||||
// draw outline
|
||||
t.pen_up().go_to(vec2(-30.0, -5.0)).pen_down();
|
||||
t.set_pen_color(BLACK)
|
||||
.forward(anzahl_reihen as f32 * 10.0 + 10.0)
|
||||
.right(90.0)
|
||||
.forward(170.0)
|
||||
.right(90.0)
|
||||
.forward(anzahl_reihen as f32 * 10.0 + 10.0)
|
||||
.right(90.0)
|
||||
.forward(170.0)
|
||||
.right(90.0);
|
||||
}
|
||||
@ -9,6 +9,7 @@ async fn main() {
|
||||
let mut plan = create_turtle_plan();
|
||||
plan.forward(100.0)
|
||||
.right(90.0)
|
||||
.set_speed(950.0)
|
||||
.forward(100.0)
|
||||
.set_pen_color(macroquad::color::GRAY)
|
||||
.set_pen_width(8.0)
|
||||
@ -17,9 +18,11 @@ async fn main() {
|
||||
.forward(100.0)
|
||||
.right(90.0)
|
||||
.forward(200.0)
|
||||
.end_fill()
|
||||
.circle_left(200., 180., 24)
|
||||
.circle_left(90.0, 180.0, 36)
|
||||
.end_fill();
|
||||
for size in 0..9 {
|
||||
plan.circle_left(200., 20., 6).write_text("a", size * 10);
|
||||
}
|
||||
plan.circle_left(90.0, 180.0, 36)
|
||||
.begin_fill()
|
||||
.circle_left(90.0, 180.0, 36)
|
||||
.circle_left(45.0, 180.0, 26)
|
||||
|
||||
@ -190,6 +190,8 @@ pub(crate) fn execute_command_side_effects(
|
||||
svg_log.push(crate::state::SvgRecord::Text {
|
||||
text: text.clone(),
|
||||
position: params.position,
|
||||
heading: params.heading,
|
||||
font_size: *font_size,
|
||||
color: params.color,
|
||||
});
|
||||
true
|
||||
|
||||
@ -174,16 +174,32 @@ pub mod svg_export {
|
||||
SvgRecord::Text {
|
||||
text,
|
||||
position,
|
||||
heading,
|
||||
font_size,
|
||||
color,
|
||||
..
|
||||
} => {
|
||||
// Match the offset/rotation applied by the on-screen renderer
|
||||
// (see draw_text_command in drawing.rs) so the SVG export lines up.
|
||||
let font_size_val = f32::from(font_size.value());
|
||||
let offset_distance = font_size_val / 3.0;
|
||||
let perpendicular_angle = *heading - std::f32::consts::PI / 2.0;
|
||||
let text_x = position.x + offset_distance * perpendicular_angle.cos();
|
||||
let text_y = position.y + offset_distance * perpendicular_angle.sin();
|
||||
update_bounds(
|
||||
&mut min_x, &mut max_x, &mut min_y, &mut max_y, position.x,
|
||||
position.y,
|
||||
&mut min_x, &mut max_x, &mut min_y, &mut max_y, text_x, text_y,
|
||||
);
|
||||
|
||||
let rotation_deg = heading.to_degrees();
|
||||
let txt = SvgText::new(text.clone())
|
||||
.set("x", position.x)
|
||||
.set("y", position.y)
|
||||
.set("fill", color_to_svg(*color));
|
||||
.set("x", text_x)
|
||||
.set("y", text_y)
|
||||
.set("fill", color_to_svg(*color))
|
||||
.set("font-size", font_size_val)
|
||||
.set(
|
||||
"transform",
|
||||
format!("rotate({rotation_deg}, {text_x}, {text_y})"),
|
||||
);
|
||||
doc = doc.add(txt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -343,6 +343,8 @@ pub(crate) enum SvgRecord {
|
||||
Text {
|
||||
text: String,
|
||||
position: Vec2,
|
||||
heading: f32,
|
||||
font_size: crate::general::FontSize,
|
||||
color: Color,
|
||||
},
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user