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

fix(mvt): wgs84 coordinates for binary mvt (WIP) #2042

Closed
wants to merge 3 commits into from
Closed
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
2 changes: 1 addition & 1 deletion modules/mvt/src/helpers/binary-util-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export function classifyRings(geom: FlatIndexedGeometry): FlatPolygon {
* @param size
*/
export function project(data: number[], x0: number, y0: number, size: number): void {
for (let j = 0, jl = data.length; j < jl; j += 2) {
for (let j = 0; j < data.length; j += 2) {
data[j] = ((data[j] + x0) * 360) / size - 180;
const y2 = 180 - ((data[j + 1] + y0) * 360) / size;
data[j + 1] = (360 / Math.PI) * Math.atan(Math.exp((y2 * Math.PI) / 180)) - 90;
Expand Down
22 changes: 10 additions & 12 deletions modules/mvt/src/lib/binary-vector-tile/vector-tile-feature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const TEST_EXPORTS = {

export default class VectorTileFeature {
properties: {[x: string]: string | number | boolean | null};
extent: any;
extent: number;
type: number;
id: number | null;
_pbf: Protobuf;
Expand All @@ -32,7 +32,7 @@ export default class VectorTileFeature {
constructor(
pbf: Protobuf,
end: number,
extent: any,
extent: number,
keys: string[],
values: (string | number | boolean | null)[],
geometryInfo: GeojsonGeometryInfo
Expand Down Expand Up @@ -107,12 +107,19 @@ export default class VectorTileFeature {
return {data, indices};
}

toBinaryCoordinates(transform: (data: number[], feature: {extent: number}) => void): FlatFeature {
if (typeof transform === 'function') {
return this._toBinaryCoordinates(transform);
}
return this._toBinaryCoordinates(project);
}

/**
*
* @param transform
* @returns result
*/
_toBinaryCoordinates(transform) {
private _toBinaryCoordinates(transform: (data: number[], x0: number, y0: number, size: number) => void) {
// Expands the protobuf data to an intermediate Flat GeoJSON
// data format, which maps closely to the binary data buffers.
// It is similar to GeoJSON, but rather than storing the coordinates
Expand Down Expand Up @@ -182,13 +189,4 @@ export default class VectorTileFeature {

return result;
}

toBinaryCoordinates(
options: {x: number; y: number; z: number} | ((data: number[], feature: {extent: any}) => void)
): FlatFeature {
if (typeof options === 'function') {
return this._toBinaryCoordinates(options);
}
return this._toBinaryCoordinates(project);
}
}
4 changes: 2 additions & 2 deletions modules/mvt/src/lib/parse-mvt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ function getDecodedFeatureBinary(
* @param line
* @param feature
*/
function transformToLocalCoordinates(line: number[], feature: {extent: any}): void {
function transformToLocalCoordinates(line: number[], feature: {extent: number}): void {
// This function transforms local coordinates in a
// [0 - bufferSize, this.extent + bufferSize] range to a
// [0 - (bufferSize / this.extent), 1 + (bufferSize / this.extent)] range.
Expand All @@ -166,7 +166,7 @@ function transformToLocalCoordinates(line: number[], feature: {extent: any}): vo
}
}

function transformToLocalCoordinatesBinary(data: number[], feature: {extent: any}) {
function transformToLocalCoordinatesBinary(data: number[], feature: {extent: number}) {
// For the binary code path, the feature data is just
// one big flat array, so we just divide each value
const {extent} = feature;
Expand Down
1 change: 0 additions & 1 deletion modules/mvt/test/index.js

This file was deleted.

3 changes: 3 additions & 0 deletions modules/mvt/test/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import './mvt-loader.spec';
import './lib/vector-tile-feature.spec';
import './mvt-loader.spec';
48 changes: 48 additions & 0 deletions modules/mvt/test/lib/vector-tile-feature.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/** @typedef {import('@loaders.gl/schema').BinaryFeatures} BinaryFeatures */
import test from 'tape-promise/tape';
import {TEST_EXPORTS} from '@loaders.gl/mvt/lib/binary-vector-tile/vector-tile-feature';

const {classifyRings} = TEST_EXPORTS;

// Rings
import ringsSingleRing from '@loaders.gl/mvt/test/data/rings_single_ring.json';
import ringsRingAndHole from '@loaders.gl/mvt/test/data/rings_ring_and_hole.json';
import ringsTwoRings from '@loaders.gl/mvt/test/data/rings_two_rings.json';
import ringsZeroSizeHole from '@loaders.gl/mvt/test/data/rings_zero_size_hole.json';


test('Rings - single ring', async (t) => {
const geom = {...ringsSingleRing};
const classified = classifyRings(geom);
t.deepEqual(classified.areas, [[-0.02624368667602539]]);
t.deepEqual(classified.indices, [[0]]);
t.end();
});

test('Rings - ring and hole', async (t) => {
const geom = {...ringsRingAndHole};
const classified = classifyRings(geom);
t.deepEqual(classified.areas, [[-0.02624368667602539, 0.001363515853881836]]);
t.deepEqual(classified.indices, [[0, 10]]);
t.end();
});

test('Rings - two rings', async (t) => {
const geom = {...ringsTwoRings};
const classified = classifyRings(geom);
t.deepEqual(classified.areas, [[-0.02624368667602539], [-0.001363515853881836]]);
t.deepEqual(classified.indices, [[0], [10]]);
t.end();
});

test('Rings - zero sized hole', async (t) => {
// In addition to checking the result,
// verify that the data array is shortened
const geom = {...ringsZeroSizeHole};
t.equal(geom.data.length, 20);
const classified = classifyRings(geom);
t.deepEqual(classified.areas, [[-0.44582176208496094]]);
t.deepEqual(classified.indices, [[0]]);
t.equal(classified.data.length, 12);
t.end();
});
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
/** @typedef {import('@loaders.gl/schema').BinaryFeatures} BinaryFeatures */
import type { BinaryFeatures } from '@loaders.gl/schema';
import test from 'tape-promise/tape';
import {MVTLoader} from '@loaders.gl/mvt';
import {setLoaderOptions, fetchFile, parse, parseSync} from '@loaders.gl/core';
import {geojsonToBinary, binaryToGeojson} from '@loaders.gl/gis';
import {TEST_EXPORTS} from '../src/lib/binary-vector-tile/vector-tile-feature';

const {classifyRings} = TEST_EXPORTS;

const MVT_POINTS_DATA_URL = '@loaders.gl/mvt/test/data/points_4-2-6.mvt';
const MVT_LINES_DATA_URL = '@loaders.gl/mvt/test/data/lines_2-2-1.mvt';
Expand All @@ -25,12 +22,6 @@ import decodedPointsGeoJSON from '@loaders.gl/mvt/test/results/decoded_mvt_point
import decodedLinesGeoJSON from '@loaders.gl/mvt/test/results/decoded_mvt_lines.json';
import decodedPolygonsGeoJSON from '@loaders.gl/mvt/test/results/decoded_mvt_polygons.json';

// Rings
import ringsSingleRing from '@loaders.gl/mvt/test/data/rings_single_ring.json';
import ringsRingAndHole from '@loaders.gl/mvt/test/data/rings_ring_and_hole.json';
import ringsTwoRings from '@loaders.gl/mvt/test/data/rings_two_rings.json';
import ringsZeroSizeHole from '@loaders.gl/mvt/test/data/rings_zero_size_hole.json';

setLoaderOptions({
_workerType: 'test'
});
Expand Down Expand Up @@ -228,6 +219,7 @@ const TEST_FILES = [
MVT_POLYGON_ZERO_SIZE_HOLE_DATA_URL,
MVT_MULTIPLE_LAYERS_DATA_URL
];

for (const filename of TEST_FILES) {
test(`geojson-to-binary generation is equivalent ${filename}`, async (t) => {
const response = await fetchFile(filename);
Expand Down Expand Up @@ -300,38 +292,19 @@ test('Triangulation is supported', async (t) => {
t.end();
});

test('Rings - single ring', async (t) => {
const geom = {...ringsSingleRing};
const classified = classifyRings(geom);
t.deepEqual(classified.areas, [[-0.02624368667602539]]);
t.deepEqual(classified.indices, [[0]]);
t.end();
});

test('Rings - ring and hole', async (t) => {
const geom = {...ringsRingAndHole};
const classified = classifyRings(geom);
t.deepEqual(classified.areas, [[-0.02624368667602539, 0.001363515853881836]]);
t.deepEqual(classified.indices, [[0, 10]]);
t.end();
});
test.only('Binary features with coordinates=wgs84', async (t) => {
debugger
const response = await fetchFile(WITH_FEATURE_ID);
const mvtArrayBuffer = await response.arrayBuffer();

test('Rings - two rings', async (t) => {
const geom = {...ringsTwoRings};
const classified = classifyRings(geom);
t.deepEqual(classified.areas, [[-0.02624368667602539], [-0.001363515853881836]]);
t.deepEqual(classified.indices, [[0], [10]]);
t.end();
});
const binary = await parse(mvtArrayBuffer, MVTLoader, {
worker: false,
mvt: {coordinates: 'wgs84'},
gis: {format: 'binary'}
}) as BinaryFeatures;
t.ok(binary.points?.positions.value.every(x => Number.isFinite(x)), 'positions are valid numbers');
t.ok(binary.lines?.positions.value.every(x => Number.isFinite(x)), 'positions are valid numbers');
t.ok(binary.polygons?.positions.value.every(x => Number.isFinite(x)), 'positions are valid numbers');

test('Rings - zero sized hole', async (t) => {
// In addition to checking the result,
// verify that the data array is shortened
const geom = {...ringsZeroSizeHole};
t.equal(geom.data.length, 20);
const classified = classifyRings(geom);
t.deepEqual(classified.areas, [[-0.44582176208496094]]);
t.deepEqual(classified.indices, [[0]]);
t.equal(classified.data.length, 12);
t.end();
});
74 changes: 0 additions & 74 deletions test/modules.js

This file was deleted.

74 changes: 74 additions & 0 deletions test/modules.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Sets up aliases for file reader

/* eslint-disable @typescript-eslint/no-var-requires */

import ALIASES from './aliases.js';
import {_addAliases} from '@loaders.gl/loader-utils';
import {installFilePolyfills} from '@loaders.gl/polyfills';

_addAliases(ALIASES);
// Install polyfills (primarily for Node)
installFilePolyfills();

// base
import '@loaders.gl/polyfills/test/index';
import '@loaders.gl/worker-utils/test/index';
import '@loaders.gl/math/test/index';

// Core
import '@loaders.gl/loader-utils/test/index';
import '@loaders.gl/core/test/index';

// Image Formats
import '@loaders.gl/images/test/index';
import '@loaders.gl/textures/test/index';
// import '@loaders.gl/video/test/index';
// import '@loaders.gl/geotiff/test/index';
// import '@loaders.gl/zarr/test/index';
import '@loaders.gl/netcdf/test/index';

// Pointcloud/Mesh Formats
import '@loaders.gl/draco/test/index';
import '@loaders.gl/las/test/index';
import '@loaders.gl/obj/test/index';
import '@loaders.gl/pcd/test/index';
import '@loaders.gl/ply/test/index';
import '@loaders.gl/terrain/test/index';

// Scenegraph Formats
import '@loaders.gl/gltf/test/index';

// 3D Tile Formats
import '@loaders.gl/3d-tiles/test/index';
import '@loaders.gl/i3s/test/index';
import '@loaders.gl/potree/test/index';
import '@loaders.gl/tiles/test/index';

// Geospatial Formats
import '@loaders.gl/flatgeobuf/test/index';
import '@loaders.gl/geopackage/test/index';
import '@loaders.gl/gis/test/index';
import '@loaders.gl/kml/test/index';
import '@loaders.gl/mvt/test/index';
import '@loaders.gl/shapefile/test/index';
import '@loaders.gl/wkt/test/index';

// Table Formats
import '@loaders.gl/schema/test/index';
import '@loaders.gl/arrow/test/index.js';
import '@loaders.gl/csv/test/index.js';
import '@loaders.gl/json/test/index.js';
import '@loaders.gl/excel/test/index.js';
import '@loaders.gl/parquet/test/index.js';

// Archive Formats
import '@loaders.gl/compression/test/index.js';
// import '@loaders.gl/crypto/test/index.js';
import '@loaders.gl/zip/test/index.js';

// Cli
export const isBrowser =
typeof process !== 'object' || String(process) !== '[object process]' || process.browser;
if (!isBrowser) {
require('@loaders.gl/tile-converter/test');
}