Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: charted/lib/core/scales.dart

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
9 /// Collection of scales for use by charts. The role of scales is to map the
10 /// input domain to an output range.
11 ///
12 /// Charted supports two types of scales:
13 /// - Quantitative, where the scales use a mathematical function for mapping
14 /// the input domain to output range.
15 /// - Ordinal, where the input domain is discrete (i.e set of values)
16 ///
17 library charted.core.scales;
18
19 import 'dart:math' as math;
20 import 'package:charted/core/utils.dart';
21 import 'package:charted/core/interpolators.dart';
22 import 'package:charted/core/time_interval.dart';
23 import 'package:charted/locale/locale.dart';
24 import 'package:charted/locale/format.dart';
25
26 part 'scales/ordinal_scale.dart';
27 part 'scales/linear_scale.dart';
28 part 'scales/log_scale.dart';
29 part 'scales/time_scale.dart';
30
31 typedef num RoundFunction(num value);
32
33 /// Minimum common interface supported by all scales. [QuantitativeScale] and
34 /// [OrdinalScale] contain the interface for their respective types.
35 abstract class Scale {
36 /// Given a [value] in the input domain, map it to the range.
37 /// On [QuantitativeScale]s both parameter and return values are numbers.
38 dynamic scale(value);
39
40 /// Given a [value] in the output range, return value in the input domain
41 /// that maps to the value.
42 /// On [QuantitativeScale]s both parameter and return values are numbers.
43 dynamic invert(value);
44
45 /// Input domain used by this scale.
46 Iterable domain;
47
48 /// Output range used by this scale.
49 Iterable range;
50
51 /// Maximum and minimum values of the scale's output range.
52 Extent get rangeExtent;
53
54 /// Creates tick values over the input domain.
55 Iterable get ticks;
56
57 /// Creates a formatter that is suitable for formatting the ticks.
58 /// For ordinal scale, the returned function is an identity function.
59 FormatFunction createTickFormatter([String format]);
60
61 /// Creates a clone of this scale.
62 Scale clone();
63
64 /// Suggested number of ticks on this scale.
65 /// Note: This property is only valid on quantitative scales.
66 int ticksCount;
67
68 /// Indicates if the current scale is using niced values for ticks.
69 /// Note: This property is only valid on quantitative scales.
70 bool nice;
71
72 /// Indicates if output range is clamped. When clamp is not true, any input
73 /// value that is not within the input domain may result in a value that is
74 /// outside the output range.
75 /// Note: This property is only valid on quantitative scales.
76 bool clamp;
77
78 /// Indicates that the scaled values must be rounded to the nearest
79 /// integer. Helps avoid anti-aliasing artifacts in the visualizations.
80 /// Note: This property is only valid on quantitative scales.
81 bool rounded;
82 }
83
84 /// Minimum common interface supported by scales whose input domain
85 /// contains discreet values (Ordinal scales).
86 abstract class OrdinalScale extends Scale {
87 factory OrdinalScale() = _OrdinalScale;
88
89 /// Amount of space that each value in the domain gets from the range. A band
90 /// is available only after [rangeBands] or [rangeRoundBands] is called by
91 /// the user. A bar-chart could use this space as width of a bar.
92 num get rangeBand;
93
94 /// Maps each value on the domain to a single point on output range. When a
95 /// non-zero value is specified, [padding] space is left unused on both ends
96 /// of the range.
97 void rangePoints(Iterable range, [double padding]);
98
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
101 /// and [outerPadding] space is left unused at both ends of the range.
102 void rangeBands(Iterable range, [double padding, double outerPadding]);
103
104 /// Similar to [rangeBands] but ensures that each band starts and ends on a
105 /// pixel boundary - helps avoid anti-aliasing artifacts.
106 void rangeRoundBands(Iterable range, [double padding, double outerPadding]);
107 }
108
109 class RoundingFunctions extends Pair<RoundFunction,RoundFunction> {
110 RoundingFunctions(RoundFunction floor, RoundFunction ceil)
111 : super(floor, ceil);
112
113 factory RoundingFunctions.defaults() =>
114 new RoundingFunctions((x) => x.floor(), (x) => x.ceil());
115
116 factory RoundingFunctions.identity() =>
117 new RoundingFunctions(identityFunction, identityFunction);
118
119 RoundFunction get floor => super.first;
120 RoundFunction get ceil => super.last;
121 }
122
123 /// Namespacing container for utilities used by scales.
124 abstract class ScaleUtils {
125 /// Utility to return extent of sorted [values].
126 static Extent extent(Iterable values) =>
127 values.first < values.last
128 ? new Extent(values.first, values.last)
129 : new Extent(values.last, values.first);
130
131 /// Extends [values] to round numbers based on the given pair of
132 /// 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
134 /// second for ceil of the number.
135 static List nice(List values, RoundingFunctions functions) {
136 if (values.last >= values.first) {
137 values[0] = functions.floor(values.first);
138 values[values.length - 1] = functions.ceil(values.last);
139 } else {
140 values[values.length - 1] = functions.floor(values.last);
141 values[0] = functions.ceil(values.first);
142 }
143 return values;
144 }
145
146 static RoundingFunctions niceStep(num step) => (step > 0)
147 ? new RoundingFunctions(
148 (x) => (x < step) ? x.floor() : (x / step).floor() * step,
149 (x) => (x < step) ? x.ceil() : (x / step).ceil() * step)
150 : new RoundingFunctions.identity();
151
152 /// Returns a Function that given a value x on the domain, returns the
153 /// corresponding value on the range on a bilinear scale.
154 ///
155 /// @param domain The domain of the scale.
156 /// @param range The range of the scale.
157 /// @param uninterpolator The uninterpolator for domain values.
158 /// @param interpolator The interpolator for range values.
159 static Function bilinearScale(List domain, List range,
160 Function uninterpolator, Function interpolator) {
161 var u = uninterpolator(domain[0], domain[1]),
162 i = interpolator(range[0], range[1]);
163 return (x) => i(u(x));
164 }
165
166 /// Returns a Function that given a value x on the domain, returns the
167 /// corresponding value on the range on a polylinear scale.
168 ///
169 /// @param domain The domain of the scale.
170 /// @param range The range of the scale.
171 /// @param uninterpolator The uninterpolator for domain values.
172 /// @param interpolator The interpolator for range values.
173 static Function polylinearScale(List domain, List range,
174 Function uninterpolator, Function interpolator) {
175 var u = [],
176 i = [],
177 j = 0,
178 k = math.min(domain.length, range.length) - 1;
179
180 // Handle descending domains.
181 if (domain[k] < domain[0]) {
182 domain = domain.reversed.toList();
183 range = range.reversed.toList();
184 }
185
186 while (++j <= k) {
187 u.add(uninterpolator(domain[j - 1], domain[j]));
188 i.add(interpolator(range[j - 1], range[j]));
189 }
190
191 return (x) {
192 int index = bisect(domain, x, 1, k) - 1;
193 return i[index](u[index](x));
194 };
195 }
196
197 /// Returns the insertion point i for value x such that all values in a[lo:i]
198 /// will be less than x and all values in a[i:hi] will be equal to or greater
199 /// than x.
200 static int bisectLeft(List a, num x, [int lo = 0, int hi = -1]) {
201 if (hi == -1) {
202 hi = a.length;
203 }
204 while (lo < hi) {
205 int mid = ((lo + hi) / 2).floor();
206 if (a[mid] < x) {
207 lo = mid + 1;
208 } else {
209 hi = mid;
210 }
211 }
212 return lo;
213 }
214
215 /// Returns the insertion point i for value x such that all values in a[lo:i]
216 /// will be less than or equalto x and all values in a[i:hi] will be greater
217 /// than x.
218 static int bisectRight(List a, num x, [int lo = 0, int hi = -1]) {
219 if (hi == -1) {
220 hi = a.length;
221 }
222 while (lo < hi) {
223 int mid = ((lo + hi) / 2).floor();
224 if (x < a[mid]) {
225 hi = mid;
226 } else {
227 lo = mid + 1;
228 }
229 }
230 return lo;
231 }
232
233 static Function bisect = bisectRight;
234 }
OLDNEW
« no previous file with comments | « charted/lib/core/interpolators/interpolators.dart ('k') | charted/lib/core/scales/linear_scale.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698