blob: 83f615ecd35d317d41149a1d0c07617e3caa5a34 [file] [log] [blame]
/**
* @fileoverview Data manipulation utility functions.
*
* @license Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var geovelo;
geovelo = geovelo || {};
geovelo.data = {
/**
* Given an array, treat falsey values as missing data and replace them
* in-line by linearly interpolating between the previous and next valid
* values. E.g. the array [1,0,3] becomes [1,2,3]
*
* @param {!Array} arry An array of numbers and possibly other falsey values.
* @return {!Array} The same array that was passed in.
*/
interpolateGaps: function(arry) {
var len = arry.length;
var i = 0;
// Scan forward looking for the first non-missing (truthy) value.
while (i < len - 1 && !arry[i]) {
i++;
}
// We can only hope to interpolate if there are at least two more elements
// in the array from where we are now.
while (i < len - 2) {
// Scan forward looking for a gap (falsey value).
while (i < len && arry[i]) {
i++;
}
// Short-circuit if there aren't enough elements left to interpolate.
if (i >= len - 1) {
return arry;
}
// At this point, i points to a missing value, so our left inde should be
// one less.
var x1 = i - 1;
// Next, scan forward looking for an end to the gap.
i++;
while (i < len && !arry[i]) {
i++;
}
// Short-circuit if we fell off the array.
if (i > len - 1 || !arry[i]) {
return arry;
}
// Fill in the missing values with interpolated ones.
var x2 = i;
var y1 = arry[x1];
var y2 = arry[x2];
var m = (y2 - y1) / (x2 - x1);
for (var j = x1 + 1; j < x2; j++) {
arry[j] = y1 + m * (j - x1);
}
// Continue where we left off.
}
return arry;
},
/**
* A beacon object has a 'lat' and a 'lon' property, both point to arrays of
* numbers. Given an array of beacon objects, use interpolateGaps to fill in
* any missing latitude and longitude values.
*
* @param {!Array} beacons An array of beacon data objects.
* @return {!Array} The same array that was passed in.
*/
fillBeaconGaps: function(beacons) {
for (var i = 0, ii = beacons.length; i < ii; i++) {
geovelo.data.interpolateGaps(beacons[i].lat);
geovelo.data.interpolateGaps(beacons[i].lon);
}
}
};