@@ -46,18 +46,23 @@ impl_log_scalable!(i, u8);
46
46
impl_log_scalable ! ( i, u16 ) ;
47
47
impl_log_scalable ! ( i, u32 ) ;
48
48
impl_log_scalable ! ( i, u64 ) ;
49
+
49
50
impl_log_scalable ! ( f, f32 ) ;
50
51
impl_log_scalable ! ( f, f64 ) ;
51
52
52
53
pub trait IntoLogRange {
53
54
type ValueType : LogScalable ;
54
- fn log_scale ( self ) -> LogRange < Self :: ValueType > ;
55
+ fn log_scale ( self ) -> LogRangeExt < Self :: ValueType > ;
55
56
}
56
57
57
58
impl < T : LogScalable > IntoLogRange for Range < T > {
58
59
type ValueType = T ;
59
- fn log_scale ( self ) -> LogRange < T > {
60
- LogRange ( self )
60
+ fn log_scale ( self ) -> LogRangeExt < T > {
61
+ LogRangeExt {
62
+ range : self ,
63
+ zero : 0.0 ,
64
+ base : 10.0 ,
65
+ }
61
66
}
62
67
}
63
68
@@ -66,11 +71,70 @@ impl<T: LogScalable> IntoLogRange for Range<T> {
66
71
#[ derive( Clone ) ]
67
72
pub struct LogRange < V : LogScalable > ( pub Range < V > ) ;
68
73
74
+ #[ derive( Clone ) ]
75
+ pub struct LogRangeExt < V : LogScalable > {
76
+ range : Range < V > ,
77
+ zero : f64 ,
78
+ base : f64 ,
79
+ }
80
+
81
+ impl < V : LogScalable > LogRangeExt < V > {
82
+ pub fn zero_point ( mut self , value : V ) -> Self
83
+ where
84
+ V : PartialEq ,
85
+ {
86
+ self . zero = if V :: from_f64 ( 0.0 ) == value {
87
+ 0.0
88
+ } else {
89
+ value. as_f64 ( )
90
+ } ;
91
+
92
+ self
93
+ }
94
+
95
+ pub fn base ( mut self , base : f64 ) -> Self {
96
+ if self . base > 1.0 {
97
+ self . base = base;
98
+ }
99
+ self
100
+ }
101
+ }
102
+
69
103
impl < V : LogScalable > From < LogRange < V > > for LogCoord < V > {
70
104
fn from ( range : LogRange < V > ) -> LogCoord < V > {
105
+ range. 0 . log_scale ( ) . into ( )
106
+ }
107
+ }
108
+
109
+ impl < V : LogScalable > From < LogRangeExt < V > > for LogCoord < V > {
110
+ fn from ( spec : LogRangeExt < V > ) -> LogCoord < V > {
111
+ let zero_point = spec. zero ;
112
+ let mut start = spec. range . start . as_f64 ( ) - zero_point;
113
+ let mut end = spec. range . end . as_f64 ( ) - zero_point;
114
+ let negative = if start < 0.0 || end < 0.0 {
115
+ start = -start;
116
+ end = -end;
117
+ true
118
+ } else {
119
+ false
120
+ } ;
121
+
122
+ if start < end {
123
+ if start == 0.0 {
124
+ start = start. max ( end * 1e-5 ) ;
125
+ }
126
+ } else {
127
+ if end == 0.0 {
128
+ end = end. max ( start * 1e-5 ) ;
129
+ }
130
+ }
71
131
LogCoord {
72
- linear : ( range. 0 . start . as_f64 ( ) . ln ( ) ..range. 0 . end . as_f64 ( ) . ln ( ) ) . into ( ) ,
73
- logic : range. 0 ,
132
+ linear : ( start. ln ( ) ..end. ln ( ) ) . into ( ) ,
133
+ logic : spec. range ,
134
+ normalized : start..end,
135
+ base : spec. base ,
136
+ zero_point,
137
+ negative,
74
138
marker : PhantomData ,
75
139
}
76
140
}
@@ -81,62 +145,107 @@ impl<V: LogScalable> AsRangedCoord for LogRange<V> {
81
145
type Value = V ;
82
146
}
83
147
148
+ impl < V : LogScalable > AsRangedCoord for LogRangeExt < V > {
149
+ type CoordDescType = LogCoord < V > ;
150
+ type Value = V ;
151
+ }
152
+
84
153
/// A log scaled coordinate axis
85
154
pub struct LogCoord < V : LogScalable > {
86
155
linear : RangedCoordf64 ,
87
156
logic : Range < V > ,
157
+ normalized : Range < f64 > ,
158
+ base : f64 ,
159
+ zero_point : f64 ,
160
+ negative : bool ,
88
161
marker : PhantomData < V > ,
89
162
}
90
163
164
+ impl < V : LogScalable > LogCoord < V > {
165
+ fn value_to_f64 ( & self , value : & V ) -> f64 {
166
+ let fv = value. as_f64 ( ) - self . zero_point ;
167
+ if self . negative {
168
+ -fv
169
+ } else {
170
+ fv
171
+ }
172
+ }
173
+
174
+ fn f64_to_value ( & self , fv : f64 ) -> V {
175
+ let fv = if self . negative { -fv } else { fv } ;
176
+ V :: from_f64 ( fv + self . zero_point )
177
+ }
178
+
179
+ fn is_inf ( & self , fv : f64 ) -> bool {
180
+ let fv = if self . negative { -fv } else { fv } ;
181
+ let a = V :: from_f64 ( fv + self . zero_point ) ;
182
+ let b = V :: from_f64 ( self . zero_point ) ;
183
+
184
+ V :: as_f64 ( & a) == V :: as_f64 ( & b)
185
+ }
186
+ }
187
+
91
188
impl < V : LogScalable > Ranged for LogCoord < V > {
92
189
type FormatOption = DefaultFormatting ;
93
190
type ValueType = V ;
94
191
95
192
fn map ( & self , value : & V , limit : ( i32 , i32 ) ) -> i32 {
96
- let value = value . as_f64 ( ) ;
97
- let value = value . max ( self . logic . start . as_f64 ( ) ) . ln ( ) ;
98
- self . linear . map ( & value , limit)
193
+ let fv = self . value_to_f64 ( value ) ;
194
+ let value_ln = fv . ln ( ) ;
195
+ self . linear . map ( & value_ln , limit)
99
196
}
100
197
101
198
fn key_points < Hint : KeyPointHint > ( & self , hint : Hint ) -> Vec < Self :: ValueType > {
102
199
let max_points = hint. max_num_points ( ) ;
103
- let tier_1 = ( self . logic . end . as_f64 ( ) / self . logic . start . as_f64 ( ) )
104
- . log10 ( )
105
- . abs ( )
106
- . floor ( )
107
- . max ( 1.0 ) as usize ;
108
200
109
- let tier_2_density = if max_points < tier_1 {
201
+ let base = self . base ;
202
+ let base_ln = base. ln ( ) ;
203
+
204
+ /*let mut start = self.//self.value_to_f64(&self.logic.start);
205
+ let mut end = self.value_to_f64(&self.logic.end);*/
206
+ let Range { mut start, mut end } = self . normalized ;
207
+
208
+ if start > end {
209
+ std:: mem:: swap ( & mut start, & mut end) ;
210
+ }
211
+
212
+ let bold_count = ( ( end / start) . ln ( ) . abs ( ) / base_ln) . floor ( ) . max ( 1.0 ) as usize ;
213
+
214
+ let light_density = if max_points < bold_count {
110
215
0
111
216
} else {
112
- let density = 1 + ( max_points - tier_1 ) / tier_1 ;
217
+ let density = 1 + ( max_points - bold_count ) / bold_count ;
113
218
let mut exp = 1 ;
114
219
while exp * 10 <= density {
115
220
exp *= 10 ;
116
221
}
117
222
exp - 1
118
223
} ;
119
224
120
- let mut multiplier = 10.0 ;
225
+ let mut multiplier = base ;
121
226
let mut cnt = 1 ;
122
- while max_points < tier_1 / cnt {
123
- multiplier *= 10.0 ;
227
+ while max_points < bold_count / cnt {
228
+ multiplier *= base ;
124
229
cnt += 1 ;
125
230
}
126
231
127
232
let mut ret = vec ! [ ] ;
128
- let mut val = ( 10f64 ) . powf ( self . logic . start . as_f64 ( ) . log10 ( ) . ceil ( ) ) ;
233
+ let mut val = ( base ) . powf ( ( start. ln ( ) / base_ln ) . ceil ( ) ) ;
129
234
130
- while val <= self . logic . end . as_f64 ( ) {
131
- ret. push ( V :: from_f64 ( val) ) ;
132
- for i in 1 ..=tier_2_density {
235
+ while val <= end {
236
+ if !self . is_inf ( val) {
237
+ ret. push ( self . f64_to_value ( val) ) ;
238
+ }
239
+ for i in 1 ..=light_density {
133
240
let v = val
134
241
* ( 1.0
135
- + multiplier / f64:: from ( tier_2_density as u32 + 1 ) * f64:: from ( i as u32 ) ) ;
136
- if v > self . logic . end . as_f64 ( ) {
242
+ + multiplier / f64:: from ( light_density as u32 + 1 ) * f64:: from ( i as u32 ) ) ;
243
+ if v > end {
137
244
break ;
138
245
}
139
- ret. push ( V :: from_f64 ( v) ) ;
246
+ if !self . is_inf ( val) {
247
+ ret. push ( self . f64_to_value ( v) ) ;
248
+ }
140
249
}
141
250
val *= multiplier;
142
251
}
0 commit comments