UNPKG

kepler.gl

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

163 lines (150 loc) 5.29 kB
// Copyright (c) 2018 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. import {OVERLAY_TYPE} from './base-layer'; /** * This function will convert layers to mapbox layers * @param layers the layers to be converted * @param layerData extra layer information * @param layerOrder the order by which we should convert layers * @returns {*} */ export function generateMapboxLayers(layers = [], layerData = [], layerOrder = []) { if (layerData.length > 0) { return layerOrder.slice() .reverse() .reduce((overlays, idx) => { const layer = layers[idx]; return layer.overlayType !== OVERLAY_TYPE.mapboxgl ? overlays : [ ...overlays, { id: layer.id, data: layerData[idx].data, config: layerData[idx].config, datasetId: layer.config.dataId } ] }, []); } return []; }; /** * Update mapbox layers on the given map * @param map * @param newLayers Array of new mapbox layers to be displayed * @param oldLayers Map of the old layers to be compare with the current ones to detect deleted layers * {layerId: datasetId} * @param mapLayers carries information about split map view */ export function updateMapboxLayers(map, newLayers = [], oldLayers = null, mapLayers = null, opt = {force: true}) { // delete non existing layers if (oldLayers) { const oldLayersKeys = Object.keys(oldLayers); if (newLayers.length === 0 && oldLayersKeys.length > 0) { oldLayersKeys.forEach(layerId => map.removeLayer(layerId)); } else { // remove layers const currentLayersIds = newLayers.reduce((final, layer) => ({ ...final, [layer.id]: true }), {}); const layersToDelete = oldLayersKeys.reduce((final, layerId) => { // if layer doesn't exists anymore if (!currentLayersIds[layerId]) { return { ...final, [layerId]: oldLayers[layerId] }; } return final; }, []); Object.keys(layersToDelete).forEach(layerId => map.removeLayer(layerId)); } } // insert or update newlayer newLayers.forEach(overlay => { const {id: layerId, config, data, datasetId} = overlay; if (!data && !config) { return; } const isAvailableAndVisible = !(mapLayers && mapLayers[layerId]) || mapLayers[layerId].isVisible; // checking if source already exists if (data && isAvailableAndVisible) { const source = map.getSource(datasetId); if (!source) { map.addSource(datasetId, { type: 'geojson', data }); } else { source.setData(data); } } const oldConfig = oldLayers[layerId]; const mapboxLayer = map.getLayer(layerId); // compare with previous configs if (!oldConfig || oldConfig !== config || !mapboxLayer || opt.force) { // check if layer already is set // remove it if exists if (mapboxLayer) { map.removeLayer(layerId); } // add if visible and available if (isAvailableAndVisible) { map.addLayer(config); } } }); // TODO: think about removing sources }; /** * * @param points * @param columns { * lat: {fieldIdx}, * lng: {fieldIdx}, * alt: {fieldIdx} * } * @param properties [{label: {fieldIdx}] * @returns {{type: string, properties: {}, features: {type: string, properties: {}, geometry: {type: string, coordinates: *[]}}[]}} */ export function geojsonFromPoints(allData = [], filteredIndex = [], columns = {}, properties = []) { return { type: 'FeatureCollection', features: filteredIndex.map(index => allData[index]).map(point => ({ type: 'Feature', properties: properties.reduce((final, property) => ({ ...final, [property.name]: point[property.tableFieldIndex - 1] }), {}), geometry: { type: 'Point', coordinates: [ columns.lng ? point[columns.lng.fieldIdx] : null, // lng columns.lat ? point[columns.lat.fieldIdx] : null, // lat columns.altitude ? point[columns.altitude.fieldIdx] : 0 // altitude ] } })) }; }