plotters/coord/ranged1d/combinators/
ckps.rs
1use std::ops::Range;
5
6use crate::coord::ranged1d::{AsRangedCoord, DiscreteRanged, KeyPointHint, Ranged};
7
8pub struct WithKeyPoints<Inner: Ranged> {
17 inner: Inner,
18 bold_points: Vec<Inner::ValueType>,
19 light_points: Vec<Inner::ValueType>,
20}
21
22impl<I: Ranged> WithKeyPoints<I> {
23 pub fn with_light_points<T: IntoIterator<Item = I::ValueType>>(mut self, iter: T) -> Self {
25 self.light_points.clear();
26 self.light_points.extend(iter);
27 self
28 }
29
30 pub fn bold_points(&self) -> &[I::ValueType] {
32 self.bold_points.as_ref()
33 }
34
35 pub fn bold_points_mut(&mut self) -> &mut [I::ValueType] {
37 self.bold_points.as_mut()
38 }
39
40 pub fn light_points(&self) -> &[I::ValueType] {
42 self.light_points.as_ref()
43 }
44
45 pub fn light_points_mut(&mut self) -> &mut [I::ValueType] {
47 self.light_points.as_mut()
48 }
49}
50
51impl<R: Ranged> Ranged for WithKeyPoints<R>
52where
53 R::ValueType: Clone,
54{
55 type ValueType = R::ValueType;
56 type FormatOption = R::FormatOption;
57
58 fn range(&self) -> Range<Self::ValueType> {
59 self.inner.range()
60 }
61
62 fn map(&self, value: &Self::ValueType, limit: (i32, i32)) -> i32 {
63 self.inner.map(value, limit)
64 }
65
66 fn key_points<Hint: KeyPointHint>(&self, hint: Hint) -> Vec<Self::ValueType> {
67 if hint.weight().allow_light_points() {
68 self.light_points.clone()
69 } else {
70 self.bold_points.clone()
71 }
72 }
73
74 fn axis_pixel_range(&self, limit: (i32, i32)) -> Range<i32> {
75 self.inner.axis_pixel_range(limit)
76 }
77}
78
79impl<R: DiscreteRanged> DiscreteRanged for WithKeyPoints<R>
80where
81 R::ValueType: Clone,
82{
83 fn size(&self) -> usize {
84 self.inner.size()
85 }
86 fn index_of(&self, value: &Self::ValueType) -> Option<usize> {
87 self.inner.index_of(value)
88 }
89 fn from_index(&self, index: usize) -> Option<Self::ValueType> {
90 self.inner.from_index(index)
91 }
92}
93
94pub trait BindKeyPoints
95where
96 Self: AsRangedCoord,
97{
98 fn with_key_points(self, points: Vec<Self::Value>) -> WithKeyPoints<Self::CoordDescType> {
113 WithKeyPoints {
114 inner: self.into(),
115 bold_points: points,
116 light_points: vec![],
117 }
118 }
119}
120
121impl<T: AsRangedCoord> BindKeyPoints for T {}
122
123pub struct WithKeyPointMethod<R: Ranged> {
129 inner: R,
130 bold_func: Box<dyn Fn(usize) -> Vec<R::ValueType>>,
131 light_func: Box<dyn Fn(usize) -> Vec<R::ValueType>>,
132}
133
134pub trait BindKeyPointMethod
135where
136 Self: AsRangedCoord,
137{
138 fn with_key_point_func<F: Fn(usize) -> Vec<Self::Value> + 'static>(
153 self,
154 func: F,
155 ) -> WithKeyPointMethod<Self::CoordDescType> {
156 WithKeyPointMethod {
157 inner: self.into(),
158 bold_func: Box::new(func),
159 light_func: Box::new(|_| vec![]),
160 }
161 }
162}
163
164impl<T: AsRangedCoord> BindKeyPointMethod for T {}
165
166impl<R: Ranged> WithKeyPointMethod<R> {
167 pub fn with_light_point_func<F: Fn(usize) -> Vec<R::ValueType> + 'static>(
169 mut self,
170 func: F,
171 ) -> Self {
172 self.light_func = Box::new(func);
173 self
174 }
175}
176
177impl<R: Ranged> Ranged for WithKeyPointMethod<R> {
178 type ValueType = R::ValueType;
179 type FormatOption = R::FormatOption;
180
181 fn range(&self) -> Range<Self::ValueType> {
182 self.inner.range()
183 }
184
185 fn map(&self, value: &Self::ValueType, limit: (i32, i32)) -> i32 {
186 self.inner.map(value, limit)
187 }
188
189 fn key_points<Hint: KeyPointHint>(&self, hint: Hint) -> Vec<Self::ValueType> {
190 if hint.weight().allow_light_points() {
191 (self.light_func)(hint.max_num_points())
192 } else {
193 (self.bold_func)(hint.max_num_points())
194 }
195 }
196
197 fn axis_pixel_range(&self, limit: (i32, i32)) -> Range<i32> {
198 self.inner.axis_pixel_range(limit)
199 }
200}
201
202impl<R: DiscreteRanged> DiscreteRanged for WithKeyPointMethod<R> {
203 fn size(&self) -> usize {
204 self.inner.size()
205 }
206 fn index_of(&self, value: &Self::ValueType) -> Option<usize> {
207 self.inner.index_of(value)
208 }
209 fn from_index(&self, index: usize) -> Option<Self::ValueType> {
210 self.inner.from_index(index)
211 }
212}
213
214#[cfg(test)]
215mod test {
216 use super::*;
217 use crate::coord::ranged1d::{BoldPoints, LightPoints};
218 #[test]
219 fn test_with_key_points() {
220 let range = (0..100).with_key_points(vec![1, 2, 3]);
221 assert_eq!(range.map(&3, (0, 1000)), 30);
222 assert_eq!(range.range(), 0..100);
223 assert_eq!(range.key_points(BoldPoints(100)), vec![1, 2, 3]);
224 assert_eq!(range.key_points(LightPoints::new(100, 100)), vec![]);
225 let range = range.with_light_points(5..10);
226 assert_eq!(range.key_points(BoldPoints(10)), vec![1, 2, 3]);
227 assert_eq!(
228 range.key_points(LightPoints::new(10, 10)),
229 (5..10).collect::<Vec<_>>()
230 );
231
232 assert_eq!(range.size(), 101);
233 assert_eq!(range.index_of(&10), Some(10));
234 assert_eq!(range.from_index(10), Some(10));
235
236 assert_eq!(range.axis_pixel_range((0, 1000)), 0..1000);
237
238 let mut range = range;
239
240 assert_eq!(range.light_points().len(), 5);
241 assert_eq!(range.light_points_mut().len(), 5);
242 assert_eq!(range.bold_points().len(), 3);
243 assert_eq!(range.bold_points_mut().len(), 3);
244 }
245
246 #[test]
247 fn test_with_key_point_method() {
248 let range = (0..100).with_key_point_func(|_| vec![1, 2, 3]);
249 assert_eq!(range.map(&3, (0, 1000)), 30);
250 assert_eq!(range.range(), 0..100);
251 assert_eq!(range.key_points(BoldPoints(100)), vec![1, 2, 3]);
252 assert_eq!(range.key_points(LightPoints::new(100, 100)), vec![]);
253 let range = range.with_light_point_func(|_| (5..10).collect());
254 assert_eq!(range.key_points(BoldPoints(10)), vec![1, 2, 3]);
255 assert_eq!(
256 range.key_points(LightPoints::new(10, 10)),
257 (5..10).collect::<Vec<_>>()
258 );
259
260 assert_eq!(range.size(), 101);
261 assert_eq!(range.index_of(&10), Some(10));
262 assert_eq!(range.from_index(10), Some(10));
263
264 assert_eq!(range.axis_pixel_range((0, 1000)), 0..1000);
265 }
266}