OLD | NEW |
| (Empty) |
1 // | |
2 // Copyright 2014 Google Inc. All rights reserved. | |
3 // | |
4 // Use of this source code is governed by a BSD-style | |
5 // license that can be found in the LICENSE file or at | |
6 // https://developers.google.com/open-source/licenses/bsd | |
7 // | |
8 part of charted.core.scales; | |
9 | |
10 class LinearScale implements Scale { | |
11 static const defaultDomain = const [0, 1]; | |
12 static const defaultRange = const [0, 1]; | |
13 | |
14 bool _rounded = false; | |
15 Iterable _domain = defaultDomain; | |
16 Iterable _range = defaultRange; | |
17 | |
18 int _ticksCount = 5; | |
19 bool _clamp = false; | |
20 bool _nice = false; | |
21 | |
22 Function _invert; | |
23 Function _scale; | |
24 | |
25 LinearScale(); | |
26 | |
27 LinearScale._clone(LinearScale source) | |
28 : _domain = source._domain.toList(), | |
29 _range = source._range.toList(), | |
30 _ticksCount = source._ticksCount, | |
31 _clamp = source._clamp, | |
32 _nice = source._nice, | |
33 _rounded = source._rounded { | |
34 _reset(); | |
35 } | |
36 | |
37 void _reset({bool nice: false}) { | |
38 if (nice) { | |
39 _domain = ScaleUtils.nice( | |
40 _domain, ScaleUtils.niceStep(_linearTickRange().step)); | |
41 } | |
42 | |
43 Function linear = math.min(_domain.length, _range.length) > 2 ? | |
44 ScaleUtils.polylinearScale : ScaleUtils.bilinearScale; | |
45 | |
46 Function uninterpolator = clamp ? uninterpolateClamp : uninterpolateNumber; | |
47 InterpolatorGenerator interpolator = | |
48 _rounded ? createRoundedNumberInterpolator : createNumberInterpolator; | |
49 | |
50 _invert = | |
51 linear(_range, _domain, uninterpolator, createNumberInterpolator); | |
52 _scale = linear(_domain, _range, uninterpolator, interpolator); | |
53 } | |
54 | |
55 @override | |
56 set range(Iterable value) { | |
57 assert(value != null); | |
58 _range = value; | |
59 _reset(); | |
60 } | |
61 | |
62 @override | |
63 Iterable get range => _range; | |
64 | |
65 @override | |
66 set domain(Iterable value) { | |
67 _domain = value; | |
68 _reset(nice: _nice); | |
69 } | |
70 | |
71 @override | |
72 Iterable get domain => _domain; | |
73 | |
74 @override | |
75 set rounded(bool value) { | |
76 assert(value != null); | |
77 if (value != null && _rounded != value) { | |
78 _rounded = value; | |
79 _reset(); | |
80 } | |
81 } | |
82 | |
83 @override | |
84 bool get rounded => _rounded; | |
85 | |
86 @override | |
87 set ticksCount(int value) { | |
88 assert(value != null); | |
89 if (value != null && _ticksCount != value) { | |
90 _ticksCount = value; | |
91 _reset(); | |
92 } | |
93 } | |
94 | |
95 @override | |
96 int get ticksCount => _ticksCount; | |
97 | |
98 @override | |
99 Iterable get ticks => _linearTickRange(); | |
100 | |
101 @override | |
102 set clamp(bool value) { | |
103 assert(value != null); | |
104 if (value != null && _clamp != value) { | |
105 _clamp = value; | |
106 _reset(); | |
107 } | |
108 } | |
109 | |
110 @override | |
111 bool get clamp => _clamp; | |
112 | |
113 @override | |
114 set nice(bool value) { | |
115 assert(value != null); | |
116 if (value != null && _nice != value) { | |
117 _nice = value; | |
118 _reset(nice: _nice); | |
119 } | |
120 } | |
121 | |
122 @override | |
123 bool get nice => _nice; | |
124 | |
125 @override | |
126 Extent get rangeExtent => ScaleUtils.extent(_range); | |
127 | |
128 @override | |
129 num scale(num value) => _scale(value); | |
130 | |
131 @override | |
132 num invert(num value) => _invert(value); | |
133 | |
134 Range _linearTickRange([Extent extent]) { | |
135 if (extent == null) { | |
136 extent = ScaleUtils.extent(_domain); | |
137 } | |
138 var span = extent.max - extent.min, | |
139 step = | |
140 math.pow(10, (math.log(span / _ticksCount) / math.LN10).floor()), | |
141 err = _ticksCount / span * step; | |
142 | |
143 // Filter ticks to get closer to the desired count. | |
144 if (err <= .15) { | |
145 step *= 10; | |
146 } | |
147 else if (err <= .35) { | |
148 step *= 5; | |
149 } | |
150 else if (err <= .75) { | |
151 step *= 2; | |
152 } | |
153 | |
154 return new Range((extent.min / step).ceil() * step, | |
155 (extent.max / step).floor() * step + step * 0.5, step); | |
156 } | |
157 | |
158 @override | |
159 FormatFunction createTickFormatter([String formatStr]) { | |
160 int precision(value) { | |
161 return -(math.log(value) / math.LN10 + .01).floor(); | |
162 } | |
163 Range tickRange = _linearTickRange(); | |
164 if (formatStr == null) { | |
165 formatStr = ".${precision(tickRange.step)}f"; | |
166 } | |
167 NumberFormat formatter = new NumberFormat(new EnUsLocale()); | |
168 return formatter.format(formatStr); | |
169 } | |
170 | |
171 @override | |
172 LinearScale clone() => new LinearScale._clone(this); | |
173 } | |
OLD | NEW |