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

Refactor Source interface to allow/prepare for extensibility #2648

Closed
wants to merge 7 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
64 changes: 64 additions & 0 deletions debug/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,70 @@
}
}, 'country-label-lg');

// Add a new source from our GeoJSON data and set the
// 'cluster' option to true.
map.addSource("earthquakes", {
type: "geojson-clustered",
// Point to GeoJSON data. This example visualizes all M1.0+ earthquakes
// from 12/22/15 to 1/21/16 as logged by USGS' Earthquake hazards program.
data: "https://www.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson",
cluster: true,
clusterMaxZoom: 14, // Max zoom to cluster points on
clusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50)
});

// Use the earthquakes source to create five layers:
// One for non-clustered markers, three for each cluster category,
// and one for cluster labels.
map.addLayer({
"id": "non-cluster-markers",
"type": "symbol",
"source": "earthquakes",
"layout": {
"icon-image": "marker-15"
}
});

// Display the earthquake data in three layers, each filtered to a range of
// count values. Each range gets a different fill color.
var layers = [
[150, '#f28cb1'],
[20, '#f1f075'],
[0, '#51bbd6']
];

layers.forEach(function (layer, i) {
map.addLayer({
"id": "cluster-" + i,
"type": "circle",
"source": "earthquakes",
"paint": {
"circle-color": layer[1],
"circle-radius": 18
},
"filter": i === 0 ?
[">=", "point_count", layer[0]] :
["all",
[">=", "point_count", layer[0]],
["<", "point_count", layers[i - 1][0]]]
});
});

// Add a layer for the clusters' count labels
map.addLayer({
"id": "cluster-count",
"type": "symbol",
"source": "earthquakes",
"layout": {
"text-field": "{point_count}",
"text-font": [
"DIN Offc Pro Medium",
"Arial Unicode MS Bold"
],
"text-size": 12
}
});

var bufferTimes = {};
map.on('tile.stats', function(bufferTimes) {
var _stats = [];
Expand Down
49 changes: 19 additions & 30 deletions debug/featuresIn.html → debug/queryFeatures.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,17 @@
var map = new mapboxgl.Map({
container: 'map',
zoom: 12.5,
center: [38.888, -77.01866],
center: [-77.01866, 38.888],
hash: true,
style: 'mapbox://styles/mapbox/streets-v8'
});

map.addControl(new mapboxgl.Navigation());

var querySource = new mapboxgl.GeoJSONSource({
data: { type: 'FeatureCollection', features: [] }
});
var boxSource = new mapboxgl.GeoJSONSource({
data: { type: 'FeatureCollection', features: [] }
});
var emptyFc = { type: 'FeatureCollection', features: [] }

map.on('style.load', function() {
map.addSource('queried', querySource);
map.addSource('queried', { type: 'geojson', data: emptyFc });
map.addLayer({
"id": "query",
"type": "line",
Expand All @@ -47,7 +42,7 @@
}
}, 'country-label-sm');

map.addSource('boxsource', boxSource);
map.addSource('boxsource', { type: 'geojson', data: emptyFc });
map.addLayer({
"id": "box",
"type": "fill",
Expand Down Expand Up @@ -81,28 +76,22 @@
[boxcoords[1][0], boxcoords[0][1]],
boxcoords[0]
];
var results = map.queryRenderedFeatures(box, {})
map.getSource('queried').setData({
type: 'FeatureCollection',
features: results
});

console.log('box', boxcoords);
map.queryRenderedFeatures(box, {
includeGeometry: true
}, function (err, results) {
console.log('queryRenderedFeatures', box, err, results);
querySource.setData({
type: 'FeatureCollection',
features: results
});

boxSource.setData({
type: 'FeatureCollection',
features: [{
type: 'Feature',
properties: {},
geometry: {
type: 'LineString',
coordinates: boxcoords
}
}]
});
map.getSource('boxsource').setData({
type: 'FeatureCollection',
features: [{
type: 'Feature',
properties: {},
geometry: {
type: 'LineString',
coordinates: boxcoords
}
}]
});
}
});
Expand Down
47 changes: 47 additions & 0 deletions js/geo/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,53 @@ Transform.prototype = {
this._constrain();
},

/**
* Return a zoom level that will cover all tiles the transform
* @param {Object} options
* @param {number} options.tileSize
* @param {boolean} options.roundZoom
* @returns {number} zoom level
* @private
*/
coveringZoomLevel: function(options) {
return (options.roundZoom ? Math.round : Math.floor)(
this.zoom + this.scaleZoom(this.tileSize / options.tileSize)
);
},

/**
* Return all coordinates that could cover this transform for a covering
* zoom level.
* @param {Object} options
* @param {number} options.tileSize
* @param {number} options.minzoom
* @param {number} options.maxzoom
* @param {boolean} options.roundZoom
* @param {boolean} options.reparseOverscaled
* @returns {Array<Tile>} tiles
* @private
*/
coveringTiles: function(options) {
var z = this.coveringZoomLevel(options);
var actualZ = z;

if (z < options.minzoom) return [];
if (z > options.maxzoom) z = options.maxzoom;

var tr = this,
tileCenter = tr.locationCoordinate(tr.center)._zoomTo(z),
centerPoint = new Point(tileCenter.column - 0.5, tileCenter.row - 0.5);

return TileCoord.cover(z, [
tr.pointCoordinate(new Point(0, 0))._zoomTo(z),
tr.pointCoordinate(new Point(tr.width, 0))._zoomTo(z),
tr.pointCoordinate(new Point(tr.width, tr.height))._zoomTo(z),
tr.pointCoordinate(new Point(0, tr.height))._zoomTo(z)
], options.reparseOverscaled ? actualZ : z).sort(function(a, b) {
return centerPoint.dist(a) - centerPoint.dist(b);
});
},

resize: function(width, height) {
this.width = width;
this.height = height;
Expand Down
7 changes: 3 additions & 4 deletions js/render/draw_background.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
'use strict';

var TilePyramid = require('../source/tile_pyramid');
var pyramid = new TilePyramid({ tileSize: 512 });
var util = require('../util/util');
var pixelsToTileUnits = require('../source/pixels_to_tile_units');
var createUniformPragmas = require('./create_uniform_pragmas');

var tileSize = 512;

module.exports = drawBackground;

function drawBackground(painter, source, layer) {
Expand Down Expand Up @@ -62,10 +62,9 @@ function drawBackground(painter, source, layer) {
// the depth and stencil buffers get into a bad state.
// This can be refactored into a single draw call once earcut lands and
// we don't have so much going on in the stencil buffer.
var coords = pyramid.coveringTiles(transform);
var coords = transform.coveringTiles({ tileSize: tileSize });
for (var c = 0; c < coords.length; c++) {
var coord = coords[c];
var tileSize = 512;
// var pixelsToTileUnitsBound = pixelsToTileUnits.bind({coord:coord, tileSize: tileSize});
if (imagePosA && imagePosB) {
var tile = {coord:coord, tileSize: tileSize};
Expand Down
4 changes: 2 additions & 2 deletions js/render/draw_raster.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function drawRasterTile(painter, source, layer, coord) {
gl.uniform1f(program.u_contrast_factor, contrastFactor(layer.paint['raster-contrast']));
gl.uniform3fv(program.u_spin_weights, spinWeights(layer.paint['raster-hue-rotate']));

var parentTile = tile.source && tile.source._pyramid.findLoadedParent(coord, 0, {}),
var parentTile = tile.source && tile.source.findLoadedParent(coord, 0, {}),
opacities = getOpacities(tile, parentTile, layer, painter.transform);

var parentScaleBy, parentTL;
Expand Down Expand Up @@ -122,7 +122,7 @@ function getOpacities(tile, parentTile, layer, transform) {
var sinceTile = (now - tile.timeAdded) / fadeDuration;
var sinceParent = parentTile ? (now - parentTile.timeAdded) / fadeDuration : -1;

var idealZ = tile.source._pyramid.coveringZoomLevel(transform);
var idealZ = transform.coveringZoomLevel(tile.source);
var parentFurther = parentTile ? Math.abs(parentTile.coord.z - idealZ) > Math.abs(tile.coord.z - idealZ) : false;

if (!parentTile || parentFurther) {
Expand Down
10 changes: 10 additions & 0 deletions js/source/clustered_geojson_source.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict';

var GeoJSONSource = require('./geojson_source');
var webworkify = require('webworkify');

module.exports.create = GeoJSONSource.create;
module.exports.workerSourceURL = URL.createObjectURL(
webworkify(require('./clustered_geojson_worker_source'), {bare: true})
);

23 changes: 23 additions & 0 deletions js/source/clustered_geojson_worker_source.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use strict';

var supercluster = require('supercluster');
var GeoJSONWorkerSource = require('./geojson_worker_base');

var workerSource = Object.create(GeoJSONWorkerSource);
workerSource.indexData = function (data, params, callback) {
var superclusterOptions = {
maxZoom: params.maxZoom,
extent: params.extent,
radius: (params.clusterRadius || 50) * params.scale,
log: false
};
try {
return callback(null, supercluster(superclusterOptions).load(data.features));
} catch (e) {
return callback(e);
}
};

module.exports = function (self) {
self.registerWorkerSource('geojson-clustered', workerSource);
};
Loading