Skip to content

Commit 2122d11

Browse files
committed
Add the customized keypoints coordinate decorator
1 parent 15b243a commit 2122d11

File tree

3 files changed

+176
-5
lines changed

3 files changed

+176
-5
lines changed

src/coord/ckps.rs

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
// The customized coordinate decorators.
2+
// This file contains a set of coorindate decorators that allows you determine the
3+
// keypoint by your own code.
4+
use std::ops::Range;
5+
6+
use super::{AsRangedCoord, DiscreteRanged, KeyPointHint, Ranged};
7+
8+
pub struct WithKeyPoints<Inner: Ranged> {
9+
inner: Inner,
10+
bold_points: Vec<Inner::ValueType>,
11+
light_points: Vec<Inner::ValueType>,
12+
}
13+
14+
impl<I: Ranged> WithKeyPoints<I> {
15+
pub fn with_light_points<T: IntoIterator<Item = I::ValueType>>(mut self, iter: T) -> Self {
16+
self.light_points.clear();
17+
self.light_points.extend(iter);
18+
self
19+
}
20+
21+
pub fn bold_points(&self) -> &[I::ValueType] {
22+
self.bold_points.as_ref()
23+
}
24+
25+
pub fn bold_points_mut(&mut self) -> &mut [I::ValueType] {
26+
self.bold_points.as_mut()
27+
}
28+
29+
pub fn light_points(&self) -> &[I::ValueType] {
30+
self.light_points.as_ref()
31+
}
32+
33+
pub fn light_points_mut(&mut self) -> &mut [I::ValueType] {
34+
self.light_points.as_mut()
35+
}
36+
}
37+
38+
impl<R: Ranged> Ranged for WithKeyPoints<R>
39+
where
40+
R::ValueType: Clone,
41+
{
42+
type ValueType = R::ValueType;
43+
type FormatOption = R::FormatOption;
44+
45+
fn range(&self) -> Range<Self::ValueType> {
46+
self.inner.range()
47+
}
48+
49+
fn map(&self, value: &Self::ValueType, limit: (i32, i32)) -> i32 {
50+
self.inner.map(value, limit)
51+
}
52+
53+
fn key_points<Hint: KeyPointHint>(&self, hint: Hint) -> Vec<Self::ValueType> {
54+
if hint.weight().allow_light_points() {
55+
self.light_points.clone()
56+
} else {
57+
self.bold_points.clone()
58+
}
59+
}
60+
61+
fn axis_pixel_range(&self, limit: (i32, i32)) -> Range<i32> {
62+
self.inner.axis_pixel_range(limit)
63+
}
64+
}
65+
66+
impl<R: DiscreteRanged> DiscreteRanged for WithKeyPoints<R>
67+
where
68+
R::ValueType: Clone,
69+
{
70+
fn size(&self) -> usize {
71+
self.inner.size()
72+
}
73+
fn index_of(&self, value: &Self::ValueType) -> Option<usize> {
74+
self.inner.index_of(value)
75+
}
76+
fn from_index(&self, index: usize) -> Option<Self::ValueType> {
77+
self.inner.from_index(index)
78+
}
79+
}
80+
81+
pub trait BindKeyPoints
82+
where
83+
Self: AsRangedCoord,
84+
{
85+
fn with_key_points(self, points: Vec<Self::Value>) -> WithKeyPoints<Self::CoordDescType> {
86+
WithKeyPoints {
87+
inner: self.into(),
88+
bold_points: points,
89+
light_points: vec![],
90+
}
91+
}
92+
}
93+
94+
impl<T: AsRangedCoord> BindKeyPoints for T {}
95+
96+
pub struct WithKeyPointMethod<R: Ranged> {
97+
inner: R,
98+
bold_func: Box<dyn Fn(usize) -> Vec<R::ValueType>>,
99+
light_func: Box<dyn Fn(usize) -> Vec<R::ValueType>>,
100+
}
101+
102+
pub trait BindKeyPointMethod
103+
where
104+
Self: AsRangedCoord,
105+
{
106+
fn with_key_point_func<F: Fn(usize) -> Vec<Self::Value> + 'static>(
107+
self,
108+
func: F,
109+
) -> WithKeyPointMethod<Self::CoordDescType> {
110+
WithKeyPointMethod {
111+
inner: self.into(),
112+
bold_func: Box::new(func),
113+
light_func: Box::new(|_| vec![]),
114+
}
115+
}
116+
}
117+
118+
impl<T: AsRangedCoord> BindKeyPointMethod for T {}
119+
120+
impl<R: Ranged> WithKeyPointMethod<R> {
121+
pub fn with_light_point_func<F: Fn(usize) -> Vec<R::ValueType> + 'static>(
122+
mut self,
123+
func: F,
124+
) -> Self {
125+
self.light_func = Box::new(func);
126+
self
127+
}
128+
}
129+
130+
impl<R: Ranged> Ranged for WithKeyPointMethod<R> {
131+
type ValueType = R::ValueType;
132+
type FormatOption = R::FormatOption;
133+
134+
fn range(&self) -> Range<Self::ValueType> {
135+
self.inner.range()
136+
}
137+
138+
fn map(&self, value: &Self::ValueType, limit: (i32, i32)) -> i32 {
139+
self.inner.map(value, limit)
140+
}
141+
142+
fn key_points<Hint: KeyPointHint>(&self, hint: Hint) -> Vec<Self::ValueType> {
143+
if hint.weight().allow_light_points() {
144+
(self.light_func)(hint.max_num_points())
145+
} else {
146+
(self.bold_func)(hint.max_num_points())
147+
}
148+
}
149+
150+
fn axis_pixel_range(&self, limit: (i32, i32)) -> Range<i32> {
151+
self.inner.axis_pixel_range(limit)
152+
}
153+
}
154+
155+
impl<R: DiscreteRanged> DiscreteRanged for WithKeyPointMethod<R> {
156+
fn size(&self) -> usize {
157+
self.inner.size()
158+
}
159+
fn index_of(&self, value: &Self::ValueType) -> Option<usize> {
160+
self.inner.index_of(value)
161+
}
162+
fn from_index(&self, index: usize) -> Option<Self::ValueType> {
163+
self.inner.from_index(index)
164+
}
165+
}

src/coord/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Also, the ranged axis can be deserted, and this is required by the histogram ser
2121
*/
2222
use plotters_backend::BackendCoord;
2323

24+
mod ckps;
2425
#[cfg(feature = "chrono")]
2526
mod datetime;
2627
mod discrete;
@@ -59,6 +60,8 @@ pub use group_by::{GroupBy, ToGroupByRange};
5960

6061
pub use nested::{BuildNestedCoord, NestedRange, NestedValue};
6162

63+
pub use ckps::{BindKeyPointMethod, BindKeyPoints, WithKeyPointMethod, WithKeyPoints};
64+
6265
use std::rc::Rc;
6366
use std::sync::Arc;
6467

src/lib.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -708,14 +708,17 @@ pub mod prelude {
708708

709709
// Coordinates
710710
pub use crate::coord::{
711-
BuildNestedCoord, CoordTranslate, DiscreteRanged, GroupBy, IntoLinspace, IntoPartialAxis,
712-
IntoSegmentedCoord, Linspace, LogCoord, LogRange, LogScalable, NestedRange, NestedValue,
713-
Ranged, RangedCoord, RangedCoordf32, RangedCoordf64, RangedCoordi32, RangedCoordi64,
714-
RangedCoordu32, RangedCoordu64, SegmentValue, ToGroupByRange,
711+
BindKeyPointMethod, BindKeyPoints, BuildNestedCoord, CoordTranslate, DiscreteRanged,
712+
GroupBy, IntoLinspace, IntoPartialAxis, IntoSegmentedCoord, Linspace, LogCoord, LogRange,
713+
LogScalable, NestedRange, NestedValue, Ranged, RangedCoord, RangedCoordf32, RangedCoordf64,
714+
RangedCoordi32, RangedCoordi64, RangedCoordu32, RangedCoordu64, SegmentValue,
715+
ToGroupByRange,
715716
};
716717

717718
#[cfg(feature = "chrono")]
718-
pub use crate::coord::{make_partial_axis, RangedDate, RangedDateTime, RangedDuration};
719+
pub use crate::coord::{
720+
make_partial_axis, IntoMonthly, IntoYearly, RangedDate, RangedDateTime, RangedDuration,
721+
};
719722

720723
// Re-export the backend for backward compatibility
721724
pub use plotters_backend::DrawingBackend;

0 commit comments

Comments
 (0)