[lab3] Finished ui refactoring
This commit is contained in:
parent
2ea5448ae3
commit
2b601e8d9a
@ -1,8 +1,15 @@
|
|||||||
use bgtu_ai_utility::graph::CompleteGraph;
|
|
||||||
use bgtu_ai_utility::UpdatePending;
|
|
||||||
use crate::algo::{AntsSimulationConfig, AntsSimulationState};
|
use crate::algo::{AntsSimulationConfig, AntsSimulationState};
|
||||||
|
use bgtu_ai_utility::UpdatePending;
|
||||||
|
use bgtu_ai_utility::graph::CompleteGraph;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
pub(crate) enum AntsVisualisationData<'cfg> {
|
pub(crate) struct AntsVisualisationData {
|
||||||
|
pub config: AntsSimulationConfig,
|
||||||
|
pub graph: CompleteGraph<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) enum AntsVisualisationState<'cfg> {
|
||||||
Edit {
|
Edit {
|
||||||
config: &'cfg mut AntsSimulationConfig,
|
config: &'cfg mut AntsSimulationConfig,
|
||||||
graph: &'cfg mut CompleteGraph<()>,
|
graph: &'cfg mut CompleteGraph<()>,
|
||||||
@ -15,28 +22,31 @@ pub(crate) enum AntsVisualisationData<'cfg> {
|
|||||||
vertex_locations: Vec<(f32, f32)>,
|
vertex_locations: Vec<(f32, f32)>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
pub(crate) struct MyApp<'cfg> {
|
|
||||||
pub state: AntsVisualisationData<'cfg>,
|
pub(crate) struct AntsVisualisationApp {
|
||||||
pub ants_per_vertex: usize,
|
pub data: Pin<Box<AntsVisualisationData>>,
|
||||||
|
pub state: AntsVisualisationState<'static /* actually not but fuck rust */>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MyApp {
|
impl AntsVisualisationApp {
|
||||||
pub(crate) fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
return Self {
|
let mut data = Box::pin(AntsVisualisationData {
|
||||||
simulation: AntsSimulationState {
|
|
||||||
graph: CompleteGraph::new(),
|
|
||||||
ants: Vec::new(),
|
|
||||||
},
|
|
||||||
vertex_update: UpdatePending::NoChange,
|
|
||||||
config: AntsSimulationConfig {
|
config: AntsSimulationConfig {
|
||||||
ferment_weight: 0.5,
|
ferment_weight: 0.5,
|
||||||
heuristic_coefficient: 0.5,
|
heuristic_coefficient: 0.5,
|
||||||
q: 1.0,
|
q: 1.0,
|
||||||
r: 0.5,
|
r: 0.5,
|
||||||
},
|
},
|
||||||
state: AntsVisualisationData::Edit {},
|
graph: CompleteGraph::new(),
|
||||||
vertex_locations: Vec::new(),
|
});
|
||||||
|
|
||||||
|
let state = AntsVisualisationState::Edit {
|
||||||
|
config: unsafe { NonNull::from_mut(&mut data.config).as_mut() },
|
||||||
|
graph: unsafe { NonNull::from_mut(&mut data.graph).as_mut() },
|
||||||
ants_per_vertex: 1,
|
ants_per_vertex: 1,
|
||||||
|
vertex_update: UpdatePending::NoChange,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return Self { data, state };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,37 +1,36 @@
|
|||||||
use super::{AntsVisualisationData, MyApp};
|
use crate::algo::AntsSimulationState;
|
||||||
use crate::algo::updateState;
|
|
||||||
use bgtu_ai_utility::gui::render_graph;
|
use bgtu_ai_utility::gui::render_graph;
|
||||||
use eframe::egui::Ui;
|
use eframe::egui::Ui;
|
||||||
|
use rand::{Rng, rng};
|
||||||
|
|
||||||
pub(crate) fn graph_with_controls(ui: &mut Ui, data: &mut MyApp) {
|
pub(crate) fn graph_with_controls(
|
||||||
|
ui: &mut Ui,
|
||||||
|
vertex_locations: &mut [(f32, f32)],
|
||||||
|
data: &mut AntsSimulationState,
|
||||||
|
exit: &mut bool,
|
||||||
|
) {
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
if ui.button("Exit").clicked() {
|
if ui.button("Exit").clicked() {
|
||||||
data.state = AntsVisualisationData::Edit
|
*exit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ui.button("Step").clicked() {
|
if ui.button("Step").clicked() {
|
||||||
updateState(&mut data.simulation, &mut data.config, &mut rand::rng());
|
data.update1(&mut rng());
|
||||||
}
|
}
|
||||||
ui.label("");
|
ui.label("");
|
||||||
});
|
});
|
||||||
draw_ants(ui, data);
|
draw_ants(ui, vertex_locations, data);
|
||||||
if ui.input(|i| i.viewport().close_requested()) {
|
if ui.input(|i| i.viewport().close_requested()) {
|
||||||
data.state = AntsVisualisationData::Edit
|
*exit = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_ants(ui: &mut Ui, data: &mut MyApp) {
|
fn draw_ants(ui: &mut Ui, vertex_locations: &mut [(f32, f32)], data: &mut AntsSimulationState) {
|
||||||
let mut cap: f64 = 0.000000000001;
|
let mut cap: f64 = 0.000000000001;
|
||||||
|
|
||||||
for w in data
|
for w in data.graph.edges.iter_indexes().map(|i| data.ferments[i]) {
|
||||||
.simulation
|
|
||||||
.graph
|
|
||||||
.edges
|
|
||||||
.iter()
|
|
||||||
.map(|e| e.extra.ferment_intensity)
|
|
||||||
{
|
|
||||||
if w > cap {
|
if w > cap {
|
||||||
cap = w
|
cap = w
|
||||||
}
|
}
|
||||||
@ -39,9 +38,20 @@ fn draw_ants(ui: &mut Ui, data: &mut MyApp) {
|
|||||||
|
|
||||||
render_graph(
|
render_graph(
|
||||||
ui,
|
ui,
|
||||||
&data.simulation.graph.vertices,
|
&data.graph.vertices,
|
||||||
data.vertex_locations.as_mut_slice(),
|
vertex_locations,
|
||||||
&data.simulation.graph.edges,
|
&data.graph.edges,
|
||||||
|e| e.extra.ferment_intensity / cap,
|
|ei, _| data.ferments[ei] / cap,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn gen_vertex_locations(rng: &mut impl Rng, count: usize) -> Vec<(f32, f32)> {
|
||||||
|
let mut v = Vec::new();
|
||||||
|
for _ in 0..count {
|
||||||
|
v.push((
|
||||||
|
rng.random::<f32>() * 0.8 + 0.1,
|
||||||
|
rng.random::<f32>() * 0.8 + 0.1,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,23 +1,24 @@
|
|||||||
use crate::algo::AntsSimulationConfig;
|
use crate::algo::AntsSimulationConfig;
|
||||||
use bgtu_ai_utility::UpdatePending;
|
use bgtu_ai_utility::UpdatePending;
|
||||||
use bgtu_ai_utility::graph::CompleteGraph;
|
use bgtu_ai_utility::graph::CompleteGraph;
|
||||||
use bgtu_ai_utility::gui::const_mut_switch::{_ConstMutSwitchUiCallback, ConstMutSwitchUi, RefType, RefGetter};
|
use bgtu_ai_utility::gui::const_mut_switch::{
|
||||||
|
_ConstMutSwitchUiCallback, ConstMutSwitchUi, MutUI, RefType,
|
||||||
|
};
|
||||||
|
use bgtu_ai_utility::gui::graph_lengths_table::{Graph, draw_lengths_table};
|
||||||
|
|
||||||
pub(crate) fn input<Ctx: ConstMutSwitchUi + RefGetter>(
|
pub(crate) fn input<Ctx: ConstMutSwitchUi>(
|
||||||
ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
mut config: Ctx::Ref<'_, AntsSimulationConfig>,
|
mut config: <Ctx::RefType as RefType>::Ref<'_, AntsSimulationConfig>,
|
||||||
mut graph: Ctx::RefType::Ref<'_, CompleteGraph<()>>,
|
graph: &mut impl Graph<RefType = Ctx::RefType>,
|
||||||
mut ants_per_vertex: Ctx::RefType::Ref<'_, usize>,
|
mut ants_per_vertex: <Ctx::RefType as RefType>::Ref<'_, usize>,
|
||||||
mut vertex_update: Ctx::RefType::Ref<'_, UpdatePending>,
|
mut vertex_update: <Ctx::RefType as RefType>::Ref<'_, UpdatePending>,
|
||||||
mut launch: Ctx::RefType::Ref<'_, bool>,
|
mut launch: <Ctx::RefType as RefType>::Ref<'_, bool>,
|
||||||
) {
|
) {
|
||||||
type Ref<'a, T> = <<Ctx as ConstMutSwitchUi>::RefType as RefType>::Ref<'a, T>;
|
|
||||||
|
|
||||||
ctx.labeled_slider(
|
ctx.labeled_slider(
|
||||||
"Ferment weight",
|
"Ferment weight",
|
||||||
0.0..=1.0,
|
0.0..=1.0,
|
||||||
0.001,
|
0.001,
|
||||||
&mut Ctx::_get(
|
&mut Ctx::RefType::_get(
|
||||||
&mut config,
|
&mut config,
|
||||||
|config| &config.ferment_weight,
|
|config| &config.ferment_weight,
|
||||||
|config| &mut config.ferment_weight,
|
|config| &mut config.ferment_weight,
|
||||||
@ -30,7 +31,7 @@ pub(crate) fn input<Ctx: ConstMutSwitchUi + RefGetter>(
|
|||||||
"Heuristic coefficient",
|
"Heuristic coefficient",
|
||||||
0.0..=1.0,
|
0.0..=1.0,
|
||||||
0.001,
|
0.001,
|
||||||
&mut Ctx::_get(
|
&mut Ctx::RefType::_get(
|
||||||
&mut config,
|
&mut config,
|
||||||
|config| &config.heuristic_coefficient,
|
|config| &config.heuristic_coefficient,
|
||||||
|config| &mut config.heuristic_coefficient,
|
|config| &mut config.heuristic_coefficient,
|
||||||
@ -43,7 +44,7 @@ pub(crate) fn input<Ctx: ConstMutSwitchUi + RefGetter>(
|
|||||||
"Q",
|
"Q",
|
||||||
0.0..=1.0,
|
0.0..=1.0,
|
||||||
0.001,
|
0.001,
|
||||||
&mut Ctx::_get(&mut config, |config| &config.q, |config| &mut config.q),
|
&mut Ctx::RefType::_get(&mut config, |config| &config.q, |config| &mut config.q),
|
||||||
);
|
);
|
||||||
|
|
||||||
ctx.space();
|
ctx.space();
|
||||||
@ -52,7 +53,7 @@ pub(crate) fn input<Ctx: ConstMutSwitchUi + RefGetter>(
|
|||||||
"R",
|
"R",
|
||||||
0.0..=1.0,
|
0.0..=1.0,
|
||||||
0.001,
|
0.001,
|
||||||
&mut Ctx::_get(&mut config, |config| &config.r, |config| &mut config.r),
|
&mut Ctx::RefType::_get(&mut config, |config| &config.r, |config| &mut config.r),
|
||||||
);
|
);
|
||||||
|
|
||||||
ctx.space();
|
ctx.space();
|
||||||
@ -61,63 +62,28 @@ pub(crate) fn input<Ctx: ConstMutSwitchUi + RefGetter>(
|
|||||||
"Ants per vertex",
|
"Ants per vertex",
|
||||||
1..=100,
|
1..=100,
|
||||||
1.0,
|
1.0,
|
||||||
&mut Ctx::_get(&mut ants_per_vertex, |apv| apv, |apv| apv),
|
&mut Ctx::RefType::_get(&mut ants_per_vertex, |apv| apv, |apv| apv),
|
||||||
);
|
);
|
||||||
|
|
||||||
ctx.space();
|
ctx.space();
|
||||||
|
|
||||||
struct ControlsRow {}
|
ctx.horizontal(ControlsRow {
|
||||||
impl _ConstMutSwitchUiCallback<Ctx::RefType> for ControlsRow {
|
update: &mut vertex_update,
|
||||||
type Clojure = (Ref<'_, UpdatePending>, Ref<'_, bool>);
|
run: &mut launch,
|
||||||
|
});
|
||||||
|
|
||||||
fn render<SubCtx: ConstMutSwitchUi<RefType = Ctx::RefType>>(
|
draw_lengths_table(ctx, graph, vertex_update)
|
||||||
ctx: &mut SubCtx,
|
}
|
||||||
mut clojure: (Ref<'_, UpdatePending>, Ref<'_, bool>),
|
|
||||||
) {
|
struct ControlsRow<'uu, 'u, 'rr, 'r, RT: RefType> {
|
||||||
ctx.button("Add vertex", &mut clojure.0, |d| *d = UpdatePending::Add);
|
update: &'uu mut RT::Ref<'u, UpdatePending>,
|
||||||
|
run: &'rr mut RT::Ref<'r, bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<RT: RefType> _ConstMutSwitchUiCallback<RT> for ControlsRow<'_, '_, '_, '_, RT> {
|
||||||
|
fn render(self, ctx: &mut impl ConstMutSwitchUi<RefType = RT>) {
|
||||||
|
ctx.button("Add vertex", self.update, |d| *d = UpdatePending::Add);
|
||||||
ctx.separator();
|
ctx.separator();
|
||||||
ctx.button("Run", &mut clojure.1, |d| *d = true);
|
ctx.button("Run", self.run, |d| *d = true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.horizontal::<ControlsRow>(&mut (vertex_update, launch))
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
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 = AntsVisualisationData::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;
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
mod data;
|
mod data;
|
||||||
mod input;
|
|
||||||
mod graph;
|
mod graph;
|
||||||
|
mod input;
|
||||||
|
|
||||||
pub(crate) use data::{MyApp, AntsVisualisationData};
|
pub(crate) use data::{AntsVisualisationApp, AntsVisualisationData, AntsVisualisationState};
|
||||||
|
pub(crate) use graph::{graph_with_controls, gen_vertex_locations};
|
||||||
pub(crate) use input::input;
|
pub(crate) use input::input;
|
||||||
pub(crate) use graph::graph_with_controls;
|
|
||||||
@ -3,42 +3,105 @@
|
|||||||
mod algo;
|
mod algo;
|
||||||
mod gui;
|
mod gui;
|
||||||
|
|
||||||
use crate::algo::EdgeExtraData;
|
use crate::algo::AntsSimulationState;
|
||||||
use bgtu_ai_utility::gui::boot_eframe;
|
use bgtu_ai_utility::gui::boot_eframe;
|
||||||
|
use bgtu_ai_utility::gui::const_mut_switch::{ConstUI, MutUI};
|
||||||
|
use bgtu_ai_utility::gui::graph_lengths_table::{ConstGraph, MutableGraph};
|
||||||
use bgtu_ai_utility::gui::subwindow;
|
use bgtu_ai_utility::gui::subwindow;
|
||||||
use bgtu_ai_utility::UpdatePending;
|
use bgtu_ai_utility::UpdatePending;
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
|
use rand::rng;
|
||||||
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
fn main() -> eframe::Result {
|
fn main() -> eframe::Result {
|
||||||
return boot_eframe("Ants simulation", || gui::MyApp::new());
|
return boot_eframe("Ants simulation", || gui::AntsVisualisationApp::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
impl eframe::App for gui::MyApp {
|
impl eframe::App for gui::AntsVisualisationApp {
|
||||||
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| match self.state {
|
let state_ptr = NonNull::from_mut(&mut self.state);
|
||||||
gui::AntsVisualisationData::Edit {} => {
|
egui::CentralPanel::default().show(ui, |ui| match &mut self.state {
|
||||||
match self.vertex_update {
|
gui::AntsVisualisationState::Edit {
|
||||||
|
config,
|
||||||
|
graph,
|
||||||
|
ants_per_vertex,
|
||||||
|
vertex_update,
|
||||||
|
} => {
|
||||||
|
match vertex_update {
|
||||||
UpdatePending::NoChange => {}
|
UpdatePending::NoChange => {}
|
||||||
UpdatePending::Add => {
|
UpdatePending::Add => {
|
||||||
self.simulation.graph.add_vertex(|| EdgeExtraData {
|
graph.add_vertex(|| ());
|
||||||
ferment_intensity: 0.0,
|
*vertex_update = UpdatePending::NoChange;
|
||||||
});
|
|
||||||
self.vertex_update = UpdatePending::NoChange;
|
|
||||||
}
|
}
|
||||||
UpdatePending::Remove(vi) => {
|
UpdatePending::Remove(vi) => {
|
||||||
self.simulation.graph.remove_vertex(vi);
|
graph.remove_vertex(*vi);
|
||||||
self.vertex_update = UpdatePending::NoChange;
|
*vertex_update = UpdatePending::NoChange;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gui::input(ui, self)
|
|
||||||
|
let mut run = false;
|
||||||
|
gui::input(
|
||||||
|
&mut MutUI { ui },
|
||||||
|
*config,
|
||||||
|
&mut MutableGraph { graph },
|
||||||
|
ants_per_vertex,
|
||||||
|
vertex_update,
|
||||||
|
&mut run,
|
||||||
|
);
|
||||||
|
|
||||||
|
if run {
|
||||||
|
let ns = gui::AntsVisualisationState::Running {
|
||||||
|
simulation: AntsSimulationState::new(*graph, *config, *ants_per_vertex),
|
||||||
|
ants_per_vertex: *ants_per_vertex,
|
||||||
|
vertex_locations: gui::gen_vertex_locations(
|
||||||
|
&mut rng(),
|
||||||
|
(*graph).vertex_count(),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
state_ptr.write(ns);
|
||||||
}
|
}
|
||||||
gui::AntsVisualisationData::Running { .. } => {
|
}
|
||||||
ui.add_enabled_ui(false, |ui| gui::input(ui, self));
|
}
|
||||||
|
gui::AntsVisualisationState::Running {
|
||||||
|
simulation,
|
||||||
|
ants_per_vertex,
|
||||||
|
vertex_locations,
|
||||||
|
} => {
|
||||||
|
gui::input(
|
||||||
|
&mut ConstUI { ui },
|
||||||
|
&simulation.cfg,
|
||||||
|
&mut ConstGraph {
|
||||||
|
graph: &simulation.graph,
|
||||||
|
},
|
||||||
|
ants_per_vertex,
|
||||||
|
&UpdatePending::NoChange,
|
||||||
|
&false,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut exit = false;
|
||||||
subwindow(
|
subwindow(
|
||||||
ui, "visualisation", "Visualisation",
|
ui,
|
||||||
|
"visualisation",
|
||||||
|
"Visualisation",
|
||||||
|vb| vb.with_inner_size([640.0, 480.0]),
|
|vb| vb.with_inner_size([640.0, 480.0]),
|
||||||
|ui| gui::graph_with_controls(ui, self),
|
|ui| gui::graph_with_controls(ui, vertex_locations, simulation, &mut exit),
|
||||||
).on_close(|| self.state = gui::AntsVisualisationData::Edit);
|
)
|
||||||
|
.on_close(|| exit = true);
|
||||||
|
|
||||||
|
if exit {
|
||||||
|
let ns = gui::AntsVisualisationState::Edit {
|
||||||
|
config: unsafe {
|
||||||
|
NonNull::from_mut(&mut self.data.config).as_mut()
|
||||||
|
},
|
||||||
|
graph: unsafe { NonNull::from_mut(&mut self.data.graph).as_mut() },
|
||||||
|
ants_per_vertex: *ants_per_vertex,
|
||||||
|
vertex_update: UpdatePending::NoChange,
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
state_ptr.write(ns);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,7 @@ impl<E> CompleteGraph<E> {
|
|||||||
}
|
}
|
||||||
self.vertices.remove(vi);
|
self.vertices.remove(vi);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vertex_count(&self) -> usize {
|
pub fn vertex_count(&self) -> usize {
|
||||||
return self.vertices.len();
|
return self.vertices.len();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,7 @@ impl<D> EdgesVec<D> {
|
|||||||
vertex1_index: vertex1,
|
vertex1_index: vertex1,
|
||||||
vertex2_index: vertex2,
|
vertex2_index: vertex2,
|
||||||
length,
|
length,
|
||||||
extra
|
extra,
|
||||||
};
|
};
|
||||||
return self.data.add(|_, _| data);
|
return self.data.add(|_, _| data);
|
||||||
}
|
}
|
||||||
@ -47,13 +47,20 @@ impl<D> EdgesVec<D> {
|
|||||||
pub fn iter(&self) -> impl Iterator<Item = &Edge<D>> {
|
pub fn iter(&self) -> impl Iterator<Item = &Edge<D>> {
|
||||||
return self.data.iter();
|
return self.data.iter();
|
||||||
}
|
}
|
||||||
|
pub fn iter_indexed(&self) -> impl Iterator<Item = (usize, &Edge<D>)> {
|
||||||
|
return self.data.iter_indexed();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Edge<D>> {
|
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Edge<D>> {
|
||||||
return self.data.iter_mut();
|
return self.data.iter_mut();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn iter_indexes(&self) -> impl Iterator<Item = usize> {
|
||||||
|
return self.data.iter_indexes();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn capacity(&self) -> usize {
|
pub fn capacity(&self) -> usize {
|
||||||
return self.data.capacity()
|
return self.data.capacity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ use eframe::emath::Numeric;
|
|||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
pub struct ConstUI<'ui> {
|
pub struct ConstUI<'ui> {
|
||||||
ui: &'ui mut Ui,
|
pub ui: &'ui mut Ui,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ui> ConstUI<'ui> {
|
impl<'ui> ConstUI<'ui> {
|
||||||
|
|||||||
@ -9,7 +9,7 @@ use eframe::emath::Numeric;
|
|||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
pub struct MutUI<'ui> {
|
pub struct MutUI<'ui> {
|
||||||
ui: &'ui mut Ui,
|
pub ui: &'ui mut Ui,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ui> MutUI<'ui> {
|
impl<'ui> MutUI<'ui> {
|
||||||
|
|||||||
@ -8,6 +8,7 @@ use eframe::egui::Ui;
|
|||||||
use egui_extras::{Column, Table, TableBuilder, TableRow};
|
use egui_extras::{Column, Table, TableBuilder, TableRow};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem::{swap, uninitialized};
|
use std::mem::{swap, uninitialized};
|
||||||
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
pub trait _ConstMutSwitchUiTableCallback<RefType: super::RefType> {
|
pub trait _ConstMutSwitchUiTableCallback<RefType: super::RefType> {
|
||||||
fn render_table(self, ctx: &mut impl ConstMutSwitchUiTable<RefType = RefType>);
|
fn render_table(self, ctx: &mut impl ConstMutSwitchUiTable<RefType = RefType>);
|
||||||
@ -107,13 +108,10 @@ impl<'a, RT: RefType, Constructor: __SwitchUiConstructor1<RT>>
|
|||||||
|
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
fn header_map(&mut self, f: impl FnOnce(TableBuilder) -> Table) {
|
fn header_map(&mut self, f: impl FnOnce(TableBuilder) -> Table) {
|
||||||
|
let sp = NonNull::from_mut(self);
|
||||||
match self {
|
match self {
|
||||||
ConstMutSwitchUiTableImplState::Header(_) => {
|
ConstMutSwitchUiTableImplState::Header(h) => {
|
||||||
let mut local = unsafe { Self::Header(uninitialized()) };
|
unsafe { sp.write(Self::Body(f(NonNull::from_mut(h).read()))) };
|
||||||
swap(self, &mut local);
|
|
||||||
if let Self::Header(local) = local {
|
|
||||||
*self = Self::Body(f(local))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => panic!("Not in header state"),
|
_ => panic!("Not in header state"),
|
||||||
}
|
}
|
||||||
@ -121,14 +119,13 @@ impl<'a, RT: RefType, Constructor: __SwitchUiConstructor1<RT>>
|
|||||||
|
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
fn body_map(&mut self, f: impl FnOnce(Table)) {
|
fn body_map(&mut self, f: impl FnOnce(Table)) {
|
||||||
|
let sp = NonNull::from_mut(self);
|
||||||
match self {
|
match self {
|
||||||
ConstMutSwitchUiTableImplState::Header(_) => {
|
ConstMutSwitchUiTableImplState::Body(b) => {
|
||||||
let mut local = unsafe { Self::Body(uninitialized()) };
|
unsafe {
|
||||||
swap(self, &mut local);
|
f(NonNull::from_mut(b).read());
|
||||||
if let Self::Body(local) = local {
|
sp.write(Self::Done(PhantomData::default()))
|
||||||
f(local);
|
};
|
||||||
*self = Self::Done(PhantomData::default())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => panic!("Not in body state"),
|
_ => panic!("Not in body state"),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1008,3 +1008,59 @@ pub trait Edge {
|
|||||||
fn get_edge_len_ptr<'s>(&'s mut self) -> <Self::RefType as RefType>::Ref<'s, f64>;
|
fn get_edge_len_ptr<'s>(&'s mut self) -> <Self::RefType as RefType>::Ref<'s, f64>;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 10
|
||||||
|
Работа с состояниями это отдельный вид искусства. Если внутри енама есть что-то, без поддержки
|
||||||
|
копирования, но это что-то нужно использовать для вычисления следующего состояния, то borrow
|
||||||
|
checker вынудит откатиться в ~~каменный век~~ обратно в C/C++ с ручной реализацией растовских
|
||||||
|
енамов.
|
||||||
|
|
||||||
|
### 10.1
|
||||||
|
Первый опробованный трюк:
|
||||||
|
```rust
|
||||||
|
enum State<AA, BB> {A(AA), B(BB)}
|
||||||
|
|
||||||
|
impl <AA, BB> State<AA, BB> {
|
||||||
|
fn map(&mut self, f: impl FnOnce(AA) -> BB) {
|
||||||
|
match self {
|
||||||
|
Self::A(_) => {
|
||||||
|
let mut local = unsafe { Self::A(uninitialized()) };
|
||||||
|
swap(self, &mut local);
|
||||||
|
if let Self::A(local) = local {
|
||||||
|
*self = Self::BB(f(local))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
успехом не увенчался, в отладочной сборке компилятор кидает панику в районе `swap` из-за того
|
||||||
|
что переменная `local` не инициализированна.
|
||||||
|
|
||||||
|
### 10.2
|
||||||
|
Следующий трюк уже рабочий, но вопросы к безопасности очень большие:
|
||||||
|
```rust
|
||||||
|
enum State<AA, BB> {A(AA), B(BB)}
|
||||||
|
|
||||||
|
impl <AA, BB> State<AA, BB> {
|
||||||
|
fn map(&mut self, f: impl FnOnce(AA) -> BB) {
|
||||||
|
let sp = NonNull::from_mut(self);
|
||||||
|
match self {
|
||||||
|
Self::A(aa) => {
|
||||||
|
unsafe { sp.write(Self::BB(f(NonNull::from_mut(aa).read()))) };
|
||||||
|
}
|
||||||
|
_ => todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Выводы
|
||||||
|
Идея с безопасностью через строгие проверки времени жизни на этапе компиляции интересная, но
|
||||||
|
в текущем виде не рабочая. Язык получился таким же низкоуровневым, как C# или Kotlin/Native:
|
||||||
|
работать с указателями и линковаться напрямую с функциями из C можно, но в любой сколько-нибудь
|
||||||
|
сложной ситуации компилятор вынуждает пользоваться динамической памятью даже там, где можно
|
||||||
|
обойтись без этого или городить костыли, которые сводят на нет всю безопасность языка. Поитогу
|
||||||
|
получился "безопасный" и многословный Python.
|
||||||
@ -46,145 +46,3 @@ pub trait Edge {
|
|||||||
|
|
||||||
fn get_edge_len_ptr<'s>(&'s mut self) -> <Self::RefType as RefType>::Ref<'s, f64>;
|
fn get_edge_len_ptr<'s>(&'s mut self) -> <Self::RefType as RefType>::Ref<'s, f64>;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MutableGraph<'g> {
|
|
||||||
graph: &'g mut CompleteGraph<()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Graph for MutableGraph<'_> {
|
|
||||||
type RefType = MutRef;
|
|
||||||
|
|
||||||
fn iter_vertices(&mut self) -> impl VerticesIterator<RefType = Self::RefType> {
|
|
||||||
return MutableVerticesIterator {
|
|
||||||
ee: &mut self.graph.edges,
|
|
||||||
it: self.graph.vertices.iter_indexed_mut(),
|
|
||||||
ordinal: 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn vertices_count(&self) -> usize {
|
|
||||||
return self.graph.vertex_count();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MutableVerticesIterator<'g, It: Iterator<Item = (usize, &'g mut HashSet<usize>)>> {
|
|
||||||
ee: &'g mut EdgesVec<()>,
|
|
||||||
it: It,
|
|
||||||
ordinal: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'g, It: Iterator<Item = (usize, &'g mut HashSet<usize>)>> VerticesIterator
|
|
||||||
for MutableVerticesIterator<'g, It>
|
|
||||||
{
|
|
||||||
type RefType = MutRef;
|
|
||||||
type Vertex<'v>
|
|
||||||
= MutableVertex<'v>
|
|
||||||
where
|
|
||||||
Self: 'v;
|
|
||||||
|
|
||||||
fn next<'v>(&'v mut self) -> Option<Self::Vertex<'v>> {
|
|
||||||
return self.it.next().map(|(i, e)| {
|
|
||||||
let v = MutableVertex {
|
|
||||||
id: i,
|
|
||||||
local_edges: e,
|
|
||||||
all_edges: self.ee,
|
|
||||||
ordinal: self.ordinal,
|
|
||||||
};
|
|
||||||
self.ordinal += 1;
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MutableVertex<'g> {
|
|
||||||
ordinal: usize,
|
|
||||||
id: usize,
|
|
||||||
local_edges: &'g mut HashSet<usize>,
|
|
||||||
all_edges: &'g mut EdgesVec<()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Vertex for MutableVertex<'_> {
|
|
||||||
type RefType = MutRef;
|
|
||||||
|
|
||||||
fn iter_edges_or_nothing_sorted(&mut self) -> impl EdgesIterator<RefType = Self::RefType> {
|
|
||||||
let mut local_edges = self
|
|
||||||
.local_edges
|
|
||||||
.iter()
|
|
||||||
.map(|i| {
|
|
||||||
(i, unsafe {
|
|
||||||
NonNull::from_mut(self.all_edges.index_mut(0)).as_mut()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.map(|(i, e)| (e.another(self.id), i, &mut e.length))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
local_edges.sort_by_key(|(k, _, _)| *k);
|
|
||||||
|
|
||||||
return MutableEdgesIterator {
|
|
||||||
it: IteratorWithHole {
|
|
||||||
it: local_edges.into_iter().map(|(_, _, x)| x),
|
|
||||||
hole: Some(self.ordinal),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_vertex_to_update_state(&self, state: &mut UpdatePending) {
|
|
||||||
*state = UpdatePending::Remove(self.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct IteratorWithHole<E, It: Iterator<Item = E>> {
|
|
||||||
hole: Option<usize>,
|
|
||||||
it: It,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E, It: Iterator<Item = E>> Iterator for IteratorWithHole<E, It> {
|
|
||||||
type Item = Option<E>;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
match self.hole {
|
|
||||||
None => return self.it.next().map(|e| Some(e)),
|
|
||||||
Some(v) => {
|
|
||||||
if v == 0 {
|
|
||||||
self.hole = None;
|
|
||||||
return Some(None);
|
|
||||||
} else {
|
|
||||||
self.hole = Some(v - 1);
|
|
||||||
return self.it.next().map(|e| Some(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MutableEdgesIterator<'g, It: Iterator<Item = Option<(&'g mut f64)>>> {
|
|
||||||
it: It,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'g, It: Iterator<Item = Option<(&'g mut f64)>>> EdgesIterator
|
|
||||||
for MutableEdgesIterator<'g, It>
|
|
||||||
{
|
|
||||||
type RefType = MutRef;
|
|
||||||
type Edge<'x>
|
|
||||||
= MutableEdge<'x>
|
|
||||||
where
|
|
||||||
Self: 'x;
|
|
||||||
|
|
||||||
fn next<'s>(&'s mut self) -> Option<Option<Self::Edge<'s>>> {
|
|
||||||
return self
|
|
||||||
.it
|
|
||||||
.next()
|
|
||||||
.map(|oi| oi.map(|len| MutableEdge { len: len }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MutableEdge<'g> {
|
|
||||||
len: &'g mut f64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Edge for MutableEdge<'_> {
|
|
||||||
type RefType = MutRef;
|
|
||||||
|
|
||||||
fn get_edge_len_ptr<'s>(&'s mut self) -> <Self::RefType as RefType>::Ref<'s, f64> {
|
|
||||||
return self.len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
123
utility/src/gui/graph_lengths_table/impl_const.rs
Normal file
123
utility/src/gui/graph_lengths_table/impl_const.rs
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
use super::{Edge, EdgesIterator, Graph, IteratorWithHole, Vertex, VerticesIterator};
|
||||||
|
use crate::UpdatePending;
|
||||||
|
use crate::graph::{CompleteGraph, EdgesVec};
|
||||||
|
use crate::gui::const_mut_switch::{ConstRef, RefType};
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::ops::Index;
|
||||||
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
|
pub struct ConstGraph<'g> {
|
||||||
|
pub graph: &'g CompleteGraph<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Graph for ConstGraph<'_> {
|
||||||
|
type RefType = ConstRef;
|
||||||
|
|
||||||
|
fn iter_vertices(&mut self) -> impl VerticesIterator<RefType = Self::RefType> {
|
||||||
|
return ConstVerticesIterator {
|
||||||
|
ee: &self.graph.edges,
|
||||||
|
it: self.graph.vertices.iter_indexed(),
|
||||||
|
ordinal: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vertices_count(&self) -> usize {
|
||||||
|
return self.graph.vertex_count();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ConstVerticesIterator<'g, It: Iterator<Item = (usize, &'g HashSet<usize>)>> {
|
||||||
|
ee: &'g EdgesVec<()>,
|
||||||
|
it: It,
|
||||||
|
ordinal: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'g, It: Iterator<Item = (usize, &'g HashSet<usize>)>> VerticesIterator
|
||||||
|
for ConstVerticesIterator<'g, It>
|
||||||
|
{
|
||||||
|
type RefType = ConstRef;
|
||||||
|
type Vertex<'v>
|
||||||
|
= ConstVertex<'v>
|
||||||
|
where
|
||||||
|
Self: 'v;
|
||||||
|
|
||||||
|
fn next<'v>(&'v mut self) -> Option<Self::Vertex<'v>> {
|
||||||
|
return self.it.next().map(|(i, e)| {
|
||||||
|
let v = ConstVertex {
|
||||||
|
id: i,
|
||||||
|
local_edges: e,
|
||||||
|
all_edges: self.ee,
|
||||||
|
ordinal: self.ordinal,
|
||||||
|
};
|
||||||
|
self.ordinal += 1;
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ConstVertex<'g> {
|
||||||
|
ordinal: usize,
|
||||||
|
id: usize,
|
||||||
|
local_edges: &'g HashSet<usize>,
|
||||||
|
all_edges: &'g EdgesVec<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Vertex for ConstVertex<'_> {
|
||||||
|
type RefType = ConstRef;
|
||||||
|
|
||||||
|
fn iter_edges_or_nothing_sorted(&mut self) -> impl EdgesIterator<RefType = Self::RefType> {
|
||||||
|
let mut local_edges = self
|
||||||
|
.local_edges
|
||||||
|
.iter()
|
||||||
|
.map(|i| {
|
||||||
|
(i, unsafe {
|
||||||
|
NonNull::from_ref(self.all_edges.index(*i)).as_ref()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.map(|(i, e)| (e.another(self.id), i, &e.length))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
local_edges.sort_by_key(|(k, _, _)| *k);
|
||||||
|
|
||||||
|
return ConstEdgesIterator {
|
||||||
|
it: IteratorWithHole {
|
||||||
|
it: local_edges.into_iter().map(|(_, _, x)| x),
|
||||||
|
hole: Some(self.ordinal),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_vertex_to_update_state(&self, state: &mut UpdatePending) {
|
||||||
|
*state = UpdatePending::Remove(self.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ConstEdgesIterator<'g, It: Iterator<Item = Option<&'g f64>>> {
|
||||||
|
it: It,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'g, It: Iterator<Item = Option<&'g f64>>> EdgesIterator for ConstEdgesIterator<'g, It> {
|
||||||
|
type RefType = ConstRef;
|
||||||
|
type Edge<'x>
|
||||||
|
= ConstEdge<'x>
|
||||||
|
where
|
||||||
|
Self: 'x;
|
||||||
|
|
||||||
|
fn next<'s>(&'s mut self) -> Option<Option<Self::Edge<'s>>> {
|
||||||
|
return self
|
||||||
|
.it
|
||||||
|
.next()
|
||||||
|
.map(|oi| oi.map(|len| ConstEdge { len: len }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ConstEdge<'g> {
|
||||||
|
len: &'g f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Edge for ConstEdge<'_> {
|
||||||
|
type RefType = ConstRef;
|
||||||
|
|
||||||
|
fn get_edge_len_ptr<'s>(&'s mut self) -> <Self::RefType as RefType>::Ref<'s, f64> {
|
||||||
|
return self.len;
|
||||||
|
}
|
||||||
|
}
|
||||||
125
utility/src/gui/graph_lengths_table/impl_mut.rs
Normal file
125
utility/src/gui/graph_lengths_table/impl_mut.rs
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
use super::{Edge, EdgesIterator, Graph, IteratorWithHole, Vertex, VerticesIterator};
|
||||||
|
use crate::graph::{CompleteGraph, EdgesVec};
|
||||||
|
use crate::gui::const_mut_switch::{MutRef, RefType};
|
||||||
|
use crate::{UpdatePending};
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::ops::IndexMut;
|
||||||
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
|
pub struct MutableGraph<'g> {
|
||||||
|
pub graph: &'g mut CompleteGraph<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Graph for MutableGraph<'_> {
|
||||||
|
type RefType = MutRef;
|
||||||
|
|
||||||
|
fn iter_vertices(&mut self) -> impl VerticesIterator<RefType = Self::RefType> {
|
||||||
|
return MutableVerticesIterator {
|
||||||
|
ee: &mut self.graph.edges,
|
||||||
|
it: self.graph.vertices.iter_indexed_mut(),
|
||||||
|
ordinal: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vertices_count(&self) -> usize {
|
||||||
|
return self.graph.vertex_count();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MutableVerticesIterator<'g, It: Iterator<Item = (usize, &'g mut HashSet<usize>)>> {
|
||||||
|
ee: &'g mut EdgesVec<()>,
|
||||||
|
it: It,
|
||||||
|
ordinal: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'g, It: Iterator<Item = (usize, &'g mut HashSet<usize>)>> VerticesIterator
|
||||||
|
for MutableVerticesIterator<'g, It>
|
||||||
|
{
|
||||||
|
type RefType = MutRef;
|
||||||
|
type Vertex<'v>
|
||||||
|
= MutableVertex<'v>
|
||||||
|
where
|
||||||
|
Self: 'v;
|
||||||
|
|
||||||
|
fn next<'v>(&'v mut self) -> Option<Self::Vertex<'v>> {
|
||||||
|
return self.it.next().map(|(i, e)| {
|
||||||
|
let v = MutableVertex {
|
||||||
|
id: i,
|
||||||
|
local_edges: e,
|
||||||
|
all_edges: self.ee,
|
||||||
|
ordinal: self.ordinal,
|
||||||
|
};
|
||||||
|
self.ordinal += 1;
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MutableVertex<'g> {
|
||||||
|
ordinal: usize,
|
||||||
|
id: usize,
|
||||||
|
local_edges: &'g mut HashSet<usize>,
|
||||||
|
all_edges: &'g mut EdgesVec<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Vertex for MutableVertex<'_> {
|
||||||
|
type RefType = MutRef;
|
||||||
|
|
||||||
|
fn iter_edges_or_nothing_sorted(&mut self) -> impl EdgesIterator<RefType = Self::RefType> {
|
||||||
|
let mut local_edges = self
|
||||||
|
.local_edges
|
||||||
|
.iter()
|
||||||
|
.map(|i| {
|
||||||
|
(i, unsafe {
|
||||||
|
NonNull::from_mut(self.all_edges.index_mut(*i)).as_mut()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.map(|(i, e)| (e.another(self.id), i, &mut e.length))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
local_edges.sort_by_key(|(k, _, _)| *k);
|
||||||
|
|
||||||
|
return MutableEdgesIterator {
|
||||||
|
it: IteratorWithHole {
|
||||||
|
it: local_edges.into_iter().map(|(_, _, x)| x),
|
||||||
|
hole: Some(self.ordinal),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_vertex_to_update_state(&self, state: &mut UpdatePending) {
|
||||||
|
*state = UpdatePending::Remove(self.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MutableEdgesIterator<'g, It: Iterator<Item = Option<&'g mut f64>>> {
|
||||||
|
it: It,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'g, It: Iterator<Item = Option<&'g mut f64>>> EdgesIterator
|
||||||
|
for MutableEdgesIterator<'g, It>
|
||||||
|
{
|
||||||
|
type RefType = MutRef;
|
||||||
|
type Edge<'x>
|
||||||
|
= MutableEdge<'x>
|
||||||
|
where
|
||||||
|
Self: 'x;
|
||||||
|
|
||||||
|
fn next<'s>(&'s mut self) -> Option<Option<Self::Edge<'s>>> {
|
||||||
|
return self
|
||||||
|
.it
|
||||||
|
.next()
|
||||||
|
.map(|oi| oi.map(|len| MutableEdge { len: len }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MutableEdge<'g> {
|
||||||
|
len: &'g mut f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Edge for MutableEdge<'_> {
|
||||||
|
type RefType = MutRef;
|
||||||
|
|
||||||
|
fn get_edge_len_ptr<'s>(&'s mut self) -> <Self::RefType as RefType>::Ref<'s, f64> {
|
||||||
|
return self.len;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,36 @@
|
|||||||
mod ui;
|
|
||||||
mod ctx;
|
mod ctx;
|
||||||
|
mod impl_mut;
|
||||||
|
mod ui;
|
||||||
|
mod impl_const;
|
||||||
|
|
||||||
pub use ctx::{Graph, Vertex, Edge, EdgesIterator, VerticesIterator};
|
pub use ctx::Graph;
|
||||||
|
use ctx::{Edge, EdgesIterator, Vertex, VerticesIterator};
|
||||||
|
pub use impl_mut::MutableGraph;
|
||||||
|
pub use impl_const::ConstGraph;
|
||||||
|
pub use ui::draw_lengths_table;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct IteratorWithHole<E, It: Iterator<Item = E>> {
|
||||||
|
hole: Option<usize>,
|
||||||
|
it: It,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E, It: Iterator<Item = E>> Iterator for IteratorWithHole<E, It> {
|
||||||
|
type Item = Option<E>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
match self.hole {
|
||||||
|
None => return self.it.next().map(|e| Some(e)),
|
||||||
|
Some(v) => {
|
||||||
|
if v == 0 {
|
||||||
|
self.hole = None;
|
||||||
|
return Some(None);
|
||||||
|
} else {
|
||||||
|
self.hole = Some(v - 1);
|
||||||
|
return self.it.next().map(|e| Some(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,13 @@
|
|||||||
use crate::gat_iterator::GatIterator;
|
use crate::UpdatePending;
|
||||||
use crate::gui::const_mut_switch::{ConstMutSwitchUi, ConstMutSwitchUiTable, ConstMutSwitchUiTableRow, RefType, _ConstMutSwitchUiCallback, _ConstMutSwitchUiTableCallback, _ConstMutSwitchUiTableHeaderCallback, _ConstMutSwitchUiTableRowCallback, _ConstMutSwitchUiTableRowsIterator};
|
use crate::gui::const_mut_switch::{
|
||||||
|
_ConstMutSwitchUiCallback, _ConstMutSwitchUiTableCallback,
|
||||||
|
_ConstMutSwitchUiTableHeaderCallback, _ConstMutSwitchUiTableRowCallback,
|
||||||
|
_ConstMutSwitchUiTableRowsIterator, ConstMutSwitchUi, ConstMutSwitchUiTable,
|
||||||
|
ConstMutSwitchUiTableRow, RefType,
|
||||||
|
};
|
||||||
use crate::gui::graph_lengths_table::ctx::EdgesIterator;
|
use crate::gui::graph_lengths_table::ctx::EdgesIterator;
|
||||||
use crate::gui::graph_lengths_table::ctx::VerticesIterator;
|
use crate::gui::graph_lengths_table::ctx::VerticesIterator;
|
||||||
use crate::gui::graph_lengths_table::{Edge, Graph, Vertex};
|
use crate::gui::graph_lengths_table::{Edge, Graph, Vertex};
|
||||||
use crate::{LambdaIterator, UpdatePending};
|
|
||||||
|
|
||||||
pub fn draw_lengths_table<G: Graph, CtxUi: ConstMutSwitchUi<RefType = G::RefType>>(
|
pub fn draw_lengths_table<G: Graph, CtxUi: ConstMutSwitchUi<RefType = G::RefType>>(
|
||||||
ctx_ui: &mut CtxUi,
|
ctx_ui: &mut CtxUi,
|
||||||
@ -19,7 +23,7 @@ struct Root<'g, 'u, G: Graph> {
|
|||||||
|
|
||||||
impl<G: Graph> _ConstMutSwitchUiCallback<G::RefType> for Root<'_, '_, G> {
|
impl<G: Graph> _ConstMutSwitchUiCallback<G::RefType> for Root<'_, '_, G> {
|
||||||
fn render(self, ctx: &mut impl ConstMutSwitchUi<RefType = G::RefType>) {
|
fn render(self, ctx: &mut impl ConstMutSwitchUi<RefType = G::RefType>) {
|
||||||
ctx.table(false, self.graph.vertices_count(), self)
|
ctx.table(false, self.graph.vertices_count() + 1, self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +92,9 @@ impl<'u, It: VerticesIterator> RowsIterators<'u, It> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'u, It: VerticesIterator> _ConstMutSwitchUiTableRowsIterator<It::RefType> for RowsIterators<'u, It> {
|
impl<'u, It: VerticesIterator> _ConstMutSwitchUiTableRowsIterator<It::RefType>
|
||||||
|
for RowsIterators<'u, It>
|
||||||
|
{
|
||||||
type Item<'x>
|
type Item<'x>
|
||||||
= Row<'x, 'u, It::Vertex<'x>>
|
= Row<'x, 'u, It::Vertex<'x>>
|
||||||
where
|
where
|
||||||
|
|||||||
@ -3,7 +3,7 @@ pub mod const_mut_switch;
|
|||||||
mod render_graph;
|
mod render_graph;
|
||||||
mod slider;
|
mod slider;
|
||||||
mod subwindow;
|
mod subwindow;
|
||||||
mod graph_lengths_table;
|
pub mod graph_lengths_table;
|
||||||
|
|
||||||
pub use boot::boot_eframe;
|
pub use boot::boot_eframe;
|
||||||
pub use render_graph::render_graph;
|
pub use render_graph::render_graph;
|
||||||
|
|||||||
@ -8,7 +8,7 @@ pub fn render_graph<D>(
|
|||||||
vertices: &VerticesVec,
|
vertices: &VerticesVec,
|
||||||
vertex_locations: &mut [(f32, f32)],
|
vertex_locations: &mut [(f32, f32)],
|
||||||
edges: &EdgesVec<D>,
|
edges: &EdgesVec<D>,
|
||||||
normalized_intensity: impl Fn(&Edge<D>) -> f64,
|
normalized_intensity: impl Fn(usize, &Edge<D>) -> f64,
|
||||||
) {
|
) {
|
||||||
let canvas = ui.painter();
|
let canvas = ui.painter();
|
||||||
let rect = ui.available_size();
|
let rect = ui.available_size();
|
||||||
@ -17,7 +17,7 @@ pub fn render_graph<D>(
|
|||||||
let rect = Rect::from_min_max(start.min, rect.to_pos2());
|
let rect = Rect::from_min_max(start.min, rect.to_pos2());
|
||||||
canvas.rect_filled(rect, CornerRadius::same(0), Color32::from_rgb(0, 0, 0));
|
canvas.rect_filled(rect, CornerRadius::same(0), Color32::from_rgb(0, 0, 0));
|
||||||
|
|
||||||
for e in edges.iter() {
|
for (ei, e) in edges.iter_indexed() {
|
||||||
let p1 = vertex_locations[e.vertex1_index];
|
let p1 = vertex_locations[e.vertex1_index];
|
||||||
let p2 = vertex_locations[e.vertex2_index];
|
let p2 = vertex_locations[e.vertex2_index];
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ pub fn render_graph<D>(
|
|||||||
p2.1 * rect.height() + rect.min.y,
|
p2.1 * rect.height() + rect.min.y,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
Stroke::new(1.0, intensity2color(normalized_intensity(e))),
|
Stroke::new(1.0, intensity2color(normalized_intensity(ei, e))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let font_id = &ui.style().text_styles[&egui::TextStyle::Body];
|
let font_id = &ui.style().text_styles[&egui::TextStyle::Body];
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user