[lab3] Ants similar visualization
This commit is contained in:
parent
6b74ba6590
commit
d2ba913525
@ -9,10 +9,4 @@ pub struct EdgeExtraData {
|
|||||||
|
|
||||||
pub type Edge = _BaseEdge<EdgeExtraData>;
|
pub type Edge = _BaseEdge<EdgeExtraData>;
|
||||||
pub type EdgesVec = _BaseEdgesVec<EdgeExtraData>;
|
pub type EdgesVec = _BaseEdgesVec<EdgeExtraData>;
|
||||||
|
pub use state::{AntsSimulationConfig, AntsSimulationState, updateState, Ant};
|
||||||
pub struct AntsSimulationConfig {
|
|
||||||
pub ferment_weight: f64,
|
|
||||||
pub heuristic_coefficient: f64,
|
|
||||||
pub q: f64,
|
|
||||||
pub r: f64,
|
|
||||||
}
|
|
||||||
@ -1,6 +1,8 @@
|
|||||||
use super::EdgesVec;
|
use super::EdgesVec;
|
||||||
|
use rand::Rng;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::ops::Mul;
|
use std::ops::Mul;
|
||||||
|
use tsp_utility::graph::VerticesVec;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum AntDirection {
|
pub enum AntDirection {
|
||||||
@ -8,11 +10,24 @@ pub enum AntDirection {
|
|||||||
ToFirst,
|
ToFirst,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Ant {
|
pub struct Ant {
|
||||||
allowed_vertices: HashSet<usize>,
|
allowed_vertices: HashSet<usize>,
|
||||||
location: AntLocation,
|
location: AntLocation,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Ant {
|
||||||
|
pub fn new(vertex: usize, allowed_vertices: HashSet<usize>) -> Self {
|
||||||
|
return Self {
|
||||||
|
allowed_vertices: allowed_vertices,
|
||||||
|
location: AntLocation::OnVertex {
|
||||||
|
vertex_index: vertex,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum AntLocation {
|
pub enum AntLocation {
|
||||||
OnEdge {
|
OnEdge {
|
||||||
edge_index: usize,
|
edge_index: usize,
|
||||||
@ -24,20 +39,32 @@ pub enum AntLocation {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AntsSimulationState<'a, Rng: rand::Rng> {
|
pub struct AntsSimulationState {
|
||||||
rng: Rng,
|
pub vertices: VerticesVec,
|
||||||
vertices: &'a Vec<HashSet<usize>>,
|
pub edges: EdgesVec,
|
||||||
edges: &'a mut EdgesVec,
|
pub ants: Vec<Ant>,
|
||||||
ants: &'a mut [Ant],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateState<Rng: rand::Rng>(
|
pub struct AntsSimulationConfig {
|
||||||
state: &mut AntsSimulationState<Rng>,
|
pub ferment_weight: f64,
|
||||||
ferment_weight: f64,
|
pub heuristic_coefficient: f64,
|
||||||
heuristic_coefficient: f64,
|
pub q: f64,
|
||||||
q: f64,
|
pub r: f64,
|
||||||
r: f64,
|
}
|
||||||
speed: u16,
|
|
||||||
|
pub fn updateState(
|
||||||
|
state: &mut AntsSimulationState,
|
||||||
|
cfg: &AntsSimulationConfig,
|
||||||
|
rng: &mut impl Rng,
|
||||||
|
) {
|
||||||
|
_updateState(state, cfg, rng);
|
||||||
|
_updateState(state, cfg, rng);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _updateState(
|
||||||
|
state: &mut AntsSimulationState,
|
||||||
|
cfg: &AntsSimulationConfig,
|
||||||
|
rng: &mut impl Rng,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut finished_ants_count = 0usize;
|
let mut finished_ants_count = 0usize;
|
||||||
for ant in state.ants.iter_mut() {
|
for ant in state.ants.iter_mut() {
|
||||||
@ -46,11 +73,9 @@ pub fn updateState<Rng: rand::Rng>(
|
|||||||
edge_index,
|
edge_index,
|
||||||
offset,
|
offset,
|
||||||
direction,
|
direction,
|
||||||
} => match offset.checked_add(speed) {
|
} => {
|
||||||
Some(newOffset) => *offset = newOffset,
|
|
||||||
None => {
|
|
||||||
let edge = &mut state.edges[*edge_index];
|
let edge = &mut state.edges[*edge_index];
|
||||||
edge.extra.ferment_intensity += (q / edge.length) * r;
|
edge.extra.ferment_intensity += (cfg.q / edge.length) * cfg.r;
|
||||||
let vertex_index;
|
let vertex_index;
|
||||||
match direction {
|
match direction {
|
||||||
AntDirection::ToSecond => vertex_index = edge.vertex2_index,
|
AntDirection::ToSecond => vertex_index = edge.vertex2_index,
|
||||||
@ -58,7 +83,6 @@ pub fn updateState<Rng: rand::Rng>(
|
|||||||
}
|
}
|
||||||
ant.location = AntLocation::OnVertex { vertex_index }
|
ant.location = AntLocation::OnVertex { vertex_index }
|
||||||
}
|
}
|
||||||
},
|
|
||||||
AntLocation::OnVertex { vertex_index } => {
|
AntLocation::OnVertex { vertex_index } => {
|
||||||
let allowed_outbounds = state.vertices[*vertex_index]
|
let allowed_outbounds = state.vertices[*vertex_index]
|
||||||
.iter()
|
.iter()
|
||||||
@ -75,8 +99,8 @@ pub fn updateState<Rng: rand::Rng>(
|
|||||||
return (
|
return (
|
||||||
e.0,
|
e.0,
|
||||||
(e.2, e.3),
|
(e.2, e.3),
|
||||||
e.1.extra.ferment_intensity.powf(ferment_weight)
|
e.1.extra.ferment_intensity.powf(cfg.ferment_weight)
|
||||||
* (1.0 / e.1.length).powf(heuristic_coefficient),
|
* (1.0 / e.1.length).powf(cfg.heuristic_coefficient),
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.collect::<Vec<(usize, (usize, AntDirection), f64)>>();
|
.collect::<Vec<(usize, (usize, AntDirection), f64)>>();
|
||||||
@ -84,7 +108,7 @@ pub fn updateState<Rng: rand::Rng>(
|
|||||||
let mut accumulator: f64 = allowed_outbounds
|
let mut accumulator: f64 = allowed_outbounds
|
||||||
.iter()
|
.iter()
|
||||||
.fold(0.0, |a, e| a + e.2)
|
.fold(0.0, |a, e| a + e.2)
|
||||||
.mul(state.rng.random::<f64>());
|
.mul(rng.random::<f64>());
|
||||||
let target_vertex_index = allowed_outbounds.iter().find(|e| {
|
let target_vertex_index = allowed_outbounds.iter().find(|e| {
|
||||||
accumulator -= e.2;
|
accumulator -= e.2;
|
||||||
return accumulator <= 0.0;
|
return accumulator <= 0.0;
|
||||||
|
|||||||
137
lab3/src/main.rs
137
lab3/src/main.rs
@ -2,13 +2,18 @@
|
|||||||
|
|
||||||
mod algo;
|
mod algo;
|
||||||
|
|
||||||
use crate::algo::{AntsSimulationConfig, EdgeExtraData, EdgesVec, VerticesVec};
|
use crate::algo::{
|
||||||
|
Ant, AntsSimulationConfig, AntsSimulationState, EdgeExtraData, EdgesVec, VerticesVec,
|
||||||
|
updateState,
|
||||||
|
};
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use eframe::egui::{Frame, Ui};
|
use eframe::egui::{Frame, Ui};
|
||||||
use eframe::emath::Numeric;
|
use eframe::emath::Numeric;
|
||||||
|
use std::cmp::max;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
use tsp_utility::gui::lengths_table::{draw_lengths_table, UpdatePending};
|
use tsp_utility::gui::lengths_table::{UpdatePending, draw_lengths_table};
|
||||||
|
use tsp_utility::gui::render::render_graph;
|
||||||
|
|
||||||
fn main() -> eframe::Result {
|
fn main() -> eframe::Result {
|
||||||
let options = eframe::NativeOptions {
|
let options = eframe::NativeOptions {
|
||||||
@ -22,33 +27,29 @@ fn main() -> eframe::Result {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ViewState {
|
|
||||||
Stop,
|
|
||||||
Running { lastUpdateTimestamp: u64 },
|
|
||||||
VertexMove { vertexId: usize },
|
|
||||||
}
|
|
||||||
|
|
||||||
enum GlobalState {
|
enum GlobalState {
|
||||||
Edit {},
|
Edit,
|
||||||
Running { view_state: ViewState },
|
Running,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MyApp {
|
struct MyApp {
|
||||||
edges: EdgesVec,
|
simulation: AntsSimulationState,
|
||||||
vertices: VerticesVec,
|
|
||||||
config: AntsSimulationConfig,
|
config: AntsSimulationConfig,
|
||||||
vertex_update: UpdatePending,
|
vertex_update: UpdatePending,
|
||||||
speed: u32,
|
|
||||||
state: GlobalState,
|
state: GlobalState,
|
||||||
|
vertex_locations: Vec<(f32, f32)>,
|
||||||
|
ants_per_vertex: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MyApp {
|
impl Default for MyApp {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
return Self {
|
return Self {
|
||||||
|
simulation: AntsSimulationState {
|
||||||
edges: EdgesVec::new(),
|
edges: EdgesVec::new(),
|
||||||
vertices: VerticesVec::new(),
|
vertices: VerticesVec::new(),
|
||||||
|
ants: Vec::new(),
|
||||||
|
},
|
||||||
vertex_update: UpdatePending::NoChange,
|
vertex_update: UpdatePending::NoChange,
|
||||||
speed: 1,
|
|
||||||
config: AntsSimulationConfig {
|
config: AntsSimulationConfig {
|
||||||
ferment_weight: 0.5,
|
ferment_weight: 0.5,
|
||||||
heuristic_coefficient: 0.5,
|
heuristic_coefficient: 0.5,
|
||||||
@ -56,6 +57,8 @@ impl Default for MyApp {
|
|||||||
r: 0.5,
|
r: 0.5,
|
||||||
},
|
},
|
||||||
state: GlobalState::Edit {},
|
state: GlobalState::Edit {},
|
||||||
|
vertex_locations: Vec::new(),
|
||||||
|
ants_per_vertex: 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,13 +88,13 @@ impl eframe::App for MyApp {
|
|||||||
match self.vertex_update {
|
match self.vertex_update {
|
||||||
UpdatePending::NoChange => {}
|
UpdatePending::NoChange => {}
|
||||||
UpdatePending::Add => {
|
UpdatePending::Add => {
|
||||||
let new_vi = self.vertices.add(HashSet::new());
|
let new_vi = self.simulation.vertices.add(HashSet::new());
|
||||||
let mut newEdgesSet = HashSet::new();
|
let mut newEdgesSet = HashSet::new();
|
||||||
for (vi, v) in self.vertices.iter_indexed_mut() {
|
for (vi, v) in self.simulation.vertices.iter_indexed_mut() {
|
||||||
if (vi == new_vi) {
|
if (vi == new_vi) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let ei = self.edges.add(
|
let ei = self.simulation.edges.add(
|
||||||
new_vi,
|
new_vi,
|
||||||
vi,
|
vi,
|
||||||
1.0,
|
1.0,
|
||||||
@ -102,19 +105,20 @@ impl eframe::App for MyApp {
|
|||||||
newEdgesSet.insert(ei);
|
newEdgesSet.insert(ei);
|
||||||
v.insert(ei);
|
v.insert(ei);
|
||||||
}
|
}
|
||||||
self.vertices[new_vi] = newEdgesSet;
|
self.simulation.vertices[new_vi] = newEdgesSet;
|
||||||
self.vertex_update = UpdatePending::NoChange;
|
self.vertex_update = UpdatePending::NoChange;
|
||||||
}
|
}
|
||||||
UpdatePending::Remove(vi) => {
|
UpdatePending::Remove(vi) => {
|
||||||
let mut eis = Vec::with_capacity(self.vertices[vi].len());
|
let mut eis = Vec::with_capacity(self.simulation.vertices[vi].len());
|
||||||
for ei in self.vertices[vi].iter() {
|
for ei in self.simulation.vertices[vi].iter() {
|
||||||
eis.push(*ei)
|
eis.push(*ei)
|
||||||
}
|
}
|
||||||
for ei in eis {
|
for ei in eis {
|
||||||
self.vertices[self.edges[ei].another(vi)].remove(&ei);
|
self.simulation.vertices[self.simulation.edges[ei].another(vi)]
|
||||||
self.edges.remove(ei);
|
.remove(&ei);
|
||||||
|
self.simulation.edges.remove(ei);
|
||||||
}
|
}
|
||||||
self.vertices.remove(vi);
|
self.simulation.vertices.remove(vi);
|
||||||
self.vertex_update = UpdatePending::NoChange;
|
self.vertex_update = UpdatePending::NoChange;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,7 +144,7 @@ impl eframe::App for MyApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn edit_panel(data: &mut MyApp, ui: &mut Ui) {
|
fn edit_panel(data: &mut MyApp, ui: &mut Ui) {
|
||||||
let run: bool;
|
let mut run: bool = false;
|
||||||
|
|
||||||
_slider(
|
_slider(
|
||||||
ui,
|
ui,
|
||||||
@ -162,30 +166,97 @@ fn edit_panel(data: &mut MyApp, ui: &mut Ui) {
|
|||||||
ui.label("");
|
ui.label("");
|
||||||
_slider(ui, "r", &mut data.config.r, 0.0..=1.0, 0.001);
|
_slider(ui, "r", &mut data.config.r, 0.0..=1.0, 0.001);
|
||||||
ui.label("");
|
ui.label("");
|
||||||
|
_slider(
|
||||||
|
ui,
|
||||||
|
"Ants per vertex",
|
||||||
|
&mut data.ants_per_vertex,
|
||||||
|
1..=100,
|
||||||
|
1.0,
|
||||||
|
);
|
||||||
|
ui.label("");
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
if ui.button("Add vertex").clicked() {
|
if ui.button("Add vertex").clicked() {
|
||||||
data.vertex_update = UpdatePending::Add;
|
data.vertex_update = UpdatePending::Add;
|
||||||
}
|
}
|
||||||
ui.separator();
|
ui.separator();
|
||||||
let run = ui.button("Run").clicked();
|
run = ui.button("Run").clicked();
|
||||||
});
|
});
|
||||||
|
|
||||||
draw_lengths_table(
|
draw_lengths_table(
|
||||||
ui,
|
ui,
|
||||||
&mut data.vertices,
|
&mut data.simulation.vertices,
|
||||||
&mut data.edges,
|
&mut data.simulation.edges,
|
||||||
&mut data.vertex_update,
|
&mut data.vertex_update,
|
||||||
|
);
|
||||||
|
|
||||||
|
if run {
|
||||||
|
let mut coords = vec![(0.0, 0.0); data.simulation.vertices.capacity()];
|
||||||
|
|
||||||
|
for (i, _) in data.simulation.vertices.iter_indexed() {
|
||||||
|
coords[i] = (
|
||||||
|
rand::random::<f32>() * 0.8 + 0.1,
|
||||||
|
rand::random::<f32>() * 0.8 + 0.1,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visualization_panel(data: &mut MyApp, ui: &mut Ui) {
|
data.state = GlobalState::Running;
|
||||||
ui.horizontal(|ui| {
|
data.vertex_locations = coords;
|
||||||
if ui.button("Exit").clicked() {}
|
|
||||||
|
|
||||||
if ui.button("Pause").clicked() {}
|
let allowed_locations = data
|
||||||
|
.simulation
|
||||||
|
.vertices
|
||||||
|
.iter_indexed()
|
||||||
|
.map(|(i, _)| i)
|
||||||
|
.collect::<HashSet<usize>>();
|
||||||
|
|
||||||
|
let mut ants = Vec::new();
|
||||||
|
for (i, _) in data.simulation.vertices.iter_indexed() {
|
||||||
|
for _ in 0..data.ants_per_vertex {
|
||||||
|
ants.push(Ant::new(i, allowed_locations.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.simulation.ants = ants;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visualization_panel(data: &mut MyApp, ui: &mut Ui) {
|
||||||
|
ui.vertical(|ui| {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
if ui.button("Exit").clicked() {
|
||||||
|
data.state = GlobalState::Edit
|
||||||
|
}
|
||||||
|
|
||||||
|
if ui.button("Step").clicked() {
|
||||||
|
updateState(&mut data.simulation, &mut data.config, &mut rand::rng());
|
||||||
|
}
|
||||||
ui.label("");
|
ui.label("");
|
||||||
_slider(ui, "Ant speed", &mut data.speed, 1..=10, 1.0);
|
});
|
||||||
|
draw_ants(data, ui);
|
||||||
|
if ui.input(|i| i.viewport().close_requested()) {
|
||||||
|
data.state = GlobalState::Edit
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_ants(data: &mut MyApp, ui: &mut Ui) {}
|
fn draw_ants(data: &mut MyApp, ui: &mut Ui) {
|
||||||
|
let mut cap: f64 = 0.000000000001;
|
||||||
|
|
||||||
|
for w in data
|
||||||
|
.simulation
|
||||||
|
.edges
|
||||||
|
.iter()
|
||||||
|
.map(|e| e.extra.ferment_intensity)
|
||||||
|
{
|
||||||
|
if w > cap {
|
||||||
|
cap = w
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render_graph(
|
||||||
|
ui,
|
||||||
|
&data.simulation.vertices,
|
||||||
|
data.vertex_locations.as_mut_slice(),
|
||||||
|
&data.simulation.edges,
|
||||||
|
|e| e.extra.ferment_intensity / cap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@ -91,6 +91,10 @@ impl<T> _PreserveIndexVec<T> {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn capacity(&self) -> usize {
|
||||||
|
return self.buffer.len();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Index<usize> for _PreserveIndexVec<T> {
|
impl<T> Index<usize> for _PreserveIndexVec<T> {
|
||||||
|
|||||||
@ -51,6 +51,10 @@ impl<D> EdgesVec<D> {
|
|||||||
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 capacity(&self) -> usize {
|
||||||
|
return self.data.capacity()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <D> Index<usize> for EdgesVec<D> {
|
impl <D> Index<usize> for EdgesVec<D> {
|
||||||
|
|||||||
@ -33,6 +33,10 @@ impl VerticesVec {
|
|||||||
pub fn iter_indexed_mut(&mut self) -> impl Iterator<Item = (usize, &mut HashSet<usize>)> {
|
pub fn iter_indexed_mut(&mut self) -> impl Iterator<Item = (usize, &mut HashSet<usize>)> {
|
||||||
return self.data.iter_indexed_mut();
|
return self.data.iter_indexed_mut();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn capacity(&self) -> usize {
|
||||||
|
return self.data.capacity()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index<usize> for VerticesVec {
|
impl Index<usize> for VerticesVec {
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
pub mod lengths_table;
|
pub mod lengths_table;
|
||||||
|
pub mod render;
|
||||||
|
|||||||
66
tsp-utility/src/gui/render.rs
Normal file
66
tsp-utility/src/gui/render.rs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
use crate::graph::{Edge, EdgesVec, VerticesVec};
|
||||||
|
use eframe::egui::{Color32, Pos2, Rect, Ui};
|
||||||
|
use eframe::epaint::{CornerRadius, Stroke};
|
||||||
|
|
||||||
|
pub fn render_graph<D>(
|
||||||
|
ui: &mut Ui,
|
||||||
|
vertices: &VerticesVec,
|
||||||
|
vertex_locations: &mut [(f32, f32)],
|
||||||
|
edges: &EdgesVec<D>,
|
||||||
|
normalized_intensity: impl Fn(&Edge<D>) -> f64,
|
||||||
|
) {
|
||||||
|
let canvas = ui.painter();
|
||||||
|
let rect = ui.available_size();
|
||||||
|
let start = ui.cursor();
|
||||||
|
|
||||||
|
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() {
|
||||||
|
let p1 = vertex_locations[e.vertex1_index];
|
||||||
|
let p2 = vertex_locations[e.vertex2_index];
|
||||||
|
|
||||||
|
canvas.line_segment(
|
||||||
|
[
|
||||||
|
Pos2::new(
|
||||||
|
p1.0 * rect.width() + rect.min.x,
|
||||||
|
p1.1 * rect.height() + rect.min.y,
|
||||||
|
),
|
||||||
|
Pos2::new(
|
||||||
|
p2.0 * rect.width() + rect.min.x,
|
||||||
|
p2.1 * rect.height() + rect.min.y,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Stroke::new(1.0, intensity2color(normalized_intensity(e))),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn intensity2color(intensity: f64) -> Color32 {
|
||||||
|
let scale = |base: f64, coefficient: u8| -> u8 {
|
||||||
|
return ((intensity - base) * 5.0 * (coefficient as f64)) as u8;
|
||||||
|
};
|
||||||
|
|
||||||
|
match intensity {
|
||||||
|
f64::NEG_INFINITY..0.2 => {
|
||||||
|
return Color32::from_rgb(
|
||||||
|
50 - scale(0.0, 50),
|
||||||
|
50 - scale(0.0, 50),
|
||||||
|
50 + scale(0.0, 155),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
0.2..0.4 => {
|
||||||
|
return Color32::from_rgb(0, scale(0.2, 255), 255);
|
||||||
|
}
|
||||||
|
0.4..0.6 => {
|
||||||
|
return Color32::from_rgb(0, 255, 255 - scale(0.4, 255));
|
||||||
|
}
|
||||||
|
0.6..0.8 => {
|
||||||
|
return Color32::from_rgb(scale(0.6, 255) as u8, 255, 0);
|
||||||
|
}
|
||||||
|
0.8..f64::INFINITY => {
|
||||||
|
return Color32::from_rgb(255, 255 - scale(0.8, 255), 0);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user