From 095dc191645671f51e45f5fe4f59ded509300807 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Mon, 6 Nov 2017 21:32:03 -0500 Subject: [PATCH] Add sequence linestrings to mapillary photo layer too --- modules/services/mapillary.js | 46 ++++++++++++++++++++++++--- modules/svg/mapillary_images.js | 56 ++++++++++++++++++++++++++++----- 2 files changed, 89 insertions(+), 13 deletions(-) diff --git a/modules/services/mapillary.js b/modules/services/mapillary.js index 7b266a511..932911d8a 100644 --- a/modules/services/mapillary.js +++ b/modules/services/mapillary.js @@ -165,6 +165,15 @@ function loadNextTilePage(which, currZoom, url, tile) { captured_at: feature.properties.captured_at, pano: feature.properties.pano }; + + } else if (which === 'sequences') { + var sk = feature.properties.key; + cache.lineString[sk] = feature; // cache sequence_key -> linestring + feature.properties.coordinateProperties.image_keys.forEach(function(ik) { + cache.forImage[ik] = sk; // cache image_key -> sequence_key + }); + return false; // nothing to actually insert + } else if (which === 'objects') { d = { loc: loc, @@ -190,11 +199,11 @@ function loadNextTilePage(which, currZoom, url, tile) { return { minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1], data: d }; - }); + }).filter(Boolean); cache.rtree.load(features); - if (which === 'images') { + if (which === 'images' || which === 'sequences') { dispatch.call('loadedImages'); } else if (which === 'objects') { dispatch.call('loadedSigns'); @@ -303,11 +312,15 @@ export default { if (cache.objects && cache.objects.inflight) { _forEach(cache.objects.inflight, abortRequest); } + if (cache.sequences && cache.sequences.inflight) { + _forEach(cache.sequences.inflight, abortRequest); + } } mapillaryCache = { images: { inflight: {}, loaded: {}, nextPage: {}, nextURL: {}, rtree: rbush() }, - objects: { inflight: {}, loaded: {}, nextPage: {}, nextURL: {}, rtree: rbush() }, + objects: { inflight: {}, loaded: {}, nextPage: {}, nextURL: {}, rtree: rbush() }, + sequences: { inflight: {}, loaded: {}, nextPage: {}, nextURL: {}, rtree: rbush(), forImage: {}, lineString: {} }, detections: {} }; @@ -328,6 +341,29 @@ export default { }, + sequences: 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(); + var sequenceKeys = {}; + + // all sequences for images in viewport + mapillaryCache.images.rtree.search(bbox) + .forEach(function(d) { + var sk = mapillaryCache.sequences.forImage[d.data.key]; + if (sk) { + sequenceKeys[sk] = true; + } + }); + + // Return linestrings for the sequences + return Object.keys(sequenceKeys).map(function(sk) { + return mapillaryCache.sequences.lineString[sk]; + }); + }, + + signsSupported: function() { var detected = utilDetect(); if (detected.ie) return false; @@ -354,8 +390,8 @@ export default { loadImages: function(projection) { - var url = apibase + 'images?'; - loadTiles('images', url, projection); + loadTiles('images', apibase + 'images?', projection); + loadTiles('sequences', apibase + 'sequences?', projection); }, diff --git a/modules/svg/mapillary_images.js b/modules/svg/mapillary_images.js index 9b537d616..3d2f21afa 100644 --- a/modules/svg/mapillary_images.js +++ b/modules/svg/mapillary_images.js @@ -1,5 +1,12 @@ import _throttle from 'lodash-es/throttle'; + +import { + geoIdentity as d3_geoIdentity, + geoPath as d3_geoPath +} from 'd3-geo'; + import { select as d3_select } from 'd3-selection'; + import { svgPointTransform } from './point_transform'; import { services } from '../services'; @@ -95,12 +102,35 @@ export function svgMapillaryImages(projection, context, dispatch) { function update() { - var mapillary = getMapillary(), - data = (mapillary ? mapillary.images(projection) : []), - imageKey = mapillary ? mapillary.selectedImage() : null; + var highZoom = ~~context.map().zoom() >= minViewfieldZoom; + var mapillary = getMapillary(); + var images = (mapillary ? mapillary.images(projection) : []); + var sequences = (mapillary && highZoom ? mapillary.sequences(projection) : []); + var imageKey = mapillary ? mapillary.selectedImage() : null; - var markers = layer.selectAll('.viewfield-group') - .data(data, function(d) { return d.key; }); + var clip = d3_geoIdentity().clipExtent(projection.clipExtent()).stream; + var project = projection.stream; + var makePath = d3_geoPath().projection({ stream: function(output) { + return project(clip(output)); + }}); + + var lineStrings = layer.selectAll('.sequences').selectAll('.sequence') + .data(sequences); + + lineStrings.exit() + .remove(); + + lineStrings = lineStrings.enter() + .append('path') + .attr('class', 'sequence') + .merge(lineStrings); + + lineStrings + .attr('d', makePath); + + + var markers = layer.selectAll('.markers').selectAll('.viewfield-group') + .data(images, function(d) { return d.key; }); markers.exit() .remove(); @@ -117,7 +147,7 @@ export function svgMapillaryImages(projection, context, dispatch) { var viewfields = markers.selectAll('.viewfield') - .data(~~context.map().zoom() >= minViewfieldZoom ? [0] : []); + .data(highZoom ? [0] : []); viewfields.exit() .remove(); @@ -148,10 +178,20 @@ export function svgMapillaryImages(projection, context, dispatch) { layer.exit() .remove(); - layer = layer.enter() + var layerEnter = layer.enter() .append('g') .attr('class', 'layer-mapillary-images') - .style('display', enabled ? 'block' : 'none') + .style('display', enabled ? 'block' : 'none'); + + layerEnter + .append('g') + .attr('class', 'sequences'); + + layerEnter + .append('g') + .attr('class', 'markers'); + + layer = layerEnter .merge(layer); if (enabled) {