UNPKG

s2-tools

Version:

A collection of geospatial tools primarily designed for WGS84, Web Mercator, and S2.

146 lines 6.54 kB
import { MetadataBuilder } from 's2-tilejson'; import VectorTileWorker from './worker/tileWorker'; /** * Build vector tiles give a guide on what sources to parse data from and how to store it * @param buildGuide - the user defined guide on building the vector tiles */ export async function toVectorTiles(buildGuide) { const { tileWriter, scheme } = buildGuide; const vectorWorker = new VectorTileWorker(); // STEP 1: Convert all features to tile slices of said features. await toVectorTilesSliceFeatures(buildGuide, vectorWorker); // STEP 2: Ensure all data is prepped/sorted for reading/building tiles await vectorWorker.sort(); // STEP 3: collect all existing multimap feature stores and build tiles for await (const { face, zoom, x, y, data } of vectorWorker.buildTiles()) { if (scheme === 'fzxy') await tileWriter.writeTileS2(face, zoom, x, y, data); else await tileWriter.writeTileWM(zoom, x, y, data); } // STEP 4: build metadata based on the guide const metaBuilder = new MetadataBuilder(); updateBuilder(metaBuilder, buildGuide); const metadata = metaBuilder.commit(); // STEP 5: Commit the metadata await tileWriter.commit(metadata); } /** * STEP 1: Convert all features to tile slices of said features. * @param buildGuide - the user defined guide on building the vector tiles * @param vectorWorker - the vector tile worker to use */ async function toVectorTilesSliceFeatures(buildGuide, vectorWorker) { const { vectorSources, rasterSources, layerGuides, scheme, encoding } = buildGuide; const featuresIterator = getFeature(vectorSources, rasterSources); // Prepare workers with init messages const stringifiedLayerGuides = prepareLayerGuides(layerGuides); const initMessage = { type: 'init', id: 0, scheme, encoding, layerGuides: stringifiedLayerGuides, }; vectorWorker.handleMessage(initMessage); for await (const nextFeature of featuresIterator) { const { sourceName, feature } = nextFeature; const featureMessage = { type: 'feature', sourceName, feature }; vectorWorker.handleMessage(featureMessage); } } /** * Prepare the layer guides for workers to be stringified * @param layerGuides - the user defined guide on building the vector tiles * @returns the stringified layer guides */ function prepareLayerGuides(layerGuides) { return layerGuides.map((layer) => { return { ...layer, onFeature: layer.onFeature !== undefined ? JSON.stringify(layer.onFeature) : undefined, }; }); } /** * Get the features that will be stored in the tile * @param vectorSources - the vector sources that the tile is built from and how the layers are to be stored. * @param rasterSources - the raster sources that will be conjoined into a single rgba pixel index for tile extraction * @yields - a features */ async function* getFeature(vectorSources, rasterSources) { if (vectorSources !== undefined) { for (const [sourceName, source] of Object.entries(vectorSources)) { for await (const feature of source) yield { sourceName, feature }; } } if (rasterSources !== undefined) { for (const [sourceName, source] of Object.entries(rasterSources)) { for await (const feature of source) yield { sourceName, feature }; } } } /** * @param metaBuilder - the metadata builder to update * @param buildGuide - the user defined guide on building the vector tiles */ function updateBuilder(metaBuilder, buildGuide) { const { name, description, version, scheme, encoding, attribution, layerGuides } = buildGuide; metaBuilder.setName(name); metaBuilder.setExtension('pbf'); metaBuilder.setDescription(description ?? 'Built by S2-Tools'); metaBuilder.setVersion(version ?? '1.0.0'); metaBuilder.setScheme(scheme ?? 'fzxy'); // 'fzxy' | 'tfzxy' | 'xyz' | 'txyz' | 'tms' metaBuilder.setType('vector'); metaBuilder.setEncoding(encoding ?? 'gz'); // 'gz' | 'br' | 'none' if (attribution !== undefined) { for (const [displayName, href] of Object.entries(attribution)) { metaBuilder.addAttribution(displayName, href); } } for (const layer of layerGuides) metaBuilder.addLayer(layer.sourceName, layer.metadata); } /** * TODO: Find all cases where prepping the data could be done wrong by the user with * TODO: explinations of how to correct them. * TODO: - metadata must be correct. - * Check and display errors * @param _layerGuides - the user defined guide on building the vector tiles */ function _findErrors(_layerGuides) { // for (const layerGuide of layerGuides) { // // const { metadata } = layerGuide; // } } // TODO: tileGuide should be modifed to match metadata minzoom, maxzoom, and projection // minzoom and maxzoom can be left alone if they already exist, but projection MUST match the // output projection. // TODO: // VECTOR: // - step 1: ship individual features to workers // - - step 1a: splite the features into tiles, requesting all tiles from range min->max of the layer // - - step 1b: store all those features into a multimap where the key is the tile-id and the value is the features // - step 2: build tiles from each worker // - - step 2a: given a tile-id, retrieve the features from the multimap // - - step 2b: build the tile from the features, gzip, etc. then ship the buffer and metadata to main thread // - - step 2c: store metadata into metaBuilder and the buffer into the store // finish // // CLUSTER: // - step 1: for each point, just add. // - step 2: cluster. // - step 3: request tiles as needed. // // RASTER: // - step 1: for every pixel, store to a point index where the m-value is the rgba value // - step 2: build tiles from the point index // - - step 2a: start at max zoom - for each pixel in the tile search the range and find average // of all the points in that range (remember color is logarithmic so multiply each pixel r-g-b-a by itself first) // If too far zoomed in, find the closest pixel within a resonable radius. // - - step 2b: after finishing max zoom, use https://github.com/rgba-image/lanczos as I move towards minzoom. // - - sidenote: I think the easiest way to build tiles is start at 0 zoom and dive down everytime we find at least one point, then move back up // finish //# sourceMappingURL=index.js.map