OLD | NEW |
1 // | 1 // |
2 // Copyright 2014 Google Inc. All rights reserved. | 2 // Copyright 2014 Google Inc. All rights reserved. |
3 // | 3 // |
4 // Use of this source code is governed by a BSD-style | 4 // Use of this source code is governed by a BSD-style |
5 // license that can be found in the LICENSE file or at | 5 // license that can be found in the LICENSE file or at |
6 // https://developers.google.com/open-source/licenses/bsd | 6 // https://developers.google.com/open-source/licenses/bsd |
7 // | 7 // |
8 | 8 |
9 /// Collection of scales for use by charts. The role of scales is to map the | 9 /// Collection of scales for use by charts. The role of scales is to map the |
10 /// input domain to an output range. | 10 /// input domain to an output range. |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 /// Maps each value on the domain to a band in the output range. When a | 99 /// Maps each value on the domain to a band in the output range. When a |
100 /// non-zero value is specified, [padding] space is left between each bands | 100 /// non-zero value is specified, [padding] space is left between each bands |
101 /// and [outerPadding] space is left unused at both ends of the range. | 101 /// and [outerPadding] space is left unused at both ends of the range. |
102 void rangeBands(Iterable range, [double padding, double outerPadding]); | 102 void rangeBands(Iterable range, [double padding, double outerPadding]); |
103 | 103 |
104 /// Similar to [rangeBands] but ensures that each band starts and ends on a | 104 /// Similar to [rangeBands] but ensures that each band starts and ends on a |
105 /// pixel boundary - helps avoid anti-aliasing artifacts. | 105 /// pixel boundary - helps avoid anti-aliasing artifacts. |
106 void rangeRoundBands(Iterable range, [double padding, double outerPadding]); | 106 void rangeRoundBands(Iterable range, [double padding, double outerPadding]); |
107 } | 107 } |
108 | 108 |
109 class RoundingFunctions extends Pair<RoundFunction,RoundFunction> { | 109 class RoundingFunctions extends Pair<RoundFunction, RoundFunction> { |
110 RoundingFunctions(RoundFunction floor, RoundFunction ceil) | 110 RoundingFunctions(RoundFunction floor, RoundFunction ceil) |
111 : super(floor, ceil); | 111 : super(floor, ceil); |
112 | 112 |
113 factory RoundingFunctions.defaults() => | 113 factory RoundingFunctions.defaults() => |
114 new RoundingFunctions((x) => x.floor(), (x) => x.ceil()); | 114 new RoundingFunctions((x) => x.floor(), (x) => x.ceil()); |
115 | 115 |
116 factory RoundingFunctions.identity() => | 116 factory RoundingFunctions.identity() => |
117 new RoundingFunctions(identityFunction, identityFunction); | 117 new RoundingFunctions(identityFunction, identityFunction); |
118 | 118 |
119 RoundFunction get floor => super.first; | 119 RoundFunction get floor => super.first; |
120 RoundFunction get ceil => super.last; | 120 RoundFunction get ceil => super.last; |
121 } | 121 } |
122 | 122 |
123 /// Namespacing container for utilities used by scales. | 123 /// Namespacing container for utilities used by scales. |
124 abstract class ScaleUtils { | 124 abstract class ScaleUtils { |
125 /// Utility to return extent of sorted [values]. | 125 /// Utility to return extent of sorted [values]. |
126 static Extent extent(Iterable values) => | 126 static Extent extent(Iterable values) => values.first < values.last |
127 values.first < values.last | 127 ? new Extent(values.first, values.last) |
128 ? new Extent(values.first, values.last) | 128 : new Extent(values.last, values.first); |
129 : new Extent(values.last, values.first); | |
130 | 129 |
131 /// Extends [values] to round numbers based on the given pair of | 130 /// Extends [values] to round numbers based on the given pair of |
132 /// floor and ceil functions. [functions] is a pair of rounding function | 131 /// floor and ceil functions. [functions] is a pair of rounding function |
133 /// among which the first is used to compute floor of a number and the | 132 /// among which the first is used to compute floor of a number and the |
134 /// second for ceil of the number. | 133 /// second for ceil of the number. |
135 static List nice(List values, RoundingFunctions functions) { | 134 static List nice(List values, RoundingFunctions functions) { |
136 if (values.last >= values.first) { | 135 if (values.last >= values.first) { |
137 values[0] = functions.floor(values.first); | 136 values[0] = functions.floor(values.first); |
138 values[values.length - 1] = functions.ceil(values.last); | 137 values[values.length - 1] = functions.ceil(values.last); |
139 } else { | 138 } else { |
140 values[values.length - 1] = functions.floor(values.last); | 139 values[values.length - 1] = functions.floor(values.last); |
141 values[0] = functions.ceil(values.first); | 140 values[0] = functions.ceil(values.first); |
142 } | 141 } |
143 return values; | 142 return values; |
144 } | 143 } |
145 | 144 |
146 static RoundingFunctions niceStep(num step) => (step > 0) | 145 static RoundingFunctions niceStep(num step) => (step > 0) |
147 ? new RoundingFunctions( | 146 ? new RoundingFunctions( |
148 (x) => (x < step) ? x.floor() : (x / step).floor() * step, | 147 (x) => (x < step) ? x.floor() : (x / step).floor() * step, |
149 (x) => (x < step) ? x.ceil() : (x / step).ceil() * step) | 148 (x) => (x < step) ? x.ceil() : (x / step).ceil() * step) |
150 : new RoundingFunctions.identity(); | 149 : new RoundingFunctions.identity(); |
151 | 150 |
152 /// Returns a Function that given a value x on the domain, returns the | 151 /// Returns a Function that given a value x on the domain, returns the |
153 /// corresponding value on the range on a bilinear scale. | 152 /// corresponding value on the range on a bilinear scale. |
154 /// | 153 /// |
155 /// @param domain The domain of the scale. | 154 /// @param domain The domain of the scale. |
156 /// @param range The range of the scale. | 155 /// @param range The range of the scale. |
157 /// @param uninterpolator The uninterpolator for domain values. | 156 /// @param uninterpolator The uninterpolator for domain values. |
158 /// @param interpolator The interpolator for range values. | 157 /// @param interpolator The interpolator for range values. |
159 static Function bilinearScale(List domain, List range, | 158 static Function bilinearScale( |
160 Function uninterpolator, Function interpolator) { | 159 List domain, List range, Function uninterpolator, Function interpolator) { |
161 var u = uninterpolator(domain[0], domain[1]), | 160 var u = uninterpolator(domain[0], domain[1]), |
162 i = interpolator(range[0], range[1]); | 161 i = interpolator(range[0], range[1]); |
163 return (x) => i(u(x)); | 162 return (x) => i(u(x)); |
164 } | 163 } |
165 | 164 |
166 /// Returns a Function that given a value x on the domain, returns the | 165 /// Returns a Function that given a value x on the domain, returns the |
167 /// corresponding value on the range on a polylinear scale. | 166 /// corresponding value on the range on a polylinear scale. |
168 /// | 167 /// |
169 /// @param domain The domain of the scale. | 168 /// @param domain The domain of the scale. |
170 /// @param range The range of the scale. | 169 /// @param range The range of the scale. |
171 /// @param uninterpolator The uninterpolator for domain values. | 170 /// @param uninterpolator The uninterpolator for domain values. |
172 /// @param interpolator The interpolator for range values. | 171 /// @param interpolator The interpolator for range values. |
173 static Function polylinearScale(List domain, List range, | 172 static Function polylinearScale( |
174 Function uninterpolator, Function interpolator) { | 173 List domain, List range, Function uninterpolator, Function interpolator) { |
175 var u = [], | 174 var u = [], i = [], j = 0, k = math.min(domain.length, range.length) - 1; |
176 i = [], | |
177 j = 0, | |
178 k = math.min(domain.length, range.length) - 1; | |
179 | 175 |
180 // Handle descending domains. | 176 // Handle descending domains. |
181 if (domain[k] < domain[0]) { | 177 if (domain[k] < domain[0]) { |
182 domain = domain.reversed.toList(); | 178 domain = domain.reversed.toList(); |
183 range = range.reversed.toList(); | 179 range = range.reversed.toList(); |
184 } | 180 } |
185 | 181 |
186 while (++j <= k) { | 182 while (++j <= k) { |
187 u.add(uninterpolator(domain[j - 1], domain[j])); | 183 u.add(uninterpolator(domain[j - 1], domain[j])); |
188 i.add(interpolator(range[j - 1], range[j])); | 184 i.add(interpolator(range[j - 1], range[j])); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 hi = mid; | 221 hi = mid; |
226 } else { | 222 } else { |
227 lo = mid + 1; | 223 lo = mid + 1; |
228 } | 224 } |
229 } | 225 } |
230 return lo; | 226 return lo; |
231 } | 227 } |
232 | 228 |
233 static Function bisect = bisectRight; | 229 static Function bisect = bisectRight; |
234 } | 230 } |
OLD | NEW |