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 =
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}