Skip to main content

ggplot_rs/coord/
mod.rs

1pub mod cartesian;
2pub mod fixed;
3pub mod flip;
4pub mod polar;
5pub mod radar;
6#[cfg(feature = "sf")]
7pub mod sf;
8pub mod trans;
9
10use crate::render::Rect;
11
12/// A trained axis domain together with the normalized panel positions of its
13/// endpoints. `pmin`/`pmax` are `scale.map(min)`/`scale.map(max)`, so a coord can
14/// invert the (linear, expanded) scale mapping exactly: given a normalized
15/// position `n`, the data value is `min + (n - pmin)/(pmax - pmin) * (max - min)`.
16#[derive(Clone, Copy, Debug)]
17pub struct AxisSpan {
18    pub min: f64,
19    pub max: f64,
20    pub pmin: f64,
21    pub pmax: f64,
22}
23
24/// Trait for coordinate systems.
25pub trait Coord: Send + Sync {
26    /// Transform normalized (0..1, 0..1) coordinates to pixel coordinates.
27    fn transform(&self, point: (f64, f64), plot_area: &Rect) -> (f64, f64);
28
29    /// Whether to draw grid lines.
30    fn gridlines(&self) -> bool {
31        true
32    }
33
34    /// Whether this coordinate system flips X and Y.
35    fn is_flipped(&self) -> bool {
36        false
37    }
38
39    /// Whether this is a non-linear polar system (bars become radial sectors,
40    /// so geoms that draw rectangles must tessellate their edges into an arc).
41    fn is_polar(&self) -> bool {
42        false
43    }
44
45    /// For a polar system, whether the *x* aesthetic maps to angle (`theta="x"`).
46    /// When false (`theta="y"`, pies), the *y* aesthetic is the angle, so sector
47    /// tessellation must sweep the y edge instead of the x edge.
48    fn polar_theta_is_x(&self) -> bool {
49        true
50    }
51
52    /// Zoom limits for x-axis (data coordinates). Clips viewport without filtering data.
53    fn zoom_x(&self) -> Option<(f64, f64)> {
54        None
55    }
56
57    /// Zoom limits for y-axis (data coordinates). Clips viewport without filtering data.
58    fn zoom_y(&self) -> Option<(f64, f64)> {
59        None
60    }
61
62    /// Supply the trained x/y axis spans after scale training. Coordinate systems
63    /// that warp the axis (e.g. `coord_trans`) need this to map a normalized
64    /// position back to a data value. Default is a no-op.
65    fn set_domains(&mut self, _x: Option<AxisSpan>, _y: Option<AxisSpan>) {}
66
67    /// Radar coordinates: straight segments between spokes, closed paths, and
68    /// ring/spoke guides instead of cartesian axes. Default false.
69    fn is_radar(&self) -> bool {
70        false
71    }
72
73    /// Inspect / adjust the trained scales once training is complete (e.g.
74    /// `coord_radar` anchors the radius at 0 and counts its spokes). Default:
75    /// no-op.
76    fn train_scales(&mut self, _scales: &mut crate::scale::ScaleSet) {}
77}