1use std::process::Command;
7use xdl_core::{XdlError, XdlResult};
8
9pub mod colormaps;
10pub mod shaders;
11pub mod templates;
12
13pub fn launch_visualization(
15 volume_data: Vec<f32>,
16 dims: [usize; 3],
17 colormap: &str,
18 title: Option<&str>,
19) -> XdlResult<()> {
20 let title = title.unwrap_or("3D Volume Visualization");
21
22 let html = templates::generate_volume_html(
24 &volume_data,
25 dims,
26 colormap,
27 title,
28 0.1, 0.8, );
31
32 let temp_dir = std::env::temp_dir();
34 let temp_file = temp_dir.join(format!("xdl_viz3d_{}.html", std::process::id()));
35
36 std::fs::write(&temp_file, html)
37 .map_err(|e| XdlError::RuntimeError(format!("Failed to write volume HTML: {}", e)))?;
38
39 let exe_dir = std::env::current_exe()
41 .map_err(|e| XdlError::RuntimeError(format!("Cannot find exe: {}", e)))?
42 .parent()
43 .ok_or_else(|| XdlError::RuntimeError("Cannot find parent directory".to_string()))?
44 .to_path_buf();
45
46 let viewer_path = if cfg!(windows) {
48 let with_exe = exe_dir.join("xdl-chart-viewer.exe");
49 if with_exe.exists() {
50 with_exe
51 } else {
52 exe_dir.join("xdl-chart-viewer")
53 }
54 } else {
55 exe_dir.join("xdl-chart-viewer")
56 };
57
58 Command::new(viewer_path)
60 .args([
61 "--html-file",
62 temp_file.to_str().unwrap(),
63 "--title",
64 title,
65 "--width",
66 "1280",
67 "--height",
68 "720",
69 ])
70 .spawn()
71 .map_err(|e| XdlError::RuntimeError(format!("Failed to launch viewer: {}", e)))?;
72
73 println!("✓ Three.js volume visualization launched");
74 println!(" Volume: {}×{}×{}", dims[0], dims[1], dims[2]);
75 println!(" Colormap: {}", colormap);
76
77 Ok(())
78}
79
80pub fn generate_html(
82 volume_data: Vec<f32>,
83 dims: [usize; 3],
84 colormap: &str,
85 title: &str,
86) -> String {
87 templates::generate_volume_html(&volume_data, dims, colormap, title, 0.1, 0.8)
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn test_html_generation() {
96 let volume_data: Vec<f32> = (0..1000).map(|i| i as f32 / 1000.0).collect();
97 let dims = [10, 10, 10];
98
99 let html = generate_html(volume_data, dims, "VIRIDIS", "Test Volume");
100
101 assert!(html.contains("<!DOCTYPE html>"));
102 assert!(html.contains("three") || html.contains("THREE")); assert!(html.contains("Test Volume"));
104 assert!(html.contains("10")); }
106
107 #[test]
108 fn test_colormap_names() {
109 let volume_data: Vec<f32> = vec![0.0; 1000];
110 let dims = [10, 10, 10];
111
112 for colormap in &[
113 "VIRIDIS",
114 "RAINBOW",
115 "PLASMA",
116 "INFERNO",
117 "TURBO",
118 "GRAYSCALE",
119 ] {
120 let html = generate_html(volume_data.clone(), dims, colormap, "Test");
121 assert!(html.contains(colormap));
122 }
123 }
124}