wip: drawing
This commit is contained in:
parent
6f2c044e1c
commit
c771f8698e
File diff suppressed because it is too large
Load Diff
|
|
@ -1,4 +1,4 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
members = ["protocol", "waybar-collectd"]
|
members = ["draw", "protocol", "waybar-collectd"]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
[package]
|
||||||
|
name = "draw"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
imageproc = { version = "0.26.1", features = ["display-window"] }
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
mod stacked;
|
||||||
|
|
||||||
|
pub use stacked::{StackedConfig, StackedSeries, StackedSeriesConfig, stacked};
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
use imageproc::{
|
||||||
|
drawing::draw_filled_rect_mut,
|
||||||
|
image::{Rgb, RgbImage},
|
||||||
|
rect::Rect,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct StackedConfig {
|
||||||
|
pub width_px_per_sample: u32,
|
||||||
|
pub height_px: u32,
|
||||||
|
pub series: Vec<StackedSeriesConfig>,
|
||||||
|
pub max_samples: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct StackedSeriesConfig {
|
||||||
|
pub color: (u8, u8, u8),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct StackedSeries<'a> {
|
||||||
|
pub config: &'a StackedConfig,
|
||||||
|
pub data: Vec<&'a Vec<f32>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stacked(graph: StackedSeries) -> RgbImage {
|
||||||
|
let mut image = RgbImage::new(
|
||||||
|
graph.config.width_px_per_sample * graph.config.max_samples,
|
||||||
|
graph.config.height_px as u32,
|
||||||
|
);
|
||||||
|
draw_scaled_graph(&mut image, &graph);
|
||||||
|
|
||||||
|
image
|
||||||
|
}
|
||||||
|
|
||||||
|
/// return scale factor to scale stacked series sum to range 0..1
|
||||||
|
fn get_scale(series: &Vec<&Vec<f32>>) -> f32 {
|
||||||
|
let len = series.iter().map(|s| s.len()).max().unwrap_or(0);
|
||||||
|
|
||||||
|
let max = (0..len)
|
||||||
|
.map(|i| series.iter().map(|s| s[i]).sum::<f32>())
|
||||||
|
.max_by(|f1, f2| f1.total_cmp(f2))
|
||||||
|
.unwrap_or(1f32);
|
||||||
|
|
||||||
|
1f32 / max
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_scaled_graph(image: &mut RgbImage, graph: &StackedSeries) {
|
||||||
|
let scale = get_scale(&graph.data);
|
||||||
|
let colors = graph
|
||||||
|
.config
|
||||||
|
.series
|
||||||
|
.iter()
|
||||||
|
.map(|s| Rgb([s.color.0, s.color.1, s.color.2]))
|
||||||
|
.collect::<Vec<Rgb<u8>>>();
|
||||||
|
|
||||||
|
let mut x_offset = 0f32;
|
||||||
|
let mut series_idx = 0usize;
|
||||||
|
|
||||||
|
let rows = graph.data.len();
|
||||||
|
let cols = graph.data[0].len();
|
||||||
|
let transposed_series: Vec<Vec<f32>> = (0..cols)
|
||||||
|
.map(|col| (0..rows).map(|row| graph.data[row][col]).collect())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for timeseries in transposed_series {
|
||||||
|
let mut y_offset = graph.config.height_px as f32;
|
||||||
|
|
||||||
|
for sample in timeseries.iter() {
|
||||||
|
println!("VAL {}", sample);
|
||||||
|
let color = colors[series_idx];
|
||||||
|
let height_px = (graph.config.height_px as f32) * sample * scale;
|
||||||
|
let rect = Rect::at(x_offset as i32, (y_offset - height_px) as i32)
|
||||||
|
.of_size(graph.config.width_px_per_sample, height_px as u32);
|
||||||
|
draw_filled_rect_mut(image, rect, color);
|
||||||
|
x_offset += graph.config.width_px_per_sample as f32;
|
||||||
|
y_offset -= height_px;
|
||||||
|
println!("rect: {:?}, height {}, yoff {}", rect, height_px, y_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("BRK");
|
||||||
|
|
||||||
|
// FIXME:
|
||||||
|
// series_idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_scale() {
|
||||||
|
let conf = vec![
|
||||||
|
vec![1., 2., 3., 4., 5.],
|
||||||
|
vec![0., 1., 0., 0., 0.],
|
||||||
|
vec![0., 0., 0., 0., 5.],
|
||||||
|
];
|
||||||
|
assert_eq!(0, 1); // FIX
|
||||||
|
// assert_eq!(get_scale(&conf), 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,4 +4,6 @@ version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
draw = { version = "0.1.0", path = "../draw" }
|
||||||
|
imageproc = { version = "0.26.1", features = ["display-window"] }
|
||||||
protocol = { path = "../protocol" }
|
protocol = { path = "../protocol" }
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,40 @@
|
||||||
|
use draw::{StackedConfig, StackedSeries, StackedSeriesConfig, stacked};
|
||||||
|
use imageproc::window::display_image;
|
||||||
use protocol::Protocol;
|
use protocol::Protocol;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let cfg = StackedConfig {
|
||||||
|
width_px_per_sample: 4,
|
||||||
|
height_px: 100,
|
||||||
|
series: vec![StackedSeriesConfig { color: (255, 0, 0) }],
|
||||||
|
max_samples: 10,
|
||||||
|
};
|
||||||
|
|
||||||
if let Ok(mut proto) = Protocol::new("/var/run/collectd-unixsock") {
|
if let Ok(mut proto) = Protocol::new("/var/run/collectd-unixsock") {
|
||||||
let rec = proto.get("tp-on/cpu-0/cpu-idle".to_string(), "value".to_string());
|
let mut data: Vec<f32> = vec![];
|
||||||
|
// loop {
|
||||||
|
for _ in 1..10 {
|
||||||
|
let rec = proto.get(
|
||||||
|
"beerpowered/cpu-0/cpu-idle".to_string(),
|
||||||
|
"value".to_string(),
|
||||||
|
);
|
||||||
if let Ok(val) = rec {
|
if let Ok(val) = rec {
|
||||||
println!("Got {}", val);
|
data.push(val);
|
||||||
} else {
|
} else {
|
||||||
println!("{}", rec.unwrap_err());
|
println!("{}", rec.unwrap_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if data.len() > 10 {
|
||||||
|
data.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
let img = stacked(StackedSeries {
|
||||||
|
config: &cfg,
|
||||||
|
data: vec![&data],
|
||||||
|
});
|
||||||
|
display_image("bzn", &img, 500, 500);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("sock not found!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue