Merge pull request #9677 from ahocevar/featureformat-tilepixels

Add support for tile pixel projection in feature formats
This commit is contained in:
Andreas Hocevar
2019-06-15 08:22:28 +02:00
committed by GitHub
3 changed files with 50 additions and 27 deletions
+16 -22
View File
@@ -6,7 +6,7 @@ import VectorTileSource from '../src/ol/source/VectorTile.js';
import {Tile as TileLayer, VectorTile as VectorTileLayer} from '../src/ol/layer.js'; import {Tile as TileLayer, VectorTile as VectorTileLayer} from '../src/ol/layer.js';
import Projection from '../src/ol/proj/Projection.js'; import Projection from '../src/ol/proj/Projection.js';
// Converts geojson-vt data to GeoJSON
const replacer = function(key, value) { const replacer = function(key, value) {
if (value.geometry) { if (value.geometry) {
let type; let type;
@@ -46,11 +46,6 @@ const replacer = function(key, value) {
} }
}; };
const tilePixels = new Projection({
code: 'TILE_PIXELS',
units: 'tile-pixels'
});
const map = new Map({ const map = new Map({
layers: [ layers: [
new TileLayer({ new TileLayer({
@@ -73,23 +68,22 @@ fetch(url).then(function(response) {
debug: 1 debug: 1
}); });
const vectorSource = new VectorTileSource({ const vectorSource = new VectorTileSource({
format: new GeoJSON(), format: new GeoJSON({
tileLoadFunction: function(tile) { // Data returned from geojson-vt is in tile pixel units
const format = tile.getFormat(); dataProjection: new Projection({
const tileCoord = tile.getTileCoord(); code: 'TILE_PIXELS',
units: 'tile-pixels',
extent: [0, 0, 4096, 4096]
})
}),
tileUrlFunction: function(tileCoord) {
const data = tileIndex.getTile(tileCoord[0], tileCoord[1], tileCoord[2]); const data = tileIndex.getTile(tileCoord[0], tileCoord[1], tileCoord[2]);
const geojson = JSON.stringify({
const features = format.readFeatures( type: 'FeatureCollection',
JSON.stringify({ features: data ? data.features : []
type: 'FeatureCollection', }, replacer);
features: data ? data.features : [] return 'data:application/json;charset=UTF-8,' + geojson;
}, replacer)); }
tile.setLoader(function() {
tile.setFeatures(features);
tile.setProjection(tilePixels);
});
},
url: 'data:' // arbitrary url, we don't use it in the tileLoadFunction
}); });
const vectorLayer = new VectorTileLayer({ const vectorLayer = new VectorTileLayer({
source: vectorSource source: vectorSource
+11 -4
View File
@@ -13,8 +13,10 @@ import {get as getProjection, equivalent as equivalentProjection, transformExten
* the `dataProjection` of the format is assigned (where set). If the projection * the `dataProjection` of the format is assigned (where set). If the projection
* can not be derived from the data and if no `dataProjection` is set for a format, * can not be derived from the data and if no `dataProjection` is set for a format,
* the features will not be reprojected. * the features will not be reprojected.
* @property {import("../extent.js").Extent} [extent] Tile extent of the tile being read. This is only used and * @property {import("../extent.js").Extent} [extent] Tile extent in map units of the tile being read.
* required for {@link module:ol/format/MVT}. * This is only required when reading data with tile pixels as geometry units. When configured,
* a `dataProjection` with `TILE_PIXELS` as `units` and the tile's pixel extent as `extent` needs to be
* provided.
* @property {import("../proj.js").ProjectionLike} [featureProjection] Projection of the feature geometries * @property {import("../proj.js").ProjectionLike} [featureProjection] Projection of the feature geometries
* created by the format reader. If not provided, features will be returned in the * created by the format reader. If not provided, features will be returned in the
* `dataProjection`. * `dataProjection`.
@@ -86,9 +88,14 @@ class FeatureFormat {
getReadOptions(source, opt_options) { getReadOptions(source, opt_options) {
let options; let options;
if (opt_options) { if (opt_options) {
let dataProjection = opt_options.dataProjection ?
opt_options.dataProjection : this.readProjection(source);
if (opt_options.extent) {
dataProjection = getProjection(dataProjection);
dataProjection.setWorldExtent(opt_options.extent);
}
options = { options = {
dataProjection: opt_options.dataProjection ? dataProjection: dataProjection,
opt_options.dataProjection : this.readProjection(source),
featureProjection: opt_options.featureProjection featureProjection: opt_options.featureProjection
}; };
} }
+23 -1
View File
@@ -8,7 +8,7 @@ import LinearRing from '../../../../src/ol/geom/LinearRing.js';
import MultiPolygon from '../../../../src/ol/geom/MultiPolygon.js'; import MultiPolygon from '../../../../src/ol/geom/MultiPolygon.js';
import Point from '../../../../src/ol/geom/Point.js'; import Point from '../../../../src/ol/geom/Point.js';
import Polygon from '../../../../src/ol/geom/Polygon.js'; import Polygon from '../../../../src/ol/geom/Polygon.js';
import {fromLonLat, get as getProjection, toLonLat, transform} from '../../../../src/ol/proj.js'; import {fromLonLat, get as getProjection, toLonLat, transform, Projection} from '../../../../src/ol/proj.js';
describe('ol.format.GeoJSON', function() { describe('ol.format.GeoJSON', function() {
@@ -260,6 +260,28 @@ describe('ol.format.GeoJSON', function() {
expect(feature.getGeometry()).to.be.an(Point); expect(feature.getGeometry()).to.be.an(Point);
}); });
it('transforms tile pixel coordinates', function() {
const geojson = {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [1024, 1024]
}
};
const format = new GeoJSON({
dataProjection: new Projection({
code: '',
units: 'tile-pixels',
extent: [0, 0, 4096, 4096]
})
});
const feature = format.readFeature(geojson, {
extent: [-180, -90, 180, 90],
featureProjection: 'EPSG:3857'
});
expect(feature.getGeometry().getCoordinates()).to.eql([-135, 45]);
});
}); });
describe('#readFeatures', function() { describe('#readFeatures', function() {