polyscope_structures/floating/
color_image.rs1use glam::{Vec3, Vec4};
4use polyscope_core::quantity::{Quantity, QuantityKind};
5
6use super::ImageOrigin;
7
8pub struct FloatingColorImage {
12 name: String,
13 width: u32,
14 height: u32,
15 colors: Vec<Vec4>, origin: ImageOrigin,
17 enabled: bool,
18}
19
20impl FloatingColorImage {
21 pub fn new(name: impl Into<String>, width: u32, height: u32, colors: Vec<Vec3>) -> Self {
23 let colors = colors.into_iter().map(|c| c.extend(1.0)).collect();
24 Self {
25 name: name.into(),
26 width,
27 height,
28 colors,
29 origin: ImageOrigin::default(),
30 enabled: true,
31 }
32 }
33
34 #[must_use]
36 pub fn width(&self) -> u32 {
37 self.width
38 }
39
40 #[must_use]
42 pub fn height(&self) -> u32 {
43 self.height
44 }
45
46 #[must_use]
48 pub fn colors(&self) -> &[Vec4] {
49 &self.colors
50 }
51
52 #[must_use]
54 pub fn origin(&self) -> ImageOrigin {
55 self.origin
56 }
57
58 pub fn set_origin(&mut self, origin: ImageOrigin) -> &mut Self {
60 self.origin = origin;
61 self
62 }
63
64 #[must_use]
66 pub fn pixel(&self, x: u32, y: u32) -> Vec4 {
67 let row = match self.origin {
68 ImageOrigin::UpperLeft => y,
69 ImageOrigin::LowerLeft => self.height - 1 - y,
70 };
71 self.colors[(row * self.width + x) as usize]
72 }
73}
74
75impl Quantity for FloatingColorImage {
76 fn as_any(&self) -> &dyn std::any::Any {
77 self
78 }
79 fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
80 self
81 }
82 fn name(&self) -> &str {
83 &self.name
84 }
85 #[allow(clippy::unnecessary_literal_bound)]
86 fn structure_name(&self) -> &str {
87 "" }
89 fn kind(&self) -> QuantityKind {
90 QuantityKind::Color
91 }
92 fn is_enabled(&self) -> bool {
93 self.enabled
94 }
95 fn set_enabled(&mut self, enabled: bool) {
96 self.enabled = enabled;
97 }
98 fn build_ui(&mut self, _ui: &dyn std::any::Any) {}
99 fn refresh(&mut self) {}
100 fn data_size(&self) -> usize {
101 self.colors.len()
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108
109 #[test]
110 fn test_color_image_creation() {
111 let colors = vec![
112 Vec3::new(1.0, 0.0, 0.0),
113 Vec3::new(0.0, 1.0, 0.0),
114 Vec3::new(0.0, 0.0, 1.0),
115 Vec3::new(1.0, 1.0, 1.0),
116 ];
117 let img = FloatingColorImage::new("test", 2, 2, colors);
118
119 assert_eq!(img.name(), "test");
120 assert_eq!(img.width(), 2);
121 assert_eq!(img.height(), 2);
122 assert_eq!(img.data_size(), 4);
123 assert_eq!(img.kind(), QuantityKind::Color);
124 }
125
126 #[test]
127 fn test_color_image_pixel_access() {
128 let colors = vec![
129 Vec3::new(1.0, 0.0, 0.0), Vec3::new(0.0, 1.0, 0.0), Vec3::new(0.0, 0.0, 1.0), Vec3::new(1.0, 1.0, 1.0), ];
134 let img = FloatingColorImage::new("test", 2, 2, colors);
135
136 assert_eq!(img.pixel(0, 0), Vec4::new(1.0, 0.0, 0.0, 1.0));
137 assert_eq!(img.pixel(1, 0), Vec4::new(0.0, 1.0, 0.0, 1.0));
138 assert_eq!(img.pixel(0, 1), Vec4::new(0.0, 0.0, 1.0, 1.0));
139 assert_eq!(img.pixel(1, 1), Vec4::new(1.0, 1.0, 1.0, 1.0));
140 }
141
142 #[test]
143 fn test_color_image_lower_left_origin() {
144 let colors = vec![
145 Vec3::new(1.0, 0.0, 0.0),
146 Vec3::new(0.0, 1.0, 0.0),
147 Vec3::new(0.0, 0.0, 1.0),
148 Vec3::new(1.0, 1.0, 1.0),
149 ];
150 let mut img = FloatingColorImage::new("test", 2, 2, colors);
151 img.set_origin(ImageOrigin::LowerLeft);
152
153 assert_eq!(img.pixel(0, 0), Vec4::new(0.0, 0.0, 1.0, 1.0));
155 assert_eq!(img.pixel(1, 0), Vec4::new(1.0, 1.0, 1.0, 1.0));
156 assert_eq!(img.pixel(0, 1), Vec4::new(1.0, 0.0, 0.0, 1.0));
157 assert_eq!(img.pixel(1, 1), Vec4::new(0.0, 1.0, 0.0, 1.0));
158 }
159}