[lab3] Decomposed gui
This commit is contained in:
parent
642bb6619d
commit
50db706436
37
lab3/src/gui/data.rs
Normal file
37
lab3/src/gui/data.rs
Normal file
@ -0,0 +1,37 @@
|
||||
use bgtu_ai_utility::graph::CompleteGraph;
|
||||
use bgtu_ai_utility::UpdatePending;
|
||||
use crate::algo::{AntsSimulationConfig, AntsSimulationState};
|
||||
|
||||
pub(crate)enum GlobalState {
|
||||
Edit,
|
||||
Running,
|
||||
}
|
||||
pub(crate) struct MyApp {
|
||||
pub simulation: AntsSimulationState,
|
||||
pub config: AntsSimulationConfig,
|
||||
pub vertex_update: UpdatePending,
|
||||
pub state: GlobalState,
|
||||
pub vertex_locations: Vec<(f32, f32)>,
|
||||
pub ants_per_vertex: usize,
|
||||
}
|
||||
|
||||
impl MyApp {
|
||||
pub(crate) fn new() -> Self {
|
||||
return Self {
|
||||
simulation: AntsSimulationState {
|
||||
graph: CompleteGraph::new(),
|
||||
ants: Vec::new(),
|
||||
},
|
||||
vertex_update: UpdatePending::NoChange,
|
||||
config: AntsSimulationConfig {
|
||||
ferment_weight: 0.5,
|
||||
heuristic_coefficient: 0.5,
|
||||
q: 1.0,
|
||||
r: 0.5,
|
||||
},
|
||||
state: GlobalState::Edit {},
|
||||
vertex_locations: Vec::new(),
|
||||
ants_per_vertex: 1,
|
||||
};
|
||||
}
|
||||
}
|
||||
47
lab3/src/gui/graph.rs
Normal file
47
lab3/src/gui/graph.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use super::{GlobalState, MyApp};
|
||||
use crate::algo::updateState;
|
||||
use bgtu_ai_utility::gui::render_graph;
|
||||
use eframe::egui::Ui;
|
||||
|
||||
pub(crate) fn graph_with_controls(ui: &mut Ui, data: &mut MyApp) {
|
||||
ui.vertical(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Exit").clicked() {
|
||||
data.state = GlobalState::Edit
|
||||
}
|
||||
|
||||
if ui.button("Step").clicked() {
|
||||
updateState(&mut data.simulation, &mut data.config, &mut rand::rng());
|
||||
}
|
||||
ui.label("");
|
||||
});
|
||||
draw_ants(ui, data);
|
||||
if ui.input(|i| i.viewport().close_requested()) {
|
||||
data.state = GlobalState::Edit
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn draw_ants(ui: &mut Ui, data: &mut MyApp) {
|
||||
let mut cap: f64 = 0.000000000001;
|
||||
|
||||
for w in data
|
||||
.simulation
|
||||
.graph
|
||||
.edges
|
||||
.iter()
|
||||
.map(|e| e.extra.ferment_intensity)
|
||||
{
|
||||
if w > cap {
|
||||
cap = w
|
||||
}
|
||||
}
|
||||
|
||||
render_graph(
|
||||
ui,
|
||||
&data.simulation.graph.vertices,
|
||||
data.vertex_locations.as_mut_slice(),
|
||||
&data.simulation.graph.edges,
|
||||
|e| e.extra.ferment_intensity / cap,
|
||||
)
|
||||
}
|
||||
83
lab3/src/gui/input.rs
Normal file
83
lab3/src/gui/input.rs
Normal file
@ -0,0 +1,83 @@
|
||||
use std::collections::HashSet;
|
||||
use eframe::egui::Ui;
|
||||
use bgtu_ai_utility::gui::labeled_slider;
|
||||
use bgtu_ai_utility::gui::lengths_table::draw_lengths_table;
|
||||
use bgtu_ai_utility::UpdatePending;
|
||||
use crate::algo::Ant;
|
||||
use super::{GlobalState, MyApp};
|
||||
|
||||
pub(crate) fn input(ui: &mut Ui, data: &mut MyApp) {
|
||||
let mut run: bool = false;
|
||||
|
||||
labeled_slider(
|
||||
ui,
|
||||
"Ferment weight",
|
||||
&mut data.config.ferment_weight,
|
||||
0.0..=1.0,
|
||||
0.001,
|
||||
);
|
||||
ui.label("");
|
||||
labeled_slider(
|
||||
ui,
|
||||
"Heuristic coefficient",
|
||||
&mut data.config.heuristic_coefficient,
|
||||
0.0..=1.0,
|
||||
0.001,
|
||||
);
|
||||
ui.label("");
|
||||
labeled_slider(ui, "Q", &mut data.config.q, 0.0..=1.0, 0.001);
|
||||
ui.label("");
|
||||
labeled_slider(ui, "r", &mut data.config.r, 0.0..=1.0, 0.001);
|
||||
ui.label("");
|
||||
labeled_slider(
|
||||
ui,
|
||||
"Ants per vertex",
|
||||
&mut data.ants_per_vertex,
|
||||
1..=100,
|
||||
1.0,
|
||||
);
|
||||
ui.label("");
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Add vertex").clicked() {
|
||||
data.vertex_update = UpdatePending::Add;
|
||||
}
|
||||
ui.separator();
|
||||
run = ui.button("Run").clicked();
|
||||
});
|
||||
|
||||
draw_lengths_table(
|
||||
ui,
|
||||
&mut data.simulation.graph.vertices,
|
||||
&mut data.simulation.graph.edges,
|
||||
&mut data.vertex_update,
|
||||
);
|
||||
|
||||
if run {
|
||||
let mut coords = vec![(0.0, 0.0); data.simulation.graph.vertices.capacity()];
|
||||
|
||||
for (i, _) in data.simulation.graph.vertices.iter_indexed() {
|
||||
coords[i] = (
|
||||
rand::random::<f32>() * 0.8 + 0.1,
|
||||
rand::random::<f32>() * 0.8 + 0.1,
|
||||
)
|
||||
}
|
||||
|
||||
data.state = GlobalState::Running;
|
||||
data.vertex_locations = coords;
|
||||
|
||||
let allowed_locations = data
|
||||
.simulation
|
||||
.graph.vertices
|
||||
.iter_indexed()
|
||||
.map(|(i, _)| i)
|
||||
.collect::<HashSet<usize>>();
|
||||
|
||||
let mut ants = Vec::new();
|
||||
for (i, _) in data.simulation.graph.vertices.iter_indexed() {
|
||||
for _ in 0..data.ants_per_vertex {
|
||||
ants.push(Ant::new(i, allowed_locations.clone()))
|
||||
}
|
||||
}
|
||||
data.simulation.ants = ants;
|
||||
}
|
||||
}
|
||||
7
lab3/src/gui/mod.rs
Normal file
7
lab3/src/gui/mod.rs
Normal file
@ -0,0 +1,7 @@
|
||||
mod data;
|
||||
mod input;
|
||||
mod graph;
|
||||
|
||||
pub(crate) use data::{MyApp, GlobalState};
|
||||
pub(crate) use input::input;
|
||||
pub(crate) use graph::graph_with_controls;
|
||||
199
lab3/src/main.rs
199
lab3/src/main.rs
@ -1,66 +1,22 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
|
||||
mod algo;
|
||||
mod gui;
|
||||
|
||||
use crate::algo::{
|
||||
Ant, AntsSimulationConfig, AntsSimulationState, EdgeExtraData, EdgesVec, VerticesVec,
|
||||
updateState,
|
||||
};
|
||||
use crate::algo::EdgeExtraData;
|
||||
use bgtu_ai_utility::gui::boot_eframe;
|
||||
use bgtu_ai_utility::gui::subwindow;
|
||||
use bgtu_ai_utility::UpdatePending;
|
||||
use bgtu_ai_utility::gui::lengths_table::draw_lengths_table;
|
||||
use bgtu_ai_utility::gui::render_graph;
|
||||
use bgtu_ai_utility::gui::{boot_eframe, labeled_slider};
|
||||
use eframe::egui;
|
||||
use eframe::egui::{Frame, Ui};
|
||||
use std::collections::HashSet;
|
||||
use bgtu_ai_utility::graph::CompleteGraph;
|
||||
|
||||
fn main() -> eframe::Result {
|
||||
return boot_eframe(
|
||||
"Ants simulation",
|
||||
|| MyApp::new()
|
||||
);
|
||||
return boot_eframe("Ants simulation", || gui::MyApp::new());
|
||||
}
|
||||
|
||||
enum GlobalState {
|
||||
Edit,
|
||||
Running,
|
||||
}
|
||||
|
||||
struct MyApp {
|
||||
simulation: AntsSimulationState,
|
||||
config: AntsSimulationConfig,
|
||||
vertex_update: UpdatePending,
|
||||
state: GlobalState,
|
||||
vertex_locations: Vec<(f32, f32)>,
|
||||
ants_per_vertex: usize,
|
||||
}
|
||||
|
||||
impl MyApp {
|
||||
fn new() -> Self {
|
||||
return Self {
|
||||
simulation: AntsSimulationState {
|
||||
graph: CompleteGraph::new(),
|
||||
ants: Vec::new(),
|
||||
},
|
||||
vertex_update: UpdatePending::NoChange,
|
||||
config: AntsSimulationConfig {
|
||||
ferment_weight: 0.5,
|
||||
heuristic_coefficient: 0.5,
|
||||
q: 1.0,
|
||||
r: 0.5,
|
||||
},
|
||||
state: GlobalState::Edit {},
|
||||
vertex_locations: Vec::new(),
|
||||
ants_per_vertex: 1,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
impl eframe::App for gui::MyApp {
|
||||
fn update(&mut self, ui: &eframe::egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ui, |ui| match self.state {
|
||||
GlobalState::Edit {} => {
|
||||
gui::GlobalState::Edit {} => {
|
||||
match self.vertex_update {
|
||||
UpdatePending::NoChange => {}
|
||||
UpdatePending::Add => {
|
||||
@ -74,141 +30,16 @@ impl eframe::App for MyApp {
|
||||
self.vertex_update = UpdatePending::NoChange;
|
||||
}
|
||||
}
|
||||
edit_panel(self, ui)
|
||||
gui::input(ui, self)
|
||||
}
|
||||
GlobalState::Running { .. } => {
|
||||
ui.add_enabled_ui(false, |ui| edit_panel(self, ui));
|
||||
ui.ctx().show_viewport_immediate(
|
||||
egui::ViewportId::from_hash_of("Visualisation"),
|
||||
egui::ViewportBuilder::default()
|
||||
.with_title("Visualisation")
|
||||
.with_inner_size([640.0, 480.0])
|
||||
.with_resizable(false),
|
||||
|ui, _| {
|
||||
egui::CentralPanel::default()
|
||||
.frame(Frame::default().inner_margin(0.0))
|
||||
.show(ui, |ui| visualization_panel(self, ui));
|
||||
},
|
||||
);
|
||||
gui::GlobalState::Running { .. } => {
|
||||
ui.add_enabled_ui(false, |ui| gui::input(ui, self));
|
||||
subwindow(
|
||||
ui, "visualisation", "Visualisation",
|
||||
|vb| vb.with_inner_size([640.0, 480.0]),
|
||||
|ui| gui::graph_with_controls(ui, self),
|
||||
).on_close(|| self.state = gui::GlobalState::Edit);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn edit_panel(data: &mut MyApp, ui: &mut Ui) {
|
||||
let mut run: bool = false;
|
||||
|
||||
labeled_slider(
|
||||
ui,
|
||||
"Ferment weight",
|
||||
&mut data.config.ferment_weight,
|
||||
0.0..=1.0,
|
||||
0.001,
|
||||
);
|
||||
ui.label("");
|
||||
labeled_slider(
|
||||
ui,
|
||||
"Heuristic coefficient",
|
||||
&mut data.config.heuristic_coefficient,
|
||||
0.0..=1.0,
|
||||
0.001,
|
||||
);
|
||||
ui.label("");
|
||||
labeled_slider(ui, "Q", &mut data.config.q, 0.0..=1.0, 0.001);
|
||||
ui.label("");
|
||||
labeled_slider(ui, "r", &mut data.config.r, 0.0..=1.0, 0.001);
|
||||
ui.label("");
|
||||
labeled_slider(
|
||||
ui,
|
||||
"Ants per vertex",
|
||||
&mut data.ants_per_vertex,
|
||||
1..=100,
|
||||
1.0,
|
||||
);
|
||||
ui.label("");
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Add vertex").clicked() {
|
||||
data.vertex_update = UpdatePending::Add;
|
||||
}
|
||||
ui.separator();
|
||||
run = ui.button("Run").clicked();
|
||||
});
|
||||
|
||||
draw_lengths_table(
|
||||
ui,
|
||||
&mut data.simulation.graph.vertices,
|
||||
&mut data.simulation.graph.edges,
|
||||
&mut data.vertex_update,
|
||||
);
|
||||
|
||||
if run {
|
||||
let mut coords = vec![(0.0, 0.0); data.simulation.graph.vertices.capacity()];
|
||||
|
||||
for (i, _) in data.simulation.graph.vertices.iter_indexed() {
|
||||
coords[i] = (
|
||||
rand::random::<f32>() * 0.8 + 0.1,
|
||||
rand::random::<f32>() * 0.8 + 0.1,
|
||||
)
|
||||
}
|
||||
|
||||
data.state = GlobalState::Running;
|
||||
data.vertex_locations = coords;
|
||||
|
||||
let allowed_locations = data
|
||||
.simulation
|
||||
.graph.vertices
|
||||
.iter_indexed()
|
||||
.map(|(i, _)| i)
|
||||
.collect::<HashSet<usize>>();
|
||||
|
||||
let mut ants = Vec::new();
|
||||
for (i, _) in data.simulation.graph.vertices.iter_indexed() {
|
||||
for _ in 0..data.ants_per_vertex {
|
||||
ants.push(Ant::new(i, allowed_locations.clone()))
|
||||
}
|
||||
}
|
||||
data.simulation.ants = ants;
|
||||
}
|
||||
}
|
||||
|
||||
fn visualization_panel(data: &mut MyApp, ui: &mut Ui) {
|
||||
ui.vertical(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Exit").clicked() {
|
||||
data.state = GlobalState::Edit
|
||||
}
|
||||
|
||||
if ui.button("Step").clicked() {
|
||||
updateState(&mut data.simulation, &mut data.config, &mut rand::rng());
|
||||
}
|
||||
ui.label("");
|
||||
});
|
||||
draw_ants(data, ui);
|
||||
if ui.input(|i| i.viewport().close_requested()) {
|
||||
data.state = GlobalState::Edit
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn draw_ants(data: &mut MyApp, ui: &mut Ui) {
|
||||
let mut cap: f64 = 0.000000000001;
|
||||
|
||||
for w in data
|
||||
.simulation
|
||||
.graph.edges
|
||||
.iter()
|
||||
.map(|e| e.extra.ferment_intensity)
|
||||
{
|
||||
if w > cap {
|
||||
cap = w
|
||||
}
|
||||
}
|
||||
|
||||
render_graph(
|
||||
ui,
|
||||
&data.simulation.graph.vertices,
|
||||
data.vertex_locations.as_mut_slice(),
|
||||
&data.simulation.graph.edges,
|
||||
|e| e.extra.ferment_intensity / cap,
|
||||
)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user