Skip to content

Commit adc8803

Browse files
committed
readd example for demo
1 parent 4ea1b88 commit adc8803

File tree

9 files changed

+248
-0
lines changed

9 files changed

+248
-0
lines changed

Cargo.lock

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3616,6 +3616,16 @@ version = "2.1.3"
36163616
source = "registry+https://github.com/rust-lang/crates.io-index"
36173617
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
36183618

3619+
[[package]]
3620+
name = "userdata_points"
3621+
version = "0.1.0"
3622+
dependencies = [
3623+
"eframe",
3624+
"egui_plot",
3625+
"env_logger",
3626+
"examples_utils",
3627+
]
3628+
36193629
[[package]]
36203630
name = "utf8_iter"
36213631
version = "1.0.4"

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ performance = { version = "0.1.0", path = "examples/performance" }
4040
plot_span = { version = "0.1.0", path = "examples/plot_span" }
4141
save_plot = { version = "0.1.0", path = "examples/save_plot" }
4242
stacked_bar = { version = "0.1.0", path = "examples/stacked_bar" }
43+
userdata_points = { version = "0.1.0", path = "examples/userdata_points" }
4344

4445
ahash = { version = "0.8.12", default-features = false, features = [
4546
"no-rng", # we don't need DOS-protection, so we let users opt-in to it instead
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[package]
2+
name = "userdata_points"
3+
version = "0.1.0"
4+
authors = ["Nicolas <bircni@icloud.com>"]
5+
license.workspace = true
6+
edition.workspace = true
7+
rust-version.workspace = true
8+
publish = false
9+
10+
[lints]
11+
workspace = true
12+
13+
[dependencies]
14+
eframe = { workspace = true, features = ["default"] }
15+
egui_plot.workspace = true
16+
env_logger = { workspace = true, default-features = false, features = [
17+
"auto-color",
18+
"humantime",
19+
] }
20+
examples_utils.workspace = true
21+
22+
[package.metadata.cargo-shear]
23+
ignored = ["env_logger"] # used by make_main! macro

examples/userdata_points/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Userdata Points Example
2+
3+
TODO
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
use eframe::egui;
2+
use eframe::egui::Response;
3+
use egui_plot::Legend;
4+
use egui_plot::Line;
5+
use egui_plot::Plot;
6+
7+
use egui::mutex::Mutex;
8+
use egui::{Color32, Id};
9+
use egui_plot::{Corner, MarkerShape, Points};
10+
use std::collections::HashMap;
11+
use std::sync::Arc;
12+
13+
pub struct UserdataPointsExample {
14+
sine_points: Vec<DemoPoint>,
15+
cosine_points: Vec<DemoPoint>,
16+
damped_points: Vec<DemoPoint>,
17+
}
18+
19+
#[derive(Clone)]
20+
struct DemoPoint {
21+
x: f64,
22+
y: f64,
23+
custom_label: String,
24+
importance: f32,
25+
}
26+
27+
impl Default for UserdataPointsExample {
28+
fn default() -> Self {
29+
// Create multiple datasets with custom metadata
30+
let sine_points = (0..=500)
31+
.map(|i| {
32+
let x = i as f64 / 100.0;
33+
DemoPoint {
34+
x,
35+
y: x.sin(),
36+
custom_label: format!("Sine #{i}"),
37+
importance: (i % 100) as f32 / 100.0,
38+
}
39+
})
40+
.collect::<Vec<_>>();
41+
let cosine_points = (0..=500)
42+
.map(|i| {
43+
let x = i as f64 / 100.0;
44+
DemoPoint {
45+
x,
46+
y: x.cos(),
47+
custom_label: format!("Cosine #{i}"),
48+
importance: (1.0 - (i % 100) as f32 / 100.0),
49+
}
50+
})
51+
.collect::<Vec<_>>();
52+
53+
let damped_points = (0..=500)
54+
.map(|i| {
55+
let x = i as f64 / 100.0;
56+
DemoPoint {
57+
x,
58+
y: (-x * 0.5).exp() * (2.0 * x).sin(),
59+
custom_label: format!("Damped #{i}"),
60+
importance: if i % 50 == 0 { 1.0 } else { 0.3 },
61+
}
62+
})
63+
.collect::<Vec<_>>();
64+
Self {
65+
sine_points,
66+
cosine_points,
67+
damped_points,
68+
}
69+
}
70+
}
71+
72+
impl UserdataPointsExample {
73+
pub fn show_plot(&self, ui: &mut egui::Ui) -> Response {
74+
let custom_data = Arc::new(Mutex::new(HashMap::<Id, Vec<DemoPoint>>::new()));
75+
76+
let custom_data_ = custom_data.clone();
77+
Plot::new("Userdata Plot Demo")
78+
.legend(Legend::default().position(Corner::LeftTop))
79+
.label_formatter(move |name, value, item| {
80+
if let Some((id, index)) = item {
81+
let lock = custom_data_.lock();
82+
if let Some(points) = lock.get(&id) {
83+
if let Some(point) = points.get(index) {
84+
return format!(
85+
"{}\nPosition: ({:.3}, {:.3})\nLabel: {}\nImportance: {:.1}%",
86+
name,
87+
value.x,
88+
value.y,
89+
point.custom_label,
90+
point.importance * 100.0
91+
);
92+
}
93+
}
94+
}
95+
format!("{}\n({:.3}, {:.3})", name, value.x, value.y)
96+
})
97+
.show(ui, |plot_ui| {
98+
let mut lock = custom_data.lock();
99+
100+
// Sine wave with custom data
101+
let sine_id = Id::new("sine_wave");
102+
lock.insert(sine_id, self.sine_points.clone());
103+
plot_ui.line(
104+
Line::new(
105+
"sin(x)",
106+
self.sine_points.iter().map(|p| [p.x, p.y]).collect::<Vec<_>>(),
107+
)
108+
.id(sine_id)
109+
.color(Color32::from_rgb(200, 100, 100)),
110+
);
111+
112+
// Cosine wave with custom data
113+
let cosine_id = Id::new("cosine_wave");
114+
lock.insert(cosine_id, self.cosine_points.clone());
115+
plot_ui.line(
116+
Line::new(
117+
"cos(x)",
118+
self.cosine_points.iter().map(|p| [p.x, p.y]).collect::<Vec<_>>(),
119+
)
120+
.id(cosine_id)
121+
.color(Color32::from_rgb(100, 200, 100)),
122+
);
123+
124+
// Damped sine wave with custom data
125+
let damped_id = Id::new("damped_wave");
126+
lock.insert(damped_id, self.damped_points.clone());
127+
plot_ui.line(
128+
Line::new(
129+
"e^(-0.5x) · sin(2x)",
130+
self.damped_points.iter().map(|p| [p.x, p.y]).collect::<Vec<_>>(),
131+
)
132+
.id(damped_id)
133+
.color(Color32::from_rgb(100, 100, 200)),
134+
);
135+
136+
// Add some points with high importance as markers
137+
let important_points: Vec<_> = self
138+
.damped_points
139+
.iter()
140+
.filter(|p| p.importance > 0.9)
141+
.map(|p| [p.x, p.y])
142+
.collect();
143+
144+
if !important_points.is_empty() {
145+
plot_ui.points(
146+
Points::new("Important Points", important_points)
147+
.color(Color32::from_rgb(255, 150, 0))
148+
.radius(4.0)
149+
.shape(MarkerShape::Diamond),
150+
);
151+
}
152+
})
153+
.response
154+
}
155+
156+
#[expect(clippy::unused_self, reason = "required by the example template")]
157+
pub fn show_controls(&self, ui: &mut egui::Ui) -> Response {
158+
ui.scope(|_ui| {}).response
159+
}
160+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#![doc = include_str!("../README.md")]
2+
3+
use eframe::egui;
4+
use examples_utils::PlotExample;
5+
6+
mod app;
7+
pub use app::UserdataPointsExample;
8+
9+
impl PlotExample for UserdataPointsExample {
10+
fn name(&self) -> &'static str {
11+
"userdata_points"
12+
}
13+
14+
fn title(&self) -> &'static str {
15+
"Example of Userdata Points"
16+
}
17+
18+
fn description(&self) -> &'static str {
19+
"This demo shows how to attach custom data to plot items and display it in tooltips."
20+
}
21+
22+
fn tags(&self) -> &'static [&'static str] {
23+
&["performance"]
24+
}
25+
26+
fn thumbnail_bytes(&self) -> &'static [u8] {
27+
include_bytes!("../screenshot_thumb.png")
28+
}
29+
30+
fn code_bytes(&self) -> &'static [u8] {
31+
include_bytes!("./app.rs")
32+
}
33+
34+
fn show_ui(&mut self, ui: &mut egui::Ui) -> egui::Response {
35+
self.show_plot(ui)
36+
}
37+
38+
fn show_controls(&mut self, ui: &mut egui::Ui) -> egui::Response {
39+
ui.scope(|_ui| {}).response
40+
}
41+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
use examples_utils::make_main;
2+
use userdata_points::UserdataPointsExample;
3+
4+
make_main!(UserdataPointsExample);

0 commit comments

Comments
 (0)