Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(mvt): MVTWriter plumbing (incomplete) #3164

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions modules/mvt/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ export type {TileJSON} from './lib/parse-tilejson';
export {MVTLoader, MVTWorkerLoader} from './mvt-loader';
export type {MVTLoaderOptions} from './mvt-loader';

// MVTWriter

export {MVTWriter} from './mvt-writer';

// MVTSource

export {MVTSource} from './mvt-source';
Expand Down
9 changes: 9 additions & 0 deletions modules/mvt/src/lib/encode-mvt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// loaders.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors

import {fromGeojson} from './mapbox-vt-pbf/to-vector-tile';

export function encodeMVT(data, options) {
return fromGeojson(data, options);
}
76 changes: 76 additions & 0 deletions modules/mvt/src/lib/mapbox-vt-pbf/geojson-to-vt.ts.disabled
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// loaders.gl
// SPDX-License-Identifier: MIT
// Copyright vis.gl contributors

// Forked from https://github.com/mapbox/vt-pbf under MIT License Copyright (c) 2015 Anand Thakker

import VectorTileFeature from "../mapbox-vector-tile-js/vector-tile-feature";

export function geojsonFeatureToVt(feature) {
const tags = null;

const vtFeature = {
type: featureTypeToVt(feature.type),
geometry: geometryToVt(feature.geometry),
tags
};

if (feature.id !== null) {
vtFeature.id = feature.id;
}

return VectorTileFeature;
}

function featureTypeToVt(type) {
switch (type) {
case 'Polygon':
case 'MultiPolygon':
return 3;
case 'LineString':
case 'MultiLineString':
return 2;
default :
return 1;
}
}

function geometryToVt(geometry, type) {
const simplified = [];

// tile.minX = Math.min(tile.minX, feature.minX);
// tile.minY = Math.min(tile.minY, feature.minY);
// tile.maxX = Math.max(tile.maxX, feature.maxX);
// tile.maxY = Math.max(tile.maxY, feature.maxY);

switch (type) {
case 'Point':
case 'MultiPoint':
for (let i = 0; i < geometry.length; i += 3) {
simplified.push(geometry[i], geometry[i + 1]);
tile.numPoints++;
tile.numSimplified++;
}
break;

case 'LineString':
addLine(simplified, geometry, tile, tolerance, false, false);
break;

case 'MultiLineString':
case 'Polygon':
for (let i = 0; i < geometry.length; i++) {
addLine(simplified, geometry[i], tile, tolerance, type === 'Polygon', i === 0);
}
break;

case 'MultiPolygon':
for (let k = 0; k < geometry.length; k++) {
const polygon = geometry[k];
for (let i = 0; i < polygon.length; i++) {
addLine(simplified, polygon[i], tile, tolerance, true, i === 0);
}
}
break;
}
}
89 changes: 89 additions & 0 deletions modules/mvt/src/lib/mapbox-vt-pbf/geojson-wrapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// loaders.gl
// SPDX-License-Identifier: MIT
// Copyright vis.gl contributors

// Forked from https://github.com/mapbox/vt-pbf under MIT License Copyright (c) 2015 Anand Thakker

class Point {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}

// conform to vectortile api
export default class GeoJSONWrapper {
options;
features: any[];
length: number;

constructor(features, options = {}) {
this.options = options;
this.features = features;
this.length = features.length;
}

feature(index) {
return new FeatureWrapper(this.features[index], this.options.extent);
}
}

class FeatureWrapper {
id;
type;
rawGeometry: any;
properties;
extent;
geometry: Point[][] = [];

constructor(feature, extent) {
this.id = typeof feature.id === 'number' ? feature.id : undefined;
this.type = feature.type;
this.rawGeometry = feature.type === 1 ? [feature.geometry] : feature.geometry;
this.properties = feature.tags;
this.extent = extent || 4096;
}

loadGeometry() {
const rings = this.rawGeometry;
this.geometry = [];

for (const ring of rings) {
const newRing: Point[] = [];
for (const coord of ring) {
newRing.push(new Point(coord[0], coord[1]));
}
this.geometry.push(newRing);
}
return this.geometry;
}

bbox() {
if (!this.geometry) {
this.loadGeometry();
}

const rings = this.geometry;
let x1 = Infinity;
let x2 = -Infinity;
let y1 = Infinity;
let y2 = -Infinity;

for (const ring of rings) {
for (const coord of ring) {
x1 = Math.min(x1, coord.x);
x2 = Math.max(x2, coord.x);
y1 = Math.min(y1, coord.y);
y2 = Math.max(y2, coord.y);
}
}

return [x1, y1, x2, y2];
}

// toGeoJSON(x, y, z) {
// return VectorTileFeature.prototype.toGeoJSON.call(this, x, y, z);
// }
}
85 changes: 85 additions & 0 deletions modules/mvt/src/lib/mapbox-vt-pbf/to-vector-tile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// loaders.gl
// SPDX-License-Identifier: MIT
// Copyright vis.gl contributors

// Forked from https://github.com/mapbox/vt-pbf under MIT License Copyright (c) 2015 Anand Thakker

import Pbf from 'pbf';
import type {MVTTile} from '../mvt-pbf/mvt-types';
import {writeMVT} from '../mvt-pbf/write-mvt-to-pbf';
import GeoJSONWrapper from './geojson-wrapper';

/**
* Serialize a map of geojson layers
* loaders.gl addition
*
* @param {object | object[]} geojson
* @param {object} [options] - An object specifying the vector-tile specification version and extent that were used to create `layers`.
* @param {number} [options.extent=4096] - Extent of the vector tile
* @return {ArrayBuffer} uncompressed, pbf-serialized tile data
*/
export function fromGeojson(geojson, options) {
options = options || {};
geojson = normalizeGeojson(geojson);
const layer = new GeoJSONWrapper(geojson.features);

// @ts-expect-error
return fromVectorTileJs({layers: {geojsonLayer: layer}});
}

/**
* Serialize a vector-tile-js-created tile to pbf
*
* @param {object} tile
* @return {ArrayBuffer} uncompressed, pbf-serialized tile data
*/
export function fromVectorTileJs(tile: MVTTile) {
const pbf = new Pbf();
writeMVT(tile, pbf);
const uint8Array = pbf.finish();
// TODO - make sure no byteOffsets/byteLenghts are used?
return uint8Array.buffer.slice(
uint8Array.byteOffset,
uint8Array.byteOffset + uint8Array.byteLength
);
}

/**
* Serialized a geojson-vt-created tile to pbf.
*
* @param {object} vtLayers - An object mapping layer names to geojson-vt-created vector tile objects
* @param {object} [options] - An object specifying the vector-tile specification version and extent that were used to create `layers`.
* @param {number} [options.version=1] - Version of vector-tile spec used
* @param {number} [options.extent=4096] - Extent of the vector tile
* @return {ArrayBuffer} uncompressed, pbf-serialized tile data
*
export function fromGeojsonVt(vtLayers, options) {
options = options || {};
const layers = {};
for (const key in vtLayers) {
layers[key] = new GeoJSONWrapper(vtLayers[key].features, options);
layers[key].name = key;
layers[key].version = options.version;
layers[key].extent = options.extent;
}
return fromVectorTileJs({layers});
}
*/

export function normalizeGeojson(geojson) {
// Array of features
if (Array.isArray(geojson)) {
return {
type: 'FeatureCollection',
features: geojson
};
}
// A single feature
if (geojson.type !== 'FeatureCollection') {
return {
type: 'FeatureCollection',
features: [geojson]
};
}
return geojson;
}
Loading
Loading