public inbox for yew-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Dominik Csapak <d.csapak@proxmox.com>
To: yew-devel@lists.proxmox.com
Subject: [yew-devel] [PATCH yew-comp 13/20] rrd: refactor series related struct and functions into own module
Date: Fri, 30 May 2025 14:21:55 +0200	[thread overview]
Message-ID: <20250530122202.2779300-14-d.csapak@proxmox.com> (raw)
In-Reply-To: <20250530122202.2779300-1-d.csapak@proxmox.com>

makes the main graph module a bit smaller. While at it, document the
compute_*_path functions.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/rrd/graph.rs  | 101 +------------------------------------------
 src/rrd/mod.rs    |   3 ++
 src/rrd/series.rs | 107 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 112 insertions(+), 99 deletions(-)
 create mode 100644 src/rrd/series.rs

diff --git a/src/rrd/graph.rs b/src/rrd/graph.rs
index b58bd58..161269f 100644
--- a/src/rrd/graph.rs
+++ b/src/rrd/graph.rs
@@ -15,20 +15,6 @@ use pwt::widget::{Button, Container, Panel};
 
 use pwt_macros::builder;
 
-pub struct Series {
-    pub label: AttrValue,
-    pub data: Vec<f64>,
-}
-
-impl Series {
-    pub fn new(label: impl Into<AttrValue>, data: Vec<f64>) -> Self {
-        Self {
-            label: label.into(),
-            data,
-        }
-    }
-}
-
 #[derive(Derivative)]
 #[derivative(Clone, PartialEq)]
 #[derive(Properties)]
@@ -166,7 +152,9 @@ impl Default for LayoutProps {
 
 use pwt::widget::canvas::{Canvas, Circle, Group, Path, Rect, SvgLength, Text};
 
+use super::series::{compute_fill_path, compute_outline_path};
 use super::units::{get_grid_unit_base10, get_grid_unit_base2, get_time_grid_unit};
+use super::Series;
 
 fn format_date_time(t: i64) -> String {
     let (time, date) = format_time(t);
@@ -264,91 +252,6 @@ fn compute_min_max(props: &RRDGraph, data1: &[f64], data2: &[f64]) -> (f64, f64,
     (min_data, max_data, grid_unit)
 }
 
-fn compute_outline_path(
-    time_data: &[i64],
-    values: &[f64],
-    compute_x: impl Fn(i64) -> f64,
-    compute_y: impl Fn(f64) -> f64,
-) -> String {
-    let mut path = String::new();
-    let mut last_undefined = true;
-    for (i, t) in time_data.iter().enumerate() {
-        let value = *values.get(i).unwrap_or(&f64::NAN);
-        let x = compute_x(*t);
-
-        if last_undefined {
-            if value.is_nan() {
-                continue;
-            }
-            last_undefined = false;
-            let y = compute_y(value);
-            path.push_str(&format!(" M {:.1} {:.1}", x, y));
-        } else {
-            if value.is_nan() {
-                last_undefined = true;
-                continue;
-            }
-            let y = compute_y(value);
-            path.push_str(&format!(" L {:.1} {:.1}", x, y));
-        }
-    }
-    path
-}
-
-fn compute_fill_path(
-    time_data: &[i64],
-    values: &[f64],
-    min_data: f64,
-    max_data: f64,
-    compute_x: impl Fn(i64) -> f64,
-    compute_y: impl Fn(f64) -> f64,
-) -> String {
-    let mut y0 = compute_y(0.0);
-    if min_data > 0.0 {
-        y0 = compute_y(min_data)
-    }
-    if max_data < 0.0 {
-        y0 = compute_y(max_data)
-    }
-    let mut path = String::new();
-    let mut last_undefined = true;
-    for i in 0..time_data.len() {
-        let t = time_data[i];
-        let value = *values.get(i).unwrap_or(&f64::NAN);
-
-        let x = compute_x(t);
-
-        if last_undefined {
-            if value.is_nan() {
-                continue;
-            }
-            last_undefined = false;
-            path.push_str(&format!(" M {:.1} {:.1}", x, y0));
-        } else if value.is_nan() {
-            last_undefined = true;
-            let x = if i > 0 {
-                compute_x(time_data[i - 1])
-            } else {
-                x
-            };
-            path.push_str(&format!(" L {:.1} {:.1}", x, y0));
-
-            continue;
-        }
-        let y = compute_y(value);
-        path.push_str(&format!(" L {:.1} {:.1}", x, y));
-    }
-
-    if let Some(t) = time_data.last() {
-        if !last_undefined {
-            let x = compute_x(*t);
-            path.push_str(&format!(" L {:.1} {:.1}", x, y0));
-        }
-    }
-
-    path
-}
-
 impl PwtRRDGraph {
     fn get_view_data<'a>(&self, ctx: &'a Context<Self>) -> (&'a [i64], &'a [f64], &'a [f64]) {
         let props = ctx.props();
diff --git a/src/rrd/mod.rs b/src/rrd/mod.rs
index 7931053..fe63ff5 100644
--- a/src/rrd/mod.rs
+++ b/src/rrd/mod.rs
@@ -1,4 +1,7 @@
 mod graph;
 pub use graph::*;
 
+pub(crate) mod series;
+pub use series::Series;
+
 pub(crate) mod units;
diff --git a/src/rrd/series.rs b/src/rrd/series.rs
new file mode 100644
index 0000000..8807598
--- /dev/null
+++ b/src/rrd/series.rs
@@ -0,0 +1,107 @@
+use yew::AttrValue;
+
+/// Represents a series of data for an [`crate::RRDGraph`]
+pub struct Series {
+    pub label: AttrValue,
+    pub data: Vec<f64>,
+}
+
+impl Series {
+    pub fn new(label: impl Into<AttrValue>, data: Vec<f64>) -> Self {
+        Self {
+            label: label.into(),
+            data,
+        }
+    }
+}
+
+/// Calculate the outline path of a series of [`f64`] data for [`i64`] points in time.
+///
+/// The line will not be drawn for points that are missing
+pub fn compute_outline_path(
+    time_data: &[i64],
+    values: &[f64],
+    compute_x: impl Fn(i64) -> f64,
+    compute_y: impl Fn(f64) -> f64,
+) -> String {
+    let mut path = String::new();
+    let mut last_undefined = true;
+    for (i, t) in time_data.iter().enumerate() {
+        let value = *values.get(i).unwrap_or(&f64::NAN);
+        let x = compute_x(*t);
+
+        if last_undefined {
+            if value.is_nan() {
+                continue;
+            }
+            last_undefined = false;
+            let y = compute_y(value);
+            path.push_str(&format!(" M {:.1} {:.1}", x, y));
+        } else {
+            if value.is_nan() {
+                last_undefined = true;
+                continue;
+            }
+            let y = compute_y(value);
+            path.push_str(&format!(" L {:.1} {:.1}", x, y));
+        }
+    }
+    path
+}
+
+/// Calculate the fill path for a series of [`f64`] points for [`i64`] points in time.
+///
+/// The area will not be filled for points that are missing
+pub fn compute_fill_path(
+    time_data: &[i64],
+    values: &[f64],
+    min_data: f64,
+    max_data: f64,
+    compute_x: impl Fn(i64) -> f64,
+    compute_y: impl Fn(f64) -> f64,
+) -> String {
+    let mut y0 = compute_y(0.0);
+    if min_data > 0.0 {
+        y0 = compute_y(min_data)
+    }
+    if max_data < 0.0 {
+        y0 = compute_y(max_data)
+    }
+    let mut path = String::new();
+    let mut last_undefined = true;
+    for i in 0..time_data.len() {
+        let t = time_data[i];
+        let value = *values.get(i).unwrap_or(&f64::NAN);
+
+        let x = compute_x(t);
+
+        if last_undefined {
+            if value.is_nan() {
+                continue;
+            }
+            last_undefined = false;
+            path.push_str(&format!(" M {:.1} {:.1}", x, y0));
+        } else if value.is_nan() {
+            last_undefined = true;
+            let x = if i > 0 {
+                compute_x(time_data[i - 1])
+            } else {
+                x
+            };
+            path.push_str(&format!(" L {:.1} {:.1}", x, y0));
+
+            continue;
+        }
+        let y = compute_y(value);
+        path.push_str(&format!(" L {:.1} {:.1}", x, y));
+    }
+
+    if let Some(t) = time_data.last() {
+        if !last_undefined {
+            let x = compute_x(*t);
+            path.push_str(&format!(" L {:.1} {:.1}", x, y0));
+        }
+    }
+
+    path
+}
-- 
2.39.5



_______________________________________________
yew-devel mailing list
yew-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/yew-devel


  parent reply	other threads:[~2025-05-30 12:22 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-30 12:21 [yew-devel] [PATCH yew-comp 00/20] refactor and improve rrd graph code Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 01/20] remove old rrd uplot code Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 02/20] rrd: refactor code for compute_min_max Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 03/20] rrd: move into own module Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 04/20] rrd: move unit calculation to " Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 05/20] rrd: units: add tests Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 06/20] rrd: units: simplify calculations for get_grid_unit_base Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 07/20] rrd: remove unnecessary `no_data` field Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 08/20] rrd: align tooltip directly to pointer position Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 09/20] rrd: use 'cross_pos' state instead of 'draw_cross' Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 10/20] rrd: give all elements in svg keys Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 11/20] rrd: simplify toggle Msg Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 12/20] rrd: remove wrongly annotated lifetime Dominik Csapak
2025-05-30 12:21 ` Dominik Csapak [this message]
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 14/20] rrd: clamp view range when time_data changes Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 15/20] rrd: refactor grid data computation Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 16/20] rrd: introduce GraphSpace struct and use it to precalculate graph data Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 17/20] rrd: precalculate the grid line and label positions Dominik Csapak
2025-05-30 12:22 ` [yew-devel] [PATCH yew-comp 18/20] rrd: calculate series svg data only when necessary Dominik Csapak
2025-05-30 12:22 ` [yew-devel] [PATCH yew-comp 19/20] rrd: refactor selection rectangle calculation Dominik Csapak
2025-05-30 12:22 ` [yew-devel] [PATCH yew-comp 20/20] rrd: refactor the cross position calculation Dominik Csapak

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250530122202.2779300-14-d.csapak@proxmox.com \
    --to=d.csapak@proxmox.com \
    --cc=yew-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal