OLD | NEW |
(Empty) | |
| 1 /* |
| 2 Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 Use of this source code is governed by a BSD-style license that can be |
| 4 found in the LICENSE file. |
| 5 */ |
| 6 |
| 7 /** |
| 8 * @fileoverview Collection of functions which operate on graph data. |
| 9 */ |
| 10 |
| 11 var graphUtils = window['graphUtils'] || {}; |
| 12 |
| 13 /** |
| 14 * Interpolate given multiple lines of graphs, and returns the lines of |
| 15 * the graphs where each line has the same number of points and x coordinates. |
| 16 * |
| 17 * For example, |
| 18 * <pre> |
| 19 * [[[0, 1], [2, 3]], // 1st line |
| 20 * [[1, 3]]] // 2nd line |
| 21 * </pre> |
| 22 * will be converted to |
| 23 * <pre> |
| 24 * [[[0, 1], [1, 2], [2, 3]], // [1, 2] is interpolated. |
| 25 * [[0, 0], [1, 3], [2, 0]]] // [0, 0] and [2, 0] are interpolated. |
| 26 * </pre> |
| 27 * where every line has points at x=0, 1 and 2. |
| 28 * Interpolated data points are marked with a property |
| 29 * {@code point.interpolated == true}. |
| 30 * |
| 31 * @param {Array.<Array.<Array.<number>>>} plotData List of arrays that |
| 32 * represent individual lines. The line itself is an Array of points. |
| 33 * @return {Array.<Array.<Array.<number>>>} An interpolated {@code plotData}. |
| 34 * The original {@code plotData} is not affected. |
| 35 */ |
| 36 graphUtils.interpolate = function(plotData) { |
| 37 var interpolated = []; // resulting interpolated {@code plotData} |
| 38 var unconsumed = []; // indices to unconsumed points in {@code plotData} |
| 39 for (var i = 0; i < plotData.length; ++i) { |
| 40 interpolated.push([]); |
| 41 unconsumed.push(0); |
| 42 } |
| 43 |
| 44 // Returns the next x-coordinate to interpolate if any, or null. |
| 45 function nextX() { |
| 46 var index = null; |
| 47 for (var i = 0; i < unconsumed.length; ++i) { |
| 48 if (0 <= unconsumed[i] && unconsumed[i] < plotData[i].length && |
| 49 (index == null || |
| 50 plotData[i][unconsumed[i]][0] < |
| 51 plotData[index][unconsumed[index]][0])) { |
| 52 index = i; |
| 53 } |
| 54 } |
| 55 return index == null ? null : plotData[index][unconsumed[index]][0]; |
| 56 } |
| 57 |
| 58 for (var x = nextX(); x != null; x = nextX()) { // for all x |
| 59 for (var i = 0; i < plotData.length; ++i) { // for all lines |
| 60 var y = 0; |
| 61 var hasPoint = false; |
| 62 if (0 <= unconsumed[i] && unconsumed[i] < plotData[i].length) { |
| 63 var p = plotData[i][unconsumed[i]]; |
| 64 if (p[0] <= x) { |
| 65 y = p[1]; // The original line has a point at x. |
| 66 hasPoint = true; |
| 67 } else if (unconsumed[i] == 0) { |
| 68 y = 0; // y = 0 before the first point |
| 69 } else { |
| 70 // Interpolate a point. |
| 71 var p0 = plotData[i][unconsumed[i] - 1]; |
| 72 y = (x - p0[0]) / (p[0] - p0[0]) * (p[1] - p0[1]) + p0[1]; |
| 73 } |
| 74 } // else y = 0 because it's out of range. |
| 75 |
| 76 var point = [x, y]; |
| 77 if (!hasPoint) { |
| 78 point.interpolated = true; |
| 79 } |
| 80 interpolated[i].push(point); |
| 81 } |
| 82 |
| 83 // Consume {@code plotData} by incrementing indices in {@code unconsumed}. |
| 84 for (var i = 0; i < unconsumed.length; ++i) { |
| 85 if (0 <= unconsumed[i] && unconsumed[i] < plotData[i].length && |
| 86 plotData[i][unconsumed[i]][0] <= x) { |
| 87 ++unconsumed[i]; |
| 88 } |
| 89 } |
| 90 } |
| 91 |
| 92 return interpolated; |
| 93 }; |
| 94 |
| 95 /** |
| 96 * Creates and returns a set of stacked graphs, assuming the given |
| 97 * {@code plotData} is interpolated by {@code graphUtils.interpolate}. |
| 98 * |
| 99 * For example, |
| 100 * <pre> |
| 101 * [[[0, 1], [1, 2]], // 1st line |
| 102 * [[0, 1], [1, 3]], // 2nd line |
| 103 * [[0, 2], [1, 1]]] // 3rd line |
| 104 * </pre> |
| 105 * will be converted to |
| 106 * <pre> |
| 107 * [[[0, 1], [1, 2]], // 1st |
| 108 * [[0, 2], [1, 5]], // 1st + 2nd |
| 109 * [[0, 4], [1, 6]]] // 1st + 2nd + 3rd |
| 110 * </pre> |
| 111 * |
| 112 * @param {Array.<Array.<Array.<number>>>} plotData List of arrays that |
| 113 * represent individual lines. The line itself is an Array of points. |
| 114 * @return {Array.<Array.<Array.<number>>>} A stacked {@code plotData}. |
| 115 * The original {@code plotData} is not affected. |
| 116 */ |
| 117 graphUtils.stackFrontToBack = function(plotData) { |
| 118 if (!(plotData && plotData[0] && plotData[0].length > 0)) { |
| 119 return []; |
| 120 } |
| 121 |
| 122 var stacked = []; |
| 123 for (var i = 0; i < plotData.length; ++i) { |
| 124 stacked.push([]); |
| 125 } |
| 126 |
| 127 for (var j = 0; j < plotData[0].length; ++j) { |
| 128 for (var i = 0; i < plotData.length; ++i) { |
| 129 var point = [ |
| 130 plotData[i][j][0], |
| 131 plotData[i][j][1] + |
| 132 (i == 0 ? 0 : stacked[i - 1][j][1])]; |
| 133 if (plotData[i][j].interpolated) { |
| 134 point.interpolated = true; |
| 135 } |
| 136 stacked[i].push(point); |
| 137 } |
| 138 } |
| 139 |
| 140 return stacked; |
| 141 }; |
OLD | NEW |