Skip to main content

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