examples/layer-browser/src/utils/grid-aggregator.js (39 lines of code) (raw):

const R_EARTH = 6378000; /** * Aggregate points for the grid layer * @param {array} points * @param {number} cellSize - cell size in meters * @returns {object} - grid data and cell dimension */ export function pointsToWorldGrid(points, cellSize) { // find the geometric center of sample points const allLat = points.map(p => p.COORDINATES[1]); const latMin = Math.min.apply(null, allLat); const latMax = Math.max.apply(null, allLat); const centerLat = (latMin + latMax) / 2; const gridOffset = _calculateGridLatLonOffset(cellSize, centerLat); // calculate count per cell const gridHash = points.reduce((accu, pt) => { const latIdx = Math.floor((pt.COORDINATES[1] + 90) / gridOffset.latOffset); const lonIdx = Math.floor((pt.COORDINATES[0] + 180) / gridOffset.lonOffset); const key = `${latIdx}-${lonIdx}`; accu[key] = accu[key] + 1 || 1; return accu; }, {}); const maxHeight = Math.max.apply(null, Object.keys(gridHash).map(k => gridHash[k])); const data = Object.keys(gridHash).reduce((accu, key) => { const idxs = key.split('-'); const latIdx = parseInt(idxs[0], 10); const lonIdx = parseInt(idxs[1], 10); accu.push({ position: [-180 + gridOffset.lonOffset * lonIdx, -90 + gridOffset.latOffset * latIdx], value: gridHash[key] / maxHeight }); return accu; }, []); return Object.assign({data}, {cellSize}); } /** * calculate grid layer cell size in lat lon based on world unit size * and current latitude * @param {number} cellSize * @param {number} latitude * @returns {object} - lat delta and lon delta */ export function _calculateGridLatLonOffset(cellSize, latitude) { const latOffset = calculateLatOffset(cellSize); const lonOffset = calculateLonOffset(latitude, cellSize); return {latOffset, lonOffset}; } /** * with a given x-km change, calculate the increment of latitude * based on stackoverflow http://stackoverflow.com/questions/7477003 * @param {number} dy - change in km * @return {number} - increment in latitude */ export function calculateLatOffset(dy) { return (dy / R_EARTH) * (180 / Math.PI); } /** * with a given x-km change, and current latitude * calculate the increment of longitude * based on stackoverflow http://stackoverflow.com/questions/7477003 * @param {number} lat - latitude of current location (based on city) * @param {number} dx - change in km * @return {number} - increment in longitude */ export function calculateLonOffset(lat, dx) { return ((dx / R_EARTH) * (180 / Math.PI)) / Math.cos((lat * Math.PI) / 180); }