aboutsummaryrefslogtreecommitdiff
path: root/src/coord/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/coord/mod.rs')
-rw-r--r--src/coord/mod.rs120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/coord/mod.rs b/src/coord/mod.rs
new file mode 100644
index 0000000..0afafa3
--- /dev/null
+++ b/src/coord/mod.rs
@@ -0,0 +1,120 @@
+/*!
+Coordinate system abstractions.
+
+Coordinate systems can be attached to drawing areas. By doing so,
+the drawing area can draw elements in the guest coordinate system.
+`DrawingArea::apply_coord_spec` is used to attach new coordinate system
+to the drawing area.
+
+`CoordTranslate` is the trait required by `DrawingArea::apply_coord_spec`. It provides
+the forward coordinate translation: from the logic coordinate to the pixel-based absolute
+backend coordinate system.
+
+When the coordinate type implements `ReverseCoordTranslate`,
+the backward translation is possible, which allows mapping pixel-based coordinate into
+the logic coordinate. It's not usually used for static figure rendering, but may be useful
+for a interactive figure.
+
+`RangedCoord` is the 2D cartesian coordinate system that has two `Ranged` axis.
+A ranged axis can be logarithmic and by applying an logarithmic axis, the figure is logarithmic scale.
+Also, the ranged axis can be deserted, and this is required by the histogram series.
+
+*/
+use crate::drawing::backend::BackendCoord;
+
+mod category;
+#[cfg(feature = "chrono")]
+mod datetime;
+mod logarithmic;
+mod numeric;
+mod ranged;
+
+#[cfg(feature = "chrono")]
+pub use datetime::{IntoMonthly, IntoYearly, RangedDate, RangedDateTime, RangedDuration};
+pub use numeric::{
+ RangedCoordf32, RangedCoordf64, RangedCoordi128, RangedCoordi32, RangedCoordi64,
+ RangedCoordu128, RangedCoordu32, RangedCoordu64,
+};
+pub use ranged::{
+ AsRangedCoord, DiscreteRanged, IntoCentric, IntoPartialAxis, MeshLine, Ranged, RangedCoord,
+ ReversibleRanged,
+};
+
+pub use ranged::make_partial_axis;
+
+pub use logarithmic::{LogCoord, LogRange, LogScalable};
+
+pub use numeric::group_integer_by::{GroupBy, ToGroupByRange};
+use std::rc::Rc;
+use std::sync::Arc;
+
+pub use category::Category;
+
+/// The trait that translates some customized object to the backend coordinate
+pub trait CoordTranslate {
+ type From;
+
+ /// Translate the guest coordinate to the guest coordinate
+ fn translate(&self, from: &Self::From) -> BackendCoord;
+}
+
+impl<T: CoordTranslate> CoordTranslate for Rc<T> {
+ type From = T::From;
+
+ fn translate(&self, from: &Self::From) -> BackendCoord {
+ self.as_ref().translate(from)
+ }
+}
+
+impl<T: CoordTranslate> CoordTranslate for Arc<T> {
+ type From = T::From;
+
+ fn translate(&self, from: &Self::From) -> BackendCoord {
+ self.as_ref().translate(from)
+ }
+}
+
+/// The trait indicates that the coordinate system supports reverse transform
+/// This is useful when we need an interactive plot, thus we need to map the event
+/// from the backend coordinate to the logical coordinate
+pub trait ReverseCoordTranslate: CoordTranslate {
+ /// Reverse translate the coordinate from the drawing coordinate to the
+ /// logic coordinate.
+ /// Note: the return value is an option, because it's possible that the drawing
+ /// coordinate isn't able to be represented in te guest coordinate system
+ fn reverse_translate(&self, input: BackendCoord) -> Option<Self::From>;
+}
+
+/// The coordinate translation that only impose shift
+#[derive(Debug, Clone)]
+pub struct Shift(pub BackendCoord);
+
+impl CoordTranslate for Shift {
+ type From = BackendCoord;
+ fn translate(&self, from: &Self::From) -> BackendCoord {
+ (from.0 + (self.0).0, from.1 + (self.0).1)
+ }
+}
+
+impl ReverseCoordTranslate for Shift {
+ fn reverse_translate(&self, input: BackendCoord) -> Option<BackendCoord> {
+ Some((input.0 - (self.0).0, input.1 - (self.0).1))
+ }
+}
+
+/// We can compose an arbitrary transformation with a shift
+pub struct ShiftAndTrans<T: CoordTranslate>(Shift, T);
+
+impl<T: CoordTranslate> CoordTranslate for ShiftAndTrans<T> {
+ type From = T::From;
+ fn translate(&self, from: &Self::From) -> BackendCoord {
+ let temp = self.1.translate(from);
+ self.0.translate(&temp)
+ }
+}
+
+impl<T: ReverseCoordTranslate> ReverseCoordTranslate for ShiftAndTrans<T> {
+ fn reverse_translate(&self, input: BackendCoord) -> Option<T::From> {
+ Some(self.1.reverse_translate(self.0.reverse_translate(input)?)?)
+ }
+}