Skip to content

Commit

Permalink
Cleanup osm service notes and caches, remove state variable
Browse files Browse the repository at this point in the history
This seems like a lot but the main things here are:
- remove the _loadingTiles "global" variable.  It was causing problems because
it was being checked from the callbacks, which are async.
- cleanup the caches
- use DOM API getElementsByTagName('id') to get note id
- set a lower tilezoom z14 for notes (meaning: fetch larger bounding boxes)
  • Loading branch information
bhousel committed Jun 30, 2018
1 parent ede5610 commit e29b8a1
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 101 deletions.
179 changes: 85 additions & 94 deletions modules/services/osm.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,20 @@ import _uniq from 'lodash-es/uniq';

import rbush from 'rbush';

var _notesCache = {};

import { dispatch as d3_dispatch } from 'd3-dispatch';
import { xml as d3_xml } from 'd3-request';

import osmAuth from 'osm-auth';
import { JXON } from '../util/jxon';
import { d3geoTile as d3_geoTile } from '../lib/d3.geo.tile';
import { geoExtent } from '../geo';

import {
osmEntity,
osmNode,
osmNote,
osmRelation,
osmWay,
osmNote
osmWay
} from '../osm';

import { utilRebind, utilIdleWorker } from '../util';
Expand All @@ -41,17 +40,18 @@ var oauth = osmAuth({
});

var _blacklists = ['.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*'];
var _tiles = { loaded: {}, inflight: {} };
var _tileCache = { loaded: {}, inflight: {} };
var _noteCache = { loaded: {}, inflight: {}, rtree: rbush() };
var _changeset = {};
var _entityCache = {};
var _noteTileCache = { loaded: {}, inflight: {}, rtree: rbush() };
var _seenEntity = {};

var _connectionID = 1;
var _tileZoom = 16;
var _noteZoom = 14;
var _rateLimitError;
var _userChangesets;
var _userDetails;
var _off;
var _loadingNotes = false;


function authLoading() {
Expand Down Expand Up @@ -146,7 +146,7 @@ var parsers = {
node: function nodeData(obj, uid) {
var attrs = obj.attributes;
return new osmNode({
id:uid,
id: uid,
visible: getVisible(attrs),
version: attrs.version.value,
changeset: attrs.changeset && attrs.changeset.value,
Expand Down Expand Up @@ -230,29 +230,19 @@ function parse(xml, callback, options) {

function parseChild(child) {
var parser = parsers[child.nodeName];
if (parser) {
if (!parser) return;

var uid;
var cache = _loadingNotes ? _notesCache : _entityCache;
var uid;
if (child.nodeName === 'note') {
uid = child.getElementsByTagName('id')[0].textContent;
} else {
uid = osmEntity.id.fromOSM(child.nodeName, child.attributes.id.value);
}

// if loading notes, get the note id
if (_loadingNotes) {
var childNodes = child.childNodes;
_forEach(childNodes, function(node) {
if (node.nodeName === 'id') {
uid = child.nodeName + node.innerHTML;
}
});
}
// otherwise, get the osmEntity id
else {
uid = osmEntity.id.fromOSM(child.nodeName, child.attributes.id.value);
}
if (options.cache && cache[uid]) {
return null;
}
return parser(child, uid);
if (options.cache && _seenEntity[uid]) {
return null;
}
return parser(child, uid);
}

utilIdleWorker(children, parseChild, callback);
Expand All @@ -271,17 +261,15 @@ export default {
_userChangesets = undefined;
_userDetails = undefined;
_rateLimitError = undefined;
_forEach(_tiles.inflight, abortRequest);

_forEach(_tileCache.inflight, abortRequest);
_forEach(_noteCache.inflight, abortRequest);
if (_changeset.inflight) abortRequest(_changeset.inflight);
_tiles = { loaded: {}, inflight: {} };
_changeset = {};
_entityCache = {};

if (_noteTileCache && _noteTileCache.inflight) {
_forEach(_noteTileCache.inflight, abortRequest);
}
_noteTileCache = { loaded: {}, inflight: {}, rtree: rbush() };
_notesCache = {};
_tileCache = { loaded: {}, inflight: {} };
_noteCache = { loaded: {}, inflight: {}, rtree: rbush() };
_changeset = {};
_seenEntity = {};

return this;
},
Expand Down Expand Up @@ -355,11 +343,7 @@ export default {
parse(xml, function (entities) {
if (options.cache) {
for (var i in entities) {
if (_loadingNotes) {
_notesCache[entities[i].id] = true;
} else {
_entityCache[entities[i].id] = true;
}
_seenEntity[entities[i].id] = true;
}
}
callback(null, entities);
Expand Down Expand Up @@ -656,56 +640,66 @@ export default {
},


loadTiles: function(projection, dimensions, callback) {
loadTiles: function(projection, dimensions, callback, loadingNotes) {
if (_off) return;

var that = this;

var cache = _loadingNotes ? _noteTileCache : _tiles;
// check if loading entities, or notes
var path, cache, tilezoom;
if (loadingNotes) {
path = '/api/0.6/notes?bbox=';
cache = _noteCache;
tilezoom = _noteZoom;
} else {
path = '/api/0.6/map?bbox=';
cache = _tileCache;
tilezoom = _tileZoom;
}

var s = projection.scale() * 2 * Math.PI;
var z = Math.max(Math.log(s) / Math.log(2) - 8, 0);
var ts = 256 * Math.pow(2, z - _tileZoom);
var ts = 256 * Math.pow(2, z - tilezoom);
var origin = [
s / 2 - projection.translate()[0],
s / 2 - projection.translate()[1]
];

var tiles = d3_geoTile()
.scaleExtent([_tileZoom, _tileZoom])
// what tiles cover the view
var tiler = d3_geoTile()
.scaleExtent([tilezoom, tilezoom])
.scale(s)
.size(dimensions)
.translate(projection.translate())()
.map(function(tile) {
var x = tile[0] * ts - origin[0];
var y = tile[1] * ts - origin[1];

return {
id: tile.toString(),
extent: geoExtent(
projection.invert([x, y + ts]),
projection.invert([x + ts, y]))
};
});
.translate(projection.translate());

var tiles = tiler().map(function(tile) {
var x = tile[0] * ts - origin[0];
var y = tile[1] * ts - origin[1];

return {
id: tile.toString(),
extent: geoExtent(
projection.invert([x, y + ts]),
projection.invert([x + ts, y])
)
};
});

_filter(cache.inflight, function(v, i) {
var wanted = _find(tiles, function(tile) {
return i === tile.id;
});
if (!wanted) delete cache.inflight[i];
var wanted = _find(tiles, function(tile) { return i === tile.id; });
if (!wanted) {
delete cache.inflight[i];
}
return !wanted;
}).map(abortRequest);

// check if loading entities, or notes
var path = _loadingNotes ? '/api/0.6/notes?bbox=' : '/api/0.6/map?bbox=';

tiles.forEach(function(tile) {
var id = tile.id;

if (cache.loaded[id] || cache.inflight[id]) return;

if (_isEmpty(cache.inflight)) {
dispatch.call('loading');
if (!loadingNotes && _isEmpty(cache.inflight)) {
dispatch.call('loading'); // start the spinner
}

cache.inflight[id] = that.loadFromAPI(
Expand All @@ -715,23 +709,19 @@ export default {
if (!err) {
cache.loaded[id] = true;
}
// NOTE: if zoom above min zoom & notes turned on before osm, osm won't render
// TODO: either pick this option, or the next one
if (_loadingNotes) {
cache.rtree.load(parsed);
}

// TODO: figure out how this callback should handle parsed results
if (callback) {
callback(err, _extend({ data: parsed }, tile));
}

if (_isEmpty(cache.inflight)) {
if (_loadingNotes) {
dispatch.call('loadedNotes');
if (loadingNotes) {
cache.rtree.load(parsed);
dispatch.call('loadedNotes');
} else {
if (callback) {
callback(err, _extend({ data: parsed }, tile));
}
if (_isEmpty(cache.inflight)) {
dispatch.call('loaded'); // stop the spinner
}
dispatch.call('loaded');
}

}
);
});
Expand Down Expand Up @@ -761,8 +751,8 @@ export default {


loadedTiles: function(_) {
if (!arguments.length) return _tiles.loaded;
_tiles.loaded = _;
if (!arguments.length) return _tileCache.loaded;
_tileCache.loaded = _;
return this;
},

Expand Down Expand Up @@ -800,30 +790,31 @@ export default {
return oauth.authenticate(done);
},

loadNotes: function(projection, dimensions, callback) {
var that = this;
_loadingNotes = true;
that.loadTiles(projection, dimensions, callback);

loadNotes: function(projection, dimensions) {
this.loadTiles(projection, dimensions, null, true); // true = loadingNotes
},

// TODO: possibly remove rtree & refactor caches

notes: function(projection) {
var viewport = projection.clipExtent();
var min = [viewport[0][0], viewport[1][1]];
var max = [viewport[1][0], viewport[0][1]];
var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();

return _noteTileCache.rtree.search(bbox)
return _noteCache.rtree.search(bbox)
.map(function(d) { return d.data; });
},


loadedNotes: function(_) {
if (!arguments.length) return _noteTileCache.loaded;
_noteTileCache.loaded = _;
if (!arguments.length) return _noteCache.loaded;
_noteCache.loaded = _;
return this;
},


notesCache: function() {
return _noteTileCache;
return _noteCache;
}
};
11 changes: 4 additions & 7 deletions modules/svg/notes.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,12 @@ export function svgNotes(projection, context, dispatch) {
}

function drawNotes(selection) {
var enabled = svgNotes.enabled,
service = getService();
var enabled = svgNotes.enabled;
var service = getService();

function dimensions() {
return [window.innerWidth, window.innerHeight];
}
function done() {
console.log('placeholder done within svg/notes.upload.done');
}

layer = selection.selectAll('.layer-notes')
.data(service ? [0] : []);
Expand All @@ -130,7 +127,7 @@ export function svgNotes(projection, context, dispatch) {
if (service && ~~context.map().zoom() >= minZoom) {
editOn();
update();
service.loadNotes(projection, dimensions(), done);
service.loadNotes(projection, dimensions());
} else {
editOff();
}
Expand All @@ -151,4 +148,4 @@ export function svgNotes(projection, context, dispatch) {

init();
return drawNotes;
}
}

0 comments on commit e29b8a1

Please sign in to comment.