Index: charted/lib/core/interpolators/interpolators.dart |
diff --git a/charted/lib/core/interpolators/interpolators.dart b/charted/lib/core/interpolators/interpolators.dart |
deleted file mode 100644 |
index 0de80eeb9684d42a19d94761d3ab79454d481942..0000000000000000000000000000000000000000 |
--- a/charted/lib/core/interpolators/interpolators.dart |
+++ /dev/null |
@@ -1,392 +0,0 @@ |
-// |
-// Copyright 2014 Google Inc. All rights reserved. |
-// |
-// Use of this source code is governed by a BSD-style |
-// license that can be found in the LICENSE file or at |
-// https://developers.google.com/open-source/licenses/bsd |
-// |
- |
-part of charted.core.interpolators; |
- |
-/// [Interpolator] accepts [t], such that 0.0 < t < 1.0 and returns |
-/// a value in a pre-defined range. |
-typedef Interpolator(num t); |
- |
-/// [InterpolatorGenerator] accepts two parameters [a], [b] and returns an |
-/// [Interpolator] for transitioning from [a] to [b] |
-typedef Interpolator InterpolatorGenerator(a, b); |
- |
-/// List of registered interpolators - [createInterpolatorFromRegistry] |
-/// iterates through this list from backwards and the first non-null |
-/// interpolate function is returned to the caller. |
-List<InterpolatorGenerator> _interpolators = [ createInterpolatorByType ]; |
- |
-/// Returns a default interpolator between values [a] and [b]. Unless |
-/// more interpolators are added, one of the internal implementations are |
-/// selected by the type of [a] and [b]. |
-Interpolator createInterpolatorFromRegistry(a, b) { |
- var fn, i = _interpolators.length; |
- while (--i >= 0 && fn == null) { |
- fn = _interpolators[i](a, b); |
- } |
- return fn; |
-} |
- |
-/// Creates an interpolator based on the type of [a] and [b]. |
-/// |
-/// Usage note: Use this method only when type of [a] and [b] are not known. |
-/// When used, this function will prevent tree shaking of all built-in |
-/// interpolators. |
-Interpolator createInterpolatorByType(a, b) => |
- (a is List && b is List) ? createListInterpolator(a, b) : |
- (a is Map && b is Map) ? createMapInterpolator(a, b) : |
- (a is String && b is String) ? createStringInterpolator(a, b) : |
- (a is num && b is num) ? createNumberInterpolator(a, b) : |
- (a is Color && b is Color) ? createRgbColorInterpolator(a, b) : |
- (t) => (t <= 0.5) ? a : b; |
- |
- |
-// |
-// Implementations of InterpolatorGenerator |
-// |
- |
-/// Generate a numeric interpolator between numbers [a] and [b] |
-Interpolator createNumberInterpolator(num a, num b) { |
- b -= a; |
- return (t) => a + b * t; |
-} |
- |
-/// Generate a rounded number interpolator between numbers [a] and [b] |
-Interpolator createRoundedNumberInterpolator(num a, num b) { |
- b -= a; |
- return (t) => (a + b * t).round(); |
-} |
- |
- |
-/// Generate an interpolator between two strings [a] and [b]. |
-/// |
-/// The interpolator will interpolate all the number pairs in both strings |
-/// that have same number of numeric parts. The function assumes the non |
-/// number part of the string to be identical and would use string [b] for |
-/// merging the non numeric part of the strings. |
-/// |
-/// Eg: Interpolate between $100.0 and $150.0 |
-Interpolator createStringInterpolator(String a, String b) { |
- if (a == null || b == null) return (t) => b; |
- |
- // See if both A and B represent colors as RGB or HEX strings. |
- // If yes, use color interpolators |
- if (Color.isRgbColorString(a) && Color.isRgbColorString(b)) { |
- return createRgbColorInterpolator( |
- new Color.fromRgbString(a), new Color.fromRgbString(b)); |
- } |
- |
- // See if both A and B represent colors as HSL strings. |
- // If yes, use color interpolators. |
- if (Color.isHslColorString(a) && Color.isHslColorString(b)) { |
- return createHslColorInterpolator( |
- new Color.fromHslString(a), new Color.fromHslString(b)); |
- } |
- |
- var numberRegEx = |
- new RegExp(r'[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?'), |
- numMatchesInA = numberRegEx.allMatches(a), |
- numMatchesInB = numberRegEx.allMatches(b), |
- stringParts = [], |
- numberPartsInA = [], |
- numberPartsInB = [], |
- interpolators = [], |
- s0 = 0; |
- |
- numberPartsInA.addAll(numMatchesInA.map((m) => m.group(0))); |
- |
- for (Match m in numMatchesInB) { |
- stringParts.add(b.substring(s0, m.start)); |
- numberPartsInB.add(m.group(0)); |
- s0 = m.end; |
- } |
- |
- if (s0 < b.length) stringParts.add(b.substring(s0)); |
- |
- int numberLength = math.min(numberPartsInA.length, numberPartsInB.length); |
- int maxLength = math.max(numberPartsInA.length, numberPartsInB.length); |
- for (var i = 0; i < numberLength; i++) { |
- interpolators.add(createNumberInterpolator(num.parse(numberPartsInA[i]), |
- num.parse(numberPartsInB[i]))); |
- } |
- if (numberPartsInA.length < numberPartsInB.length) { |
- for (var i = numberLength; i < maxLength; i++) { |
- interpolators.add(createNumberInterpolator(num.parse(numberPartsInB[i]), |
- num.parse(numberPartsInB[i]))); |
- } |
- } |
- |
- return (t) { |
- StringBuffer sb = new StringBuffer(); |
- for (var i = 0; i < stringParts.length; i++) { |
- sb.write(stringParts[i]); |
- if (interpolators.length > i) { |
- sb.write(interpolators[i](t)); |
- } |
- } |
- return sb.toString(); |
- }; |
-} |
- |
-/// Generate an interpolator for RGB values. |
-Interpolator createRgbColorInterpolator(Color a, Color b) { |
- if (a == null || b == null) return (t) => b; |
- var ar = a.r, |
- ag = a.g, |
- ab = a.b, |
- br = b.r - ar, |
- bg = b.g - ag, |
- bb = b.b - ab; |
- |
- return (t) => new Color.fromRgba((ar + br * t).round(), |
- (ag + bg * t).round(), (ab + bb * t).round(), 1.0).toRgbaString(); |
-} |
- |
-/// Generate an interpolator using HSL color system converted to Hex string. |
-Interpolator createHslColorInterpolator(Color a, Color b) { |
- if (a == null || b == null) return (t) => b; |
- var ah = a.h, |
- as = a.s, |
- al = a.l, |
- bh = b.h - ah, |
- bs = b.s - as, |
- bl = b.l - al; |
- |
- return (t) => new Color.fromHsla((ah + bh * t).round(), |
- (as + bs * t).round(), (al + bl * t).round(), 1.0).toHslaString(); |
-} |
- |
-/// Generates an interpolator to interpolate each element between lists |
-/// [a] and [b] using registered interpolators. |
-Interpolator createListInterpolator(List a, List b) { |
- if (a == null || b == null) return (t) => b; |
- var x = [], |
- aLength = a.length, |
- numInterpolated = b.length, |
- n0 = math.min(aLength, numInterpolated), |
- output = new List.filled(math.max(aLength, numInterpolated), null), |
- i; |
- |
- for (i = 0; i < n0; i++) x.add(createInterpolatorFromRegistry(a[i], b[i])); |
- for (; i < aLength; ++i) output[i] = a[i]; |
- for (; i < numInterpolated; ++i) output[i] = b[i]; |
- |
- return (t) { |
- for (i = 0; i < n0; ++i) output[i] = x[i](t); |
- return output; |
- }; |
-} |
- |
-/// Generates an interpolator to interpolate each value on [a] to [b] using |
-/// registered interpolators. |
-Interpolator createMapInterpolator(Map a, Map b) { |
- if (a == null || b == null) return (t) => b; |
- var interpolatorsMap = new Map(), |
- output = new Map(), |
- aKeys = a.keys.toList(), |
- bKeys = b.keys.toList(); |
- |
- aKeys.forEach((k) { |
- if (b[k] != null) { |
- interpolatorsMap[k] = (createInterpolatorFromRegistry(a[k], b[k])); |
- } else { |
- output[k] = a[k]; |
- } |
- }); |
- |
- bKeys.forEach((k) { |
- if (output[k] == null) { |
- output[k] = b[k]; |
- } |
- }); |
- |
- return (t) { |
- interpolatorsMap.forEach((k, v) => output[k] = v(t)); |
- return output; |
- }; |
-} |
- |
-/// Returns the interpolator that interpolators two transform strings |
-/// [a] and [b] by their translate, rotate, scale and skewX parts. |
-Interpolator createTransformInterpolator(String a, String b) { |
- if (a == null || b == null) return (t) => b; |
- var numRegExStr = r'[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?', |
- numberRegEx = new RegExp(numRegExStr), |
- translateRegEx = |
- new RegExp(r'translate\(' + '$numRegExStr,$numRegExStr' + r'\)'), |
- scaleRegEx = |
- new RegExp(r'scale\(' + numRegExStr + r',' + numRegExStr + r'\)'), |
- rotateRegEx = new RegExp(r'rotate\(' + numRegExStr + r'(deg)?\)'), |
- skewRegEx = new RegExp(r'skewX\(' + numRegExStr + r'(deg)?\)'), |
- |
- translateA = translateRegEx.firstMatch(a), |
- scaleA = scaleRegEx.firstMatch(a), |
- rotateA = rotateRegEx.firstMatch(a), |
- skewA = skewRegEx.firstMatch(a), |
- |
- translateB = translateRegEx.firstMatch(b), |
- scaleB = scaleRegEx.firstMatch(b), |
- rotateB = rotateRegEx.firstMatch(b), |
- skewB = skewRegEx.firstMatch(b); |
- |
- var numSetA = [], |
- numSetB = [], |
- tempStr, match; |
- |
- // translate |
- if (translateA != null) { |
- tempStr = a.substring(translateA.start, translateA.end); |
- match = numberRegEx.allMatches(tempStr); |
- for (Match m in match) { |
- numSetA.add(num.parse(m.group(0))); |
- } |
- } else { |
- numSetA.addAll(const[0, 0]); |
- } |
- |
- if (translateB != null) { |
- tempStr = b.substring(translateB.start, translateB.end); |
- match = numberRegEx.allMatches(tempStr); |
- for (Match m in match) { |
- numSetB.add(num.parse(m.group(0))); |
- } |
- } else { |
- numSetB.addAll(const[0, 0]); |
- } |
- |
- // scale |
- if (scaleA != null) { |
- tempStr = a.substring(scaleA.start, scaleA.end); |
- match = numberRegEx.allMatches(tempStr); |
- for (Match m in match) { |
- numSetA.add(num.parse(m.group(0))); |
- } |
- } else { |
- numSetA.addAll(const[1, 1]); |
- } |
- |
- if (scaleB != null) { |
- tempStr = b.substring(scaleB.start, scaleB.end); |
- match = numberRegEx.allMatches(tempStr); |
- for (Match m in match) { |
- numSetB.add(num.parse(m.group(0))); |
- } |
- } else { |
- numSetB.addAll(const[1, 1]); |
- } |
- |
- // rotate |
- if (rotateA != null) { |
- tempStr = a.substring(rotateA.start, rotateA.end); |
- match = numberRegEx.firstMatch(tempStr); |
- numSetA.add(num.parse(match.group(0))); |
- } else { |
- numSetA.add(0); |
- } |
- |
- if (rotateB != null) { |
- tempStr = b.substring(rotateB.start, rotateB.end); |
- match = numberRegEx.firstMatch(tempStr); |
- numSetB.add(num.parse(match.group(0))); |
- } else { |
- numSetB.add(0); |
- } |
- |
- // rotate < 180 degree |
- if (numSetA[4] != numSetB[4]) { |
- if (numSetA[4] - numSetB[4] > 180) { |
- numSetB[4] += 360; |
- } else if (numSetB[4] - numSetA[4] > 180) { |
- numSetA[4] += 360; |
- } |
- } |
- |
- // skew |
- if (skewA != null) { |
- tempStr = a.substring(skewA.start, skewA.end); |
- match = numberRegEx.firstMatch(tempStr); |
- numSetA.add(num.parse(match.group(0))); |
- } else { |
- numSetA.add(0); |
- } |
- |
- if (skewB != null) { |
- tempStr = b.substring(skewB.start, skewB.end); |
- match = numberRegEx.firstMatch(tempStr); |
- numSetB.add(num.parse(match.group(0))); |
- } else { |
- numSetB.add(0); |
- } |
- |
- return (t) { |
- return |
- 'translate(${createNumberInterpolator(numSetA[0], numSetB[0])(t)},' |
- '${createNumberInterpolator(numSetA[1], numSetB[1])(t)})' |
- 'scale(${createNumberInterpolator(numSetA[2], numSetB[2])(t)},' |
- '${createNumberInterpolator(numSetA[3], numSetB[3])(t)})' |
- 'rotate(${createNumberInterpolator(numSetA[4], numSetB[4])(t)})' |
- 'skewX(${createNumberInterpolator(numSetA[5], numSetB[5])(t)})'; |
- }; |
-} |
- |
-/// Returns the interpolator that interpolators zoom list [a] to [b]. Zoom |
-/// lists are described by triple elements [ux0, uy0, w0] and [ux1, uy1, w1]. |
-Interpolator createZoomInterpolator(List a, List b) { |
- if (a == null || b == null) return (t) => b; |
- assert(a.length == b.length && a.length == 3); |
- |
- var sqrt2 = math.SQRT2, |
- param2 = 2, |
- param4 = 4; |
- |
- var ux0 = a[0], uy0 = a[1], w0 = a[2], |
- ux1 = b[0], uy1 = b[1], w1 = b[2]; |
- |
- var dx = ux1 - ux0, |
- dy = uy1 - uy0, |
- d2 = dx * dx + dy * dy, |
- d1 = math.sqrt(d2), |
- b0 = (w1 * w1 - w0 * w0 + param4 * d2) / (2 * w0 * param2 * d1), |
- b1 = (w1 * w1 - w0 * w0 - param4 * d2) / (2 * w1 * param2 * d1), |
- r0 = math.log(math.sqrt(b0 * b0 + 1) - b0), |
- r1 = math.log(math.sqrt(b1 * b1 + 1) - b1), |
- dr = r1 - r0, |
- S = ((!dr.isNaN) ? dr : math.log(w1 / w0)) / sqrt2; |
- |
- return (t) { |
- var s = t * S; |
- if (!dr.isNaN) { |
- // General case. |
- var coshr0 = cosh(r0), |
- u = w0 / (param2 * d1) * (coshr0 * tanh(sqrt2 * s + r0) - sinh(r0)); |
- return [ |
- ux0 + u * dx, |
- uy0 + u * dy, |
- w0 * coshr0 / cosh(sqrt2 * s + r0) |
- ]; |
- } |
- // Special case for u0 ~= u1. |
- return [ |
- ux0 + t * dx, |
- uy0 + t * dy, |
- w0 * math.exp(sqrt2 * s) |
- ]; |
- }; |
-} |
- |
-/// Reverse interpolator for a number. |
-Interpolator uninterpolateNumber(num a, num b) { |
- b = 1 / (b - a); |
- return (x) => (x - a) * b; |
-} |
- |
-/// Reverse interpolator for a clamped number. |
-Interpolator uninterpolateClamp(num a, num b) { |
- b = 1 / (b - a); |
- return (x) => math.max(0, math.min(1, (x - a) * b)); |
-} |