|
| 1 | +//! Density mapbox scatter plot |
| 2 | +
|
| 3 | +use plotly_derive::FieldSetter; |
| 4 | +use serde::Serialize; |
| 5 | + |
| 6 | +use crate::color::NamedColor; |
| 7 | +use crate::common::{ |
| 8 | + color::Color, Dim, Font, HoverInfo, Label, LegendGroupTitle, Line, Marker, Mode, PlotType, |
| 9 | + Position, Visible, |
| 10 | +}; |
| 11 | +use crate::private::{NumOrString, NumOrStringCollection}; |
| 12 | +use crate::traces::scatter_mapbox::Fill; |
| 13 | +use crate::Trace; |
| 14 | + |
| 15 | +#[derive(Serialize, Clone, Debug)] |
| 16 | +pub struct MapboxCenter<Lat, Lon> |
| 17 | +where |
| 18 | + Lat: Serialize + Clone, |
| 19 | + Lon: Serialize + Clone, |
| 20 | +{ |
| 21 | + pub lat: Lat, |
| 22 | + pub lon: Lon, |
| 23 | +} |
| 24 | + |
| 25 | +#[serde_with::skip_serializing_none] |
| 26 | +#[derive(Serialize, Clone, Debug, FieldSetter)] |
| 27 | +#[field_setter(box_self, kind = "trace")] |
| 28 | +pub struct DensityMapbox<Lat, Lon, Z> |
| 29 | +where |
| 30 | + Lat: Serialize + Clone, |
| 31 | + Lon: Serialize + Clone, |
| 32 | + Z: Serialize + Clone, |
| 33 | +{ |
| 34 | + #[field_setter(default = "PlotType::DensityMapbox")] |
| 35 | + r#type: PlotType, |
| 36 | + /// Sets the trace name. The trace name appear as the legend item and on |
| 37 | + /// hover. |
| 38 | + name: Option<String>, |
| 39 | + /// Determines whether or not this trace is visible. If |
| 40 | + /// `Visible::LegendOnly`, the trace is not drawn, but can appear as a |
| 41 | + /// legend item (provided that the legend itself is visible). |
| 42 | + visible: Option<Visible>, |
| 43 | + |
| 44 | + /// Determines whether or not an item corresponding to this trace is shown |
| 45 | + /// in the legend. |
| 46 | + #[serde(rename = "showlegend")] |
| 47 | + show_legend: Option<bool>, |
| 48 | + |
| 49 | + /// Sets the legend rank for this trace. Items and groups with smaller ranks |
| 50 | + /// are presented on top/left side while with `"reversed" |
| 51 | + /// `legend.trace_order` they are on bottom/right side. The default |
| 52 | + /// legendrank is 1000, so that you can use ranks less than 1000 to |
| 53 | + /// place certain items before all unranked items, and ranks greater |
| 54 | + /// than 1000 to go after all unranked items. |
| 55 | + #[serde(rename = "legendrank")] |
| 56 | + legend_rank: Option<usize>, |
| 57 | + /// Sets the legend group for this trace. Traces part of the same legend |
| 58 | + /// group show/hide at the same time when toggling legend items. |
| 59 | + #[serde(rename = "legendgroup")] |
| 60 | + legend_group: Option<String>, |
| 61 | + /// Set and style the title to appear for the legend group. |
| 62 | + #[serde(rename = "legendgrouptitle")] |
| 63 | + legend_group_title: Option<LegendGroupTitle>, |
| 64 | + |
| 65 | + /// Line display properties. |
| 66 | + line: Option<Line>, |
| 67 | + |
| 68 | + lat: Option<Vec<Lat>>, |
| 69 | + lon: Option<Vec<Lon>>, |
| 70 | + z: Option<Vec<Z>>, |
| 71 | + |
| 72 | + /// Sets the opacity of the trace. |
| 73 | + opacity: Option<f64>, |
| 74 | + |
| 75 | + /// Sets a reference between this trace's data coordinates and a mapbox |
| 76 | + /// subplot. If "mapbox" (the default value), the data refer to |
| 77 | + /// `layout.mapbox`. If "mapbox2", the data refer to `layout.mapbox2`, and |
| 78 | + /// so on. |
| 79 | + subplot: Option<String>, |
| 80 | + |
| 81 | + center: Option<MapboxCenter<Lat, Lon>>, |
| 82 | + |
| 83 | + /// Determines whether or not the color domain is computed |
| 84 | + /// with respect to the input data (here in `z`) or the bounds set |
| 85 | + /// in `zmin` and `zmax`. Defaults to false when `zmin` and `zmax` are |
| 86 | + /// set by the user. |
| 87 | + zauto: Option<bool>, |
| 88 | + |
| 89 | + /// Sets the upper bound of the color domain. Value should have the |
| 90 | + /// same units as in `z` and if set, `zmin` must be set as well. |
| 91 | + zmax: Option<Z>, |
| 92 | + |
| 93 | + zmid: Option<Z>, |
| 94 | + |
| 95 | + zmin: Option<Z>, |
| 96 | + |
| 97 | + zoom: Option<u8>, |
| 98 | + |
| 99 | + radius: Option<u8>, |
| 100 | + //color_continuous_scale: Option<HashMap<Z, NamedColor>>, |
| 101 | + //color_continuous_midpoint: Option<ContinuousColorScale>, |
| 102 | +} |
| 103 | + |
| 104 | +impl<Lat, Lon, Z> DensityMapbox<Lat, Lon, Z> |
| 105 | +where |
| 106 | + Lat: Serialize + Clone + std::default::Default, // TODO why is "+ Default" necessary? |
| 107 | + Lon: Serialize + Clone + std::default::Default, |
| 108 | + Z: Serialize + Clone + std::default::Default, |
| 109 | +{ |
| 110 | + pub fn new(lat: Vec<Lat>, lon: Vec<Lon>, z: Vec<Z>) -> Box<Self> { |
| 111 | + Box::new(Self { |
| 112 | + lat: Some(lat), |
| 113 | + lon: Some(lon), |
| 114 | + z: Some(z), |
| 115 | + ..Default::default() |
| 116 | + }) |
| 117 | + } |
| 118 | +} |
| 119 | + |
| 120 | +impl<Lat, Lon, Z> Trace for DensityMapbox<Lat, Lon, Z> |
| 121 | +where |
| 122 | + Lat: Serialize + Clone, |
| 123 | + Lon: Serialize + Clone, |
| 124 | + Z: Serialize + Clone, |
| 125 | +{ |
| 126 | + fn to_json(&self) -> String { |
| 127 | + serde_json::to_string(&self).unwrap() |
| 128 | + } |
| 129 | +} |
| 130 | + |
| 131 | +#[cfg(test)] |
| 132 | +mod tests { |
| 133 | + use serde_json::{json, to_value}; |
| 134 | + |
| 135 | + use super::*; |
| 136 | + |
| 137 | + #[test] |
| 138 | + fn test_serialize_density_mapbox() { |
| 139 | + let density_mapbox = DensityMapbox::new(vec![45.5017], vec![-73.5673], vec![1.0]) |
| 140 | + .name("name") |
| 141 | + .visible(Visible::True) |
| 142 | + .show_legend(true) |
| 143 | + .legend_rank(1000) |
| 144 | + .legend_group("legend group") |
| 145 | + .center(MapboxCenter { |
| 146 | + lat: 45.5017, |
| 147 | + lon: -73.5673, |
| 148 | + }) |
| 149 | + .zoom(5) |
| 150 | + .radius(20) |
| 151 | + .opacity(0.5); |
| 152 | + let expected = json!({ |
| 153 | + "type": "densitymapbox", |
| 154 | + "lat": [45.5017], |
| 155 | + "lon": [-73.5673], |
| 156 | + "z": [1.0], |
| 157 | + "name": "name", |
| 158 | + "visible": true, |
| 159 | + "showlegend": true, |
| 160 | + "legendrank": 1000, |
| 161 | + "legendgroup": "legend group", |
| 162 | + "opacity": 0.5, |
| 163 | + "zoom": 5, |
| 164 | + "radius": 20, |
| 165 | + "center": { |
| 166 | + "lat": 45.5017, |
| 167 | + "lon": -73.5673 |
| 168 | + }, |
| 169 | + }); |
| 170 | + assert_eq!(to_value(density_mapbox.clone()).unwrap(), expected); |
| 171 | + } |
| 172 | +} |
0 commit comments