1use super::common::parse_color_bar;
2use super::until::{Color, must_translate_from_context};
3use crate::code_handler::parse_context::ParseContext;
4use crate::{translate_enum_with_config, translate_with_config};
5use anyhow::Result;
6use plotly::{Mesh3D, Trace};
7
8pub fn parse_mesh3d_data(
9 mesh_obj: &mut serde_json::Value,
10 context: &ParseContext<'_>,
11) -> Result<Box<Mesh3D<f64, f64, f64>>> {
12 let x: Vec<f64> = must_translate_from_context(mesh_obj, context, "x")?;
13 let y: Vec<f64> = must_translate_from_context(mesh_obj, context, "y")?;
14 let z: Vec<f64> = must_translate_from_context(mesh_obj, context, "z")?;
15 let i: Option<Vec<usize>> = if mesh_obj.get("i").is_some() {
16 Some(must_translate_from_context(mesh_obj, context, "i")?)
17 } else {
18 None
19 };
20 let j: Option<Vec<usize>> = if mesh_obj.get("j").is_some() {
21 Some(must_translate_from_context(mesh_obj, context, "j")?)
22 } else {
23 None
24 };
25 let k: Option<Vec<usize>> = if mesh_obj.get("k").is_some() {
26 Some(must_translate_from_context(mesh_obj, context, "k")?)
27 } else {
28 None
29 };
30 let mesh = Mesh3D::new(x, y, z, i, j, k);
31
32 let mesh = translate_with_config! {
33 mesh,
34 mesh_obj,
35 context.map(),
36 context.map_eval(),
37 (name, String),
38 (opacity, f64),
39 (ids, Vec<String>),
40 (text, String),
41 (text_array, Vec<String>),
42 (hover_text, String),
43 (hover_text_array, Vec<String>),
44 (hover_template, String),
45 (hover_template_array, Vec<String>),
46 (show_legend, bool),
47 (legend_group, String),
48 (legend_rank, usize),
49 (color, Color),
50 (face_color, Vec<Color>),
51 (vertex_color, Vec<Color>),
52 (intensity, Vec<f64>),
53 (scene, String),
54 (flat_shading, bool),
55 (alpha_hull, f64),
56 (meta, String),
57 (color_axis, String),
58 (auto_color_scale, bool),
59 (reverse_scale, bool),
60 (show_scale, bool),
61 (c_auto, bool),
62 (c_max, f64),
63 (c_min, f64),
64 (c_mid, f64),
65 }?;
66
67 use plotly::common::HoverInfo;
68 let mesh = translate_enum_with_config! {
69 mesh,
70 mesh_obj,
71 context.map(),
72 context.map_eval(),
73 (hover_info, {
74 "all" => HoverInfo::All,
75 "x" => HoverInfo::X,
76 "y" => HoverInfo::Y,
77 "z" => HoverInfo::Z,
78 "x+y" => HoverInfo::XAndY,
79 "x+z" => HoverInfo::XAndZ,
80 "y+z" => HoverInfo::YAndZ,
81 "x+y+z" => HoverInfo::XAndYAndZ,
82 "text" => HoverInfo::Text,
83 "name" => HoverInfo::Name,
84 "none" => HoverInfo::None,
85 "skip" => HoverInfo::Skip,
86 }),
87 }?;
88
89 use plotly::traces::mesh3d::{DelaunayAxis, IntensityMode};
90 let mesh = translate_enum_with_config! {
91 mesh,
92 mesh_obj,
93 context.map(),
94 context.map_eval(),
95 (intensity_mode, {
96 "vertex" => IntensityMode::Vertex,
97 "cell" => IntensityMode::Cell,
98 }),
99 (delaunay_axis, {
100 "x" => DelaunayAxis::X,
101 "y" => DelaunayAxis::Y,
102 "z" => DelaunayAxis::Z,
103 }),
104 }?;
105
106 let mesh = if let Some(color_bar_obj) = mesh_obj.get_mut("color_bar")
107 && color_bar_obj.is_object()
108 {
109 let color_bar = parse_color_bar(color_bar_obj, context)?;
110 mesh.color_bar(color_bar)
111 } else {
112 mesh
113 };
114
115 let mesh = if mesh_obj.get("color_scale").is_some() {
116 use plotly::common::{ColorScale, ColorScalePalette};
117 let color_scale_str: String = must_translate_from_context(mesh_obj, context, "color_scale")?;
118 let palette = match color_scale_str.to_lowercase().as_str() {
119 "greys" => ColorScalePalette::Greys,
120 "ylgnbu" => ColorScalePalette::YlGnBu,
121 "greens" => ColorScalePalette::Greens,
122 "ylorrd" => ColorScalePalette::YlOrRd,
123 "bluered" => ColorScalePalette::Bluered,
124 "rdbu" => ColorScalePalette::RdBu,
125 "reds" => ColorScalePalette::Reds,
126 "blues" => ColorScalePalette::Blues,
127 "picnic" => ColorScalePalette::Picnic,
128 "rainbow" => ColorScalePalette::Rainbow,
129 "portland" => ColorScalePalette::Portland,
130 "jet" => ColorScalePalette::Jet,
131 "hot" => ColorScalePalette::Hot,
132 "blackbody" => ColorScalePalette::Blackbody,
133 "earth" => ColorScalePalette::Earth,
134 "electric" => ColorScalePalette::Electric,
135 "viridis" => ColorScalePalette::Viridis,
136 "cividis" => ColorScalePalette::Cividis,
137 _ => return Err(anyhow::anyhow!("unknown color_scale: {}", color_scale_str)),
138 };
139 mesh.color_scale(ColorScale::Palette(palette))
140 } else {
141 mesh
142 };
143
144 let mesh = if let Some(lighting_obj) = mesh_obj.get_mut("lighting")
145 && lighting_obj.is_object()
146 {
147 use plotly::traces::mesh3d::Lighting;
148 let lighting = translate_with_config! {
149 Lighting::new(),
150 lighting_obj,
151 context.map(),
152 context.map_eval(),
153 (ambient, f64),
154 (diffuse, f64),
155 (specular, f64),
156 (roughness, f64),
157 (fresnel, f64),
158 }?;
159 mesh.lighting(lighting)
160 } else {
161 mesh
162 };
163
164 let mesh = if let Some(light_pos_obj) = mesh_obj.get_mut("light_position")
165 && light_pos_obj.is_object()
166 {
167 use plotly::traces::mesh3d::LightPosition;
168 let light_pos = translate_with_config! {
169 LightPosition::new(),
170 light_pos_obj,
171 context.map(),
172 context.map_eval(),
173 (x, Vec<f64>),
174 (y, Vec<f64>),
175 (z, Vec<f64>),
176 }?;
177 mesh.light_position(light_pos)
178 } else {
179 mesh
180 };
181
182 Ok(mesh)
183}
184
185pub fn parse_mesh3d_trace(
186 mesh_obj: &mut serde_json::Value,
187 context: &ParseContext<'_>,
188) -> Result<Box<dyn Trace>> {
189 Ok(parse_mesh3d_data(mesh_obj, context)?)
190}