polygon struct and draw polygons

This commit is contained in:
2025-05-29 22:05:37 +02:00
parent 3a83937ced
commit ba220d1b8f
2 changed files with 79 additions and 41 deletions

View File

@@ -1,17 +1,18 @@
mod polygon_draw; mod polygon_draw;
use iced::{ use iced::{
Task, Settings, Task, Theme,
time::{self, Duration}, time::{self, Duration},
widget::{button, canvas, column, row, text}, widget::{button, canvas, column, row, text},
}; };
use polygon_draw::PolygonFrame; use polygon_draw::{Polygon, PolygonFrame};
use std::f32::consts::PI; use std::f32::consts::PI;
use std::time::Instant; use std::time::Instant;
fn main() -> iced::Result { fn main() -> iced::Result {
iced::application("My App", MyApp::update, MyApp::view) iced::application("My App", MyApp::update, MyApp::view)
.theme(|_| Theme::Dark)
.subscription(MyApp::subscription) .subscription(MyApp::subscription)
.run_with(MyApp::new) .run_with(MyApp::new)
} }
@@ -26,18 +27,18 @@ enum Message {
struct MyApp { struct MyApp {
polys: PolygonFrame, polys: PolygonFrame,
time_last_frame: Instant, time_last_frame: Instant,
revo_per_sec: u32, nb_sec_for_rev: u32,
} }
impl MyApp { impl MyApp {
fn new() -> (Self, Task<Message>) { fn new() -> (Self, Task<Message>) {
( (
Self { Self {
revo_per_sec: 1, nb_sec_for_rev: 4,
time_last_frame: Instant::now(), time_last_frame: Instant::now(),
polys: PolygonFrame { polys: PolygonFrame {
radius: 128.0,
teta: 0.0, teta: 0.0,
polygons: vec![Polygon::triangle(0.0), Polygon::triangle(PI / 2.0)],
}, },
}, },
Task::none(), Task::none(),
@@ -45,17 +46,17 @@ impl MyApp {
} }
fn update(&mut self, message: Message) { fn update(&mut self, message: Message) {
match message { match message {
Message::ButtonPressedIncrement => self.revo_per_sec += 1, Message::ButtonPressedIncrement => self.nb_sec_for_rev += 1,
Message::ButtonPressedDecrement => { Message::ButtonPressedDecrement => {
if self.revo_per_sec > 1 { if self.nb_sec_for_rev > 1 {
self.revo_per_sec -= 1 self.nb_sec_for_rev -= 1
} }
} }
Message::Tick => { Message::Tick => {
let time_btw = Instant::now().duration_since(self.time_last_frame); let time_btw = Instant::now().duration_since(self.time_last_frame);
self.polys.teta += 2.0 self.polys.teta += 2.0
* PI * PI
* (1.0 / self.revo_per_sec as f32) * (1.0 / self.nb_sec_for_rev as f32)
* (time_btw.as_millis() as f32 / 1_000.0); * (time_btw.as_millis() as f32 / 1_000.0);
self.polys.teta %= 2.0 * PI; self.polys.teta %= 2.0 * PI;
//println!("Teta : {}", self.polys.teta); //println!("Teta : {}", self.polys.teta);
@@ -65,18 +66,23 @@ impl MyApp {
} }
fn view(&self) -> iced::Element<Message> { fn view(&self) -> iced::Element<Message> {
let txt_nb_rev = format!("Revolution per second : {}", self.revo_per_sec); let txt_nb_rev = format!("Revolution per second : {}", self.nb_sec_for_rev);
column![ column![
text(txt_nb_rev), text("Polymusic").size(32.0),
row![ row![
button("Increment").on_press(Message::ButtonPressedIncrement), canvas(&self.polys).height(500).width(500),
button("Decrement").on_press(Message::ButtonPressedDecrement), column![
], text(txt_nb_rev),
canvas(&self.polys).height(500).width(500), row![
button("Increment").on_press(Message::ButtonPressedIncrement),
button("Decrement").on_press(Message::ButtonPressedDecrement),
],
],
]
] ]
.into() .into()
} }
fn subscription(&self) -> iced::Subscription<Message> { fn subscription(&self) -> iced::Subscription<Message> {
time::every(Duration::from_millis(16)).map(|_| Message::Tick) time::every(Duration::from_millis(1)).map(|_| Message::Tick)
} }
} }

View File

@@ -12,17 +12,16 @@ pub trait RotationExt {
} }
impl RotationExt for Vector { impl RotationExt for Vector {
fn rotate(&mut self, teta: f32) -> Self { fn rotate(&mut self, teta: f32) -> Vector {
let temp_x = self.x; Vector::new(
let temp_y = self.y; self.x * teta.cos() - self.y * teta.sin(),
self.x = temp_x * teta.cos() - temp_y * teta.sin(); self.x * teta.sin() + self.y * teta.cos(),
self.y = temp_x * teta.sin() + temp_y * teta.cos(); )
*self
} }
} }
pub struct PolygonFrame { pub struct PolygonFrame {
pub radius: f32,
pub teta: f32, pub teta: f32,
pub polygons: Vec<Polygon>,
} }
impl<Message> canvas::Program<Message> for PolygonFrame { impl<Message> canvas::Program<Message> for PolygonFrame {
@@ -37,27 +36,34 @@ impl<Message> canvas::Program<Message> for PolygonFrame {
bounds: Rectangle, bounds: Rectangle,
_cursor: mouse::Cursor, _cursor: mouse::Cursor,
) -> Vec<canvas::Geometry> { ) -> Vec<canvas::Geometry> {
// We prepare a new `Frame`
let mut frame = canvas::Frame::new(renderer, bounds.size()); let mut frame = canvas::Frame::new(renderer, bounds.size());
let radius = frame.size().width / 2.0 - 32.0;
let mut vec = Vector::new(0.0, -radius);
let c = frame.center();
// We create a `Path` representing a simple circle // Draw all polygons by there points
let circle = canvas::Path::circle(frame.center(), self.radius); for poly in &self.polygons {
let mut vec = Vector::new(0.0, -self.radius); let l = poly.points_teta.len();
let line = canvas::Path::line( let mut line: canvas::Path;
frame.center() + vec, let mut t1: f32;
frame.center() + vec.rotate(2.0 * PI / 3.0), let mut t2: f32;
); for i in 0..l {
let dot = canvas::Path::circle(frame.center() + vec.rotate(self.teta), 10.0); t1 = poly.points_teta[i] + poly.global_teta;
t2 = poly.points_teta[(i + 1) % l] + poly.global_teta;
line = canvas::Path::line(c + vec.rotate(t1), c + vec.rotate(t2));
frame.stroke(
&line,
Stroke {
width: 5.0,
style: Style::Solid(Color::BLACK),
..Stroke::default()
},
);
}
}
frame.stroke( // Draw Circle
&line, let circle = canvas::Path::circle(frame.center(), radius);
Stroke {
width: 5.0,
..Stroke::default()
},
);
// And fill it with some color
frame.stroke( frame.stroke(
&circle, &circle,
Stroke { Stroke {
@@ -66,9 +72,35 @@ impl<Message> canvas::Program<Message> for PolygonFrame {
..Stroke::default() ..Stroke::default()
}, },
); );
// Draw the red dot on the current position
let dot = canvas::Path::circle(frame.center() + vec.rotate(self.teta), 5.0);
frame.fill(&dot, Color::from_rgb(1.0, 0.0, 0.0)); frame.fill(&dot, Color::from_rgb(1.0, 0.0, 0.0));
// Draw the frame
frame.stroke_rectangle(
iced::Point { x: 0.0, y: 0.0 },
frame.size(),
Stroke {
width: 16.0,
..Stroke::default()
},
);
// Then, we produce the geometry // Then, we produce the geometry
vec![frame.into_geometry()] vec![frame.into_geometry()]
} }
} }
pub struct Polygon {
pub global_teta: f32,
pub points_teta: Vec<f32>,
}
impl Polygon {
pub fn triangle(teta: f32) -> Self {
Polygon {
global_teta: teta,
points_teta: vec![0.0, 2.0 * PI / 3.0, 4.0 * PI / 3.0],
}
}
}