1use crate::error::{Result, TimeSeriesError};
20use scirs2_core::ndarray::{Array1, Array2};
21use std::collections::VecDeque;
22
23#[derive(Debug, Clone)]
25pub struct AdvancedPlotConfig {
26 pub width: u32,
28 pub height: u32,
30
31 pub renderer: RenderingEngine,
33 pub anti_aliasing: bool,
35 pub hardware_acceleration: bool,
37 pub max_fps: u32,
39
40 pub enable_ai_insights: bool,
42 pub auto_pattern_detection: bool,
44 pub smart_axis_scaling: bool,
46 pub intelligent_color_schemes: bool,
48
49 pub color_blind_friendly: bool,
51 pub high_contrast_mode: bool,
53 pub screen_reader_support: bool,
55 pub keyboard_navigation: bool,
57
58 pub level_of_detail: LevelOfDetail,
60 pub data_decimation: DataDecimationConfig,
62 pub progressive_rendering: bool,
64 pub memory_limit_mb: usize,
66}
67
68impl Default for AdvancedPlotConfig {
69 fn default() -> Self {
70 Self {
71 width: 1920,
72 height: 1080,
73 renderer: RenderingEngine::WebGL,
74 anti_aliasing: true,
75 hardware_acceleration: true,
76 max_fps: 60,
77 enable_ai_insights: true,
78 auto_pattern_detection: true,
79 smart_axis_scaling: true,
80 intelligent_color_schemes: true,
81 color_blind_friendly: false,
82 high_contrast_mode: false,
83 screen_reader_support: false,
84 keyboard_navigation: true,
85 level_of_detail: LevelOfDetail::default(),
86 data_decimation: DataDecimationConfig::default(),
87 progressive_rendering: true,
88 memory_limit_mb: 1024,
89 }
90 }
91}
92
93#[derive(Debug, Clone, Copy)]
95pub enum RenderingEngine {
96 WebGL,
98 Canvas2D,
100 SVG,
102 Native,
104 GpuAccelerated,
106}
107
108#[derive(Debug, Clone)]
110pub struct LevelOfDetail {
111 pub enabled: bool,
113 pub distance_thresholds: Vec<f32>,
115 pub reduction_factors: Vec<f32>,
117}
118
119impl Default for LevelOfDetail {
120 fn default() -> Self {
121 Self {
122 enabled: true,
123 distance_thresholds: vec![1000.0, 5000.0, 20000.0],
124 reduction_factors: vec![1.0, 0.5, 0.25, 0.1],
125 }
126 }
127}
128
129#[derive(Debug, Clone)]
131pub struct DataDecimationConfig {
132 pub enabled: bool,
134 pub max_points: usize,
136 pub algorithm: DecimationAlgorithm,
138}
139
140impl Default for DataDecimationConfig {
141 fn default() -> Self {
142 Self {
143 enabled: true,
144 max_points: 100_000,
145 algorithm: DecimationAlgorithm::Adaptive,
146 }
147 }
148}
149
150#[derive(Debug, Clone, Copy)]
152pub enum DecimationAlgorithm {
153 NthPoint,
155 Adaptive,
157 Statistical,
159 Perceptual,
161}
162
163#[derive(Debug, Clone, Copy)]
165pub struct Point3D {
166 pub x: f32,
168 pub y: f32,
170 pub z: f32,
172}
173
174#[derive(Debug, Clone, Copy)]
176pub struct Color {
177 pub r: f32,
179 pub g: f32,
181 pub b: f32,
183 pub a: f32,
185}
186
187#[derive(Debug, Clone)]
189pub struct Surface3D {
190 pub vertices: Vec<Point3D>,
192 pub indices: Vec<u32>,
194 pub colors: Vec<Color>,
196 pub normals: Vec<Point3D>,
198}
199
200#[derive(Debug, Clone)]
202pub struct LightingConfig {
203 pub ambient_light: Color,
205 pub point_lights: Vec<PointLight>,
207 pub directional_light: Option<DirectionalLight>,
209}
210
211#[derive(Debug, Clone)]
213pub struct PointLight {
214 pub position: Point3D,
216 pub color: Color,
218 pub intensity: f32,
220 pub attenuation: (f32, f32, f32),
222}
223
224#[derive(Debug, Clone)]
226pub struct DirectionalLight {
227 pub direction: Point3D,
229 pub color: Color,
231 pub intensity: f32,
233}
234
235#[derive(Debug)]
237pub struct Advanced3DVisualization {
238 pub config: AdvancedPlotConfig,
240 pub surfaces: Vec<Surface3D>,
242 pub lighting: LightingConfig,
244 pub camera_position: Point3D,
246 pub camera_target: Point3D,
248}
249
250impl Advanced3DVisualization {
251 pub fn new(config: AdvancedPlotConfig) -> Self {
253 Self {
254 config,
255 surfaces: Vec::new(),
256 lighting: LightingConfig {
257 ambient_light: Color {
258 r: 0.2,
259 g: 0.2,
260 b: 0.2,
261 a: 1.0,
262 },
263 point_lights: Vec::new(),
264 directional_light: Some(DirectionalLight {
265 direction: Point3D {
266 x: -1.0,
267 y: -1.0,
268 z: -1.0,
269 },
270 color: Color {
271 r: 1.0,
272 g: 1.0,
273 b: 1.0,
274 a: 1.0,
275 },
276 intensity: 0.8,
277 }),
278 },
279 camera_position: Point3D {
280 x: 0.0,
281 y: 0.0,
282 z: 10.0,
283 },
284 camera_target: Point3D {
285 x: 0.0,
286 y: 0.0,
287 z: 0.0,
288 },
289 }
290 }
291
292 pub fn add_time_series_surface(&mut self, data: &Array2<f64>) -> Result<()> {
294 let (rows, cols) = data.dim();
295 let mut vertices = Vec::new();
296 let mut colors = Vec::new();
297 let mut indices = Vec::new();
298
299 for i in 0..rows {
301 for j in 0..cols {
302 let x = j as f32 - cols as f32 / 2.0;
303 let z = i as f32 - rows as f32 / 2.0;
304 let y = data[[i, j]] as f32;
305
306 vertices.push(Point3D { x, y, z });
307 colors.push(self.value_to_color(data[[i, j]]));
308 }
309 }
310
311 for i in 0..(rows - 1) {
313 for j in 0..(cols - 1) {
314 let base = (i * cols + j) as u32;
315
316 indices.push(base);
318 indices.push(base + 1);
319 indices.push(base + cols as u32);
320
321 indices.push(base + 1);
323 indices.push(base + cols as u32 + 1);
324 indices.push(base + cols as u32);
325 }
326 }
327
328 let normals = vertices
330 .iter()
331 .map(|_| Point3D {
332 x: 0.0,
333 y: 1.0,
334 z: 0.0,
335 })
336 .collect();
337
338 self.surfaces.push(Surface3D {
339 vertices,
340 indices,
341 colors,
342 normals,
343 });
344
345 Ok(())
346 }
347
348 pub fn add_point_light(&mut self, position: Point3D, color: Color, intensity: f32) {
350 let light = PointLight {
351 position,
352 color,
353 intensity,
354 attenuation: (1.0, 0.1, 0.01), };
356
357 self.lighting.point_lights.push(light);
358 }
359
360 pub fn export_vr_compatible(&self, path: &str) -> Result<()> {
362 let vr_content = format!(
363 "<html><head><title>Advanced VR Time Series</title></head><body><h1>VR Visualization with {} surfaces</h1></body></html>",
364 self.surfaces.len()
365 );
366
367 std::fs::write(path, vr_content)
368 .map_err(|e| TimeSeriesError::IOError(format!("Failed to write VR content: {e}")))?;
369
370 Ok(())
371 }
372
373 fn value_to_color(&self, value: f64) -> Color {
375 let normalized = (value + 1.0) / 2.0; let clamped = normalized.clamp(0.0, 1.0);
378
379 Color {
380 r: clamped as f32,
381 g: 0.0,
382 b: (1.0 - clamped) as f32,
383 a: 1.0,
384 }
385 }
386}
387
388#[derive(Debug)]
390pub struct StreamingVisualization {
391 pub config: AdvancedPlotConfig,
393 pub data_buffer: VecDeque<Array1<f64>>,
395 pub max_buffer_size: usize,
397}
398
399impl StreamingVisualization {
400 pub fn new(config: AdvancedPlotConfig, buffersize: usize) -> Self {
402 Self {
403 config,
404 data_buffer: VecDeque::with_capacity(buffersize),
405 max_buffer_size: buffersize,
406 }
407 }
408
409 pub fn add_data_point(&mut self, data: Array1<f64>) {
411 if self.data_buffer.len() >= self.max_buffer_size {
412 self.data_buffer.pop_front();
413 }
414 self.data_buffer.push_back(data);
415 }
416
417 pub fn generate_plot(&self) -> Result<String> {
419 let data_points = self.data_buffer.len();
420 let html_content = format!(
421 "<html><head><title>Streaming Visualization</title></head><body><h1>Streaming plot with {data_points} data points</h1></body></html>"
422 );
423 Ok(html_content)
424 }
425}
426
427pub struct AdvancedExporter;
429
430impl AdvancedExporter {
431 pub fn export_interactive_html(plot: &StreamingVisualization, path: &str) -> Result<()> {
433 let html_content = plot.generate_plot()?;
434
435 std::fs::write(path, html_content)
436 .map_err(|e| TimeSeriesError::IOError(format!("Failed to write HTML: {e}")))?;
437
438 Ok(())
439 }
440}