first commit

This commit is contained in:
sezerbozbiyik
2023-05-24 14:54:56 +03:00
parent bd98ff904b
commit 7c90e2d6af
7 changed files with 341 additions and 5 deletions
+2 -1
View File
@@ -251,7 +251,8 @@ export function rendererBackground(context) {
mapillary: 'Mapillary Images',
'mapillary-map-features': 'Mapillary Map Features',
'mapillary-signs': 'Mapillary Signs',
kartaview: 'KartaView Images'
kartaview: 'KartaView Images',
mapilio: 'Mapilio Images'
};
for (let layerID in photoOverlayLayers) {
+1 -1
View File
@@ -7,7 +7,7 @@ import { utilQsString, utilStringQs } from '../util';
export function rendererPhotos(context) {
var dispatch = d3_dispatch('change');
var _layerIDs = ['streetside', 'mapillary', 'mapillary-map-features', 'mapillary-signs', 'kartaview'];
var _layerIDs = ['streetside', 'mapillary', 'mapillary-map-features', 'mapillary-signs', 'kartaview', 'mapilio'];
var _allPhotoTypes = ['flat', 'panoramic'];
var _shownPhotoTypes = _allPhotoTypes.slice(); // shallow copy
var _dateFilters = ['fromDate', 'toDate'];
+5 -2
View File
@@ -13,6 +13,7 @@ import serviceTaginfo from './taginfo';
import serviceVectorTile from './vector_tile';
import serviceWikidata from './wikidata';
import serviceWikipedia from './wikipedia';
import serviceMapilio from './mapilio';
export let services = {
@@ -30,7 +31,8 @@ export let services = {
taginfo: serviceTaginfo,
vectorTile: serviceVectorTile,
wikidata: serviceWikidata,
wikipedia: serviceWikipedia
wikipedia: serviceWikipedia,
mapilio: serviceMapilio
};
export {
@@ -48,5 +50,6 @@ export {
serviceTaginfo,
serviceVectorTile,
serviceWikidata,
serviceWikipedia
serviceWikipedia,
serviceMapilio
};
+200
View File
@@ -0,0 +1,200 @@
import { dispatch as d3_dispatch } from 'd3-dispatch';
import Protobuf from 'pbf';
import RBush from 'rbush';
import { VectorTile } from '@mapbox/vector-tile';
import { utilRebind, utilTiler } from '../util';
const baseTileUrl = 'https://geo.mapilio.com/geoserver/gwc/service/wmts?REQUEST=GetTile&SERVICE=WMTS&VERSION=1.0.0&LAYER=mapilio:';
const pointsTileUrl = `${baseTileUrl}points_mapilio_map&STYLE=&TILEMATRIX=EPSG:900913:{z}&TILEMATRIXSET=EPSG:900913&FORMAT=application/vnd.mapbox-vector-tile&TILECOL={x}&TILEROW={y}`;
const minZoom = 14;
const dispatch = d3_dispatch('change', 'loadedImages', 'loadedSigns', 'loadedMapFeatures', 'bearingChanged', 'imageChanged');
let _mlyActiveImage;
let _mlyCache;
// Load all data for the specified type from Mapilio vector tiles
function loadTiles(which, url, maxZoom, projection) {
const tiler = utilTiler().zoomExtent([minZoom, maxZoom]).skipNullIsland(true);
const tiles = tiler.getTiles(projection);
tiles.forEach(function(tile) {
loadTile(which, url, tile);
});
}
// Load all data for the specified type from one vector tile
function loadTile(which, url, tile) {
const cache = _mlyCache.requests;
const tileId = `${tile.id}-${which}`;
if (cache.loaded[tileId] || cache.inflight[tileId]) return;
const controller = new AbortController();
cache.inflight[tileId] = controller;
const requestUrl = url.replace('{x}', tile.xyz[0])
.replace('{y}', tile.xyz[1])
.replace('{z}', tile.xyz[2]);
fetch(requestUrl, { signal: controller.signal })
.then(function(response) {
if (!response.ok) {
throw new Error(response.status + ' ' + response.statusText);
}
cache.loaded[tileId] = true;
delete cache.inflight[tileId];
return response.arrayBuffer();
})
.then(function(data) {
if (!data) {
throw new Error('No Data');
}
loadTileDataToCache(data, tile, which);
if (which === 'images') {
dispatch.call('loadedImages');
}
})
.catch(function() {
cache.loaded[tileId] = true;
delete cache.inflight[tileId];
});
}
// Load the data from the vector tile into cache
function loadTileDataToCache(data, tile, which) {
const vectorTile = new VectorTile(new Protobuf(data));
let features,
cache,
layer,
i,
feature,
loc,
d;
if (vectorTile.layers.hasOwnProperty('points_mapilio_map')) {
features = [];
cache = _mlyCache.images;
layer = vectorTile.layers.points_mapilio_map;
for (i = 0; i < layer.length; i++) {
feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
loc = feature.geometry.coordinates;
d = {
loc: loc,
captured_at: feature.properties.captured_at,
created_at: feature.properties.created_at,
id: feature.properties.id,
sequence_id: feature.properties.sequence_uuid,
};
cache.forImageId[d.id] = d;
features.push({
minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1], data: d
});
}
if (cache.rtree) {
cache.rtree.load(features);
}
}
if (vectorTile.layers.hasOwnProperty('sequence')) {
features = [];
cache = _mlyCache.sequences;
layer = vectorTile.layers.sequence;
for (i = 0; i < layer.length; i++) {
feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
if (cache.lineString[feature.properties.id]) {
cache.lineString[feature.properties.id].push(feature);
} else {
cache.lineString[feature.properties.id] = [feature];
}
}
}
if (vectorTile.layers.hasOwnProperty('point')) {
features = [];
cache = _mlyCache[which];
layer = vectorTile.layers.point;
for (i = 0; i < layer.length; i++) {
feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
loc = feature.geometry.coordinates;
d = {
loc: loc,
id: feature.properties.id,
first_seen_at: feature.properties.first_seen_at,
last_seen_at: feature.properties.last_seen_at,
value: feature.properties.value
};
features.push({
minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1], data: d
});
}
if (cache.rtree) {
cache.rtree.load(features);
}
}
}
export default {
// Initialize Mapilio
init: function() {
if (!_mlyCache) {
this.reset();
}
this.event = utilRebind(this, dispatch, 'on');
},
// Reset cache and state
reset: function() {
if (_mlyCache) {
Object.values(_mlyCache.requests.inflight).forEach(function(request) { request.abort(); });
}
_mlyCache = {
images: { rtree: new RBush(), forImageId: {} },
sequences: { rtree: new RBush(), lineString: {} },
requests: { loaded: {}, inflight: {} }
};
_mlyActiveImage = null;
},
// Load images in the visible area
loadImages: function(projection) {
loadTiles('images', pointsTileUrl, 14, projection);
},
// Update the currently highlighted sequence and selected bubble.
setStyles: function(context, hovered) {
const hoveredImageId = hovered && hovered.id;
const hoveredSequenceId = hovered && hovered.sequence_id;
const selectedSequenceId = _mlyActiveImage && _mlyActiveImage.sequence_id;
context.container().selectAll('.layer-mapilio .viewfield-group')
.classed('highlighted', function(d) { return (d.sequence_id === selectedSequenceId) || (d.id === hoveredImageId); })
.classed('hovered', function(d) { return d.id === hoveredImageId; });
context.container().selectAll('.layer-mapilio .sequence')
.classed('highlighted', function(d) { return d.properties.id === hoveredSequenceId; })
.classed('currentView', function(d) { return d.properties.id === selectedSequenceId; });
return this;
},
// Return the current cache
cache: function() {
return _mlyCache;
}
};
+1
View File
@@ -27,3 +27,4 @@ export { svgTagPattern } from './tag_pattern.js';
export { svgTouch } from './touch.js';
export { svgTurns } from './turns.js';
export { svgVertices } from './vertices.js';
export { svgMapilioImages } from './mapilio_images.js';
+3 -1
View File
@@ -13,6 +13,7 @@ import { svgMapillaryPosition } from './mapillary_position';
import { svgMapillarySigns } from './mapillary_signs';
import { svgMapillaryMapFeatures } from './mapillary_map_features';
import { svgKartaviewImages } from './kartaview_images';
import { svgMapilioImages } from './mapilio_images';
import { svgOsm } from './osm';
import { svgNotes } from './notes';
import { svgTouch } from './touch';
@@ -38,7 +39,8 @@ export function svgLayers(projection, context) {
{ id: 'kartaview', layer: svgKartaviewImages(projection, context, dispatch) },
{ id: 'debug', layer: svgDebug(projection, context, dispatch) },
{ id: 'geolocate', layer: svgGeolocate(projection, context, dispatch) },
{ id: 'touch', layer: svgTouch(projection, context, dispatch) }
{ id: 'touch', layer: svgTouch(projection, context, dispatch) },
{ id: 'mapilio', layer: svgMapilioImages(projection, context, dispatch) }
];
+129
View File
@@ -0,0 +1,129 @@
import _throttle from 'lodash-es/throttle';
import { select as d3_select } from 'd3-selection';
import { services } from '../services';
export function svgMapilioImages(projection, context, dispatch) {
const throttledRedraw = _throttle(function () { dispatch.call('change'); }, 1000);
const minZoom = 12;
let layer = d3_select(null);
let _mapilio;
function init() {
if (svgMapilioImages.initialized) return;
svgMapilioImages.enabled = false;
svgMapilioImages.initialized = true;
}
function getService() {
if (services.mapilio && !_mapilio) {
_mapilio = services.mapilio;
_mapilio.event.on('loadedImages', throttledRedraw);
} else if (!services.mapilio && _mapilio) {
_mapilio = null;
}
return _mapilio;
}
function showLayer() {
const service = getService();
if (!service) return;
editOn();
layer
.style('opacity', 0)
.transition()
.duration(250)
.style('opacity', 1)
.on('end', function () { dispatch.call('change'); });
}
function hideLayer() {
throttledRedraw.cancel();
layer
.transition()
.duration(250)
.style('opacity', 0)
.on('end', editOff);
}
function editOn() {
layer.style('display', 'block');
}
function editOff() {
layer.selectAll('.viewfield-group').remove();
layer.style('display', 'none');
}
function drawImages(selection) {
const enabled = svgMapilioImages.enabled;
const service = getService();
layer = selection.selectAll('.layer-mapilio')
.data(service ? [0] : []);
layer.exit()
.remove();
const layerEnter = layer.enter()
.append('g')
.attr('class', 'layer-mapilio')
.style('display', enabled ? 'block' : 'none');
layerEnter
.append('g')
.attr('class', 'sequences');
layerEnter
.append('g')
.attr('class', 'markers');
layer = layerEnter
.merge(layer);
if (enabled) {
if (service && ~~context.map().zoom() >= minZoom) {
editOn();
service.loadImages(projection);
} else {
editOff();
}
}
}
drawImages.enabled = function(_) {
if (!arguments.length) return svgMapilioImages.enabled;
svgMapilioImages.enabled = _;
if (svgMapilioImages.enabled) {
showLayer();
context.photos().on('change.mapilio_images', null);
} else {
hideLayer();
context.photos().on('change.mapilio_images', null);
}
dispatch.call('change');
return this;
};
drawImages.supported = function() {
return !!getService();
};
init();
return drawImages;
}