Skip to main content

mdbook_plotly/code_handler/plot_obj_parser/
mesh3d_parser.rs

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}