[lab3] Edit panel (with actions)
This commit is contained in:
parent
16444210e2
commit
c0f03fd71a
109
lab3/src/algo/_preserve_index_vec.rs
Normal file
109
lab3/src/algo/_preserve_index_vec.rs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
|
enum Cell<T> {
|
||||||
|
Free { next_free_cell_id: Option<usize> },
|
||||||
|
Value { value: T },
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) struct _PreserveIndexVec<T> {
|
||||||
|
next_free: Option<usize>,
|
||||||
|
buffer: Vec<Cell<T>>,
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> _PreserveIndexVec<T> {
|
||||||
|
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<Item=&T>{
|
||||||
|
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<Item=(usize, &T)>{
|
||||||
|
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<Item=(usize, &mut T)>{
|
||||||
|
return self.buffer.iter_mut().enumerate().filter_map(|(i, c)| {
|
||||||
|
match c {
|
||||||
|
Cell::Free { .. } => return None,
|
||||||
|
Cell::Value { value } => return Some((i, value))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Index<usize> for _PreserveIndexVec<T> {
|
||||||
|
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<T> IndexMut<usize> for _PreserveIndexVec<T> {
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
use super::_PreserveIndexVec;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
pub struct Edge {
|
pub struct Edge {
|
||||||
@ -7,43 +8,54 @@ pub struct Edge {
|
|||||||
pub ferment_intensity: f64,
|
pub ferment_intensity: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EdgeCell {
|
impl Edge {
|
||||||
Free { next_free_cell_id: Option<usize> },
|
pub fn another(&self, current: usize) -> usize {
|
||||||
Value { data: Edge },
|
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 {
|
pub struct EdgesVec {
|
||||||
storage: Vec<EdgeCell>,
|
data: _PreserveIndexVec<Edge>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EdgesVec {
|
impl EdgesVec {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
return 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<usize> for EdgesVec {
|
impl Index<usize> for EdgesVec {
|
||||||
type Output = Edge;
|
type Output = Edge;
|
||||||
|
|
||||||
fn index(&self, index: usize) -> &Self::Output {
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
match self.storage.get(index).expect("Edge index out of bounds") {
|
return self.data.index(index);
|
||||||
EdgeCell::Free { .. } => panic!("Referenced edge doesn't exists"),
|
|
||||||
EdgeCell::Value { data } => return data,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndexMut<usize> for EdgesVec {
|
impl IndexMut<usize> for EdgesVec {
|
||||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||||
match self
|
return self.data.index_mut(index);
|
||||||
.storage
|
|
||||||
.get_mut(index)
|
|
||||||
.expect("Edge index out of bounds")
|
|
||||||
{
|
|
||||||
EdgeCell::Free { .. } => panic!("Referenced edge doesn't exists"),
|
|
||||||
EdgeCell::Value { data } => return data,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
mod edges;
|
mod edges;
|
||||||
mod state;
|
mod state;
|
||||||
|
mod vertices;
|
||||||
|
mod _preserve_index_vec;
|
||||||
|
|
||||||
pub use edges::EdgesVec;
|
pub use edges::EdgesVec;
|
||||||
|
pub use vertices::VerticesVec;
|
||||||
|
use _preserve_index_vec::_PreserveIndexVec;
|
||||||
|
|
||||||
|
|
||||||
pub struct AntsSimulationConfig {
|
pub struct AntsSimulationConfig {
|
||||||
pub ferment_weight: f64,
|
pub ferment_weight: f64,
|
||||||
|
|||||||
50
lab3/src/algo/vertices.rs
Normal file
50
lab3/src/algo/vertices.rs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
use super::_PreserveIndexVec;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
|
pub struct VerticesVec {
|
||||||
|
data: _PreserveIndexVec<HashSet<usize>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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>) -> 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<Item = &HashSet<usize>> {
|
||||||
|
return self.data.iter();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter_indexed(&self) -> impl Iterator<Item = (usize, &HashSet<usize>)> {
|
||||||
|
return self.data.iter_indexed();
|
||||||
|
}
|
||||||
|
pub fn iter_indexed_mut(&mut self) -> impl Iterator<Item = (usize, &mut HashSet<usize>)> {
|
||||||
|
return self.data.iter_indexed_mut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Index<usize> for VerticesVec {
|
||||||
|
type Output = HashSet<usize>;
|
||||||
|
|
||||||
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
|
return self.data.index(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexMut<usize> for VerticesVec {
|
||||||
|
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||||
|
return self.data.index_mut(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
105
lab3/src/main.rs
105
lab3/src/main.rs
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
mod algo;
|
mod algo;
|
||||||
|
|
||||||
use crate::algo::{AntsSimulationConfig, EdgesVec};
|
use crate::algo::{AntsSimulationConfig, EdgesVec, VerticesVec};
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use eframe::egui::scroll_area::ScrollBarVisibility;
|
use eframe::egui::scroll_area::ScrollBarVisibility;
|
||||||
use eframe::egui::{ScrollArea, Ui};
|
use eframe::egui::{ScrollArea, Ui};
|
||||||
use eframe::emath::Numeric;
|
use eframe::emath::Numeric;
|
||||||
use egui_extras::{Column, TableBuilder};
|
use egui_extras::{Column, TableBuilder};
|
||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::ptr::{NonNull, fn_addr_eq};
|
use std::ptr::{NonNull, fn_addr_eq};
|
||||||
@ -44,7 +44,7 @@ enum GlobalState {
|
|||||||
|
|
||||||
struct MyApp {
|
struct MyApp {
|
||||||
edges: EdgesVec,
|
edges: EdgesVec,
|
||||||
vertices: Vec<HashSet<usize>>,
|
vertices: VerticesVec,
|
||||||
config: AntsSimulationConfig,
|
config: AntsSimulationConfig,
|
||||||
vertex_update: UpdatePending,
|
vertex_update: UpdatePending,
|
||||||
speed: u32,
|
speed: u32,
|
||||||
@ -55,7 +55,7 @@ impl Default for MyApp {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
return Self {
|
return Self {
|
||||||
edges: EdgesVec::new(),
|
edges: EdgesVec::new(),
|
||||||
vertices: Vec::new(),
|
vertices: VerticesVec::new(),
|
||||||
vertex_update: UpdatePending::NoChange,
|
vertex_update: UpdatePending::NoChange,
|
||||||
speed: 1,
|
speed: 1,
|
||||||
config: AntsSimulationConfig {
|
config: AntsSimulationConfig {
|
||||||
@ -90,6 +90,38 @@ fn _slider<T: Numeric>(
|
|||||||
impl eframe::App for MyApp {
|
impl eframe::App for MyApp {
|
||||||
fn update(&mut self, ui: &eframe::egui::Context, _frame: &mut eframe::Frame) {
|
fn update(&mut self, ui: &eframe::egui::Context, _frame: &mut eframe::Frame) {
|
||||||
egui::CentralPanel::default().show(ui, |ui| {
|
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)
|
edit_panel(self, ui)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -133,8 +165,12 @@ fn edit_panel(data: &mut MyApp, ui: &mut Ui) {
|
|||||||
.striped(true) // Alternating row colors
|
.striped(true) // Alternating row colors
|
||||||
.resizable(true)
|
.resizable(true)
|
||||||
.vscroll(false)
|
.vscroll(false)
|
||||||
|
.column(Column::remainder())
|
||||||
.columns(Column::remainder(), data.vertices.len())
|
.columns(Column::remainder(), data.vertices.len())
|
||||||
.header(20.0, |mut header| {
|
.header(20.0, |mut header| {
|
||||||
|
header.col(|ui| {
|
||||||
|
ui.label("#");
|
||||||
|
});
|
||||||
for (i, _) in data.vertices.iter().enumerate() {
|
for (i, _) in data.vertices.iter().enumerate() {
|
||||||
header.col(|ui| {
|
header.col(|ui| {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
@ -146,31 +182,46 @@ fn edit_panel(data: &mut MyApp, ui: &mut Ui) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.body(|body| {
|
.body(|mut body| {
|
||||||
body.rows(20.0, data.vertices.len(), |mut row| {
|
for (ri, (vi, v)) in data.vertices.iter_indexed().enumerate() {
|
||||||
let vi = row.index();
|
body.row(20.0, |mut row| {
|
||||||
let mut edges =
|
|
||||||
Vec::<(usize, NonNull<f64>)>::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 {
|
|
||||||
row.col(|ui| {
|
row.col(|ui| {
|
||||||
ui.add(
|
ui.horizontal(|ui| {
|
||||||
egui::Slider::new(unsafe { v.as_mut() }, 0.0..=10.0)
|
ui.label(ri.to_string());
|
||||||
.step_by(0.1),
|
if ui.button("-").clicked() {
|
||||||
);
|
data.vertex_update = UpdatePending::Remove(vi);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
|
||||||
})
|
let mut edges = Vec::<(usize, NonNull<f64>)>::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| {});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user