diff --git a/lab3/src/algo/_preserve_index_vec.rs b/lab3/src/algo/_preserve_index_vec.rs new file mode 100644 index 0000000..41631eb --- /dev/null +++ b/lab3/src/algo/_preserve_index_vec.rs @@ -0,0 +1,109 @@ +use std::ops::{Index, IndexMut}; + +enum Cell { + Free { next_free_cell_id: Option }, + Value { value: T }, +} + +pub(super) struct _PreserveIndexVec { + next_free: Option, + buffer: Vec>, + len: usize, +} + +impl _PreserveIndexVec { + pub fn new() -> Self { + return Self { + next_free: None, + buffer: Vec::new(), + len: 0, + }; + } + pub fn len(&self) -> usize { + return self.len; + } + + pub fn add(&mut self, value: T) -> usize { + match self.next_free { + None => { + self.buffer.push(Cell::Value { value }); + self.len += 1; + return self.buffer.len() - 1; + } + Some(i) => match self.buffer[i] { + Cell::Free { next_free_cell_id } => { + self.next_free = next_free_cell_id; + self.buffer[i] = Cell::Value { value }; + self.len += 1; + return i; + } + Cell::Value { .. } => panic!("Busy cell marked as free"), + }, + } + } + + pub fn remove(&mut self, cell_index: usize) { + match self.buffer[cell_index] { + Cell::Free { .. } => panic!("Cell already free"), + Cell::Value { .. } => { + self.buffer[cell_index] = Cell::Free { + next_free_cell_id: self.next_free, + }; + self.next_free = Some(cell_index); + self.len -= 1; + } + } + } + + pub fn iter(&self) -> impl Iterator{ + return self.buffer.iter().filter_map(|c| { + match c { + Cell::Free { .. } => return None, + Cell::Value { value } => return Some(value) + } + }) + } + + pub fn iter_indexed(&self) -> impl Iterator{ + return self.buffer.iter().enumerate().filter_map(|(i, c)| { + match c { + Cell::Free { .. } => return None, + Cell::Value { value } => return Some((i, value)) + } + }) + } + + pub fn iter_indexed_mut(&mut self) -> impl Iterator{ + return self.buffer.iter_mut().enumerate().filter_map(|(i, c)| { + match c { + Cell::Free { .. } => return None, + Cell::Value { value } => return Some((i, value)) + } + }) + } +} + +impl Index for _PreserveIndexVec { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + match self.buffer.get(index).expect("Cell index out of bounds") { + Cell::Free { .. } => panic!("Referenced cell doesn't exists"), + Cell::Value { value } => return value, + } + } +} + +impl IndexMut for _PreserveIndexVec { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + match self + .buffer + .get_mut(index) + .expect("Cell index out of bounds") + { + Cell::Free { .. } => panic!("Referenced cell doesn't exists"), + Cell::Value { value } => return value, + } + } +} + diff --git a/lab3/src/algo/edges.rs b/lab3/src/algo/edges.rs index 7d5a41e..3039d53 100644 --- a/lab3/src/algo/edges.rs +++ b/lab3/src/algo/edges.rs @@ -1,3 +1,4 @@ +use super::_PreserveIndexVec; use std::ops::{Index, IndexMut}; pub struct Edge { @@ -7,43 +8,54 @@ pub struct Edge { pub ferment_intensity: f64, } -enum EdgeCell { - Free { next_free_cell_id: Option }, - Value { data: Edge }, +impl Edge { + pub fn another(&self, current: usize) -> usize { + if self.vertex1_index == current { + return self.vertex2_index; + } else if self.vertex2_index == current { + return self.vertex1_index; + } else { + panic!("Edge not connected to specified vertex"); + } + } } pub struct EdgesVec { - storage: Vec, + data: _PreserveIndexVec, } impl EdgesVec { pub fn new() -> Self { return Self { - storage: Vec::new(), + data: _PreserveIndexVec::new(), }; } + + pub fn add(&mut self, vertex1: usize, vertex2: usize, length: f64) -> usize { + let data = Edge { + vertex1_index: vertex1, + vertex2_index: vertex2, + length, + ferment_intensity: 0.0, + }; + return self.data.add(data); + } + + pub fn remove(&mut self, edge_index: usize) { + self.data.remove(edge_index) + } } impl Index for EdgesVec { type Output = Edge; fn index(&self, index: usize) -> &Self::Output { - match self.storage.get(index).expect("Edge index out of bounds") { - EdgeCell::Free { .. } => panic!("Referenced edge doesn't exists"), - EdgeCell::Value { data } => return data, - } + return self.data.index(index); } } impl IndexMut for EdgesVec { fn index_mut(&mut self, index: usize) -> &mut Self::Output { - match self - .storage - .get_mut(index) - .expect("Edge index out of bounds") - { - EdgeCell::Free { .. } => panic!("Referenced edge doesn't exists"), - EdgeCell::Value { data } => return data, - } + return self.data.index_mut(index); } } diff --git a/lab3/src/algo/mod.rs b/lab3/src/algo/mod.rs index 5823aa5..c168195 100644 --- a/lab3/src/algo/mod.rs +++ b/lab3/src/algo/mod.rs @@ -1,7 +1,12 @@ mod edges; mod state; +mod vertices; +mod _preserve_index_vec; pub use edges::EdgesVec; +pub use vertices::VerticesVec; +use _preserve_index_vec::_PreserveIndexVec; + pub struct AntsSimulationConfig { pub ferment_weight: f64, diff --git a/lab3/src/algo/vertices.rs b/lab3/src/algo/vertices.rs new file mode 100644 index 0000000..4402be7 --- /dev/null +++ b/lab3/src/algo/vertices.rs @@ -0,0 +1,50 @@ +use super::_PreserveIndexVec; +use std::collections::HashSet; +use std::ops::{Index, IndexMut}; + +pub struct VerticesVec { + data: _PreserveIndexVec>, +} + +impl VerticesVec { + pub fn new() -> Self { + return Self { + data: _PreserveIndexVec::new(), + }; + } + + pub fn len(&self) -> usize { + return self.data.len(); + } + pub fn add(&mut self, edges: HashSet) -> usize { + return self.data.add(edges); + } + + pub fn remove(&mut self, edge_index: usize) { + self.data.remove(edge_index) + } + pub fn iter(&self) -> impl Iterator> { + return self.data.iter(); + } + + pub fn iter_indexed(&self) -> impl Iterator)> { + return self.data.iter_indexed(); + } + pub fn iter_indexed_mut(&mut self) -> impl Iterator)> { + return self.data.iter_indexed_mut(); + } +} + +impl Index for VerticesVec { + type Output = HashSet; + + fn index(&self, index: usize) -> &Self::Output { + return self.data.index(index); + } +} + +impl IndexMut for VerticesVec { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + return self.data.index_mut(index); + } +} diff --git a/lab3/src/main.rs b/lab3/src/main.rs index 5735a09..60af373 100644 --- a/lab3/src/main.rs +++ b/lab3/src/main.rs @@ -2,13 +2,13 @@ mod algo; -use crate::algo::{AntsSimulationConfig, EdgesVec}; +use crate::algo::{AntsSimulationConfig, EdgesVec, VerticesVec}; use eframe::egui; use eframe::egui::scroll_area::ScrollBarVisibility; use eframe::egui::{ScrollArea, Ui}; use eframe::emath::Numeric; use egui_extras::{Column, TableBuilder}; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::ops::RangeInclusive; use std::ptr; use std::ptr::{NonNull, fn_addr_eq}; @@ -44,7 +44,7 @@ enum GlobalState { struct MyApp { edges: EdgesVec, - vertices: Vec>, + vertices: VerticesVec, config: AntsSimulationConfig, vertex_update: UpdatePending, speed: u32, @@ -55,7 +55,7 @@ impl Default for MyApp { fn default() -> Self { return Self { edges: EdgesVec::new(), - vertices: Vec::new(), + vertices: VerticesVec::new(), vertex_update: UpdatePending::NoChange, speed: 1, config: AntsSimulationConfig { @@ -90,6 +90,38 @@ fn _slider( impl eframe::App for MyApp { fn update(&mut self, ui: &eframe::egui::Context, _frame: &mut eframe::Frame) { egui::CentralPanel::default().show(ui, |ui| { + match self.state { + GlobalState::Edit {} => match self.vertex_update { + UpdatePending::NoChange => {} + UpdatePending::Add => { + let new_vi = self.vertices.add(HashSet::new()); + let mut newEdgesSet = HashSet::new(); + for (vi, v) in self.vertices.iter_indexed_mut() { + if (vi == new_vi) { + continue; + } + let ei = self.edges.add(new_vi, vi, 1.0); + newEdgesSet.insert(ei); + v.insert(ei); + } + self.vertices[new_vi] = newEdgesSet; + self.vertex_update = UpdatePending::NoChange; + } + UpdatePending::Remove(vi) => { + let mut eis = Vec::with_capacity(self.vertices[vi].len()); + for ei in self.vertices[vi].iter() { + eis.push(*ei) + } + for ei in eis { + self.vertices[self.edges[ei].another(vi)].remove(&ei); + self.edges.remove(ei); + } + self.vertices.remove(vi); + self.vertex_update = UpdatePending::NoChange; + } + }, + GlobalState::Running { .. } => {} + } edit_panel(self, ui) }); } @@ -133,8 +165,12 @@ fn edit_panel(data: &mut MyApp, ui: &mut Ui) { .striped(true) // Alternating row colors .resizable(true) .vscroll(false) + .column(Column::remainder()) .columns(Column::remainder(), data.vertices.len()) .header(20.0, |mut header| { + header.col(|ui| { + ui.label("#"); + }); for (i, _) in data.vertices.iter().enumerate() { header.col(|ui| { ui.horizontal(|ui| { @@ -146,31 +182,46 @@ fn edit_panel(data: &mut MyApp, ui: &mut Ui) { }); } }) - .body(|body| { - body.rows(20.0, data.vertices.len(), |mut row| { - let vi = row.index(); - let mut edges = - Vec::<(usize, NonNull)>::with_capacity(data.vertices[vi].len()); - for ei in data.vertices[vi].iter() { - let e = &mut data.edges[*ei]; - let p; - if vi == e.vertex1_index { - p = (e.vertex2_index, &mut e.length); - } else { - p = (e.vertex1_index, &mut e.length); - } - edges.push((p.0, NonNull::from_mut(p.1))); - } - edges.sort_by_key(|(k, _)| *k); - for (_, mut v) in edges { + .body(|mut body| { + for (ri, (vi, v)) in data.vertices.iter_indexed().enumerate() { + body.row(20.0, |mut row| { row.col(|ui| { - ui.add( - egui::Slider::new(unsafe { v.as_mut() }, 0.0..=10.0) - .step_by(0.1), - ); + ui.horizontal(|ui| { + ui.label(ri.to_string()); + if ui.button("-").clicked() { + data.vertex_update = UpdatePending::Remove(vi); + } + }); }); - } - }) + + let mut edges = Vec::<(usize, NonNull)>::with_capacity(v.len()); + for ei in v.iter() { + let e = &mut data.edges[*ei]; + let p = (e.another(vi), &mut e.length); + edges.push((p.0, NonNull::from_mut(p.1))); + } + edges.sort_by_key(|(k, _)| *k); + + let mut ci = 0usize; + for &(_, mut l) in edges.iter() { + if (ci == ri) { + row.col(|ui| {}); + ci += 1 + } + row.col(|ui| { + ui.add( + egui::Slider::new(unsafe { l.as_mut() }, 0.0..=10.0) + .step_by(0.1), + ); + }); + ci += 1; + } + + if ri == data.vertices.len() - 1 { + row.col(|ui| {}); + } + }); + } }); }); }