mdbook_plotly/code_handler/plot_obj_parser/
surface_parser.rs1use 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}