[lab3] Finished ui refactoring

This commit is contained in:
Andrew Golovashevich 2026-02-24 21:08:01 +03:00
parent 2ea5448ae3
commit 2b601e8d9a
18 changed files with 551 additions and 297 deletions

View File

@ -1,8 +1,15 @@
use bgtu_ai_utility::graph::CompleteGraph;
use bgtu_ai_utility::UpdatePending;
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 {
config: &'cfg mut AntsSimulationConfig,
graph: &'cfg mut CompleteGraph<()>,
@ -15,28 +22,31 @@ pub(crate) enum AntsVisualisationData<'cfg> {
vertex_locations: Vec<(f32, f32)>,
},
}
pub(crate) struct MyApp<'cfg> {
pub state: AntsVisualisationData<'cfg>,
pub ants_per_vertex: usize,
pub(crate) struct AntsVisualisationApp {
pub data: Pin<Box<AntsVisualisationData>>,
pub state: AntsVisualisationState<'static /* actually not but fuck rust */>,
}
impl MyApp {
pub(crate) fn new() -> Self {
return Self {
simulation: AntsSimulationState {
graph: CompleteGraph::new(),
ants: Vec::new(),
},
vertex_update: UpdatePending::NoChange,
impl AntsVisualisationApp {
pub fn new() -> Self {
let mut data = Box::pin(AntsVisualisationData {
config: AntsSimulationConfig {
ferment_weight: 0.5,
heuristic_coefficient: 0.5,
q: 1.0,
r: 0.5,
},
state: AntsVisualisationData::Edit {},
vertex_locations: Vec::new(),
graph: CompleteGraph::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,
vertex_update: UpdatePending::NoChange,
};
return Self { data, state };
}
}

View File

@ -1,37 +1,36 @@
use super::{AntsVisualisationData, MyApp};
use crate::algo::updateState;
use crate::algo::AntsSimulationState;
use bgtu_ai_utility::gui::render_graph;
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.horizontal(|ui| {
if ui.button("Exit").clicked() {
data.state = AntsVisualisationData::Edit
*exit = true;
}
if ui.button("Step").clicked() {
updateState(&mut data.simulation, &mut data.config, &mut rand::rng());
data.update1(&mut rng());
}
ui.label("");
});
draw_ants(ui, data);
draw_ants(ui, vertex_locations, data);
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;
for w in data
.simulation
.graph
.edges
.iter()
.map(|e| e.extra.ferment_intensity)
{
for w in data.graph.edges.iter_indexes().map(|i| data.ferments[i]) {
if w > cap {
cap = w
}
@ -39,9 +38,20 @@ fn draw_ants(ui: &mut Ui, data: &mut MyApp) {
render_graph(
ui,
&data.simulation.graph.vertices,
data.vertex_locations.as_mut_slice(),
&data.simulation.graph.edges,
|e| e.extra.ferment_intensity / cap,
&data.graph.vertices,
vertex_locations,
&data.graph.edges,
|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;
}

View File

@ -1,23 +1,24 @@
use crate::algo::AntsSimulationConfig;
use bgtu_ai_utility::UpdatePending;
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,
mut config: Ctx::Ref<'_, AntsSimulationConfig>,
mut graph: Ctx::RefType::Ref<'_, CompleteGraph<()>>,
mut ants_per_vertex: Ctx::RefType::Ref<'_, usize>,
mut vertex_update: Ctx::RefType::Ref<'_, UpdatePending>,
mut launch: Ctx::RefType::Ref<'_, bool>,
mut config: <Ctx::RefType as RefType>::Ref<'_, AntsSimulationConfig>,
graph: &mut impl Graph<RefType = Ctx::RefType>,
mut ants_per_vertex: <Ctx::RefType as RefType>::Ref<'_, usize>,
mut vertex_update: <Ctx::RefType as RefType>::Ref<'_, UpdatePending>,
mut launch: <Ctx::RefType as RefType>::Ref<'_, bool>,
) {
type Ref<'a, T> = <<Ctx as ConstMutSwitchUi>::RefType as RefType>::Ref<'a, T>;
ctx.labeled_slider(
"Ferment weight",
0.0..=1.0,
0.001,
&mut Ctx::_get(
&mut Ctx::RefType::_get(
&mut config,
|config| &config.ferment_weight,
|config| &mut config.ferment_weight,
@ -30,7 +31,7 @@ pub(crate) fn input<Ctx: ConstMutSwitchUi + RefGetter>(
"Heuristic coefficient",
0.0..=1.0,
0.001,
&mut Ctx::_get(
&mut Ctx::RefType::_get(
&mut config,
|config| &config.heuristic_coefficient,
|config| &mut config.heuristic_coefficient,
@ -43,7 +44,7 @@ pub(crate) fn input<Ctx: ConstMutSwitchUi + RefGetter>(
"Q",
0.0..=1.0,
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();
@ -52,7 +53,7 @@ pub(crate) fn input<Ctx: ConstMutSwitchUi + RefGetter>(
"R",
0.0..=1.0,
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();
@ -61,63 +62,28 @@ pub(crate) fn input<Ctx: ConstMutSwitchUi + RefGetter>(
"Ants per vertex",
1..=100,
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();
struct ControlsRow {}
impl _ConstMutSwitchUiCallback<Ctx::RefType> for ControlsRow {
type Clojure = (Ref<'_, UpdatePending>, Ref<'_, bool>);
ctx.horizontal(ControlsRow {
update: &mut vertex_update,
run: &mut launch,
});
fn render<SubCtx: ConstMutSwitchUi<RefType = Ctx::RefType>>(
ctx: &mut SubCtx,
mut clojure: (Ref<'_, UpdatePending>, Ref<'_, bool>),
) {
ctx.button("Add vertex", &mut clojure.0, |d| *d = UpdatePending::Add);
ctx.separator();
ctx.button("Run", &mut clojure.1, |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;
}*/
draw_lengths_table(ctx, graph, vertex_update)
}
struct ControlsRow<'uu, 'u, 'rr, 'r, RT: RefType> {
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.button("Run", self.run, |d| *d = true);
}
}

View File

@ -1,7 +1,7 @@
mod data;
mod input;
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 graph::graph_with_controls;

View File

@ -3,42 +3,105 @@
mod algo;
mod gui;
use crate::algo::EdgeExtraData;
use crate::algo::AntsSimulationState;
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::UpdatePending;
use eframe::egui;
use rand::rng;
use std::ptr::NonNull;
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) {
egui::CentralPanel::default().show(ui, |ui| match self.state {
gui::AntsVisualisationData::Edit {} => {
match self.vertex_update {
let state_ptr = NonNull::from_mut(&mut self.state);
egui::CentralPanel::default().show(ui, |ui| match &mut self.state {
gui::AntsVisualisationState::Edit {
config,
graph,
ants_per_vertex,
vertex_update,
} => {
match vertex_update {
UpdatePending::NoChange => {}
UpdatePending::Add => {
self.simulation.graph.add_vertex(|| EdgeExtraData {
ferment_intensity: 0.0,
});
self.vertex_update = UpdatePending::NoChange;
graph.add_vertex(|| ());
*vertex_update = UpdatePending::NoChange;
}
UpdatePending::Remove(vi) => {
self.simulation.graph.remove_vertex(vi);
self.vertex_update = UpdatePending::NoChange;
graph.remove_vertex(*vi);
*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(
ui, "visualisation", "Visualisation",
ui,
"visualisation",
"Visualisation",
|vb| vb.with_inner_size([640.0, 480.0]),
|ui| gui::graph_with_controls(ui, self),
).on_close(|| self.state = gui::AntsVisualisationData::Edit);
|ui| gui::graph_with_controls(ui, vertex_locations, simulation, &mut exit),
)
.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);
}
}
}
});
}

View File

@ -34,6 +34,7 @@ impl<E> CompleteGraph<E> {
}
self.vertices.remove(vi);
}
pub fn vertex_count(&self) -> usize {
return self.vertices.len();
}

View File

@ -36,7 +36,7 @@ impl<D> EdgesVec<D> {
vertex1_index: vertex1,
vertex2_index: vertex2,
length,
extra
extra,
};
return self.data.add(|_, _| data);
}
@ -47,17 +47,24 @@ impl<D> EdgesVec<D> {
pub fn iter(&self) -> impl Iterator<Item = &Edge<D>> {
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>> {
return self.data.iter_mut();
}
pub fn iter_indexes(&self) -> impl Iterator<Item = usize> {
return self.data.iter_indexes();
}
pub fn capacity(&self) -> usize {
return self.data.capacity()
return self.data.capacity();
}
}
impl <D> Index<usize> for EdgesVec<D> {
impl<D> Index<usize> for EdgesVec<D> {
type Output = Edge<D>;
fn index(&self, index: usize) -> &Self::Output {
@ -65,7 +72,7 @@ impl <D> Index<usize> for EdgesVec<D> {
}
}
impl <D> IndexMut<usize> for EdgesVec<D> {
impl<D> IndexMut<usize> for EdgesVec<D> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
return self.data.index_mut(index);
}

View File

@ -8,7 +8,7 @@ use eframe::emath::Numeric;
use std::ops::RangeInclusive;
pub struct ConstUI<'ui> {
ui: &'ui mut Ui,
pub ui: &'ui mut Ui,
}
impl<'ui> ConstUI<'ui> {

View File

@ -9,7 +9,7 @@ use eframe::emath::Numeric;
use std::ops::RangeInclusive;
pub struct MutUI<'ui> {
ui: &'ui mut Ui,
pub ui: &'ui mut Ui,
}
impl<'ui> MutUI<'ui> {

View File

@ -8,6 +8,7 @@ use eframe::egui::Ui;
use egui_extras::{Column, Table, TableBuilder, TableRow};
use std::marker::PhantomData;
use std::mem::{swap, uninitialized};
use std::ptr::NonNull;
pub trait _ConstMutSwitchUiTableCallback<RefType: super::RefType> {
fn render_table(self, ctx: &mut impl ConstMutSwitchUiTable<RefType = RefType>);
@ -107,13 +108,10 @@ impl<'a, RT: RefType, Constructor: __SwitchUiConstructor1<RT>>
#[allow(deprecated)]
fn header_map(&mut self, f: impl FnOnce(TableBuilder) -> Table) {
let sp = NonNull::from_mut(self);
match self {
ConstMutSwitchUiTableImplState::Header(_) => {
let mut local = unsafe { Self::Header(uninitialized()) };
swap(self, &mut local);
if let Self::Header(local) = local {
*self = Self::Body(f(local))
}
ConstMutSwitchUiTableImplState::Header(h) => {
unsafe { sp.write(Self::Body(f(NonNull::from_mut(h).read()))) };
}
_ => panic!("Not in header state"),
}
@ -121,14 +119,13 @@ impl<'a, RT: RefType, Constructor: __SwitchUiConstructor1<RT>>
#[allow(deprecated)]
fn body_map(&mut self, f: impl FnOnce(Table)) {
let sp = NonNull::from_mut(self);
match self {
ConstMutSwitchUiTableImplState::Header(_) => {
let mut local = unsafe { Self::Body(uninitialized()) };
swap(self, &mut local);
if let Self::Body(local) = local {
f(local);
*self = Self::Done(PhantomData::default())
}
ConstMutSwitchUiTableImplState::Body(b) => {
unsafe {
f(NonNull::from_mut(b).read());
sp.write(Self::Done(PhantomData::default()))
};
}
_ => panic!("Not in body state"),
}

View File

@ -1008,3 +1008,59 @@ pub trait Edge {
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.

View File

@ -46,145 +46,3 @@ pub trait Edge {
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;
}
}

View 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;
}
}

View 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;
}
}

View File

@ -1,4 +1,36 @@
mod ui;
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));
}
}
}
}
}

View File

@ -1,9 +1,13 @@
use crate::gat_iterator::GatIterator;
use crate::gui::const_mut_switch::{ConstMutSwitchUi, ConstMutSwitchUiTable, ConstMutSwitchUiTableRow, RefType, _ConstMutSwitchUiCallback, _ConstMutSwitchUiTableCallback, _ConstMutSwitchUiTableHeaderCallback, _ConstMutSwitchUiTableRowCallback, _ConstMutSwitchUiTableRowsIterator};
use crate::UpdatePending;
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::VerticesIterator;
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>>(
ctx_ui: &mut CtxUi,
@ -19,7 +23,7 @@ struct Root<'g, 'u, G: Graph> {
impl<G: Graph> _ConstMutSwitchUiCallback<G::RefType> for Root<'_, '_, G> {
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>
= Row<'x, 'u, It::Vertex<'x>>
where

View File

@ -3,7 +3,7 @@ pub mod const_mut_switch;
mod render_graph;
mod slider;
mod subwindow;
mod graph_lengths_table;
pub mod graph_lengths_table;
pub use boot::boot_eframe;
pub use render_graph::render_graph;

View File

@ -8,7 +8,7 @@ pub fn render_graph<D>(
vertices: &VerticesVec,
vertex_locations: &mut [(f32, f32)],
edges: &EdgesVec<D>,
normalized_intensity: impl Fn(&Edge<D>) -> f64,
normalized_intensity: impl Fn(usize, &Edge<D>) -> f64,
) {
let canvas = ui.painter();
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());
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 p2 = vertex_locations[e.vertex2_index];
@ -32,7 +32,7 @@ pub fn render_graph<D>(
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];