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 =
118 must_translate_from_context(mesh_obj, context, "color_scale")?;
119 let palette = match color_scale_str.to_lowercase().as_str() {
120 "greys" => ColorScalePalette::Greys,
121 "ylgnbu" => ColorScalePalette::YlGnBu,
122 "greens" => ColorScalePalette::Greens,
123 "ylorrd" => ColorScalePalette::YlOrRd,
124 "bluered" => ColorScalePalette::Bluered,
125 "rdbu" => ColorScalePalette::RdBu,
126 "reds" => ColorScalePalette::Reds,
127 "blues" => ColorScalePalette::Blues,
128 "picnic" => ColorScalePalette::Picnic,
129 "rainbow" => ColorScalePalette::Rainbow,
130 "portland" => ColorScalePalette::Portland,
131 "jet" => ColorScalePalette::Jet,
132 "hot" => ColorScalePalette::Hot,
133 "blackbody" => ColorScalePalette::Blackbody,
134 "earth" => ColorScalePalette::Earth,
135 "electric" => ColorScalePalette::Electric,
136 "viridis" => ColorScalePalette::Viridis,
137 "cividis" => ColorScalePalette::Cividis,
138 _ => return Err(anyhow::anyhow!("unknown color_scale: {}", color_scale_str)),
139 };
140 mesh.color_scale(ColorScale::Palette(palette))
141 } else {
142 mesh
143 };
144
145 let mesh = if let Some(lighting_obj) = mesh_obj.get_mut("lighting")
146 && lighting_obj.is_object()
147 {
148 use plotly::traces::mesh3d::Lighting;
149 let lighting = translate_with_config! {
150 Lighting::new(),
151 lighting_obj,
152 context.map(),
153 context.map_eval(),
154 (ambient, f64),
155 (diffuse, f64),
156 (specular, f64),
157 (roughness, f64),
158 (fresnel, f64),
159 }?;
160 mesh.lighting(lighting)
161 } else {
162 mesh
163 };
164
165 let mesh = if let Some(light_pos_obj) = mesh_obj.get_mut("light_position")
166 && light_pos_obj.is_object()
167 {
168 use plotly::traces::mesh3d::LightPosition;
169 let light_pos = translate_with_config! {
170 LightPosition::new(),
171 light_pos_obj,
172 context.map(),
173 context.map_eval(),
174 (x, Vec<f64>),
175 (y, Vec<f64>),
176 (z, Vec<f64>),
177 }?;
178 mesh.light_position(light_pos)
179 } else {
180 mesh
181 };
182
183 Ok(mesh)
184}
185
186pub fn parse_mesh3d_trace(
187 mesh_obj: &mut serde_json::Value,
188 context: &ParseContext<'_>,
189) -> Result<Box<dyn Trace>> {
190 Ok(parse_mesh3d_data(mesh_obj, context)?)
191}