Skip to main content

mdbook_plotly/code_handler/plot_obj_parser/
surface_parser.rs

1use super::until::{Color, Map, must_translate};
2use crate::{translate, translate_enum};
3use anyhow::Result;
4use plotly::Surface;
5
6pub fn parse_surface_data(
7    sf_obj: &mut serde_json::Value,
8    map: &Map,
9) -> Result<Box<Surface<f64, f64, f64>>> {
10    let z: Vec<Vec<f64>> = must_translate(sf_obj, map, "z")?;
11    let surface = Surface::new(z);
12
13    let surface = translate! {
14        surface,
15        sf_obj,
16        map,
17        (x, Vec<f64>),
18        (y, Vec<f64>),
19        (name, String),
20        (opacity, f64),
21        (text, String),
22        (text_array, Vec<String>),
23        (hover_text, String),
24        (hover_text_array, Vec<String>),
25        (hover_template, String),
26        (hover_template_array, Vec<String>),
27        (show_legend, bool),
28        (legend_group, String),
29        (connect_gaps, bool),
30        (hide_surface, bool),
31        (surface_color, Vec<Color>),
32        (auto_color_scale, bool),
33        (reverse_scale, bool),
34        (show_scale, bool),
35        (cauto, bool),
36        (cmax, f64),
37        (cmin, f64),
38        (cmid, f64),
39    }?;
40
41    use plotly::common::HoverInfo;
42    let surface = translate_enum! {
43        surface,
44        sf_obj,
45        map,
46        (hover_info, {
47            "all" => HoverInfo::All,
48            "x" => HoverInfo::X,
49            "y" => HoverInfo::Y,
50            "z" => HoverInfo::Z,
51            "x+y" => HoverInfo::XAndY,
52            "x+z" => HoverInfo::XAndZ,
53            "y+z" => HoverInfo::YAndZ,
54            "x+y+z" => HoverInfo::XAndYAndZ,
55            "text" => HoverInfo::Text,
56            "name" => HoverInfo::Name,
57            "none" => HoverInfo::None,
58            "skip" => HoverInfo::Skip,
59        }),
60    }?;
61
62    let surface = if let Some(color_bar_obj) = sf_obj.get_mut("color_bar")
63        && color_bar_obj.is_object()
64    {
65        use plotly::common::ColorBar;
66        let color_bar = translate! {
67            ColorBar::new(),
68            color_bar_obj,
69            map,
70            (thickness, usize),
71            (len, usize),
72            (x, f64),
73            (y, f64),
74            (title, String),
75        }?;
76        surface.color_bar(color_bar)
77    } else {
78        surface
79    };
80
81    let surface = if sf_obj.get("color_scale").is_some() {
82        use plotly::common::{ColorScale, ColorScalePalette};
83        let color_scale_str: String = must_translate(sf_obj, map, "color_scale")?;
84        let palette = match color_scale_str.to_lowercase().as_str() {
85            "greys" => ColorScalePalette::Greys,
86            "ylgnbu" => ColorScalePalette::YlGnBu,
87            "greens" => ColorScalePalette::Greens,
88            "ylorrd" => ColorScalePalette::YlOrRd,
89            "bluered" => ColorScalePalette::Bluered,
90            "rdbu" => ColorScalePalette::RdBu,
91            "reds" => ColorScalePalette::Reds,
92            "blues" => ColorScalePalette::Blues,
93            "picnic" => ColorScalePalette::Picnic,
94            "rainbow" => ColorScalePalette::Rainbow,
95            "portland" => ColorScalePalette::Portland,
96            "jet" => ColorScalePalette::Jet,
97            "hot" => ColorScalePalette::Hot,
98            "blackbody" => ColorScalePalette::Blackbody,
99            "earth" => ColorScalePalette::Earth,
100            "electric" => ColorScalePalette::Electric,
101            "viridis" => ColorScalePalette::Viridis,
102            "cividis" => ColorScalePalette::Cividis,
103            _ => return Err(anyhow::anyhow!("unknown color_scale: {}", color_scale_str)),
104        };
105        surface.color_scale(ColorScale::Palette(palette))
106    } else {
107        surface
108    };
109
110    let surface = if let Some(lighting_obj) = sf_obj.get_mut("lighting")
111        && lighting_obj.is_object()
112    {
113        use plotly::traces::surface::Lighting;
114        let lighting = translate! {
115            Lighting::new(),
116            lighting_obj,
117            map,
118            (ambient, f64),
119            (diffuse, f64),
120            (specular, f64),
121            (roughness, f64),
122            (fresnel, f64),
123        }?;
124        surface.lighting(lighting)
125    } else {
126        surface
127    };
128
129    let surface = if let Some(light_pos_obj) = sf_obj.get_mut("light_position")
130        && light_pos_obj.is_object()
131    {
132        use plotly::traces::surface::Position;
133        let x: i32 = must_translate(light_pos_obj, map, "x")?;
134        let y: i32 = must_translate(light_pos_obj, map, "y")?;
135        let z: i32 = must_translate(light_pos_obj, map, "z")?;
136        surface.light_position(Position::new(x, y, z))
137    } else {
138        surface
139    };
140
141    Ok(surface)
142}