|
| 1 | +//! Density heatmap trace for the MapLibre `map` subplot. |
| 2 | +
|
| 3 | +use plotly_derive::FieldSetter; |
| 4 | +use serde::Serialize; |
| 5 | + |
| 6 | +use crate::common::{ |
| 7 | + ColorBar, ColorScale, Dim, HoverInfo, Label, LegendGroupTitle, PlotType, Visible, |
| 8 | +}; |
| 9 | +use crate::private::{NumOrString, NumOrStringCollection}; |
| 10 | +use crate::Trace; |
| 11 | + |
| 12 | +/// Construct a density heatmap trace drawn on the MapLibre `map` subplot |
| 13 | +/// (configured via [`LayoutMap`](crate::layout::LayoutMap)). |
| 14 | +/// |
| 15 | +/// `DensityMap` is the modern MapLibre-based counterpart to |
| 16 | +/// [`DensityMapbox`](crate::DensityMapbox): it draws a weighted kernel-density |
| 17 | +/// heatmap from `lat`/`lon` points (with an optional per-point weight `z`) onto |
| 18 | +/// the `layout.map` subplot. |
| 19 | +/// |
| 20 | +/// # Examples |
| 21 | +/// |
| 22 | +/// ``` |
| 23 | +/// use plotly::DensityMap; |
| 24 | +/// |
| 25 | +/// let trace = DensityMap::new(vec![45.5017], vec![-73.5673], vec![1.0]) |
| 26 | +/// .radius(20) |
| 27 | +/// .name("montreal"); |
| 28 | +/// ``` |
| 29 | +#[serde_with::skip_serializing_none] |
| 30 | +#[derive(Serialize, Clone, Debug, FieldSetter)] |
| 31 | +#[field_setter(box_self, kind = "trace")] |
| 32 | +pub struct DensityMap<Lat, Lon, Z> |
| 33 | +where |
| 34 | + Lat: Serialize + Clone, |
| 35 | + Lon: Serialize + Clone, |
| 36 | + Z: Serialize + Clone, |
| 37 | +{ |
| 38 | + #[field_setter(default = "PlotType::DensityMap")] |
| 39 | + r#type: PlotType, |
| 40 | + /// Sets the trace name. The trace name appears as the legend item and on |
| 41 | + /// hover. |
| 42 | + name: Option<String>, |
| 43 | + /// Determines whether or not this trace is visible. |
| 44 | + visible: Option<Visible>, |
| 45 | + /// Determines whether or not an item corresponding to this trace is shown |
| 46 | + /// in the legend. |
| 47 | + #[serde(rename = "showlegend")] |
| 48 | + show_legend: Option<bool>, |
| 49 | + /// Sets the legend rank for this trace. |
| 50 | + #[serde(rename = "legendrank")] |
| 51 | + legend_rank: Option<usize>, |
| 52 | + /// Sets the legend group for this trace. |
| 53 | + #[serde(rename = "legendgroup")] |
| 54 | + legend_group: Option<String>, |
| 55 | + /// Set and style the title to appear for the legend group. |
| 56 | + #[serde(rename = "legendgrouptitle")] |
| 57 | + legend_group_title: Option<LegendGroupTitle>, |
| 58 | + /// Assigns id labels to each datum. |
| 59 | + ids: Option<Vec<String>>, |
| 60 | + |
| 61 | + /// Sets the latitude coordinates (in degrees North). |
| 62 | + lat: Option<Vec<Lat>>, |
| 63 | + /// Sets the longitude coordinates (in degrees East). |
| 64 | + lon: Option<Vec<Lon>>, |
| 65 | + /// Sets the points' weight. For example, a value of 10 would be equivalent |
| 66 | + /// to having 10 points of weight 1 in the same spot. |
| 67 | + z: Option<Vec<Z>>, |
| 68 | + /// Sets the radius of influence of one `lat`/`lon` point in pixels. |
| 69 | + /// Increasing the value makes the density map smoother, but less detailed. |
| 70 | + radius: Option<u8>, |
| 71 | + /// Sets the opacity of the trace. |
| 72 | + opacity: Option<f64>, |
| 73 | + |
| 74 | + /// Sets the text elements associated with each (lat,lon,z) triplet. |
| 75 | + text: Option<Dim<String>>, |
| 76 | + /// Sets the hover text elements associated with each (lat,lon,z) triplet. |
| 77 | + #[serde(rename = "hovertext")] |
| 78 | + hover_text: Option<Dim<String>>, |
| 79 | + /// Determines which trace information appears on hover. |
| 80 | + #[serde(rename = "hoverinfo")] |
| 81 | + hover_info: Option<HoverInfo>, |
| 82 | + /// Template string used for rendering the information that appears on the |
| 83 | + /// hover box. |
| 84 | + #[serde(rename = "hovertemplate")] |
| 85 | + hover_template: Option<Dim<String>>, |
| 86 | + #[serde(rename = "hovertemplatefallback")] |
| 87 | + hover_template_fallback: Option<Dim<String>>, |
| 88 | + /// Properties of the hover label. |
| 89 | + #[serde(rename = "hoverlabel")] |
| 90 | + hover_label: Option<Label>, |
| 91 | + |
| 92 | + /// Determines whether or not the color domain is computed with respect to |
| 93 | + /// the input data (here in `z`) or the bounds set in `zmin` and `zmax`. |
| 94 | + #[serde(rename = "zauto")] |
| 95 | + z_auto: Option<bool>, |
| 96 | + /// Sets the lower bound of the color domain. |
| 97 | + #[serde(rename = "zmin")] |
| 98 | + z_min: Option<f64>, |
| 99 | + /// Sets the upper bound of the color domain. |
| 100 | + #[serde(rename = "zmax")] |
| 101 | + z_max: Option<f64>, |
| 102 | + /// Sets the mid-point of the color domain. |
| 103 | + #[serde(rename = "zmid")] |
| 104 | + z_mid: Option<f64>, |
| 105 | + /// Sets the colorscale. |
| 106 | + #[serde(rename = "colorscale")] |
| 107 | + color_scale: Option<ColorScale>, |
| 108 | + /// Determines whether the colorscale is a default palette. |
| 109 | + #[serde(rename = "autocolorscale")] |
| 110 | + auto_color_scale: Option<bool>, |
| 111 | + /// Reverses the color mapping if true. |
| 112 | + #[serde(rename = "reversescale")] |
| 113 | + reverse_scale: Option<bool>, |
| 114 | + /// Determines whether or not a colorbar is displayed for this trace. |
| 115 | + #[serde(rename = "showscale")] |
| 116 | + show_scale: Option<bool>, |
| 117 | + /// Properties of the colorbar. |
| 118 | + #[serde(rename = "colorbar")] |
| 119 | + color_bar: Option<ColorBar>, |
| 120 | + /// Sets a reference to a shared color axis. |
| 121 | + #[serde(rename = "coloraxis")] |
| 122 | + color_axis: Option<String>, |
| 123 | + |
| 124 | + /// Sets a reference to the `map` subplot this trace is drawn on. Defaults |
| 125 | + /// to `"map"`. |
| 126 | + subplot: Option<String>, |
| 127 | + /// Determines if this trace's layer is inserted below the layer with the |
| 128 | + /// specified ID. By default, the layer is inserted above every existing |
| 129 | + /// layer. |
| 130 | + below: Option<String>, |
| 131 | + |
| 132 | + /// Assigns extra meta information associated with this trace. |
| 133 | + meta: Option<NumOrString>, |
| 134 | + /// Assigns extra data to each datum. |
| 135 | + #[serde(rename = "customdata")] |
| 136 | + custom_data: Option<NumOrStringCollection>, |
| 137 | + /// Controls persistence of some user-driven changes to the trace. |
| 138 | + #[serde(rename = "uirevision")] |
| 139 | + ui_revision: Option<NumOrString>, |
| 140 | +} |
| 141 | + |
| 142 | +impl<Lat, Lon, Z> DensityMap<Lat, Lon, Z> |
| 143 | +where |
| 144 | + Lat: Serialize + Clone + std::default::Default, |
| 145 | + Lon: Serialize + Clone + std::default::Default, |
| 146 | + Z: Serialize + Clone + std::default::Default, |
| 147 | +{ |
| 148 | + pub fn new(lat: Vec<Lat>, lon: Vec<Lon>, z: Vec<Z>) -> Box<Self> { |
| 149 | + Box::new(Self { |
| 150 | + lat: Some(lat), |
| 151 | + lon: Some(lon), |
| 152 | + z: Some(z), |
| 153 | + ..Default::default() |
| 154 | + }) |
| 155 | + } |
| 156 | +} |
| 157 | + |
| 158 | +impl<Lat, Lon, Z> Trace for DensityMap<Lat, Lon, Z> |
| 159 | +where |
| 160 | + Lat: Serialize + Clone, |
| 161 | + Lon: Serialize + Clone, |
| 162 | + Z: Serialize + Clone, |
| 163 | +{ |
| 164 | + fn to_json(&self) -> String { |
| 165 | + serde_json::to_string(&self).unwrap() |
| 166 | + } |
| 167 | +} |
| 168 | + |
| 169 | +#[cfg(test)] |
| 170 | +mod tests { |
| 171 | + use serde_json::{json, to_value}; |
| 172 | + |
| 173 | + use super::*; |
| 174 | + use crate::common::ColorScalePalette; |
| 175 | + |
| 176 | + #[test] |
| 177 | + fn serialize_density_map() { |
| 178 | + let trace = DensityMap::new(vec![45.5017], vec![-73.5673], vec![1.0]) |
| 179 | + .name("montreal") |
| 180 | + .radius(20) |
| 181 | + .opacity(0.5) |
| 182 | + .hover_text_array(vec!["Montreal"]) |
| 183 | + .hover_info(HoverInfo::Text) |
| 184 | + .color_scale(ColorScale::Palette(ColorScalePalette::Viridis)) |
| 185 | + .show_scale(true) |
| 186 | + .subplot("map") |
| 187 | + .below(""); |
| 188 | + |
| 189 | + let expected = json!({ |
| 190 | + "type": "densitymap", |
| 191 | + "lat": [45.5017], |
| 192 | + "lon": [-73.5673], |
| 193 | + "z": [1.0], |
| 194 | + "name": "montreal", |
| 195 | + "radius": 20, |
| 196 | + "opacity": 0.5, |
| 197 | + "hovertext": ["Montreal"], |
| 198 | + "hoverinfo": "text", |
| 199 | + "colorscale": "Viridis", |
| 200 | + "showscale": true, |
| 201 | + "subplot": "map", |
| 202 | + "below": "", |
| 203 | + }); |
| 204 | + |
| 205 | + assert_eq!(to_value(trace).unwrap(), expected); |
| 206 | + } |
| 207 | +} |
0 commit comments