mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-19 06:58:32 +02:00
Merge pull request #8372 from mapillary/mapillary-vector-tiles
Use Mapillary vector tiles and switch to v4
This commit is contained in:
+13
-7
@@ -305,17 +305,23 @@ label.streetside-hires {
|
||||
top: -25px;
|
||||
}
|
||||
|
||||
.mly-wrapper .AttributionContainer .AttributionIconContainer .AttributionMapillaryLogo {
|
||||
margin-top: 3px;
|
||||
.mly-wrapper .mapillary-attribution-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mly-wrapper .AttributionContainer .AttributionImageContainer {
|
||||
color: #fff;
|
||||
font-size: 10px;
|
||||
font-weight: 300;
|
||||
overflow: hidden;
|
||||
.mly-wrapper .mapillary-attribution-container .mapillary-attribution-icon-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mly-wrapper .mapillary-attribution-container .mapillary-attribution-username {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mly-wrapper .mapillary-attribution-container .mapillary-attribution-date {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
/* OpenStreetCam viewer */
|
||||
.osc-wrapper {
|
||||
|
||||
+27
-1
@@ -1318,11 +1318,27 @@ en:
|
||||
title: "Map Features"
|
||||
tooltip: "Map features from Mapillary"
|
||||
construction:
|
||||
barrier:
|
||||
temporary: temporary barrier
|
||||
flat:
|
||||
crosswalk_plain: plain crosswalk
|
||||
driveway: driveway
|
||||
marking:
|
||||
discrete:
|
||||
crosswalk_zebra: zebra crosswalk
|
||||
arrow:
|
||||
left: lane marking - arrow (left)
|
||||
right: lane marking - arrow (right)
|
||||
split_left_or_straight: lane marking - arrow (split left or straight)
|
||||
split_right_or_straight: lane marking - arrow (split right or straight)
|
||||
straight: lane marking - arrow (straight)
|
||||
crosswalk_zebra: lane marking - crosswalk
|
||||
give_way_row: lane marking - give way (row)
|
||||
give_way_single: lane marking - give way (single)
|
||||
other_marking: lane marking - other
|
||||
stop_line: lane marking - stop line
|
||||
symbol:
|
||||
bicycle: lane marking - symbol (bicycle)
|
||||
text: lane marking - text
|
||||
object:
|
||||
banner: banner
|
||||
bench: bench
|
||||
@@ -1331,15 +1347,24 @@ en:
|
||||
catch_basin: catch basin
|
||||
cctv_camera: CCTV camera
|
||||
fire_hydrant: fire hydrant
|
||||
junction_box: junction box
|
||||
mailbox: mailbox
|
||||
manhole: manhole
|
||||
parking_meter: parking meter
|
||||
phone_booth: phone booth
|
||||
sign:
|
||||
advertisement: advertisement
|
||||
information: information sign
|
||||
other: other sign
|
||||
store: shop sign
|
||||
traffic_sign:
|
||||
back: traffic sign - back
|
||||
direction_front: traffic sign - front
|
||||
front: traffic sign - front
|
||||
street_light: street light
|
||||
support:
|
||||
pole: pole
|
||||
traffic_sign_frame: traffic sign frame
|
||||
utility_pole: utility pole
|
||||
traffic_cone: traffic cone
|
||||
traffic_light:
|
||||
@@ -1350,6 +1375,7 @@ en:
|
||||
other: traffic light
|
||||
pedestrians: pedestrian traffic light
|
||||
trash_can: trash can
|
||||
water_valve: water valve
|
||||
mapillary:
|
||||
title: Mapillary
|
||||
signs:
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -128,7 +128,7 @@ export function rendererPhotos(context) {
|
||||
};
|
||||
|
||||
photos.shouldFilterByUsername = function() {
|
||||
return showsLayer('mapillary') || showsLayer('openstreetcam') || showsLayer('streetside');
|
||||
return !showsLayer('mapillary') && showsLayer('openstreetcam') && !showsLayer('streetside');
|
||||
};
|
||||
|
||||
photos.showsPhotoType = function(val) {
|
||||
|
||||
+362
-485
File diff suppressed because it is too large
Load Diff
@@ -544,7 +544,7 @@ export default {
|
||||
.classed('currentView', function(d) { return d.properties.key === selectedSequenceKey; });
|
||||
|
||||
// update viewfields if needed
|
||||
context.container().selectAll('.viewfield-group .viewfield')
|
||||
context.container().selectAll('.layer-openstreetcam .viewfield-group .viewfield')
|
||||
.attr('d', viewfieldPath);
|
||||
|
||||
function viewfieldPath() {
|
||||
|
||||
@@ -942,7 +942,7 @@ export default {
|
||||
.classed('currentView', d => d.properties.key === selectedSequenceKey);
|
||||
|
||||
// update viewfields if needed
|
||||
context.container().selectAll('.viewfield-group .viewfield')
|
||||
context.container().selectAll('.layer-streetside-images .viewfield-group .viewfield')
|
||||
.attr('d', viewfieldPath);
|
||||
|
||||
function viewfieldPath() {
|
||||
|
||||
@@ -6,13 +6,12 @@ import { services } from '../services';
|
||||
|
||||
|
||||
export function svgMapillaryImages(projection, context, dispatch) {
|
||||
var throttledRedraw = _throttle(function () { dispatch.call('change'); }, 1000);
|
||||
var minZoom = 12;
|
||||
var minMarkerZoom = 16;
|
||||
var minViewfieldZoom = 18;
|
||||
var layer = d3_select(null);
|
||||
var _mapillary;
|
||||
var viewerCompassAngle;
|
||||
const throttledRedraw = _throttle(function () { dispatch.call('change'); }, 1000);
|
||||
const minZoom = 12;
|
||||
const minMarkerZoom = 16;
|
||||
const minViewfieldZoom = 18;
|
||||
let layer = d3_select(null);
|
||||
let _mapillary;
|
||||
|
||||
|
||||
function init() {
|
||||
@@ -35,7 +34,7 @@ export function svgMapillaryImages(projection, context, dispatch) {
|
||||
|
||||
|
||||
function showLayer() {
|
||||
var service = getService();
|
||||
const service = getService();
|
||||
if (!service) return;
|
||||
|
||||
editOn();
|
||||
@@ -71,39 +70,38 @@ export function svgMapillaryImages(projection, context, dispatch) {
|
||||
}
|
||||
|
||||
|
||||
function click(d3_event, d) {
|
||||
var service = getService();
|
||||
function click(d3_event, image) {
|
||||
const service = getService();
|
||||
if (!service) return;
|
||||
|
||||
service
|
||||
.ensureViewerLoaded(context)
|
||||
.then(function() {
|
||||
service
|
||||
.selectImage(context, d.key)
|
||||
.selectImage(context, image.id)
|
||||
.showViewer(context);
|
||||
});
|
||||
|
||||
context.map().centerEase(d.loc);
|
||||
context.map().centerEase(image.loc);
|
||||
}
|
||||
|
||||
|
||||
function mouseover(d) {
|
||||
var service = getService();
|
||||
if (service) service.setStyles(context, d);
|
||||
function mouseover(d3_event, image) {
|
||||
const service = getService();
|
||||
|
||||
if (service) service.setStyles(context, image);
|
||||
}
|
||||
|
||||
|
||||
function mouseout() {
|
||||
var service = getService();
|
||||
const service = getService();
|
||||
if (service) service.setStyles(context, null);
|
||||
}
|
||||
|
||||
|
||||
function transform(d) {
|
||||
var t = svgPointTransform(projection)(d);
|
||||
if (d.pano && viewerCompassAngle !== null && isFinite(viewerCompassAngle)) {
|
||||
t += ' rotate(' + Math.floor(viewerCompassAngle) + ',0,0)';
|
||||
} else if (d.ca) {
|
||||
let t = svgPointTransform(projection)(d);
|
||||
if (d.ca) {
|
||||
t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
|
||||
}
|
||||
return t;
|
||||
@@ -111,82 +109,54 @@ export function svgMapillaryImages(projection, context, dispatch) {
|
||||
|
||||
|
||||
function filterImages(images) {
|
||||
var showsPano = context.photos().showsPanoramic();
|
||||
var showsFlat = context.photos().showsFlat();
|
||||
var fromDate = context.photos().fromDate();
|
||||
var toDate = context.photos().toDate();
|
||||
var usernames = context.photos().usernames();
|
||||
const showsPano = context.photos().showsPanoramic();
|
||||
const showsFlat = context.photos().showsFlat();
|
||||
const fromDate = context.photos().fromDate();
|
||||
const toDate = context.photos().toDate();
|
||||
|
||||
if (!showsPano || !showsFlat) {
|
||||
images = images.filter(function(image) {
|
||||
if (image.pano) return showsPano;
|
||||
if (image.is_pano) return showsPano;
|
||||
return showsFlat;
|
||||
});
|
||||
}
|
||||
if (fromDate) {
|
||||
var fromTimestamp = new Date(fromDate).getTime();
|
||||
images = images.filter(function(image) {
|
||||
return new Date(image.captured_at).getTime() >= fromTimestamp;
|
||||
return new Date(image.captured_at).getTime() >= new Date(fromDate).getTime();
|
||||
});
|
||||
}
|
||||
if (toDate) {
|
||||
var toTimestamp = new Date(toDate).getTime();
|
||||
images = images.filter(function(image) {
|
||||
return new Date(image.captured_at).getTime() <= toTimestamp;
|
||||
});
|
||||
}
|
||||
if (usernames) {
|
||||
images = images.filter(function(image) {
|
||||
return usernames.indexOf(image.captured_by) !== -1;
|
||||
return new Date(image.captured_at).getTime() <= new Date(toDate).getTime();
|
||||
});
|
||||
}
|
||||
|
||||
return images;
|
||||
}
|
||||
|
||||
function filterSequences(sequences, service) {
|
||||
var showsPano = context.photos().showsPanoramic();
|
||||
var showsFlat = context.photos().showsFlat();
|
||||
var fromDate = context.photos().fromDate();
|
||||
var toDate = context.photos().toDate();
|
||||
var usernames = context.photos().usernames();
|
||||
function filterSequences(sequences) {
|
||||
const showsPano = context.photos().showsPanoramic();
|
||||
const showsFlat = context.photos().showsFlat();
|
||||
const fromDate = context.photos().fromDate();
|
||||
const toDate = context.photos().toDate();
|
||||
|
||||
if (!showsPano || !showsFlat) {
|
||||
sequences = sequences.filter(function(sequence) {
|
||||
if (sequence.properties.hasOwnProperty('pano')) {
|
||||
if (sequence.properties.pano) return showsPano;
|
||||
if (sequence.properties.hasOwnProperty('is_pano')) {
|
||||
if (sequence.properties.is_pano) return showsPano;
|
||||
return showsFlat;
|
||||
} else {
|
||||
// if the sequence doesn't specify pano or not, search its images
|
||||
var cProps = sequence.properties.coordinateProperties;
|
||||
if (cProps && cProps.image_keys && cProps.image_keys.length > 0) {
|
||||
for (var index in cProps.image_keys) {
|
||||
var imageKey = cProps.image_keys[index];
|
||||
var image = service.cachedImage(imageKey);
|
||||
if (image && image.hasOwnProperty('pano')) {
|
||||
if (image.pano) return showsPano;
|
||||
return showsFlat;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
if (fromDate) {
|
||||
var fromTimestamp = new Date(fromDate).getTime();
|
||||
sequences = sequences.filter(function(sequence) {
|
||||
return new Date(sequence.properties.captured_at).getTime() >= fromTimestamp;
|
||||
return new Date(sequence.properties.captured_at).getTime() >= new Date(fromDate).getTime().toString();
|
||||
});
|
||||
}
|
||||
if (toDate) {
|
||||
var toTimestamp = new Date(toDate).getTime();
|
||||
sequences = sequences.filter(function(sequence) {
|
||||
return new Date(sequence.properties.captured_at).getTime() <= toTimestamp;
|
||||
});
|
||||
}
|
||||
if (usernames) {
|
||||
sequences = sequences.filter(function(sequence) {
|
||||
return usernames.indexOf(sequence.properties.username) !== -1;
|
||||
return new Date(sequence.properties.captured_at).getTime() <= new Date(toDate).getTime().toString();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -195,20 +165,21 @@ export function svgMapillaryImages(projection, context, dispatch) {
|
||||
|
||||
function update() {
|
||||
|
||||
var z = ~~context.map().zoom();
|
||||
var showMarkers = (z >= minMarkerZoom);
|
||||
var showViewfields = (z >= minViewfieldZoom);
|
||||
const z = ~~context.map().zoom();
|
||||
const showMarkers = (z >= minMarkerZoom);
|
||||
const showViewfields = (z >= minViewfieldZoom);
|
||||
|
||||
var service = getService();
|
||||
var sequences = (service ? service.sequences(projection) : []);
|
||||
var images = (service && showMarkers ? service.images(projection) : []);
|
||||
const service = getService();
|
||||
let sequences = (service ? service.sequences(projection) : []);
|
||||
let images = (service && showMarkers ? service.images(projection) : []);
|
||||
|
||||
images = filterImages(images);
|
||||
sequences = filterSequences(sequences, service);
|
||||
|
||||
service.filterViewer(context);
|
||||
|
||||
var traces = layer.selectAll('.sequences').selectAll('.sequence')
|
||||
.data(sequences, function(d) { return d.properties.key; });
|
||||
let traces = layer.selectAll('.sequences').selectAll('.sequence')
|
||||
.data(sequences, function(d) { return d.properties.id; });
|
||||
|
||||
// exit
|
||||
traces.exit()
|
||||
@@ -222,15 +193,15 @@ export function svgMapillaryImages(projection, context, dispatch) {
|
||||
.attr('d', svgPath(projection).geojson);
|
||||
|
||||
|
||||
var groups = layer.selectAll('.markers').selectAll('.viewfield-group')
|
||||
.data(images, function(d) { return d.key; });
|
||||
const groups = layer.selectAll('.markers').selectAll('.viewfield-group')
|
||||
.data(images, function(d) { return d.id; });
|
||||
|
||||
// exit
|
||||
groups.exit()
|
||||
.remove();
|
||||
|
||||
// enter
|
||||
var groupsEnter = groups.enter()
|
||||
const groupsEnter = groups.enter()
|
||||
.append('g')
|
||||
.attr('class', 'viewfield-group')
|
||||
.on('mouseenter', mouseover)
|
||||
@@ -242,7 +213,7 @@ export function svgMapillaryImages(projection, context, dispatch) {
|
||||
.attr('class', 'viewfield-scale');
|
||||
|
||||
// update
|
||||
var markers = groups
|
||||
const markers = groups
|
||||
.merge(groupsEnter)
|
||||
.sort(function(a, b) {
|
||||
return b.loc[1] - a.loc[1]; // sort Y
|
||||
@@ -259,7 +230,7 @@ export function svgMapillaryImages(projection, context, dispatch) {
|
||||
.attr('dy', '0')
|
||||
.attr('r', '6');
|
||||
|
||||
var viewfields = markers.selectAll('.viewfield')
|
||||
const viewfields = markers.selectAll('.viewfield')
|
||||
.data(showViewfields ? [0] : []);
|
||||
|
||||
viewfields.exit()
|
||||
@@ -268,13 +239,12 @@ export function svgMapillaryImages(projection, context, dispatch) {
|
||||
viewfields.enter() // viewfields may or may not be drawn...
|
||||
.insert('path', 'circle') // but if they are, draw below the circles
|
||||
.attr('class', 'viewfield')
|
||||
.classed('pano', function() { return this.parentNode.__data__.pano; })
|
||||
.classed('pano', function() { return this.parentNode.__data__.is_pano; })
|
||||
.attr('transform', 'scale(1.5,1.5),translate(-8, -13)')
|
||||
.attr('d', viewfieldPath);
|
||||
|
||||
function viewfieldPath() {
|
||||
var d = this.parentNode.__data__;
|
||||
if (d.pano) {
|
||||
if (this.parentNode.__data__.is_pano) {
|
||||
return 'M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0';
|
||||
} else {
|
||||
return 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z';
|
||||
@@ -284,8 +254,8 @@ export function svgMapillaryImages(projection, context, dispatch) {
|
||||
|
||||
|
||||
function drawImages(selection) {
|
||||
var enabled = svgMapillaryImages.enabled;
|
||||
var service = getService();
|
||||
const enabled = svgMapillaryImages.enabled;
|
||||
const service = getService();
|
||||
|
||||
layer = selection.selectAll('.layer-mapillary')
|
||||
.data(service ? [0] : []);
|
||||
@@ -293,7 +263,7 @@ export function svgMapillaryImages(projection, context, dispatch) {
|
||||
layer.exit()
|
||||
.remove();
|
||||
|
||||
var layerEnter = layer.enter()
|
||||
const layerEnter = layer.enter()
|
||||
.append('g')
|
||||
.attr('class', 'layer-mapillary')
|
||||
.style('display', enabled ? 'block' : 'none');
|
||||
|
||||
@@ -5,10 +5,10 @@ import { services } from '../services';
|
||||
import { t } from '../core/localizer';
|
||||
|
||||
export function svgMapillaryMapFeatures(projection, context, dispatch) {
|
||||
var throttledRedraw = _throttle(function () { dispatch.call('change'); }, 1000);
|
||||
var minZoom = 12;
|
||||
var layer = d3_select(null);
|
||||
var _mapillary;
|
||||
const throttledRedraw = _throttle(function () { dispatch.call('change'); }, 1000);
|
||||
const minZoom = 12;
|
||||
let layer = d3_select(null);
|
||||
let _mapillary;
|
||||
|
||||
|
||||
function init() {
|
||||
@@ -30,7 +30,7 @@ export function svgMapillaryMapFeatures(projection, context, dispatch) {
|
||||
|
||||
|
||||
function showLayer() {
|
||||
var service = getService();
|
||||
const service = getService();
|
||||
if (!service) return;
|
||||
|
||||
service.loadObjectResources(context);
|
||||
@@ -56,88 +56,69 @@ export function svgMapillaryMapFeatures(projection, context, dispatch) {
|
||||
|
||||
|
||||
function click(d3_event, d) {
|
||||
var service = getService();
|
||||
const service = getService();
|
||||
if (!service) return;
|
||||
|
||||
context.map().centerEase(d.loc);
|
||||
|
||||
var selectedImageKey = service.getSelectedImageKey();
|
||||
var imageKey;
|
||||
var highlightedDetection;
|
||||
// Pick one of the images the map feature was detected in,
|
||||
// preference given to an image already selected.
|
||||
d.detections.forEach(function(detection) {
|
||||
if (!imageKey || selectedImageKey === detection.image_key) {
|
||||
imageKey = detection.image_key;
|
||||
highlightedDetection = detection;
|
||||
const selectedImageId = service.getActiveImage() && service.getActiveImage().id;
|
||||
|
||||
service.getDetections(d.id).then(detections => {
|
||||
if (detections.length) {
|
||||
const imageId = detections[0].image.id;
|
||||
if (imageId === selectedImageId) {
|
||||
service
|
||||
.highlightDetection(detections[0])
|
||||
.selectImage(context, imageId);
|
||||
} else {
|
||||
service.ensureViewerLoaded(context)
|
||||
.then(function() {
|
||||
service
|
||||
.highlightDetection(detections[0])
|
||||
.selectImage(context, imageId)
|
||||
.showViewer(context);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (imageKey === selectedImageKey) {
|
||||
service
|
||||
.highlightDetection(highlightedDetection)
|
||||
.selectImage(context, imageKey);
|
||||
} else {
|
||||
service.ensureViewerLoaded(context)
|
||||
.then(function() {
|
||||
service
|
||||
.highlightDetection(highlightedDetection)
|
||||
.selectImage(context, imageKey)
|
||||
.showViewer(context);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function filterData(detectedFeatures) {
|
||||
var service = getService();
|
||||
|
||||
var fromDate = context.photos().fromDate();
|
||||
var toDate = context.photos().toDate();
|
||||
var usernames = context.photos().usernames();
|
||||
const fromDate = context.photos().fromDate();
|
||||
const toDate = context.photos().toDate();
|
||||
|
||||
if (fromDate) {
|
||||
var fromTimestamp = new Date(fromDate).getTime();
|
||||
detectedFeatures = detectedFeatures.filter(function(feature) {
|
||||
return new Date(feature.last_seen_at).getTime() >= fromTimestamp;
|
||||
return new Date(feature.last_seen_at).getTime() >= new Date(fromDate).getTime();
|
||||
});
|
||||
}
|
||||
if (toDate) {
|
||||
var toTimestamp = new Date(toDate).getTime();
|
||||
detectedFeatures = detectedFeatures.filter(function(feature) {
|
||||
return new Date(feature.first_seen_at).getTime() <= toTimestamp;
|
||||
});
|
||||
}
|
||||
if (usernames && service) {
|
||||
detectedFeatures = detectedFeatures.filter(function(feature) {
|
||||
return feature.detections.some(function(detection) {
|
||||
var imageKey = detection.image_key;
|
||||
var image = service.cachedImage(imageKey);
|
||||
return image && usernames.indexOf(image.captured_by) !== -1;
|
||||
});
|
||||
return new Date(feature.first_seen_at).getTime() <= new Date(toDate).getTime();
|
||||
});
|
||||
}
|
||||
|
||||
return detectedFeatures;
|
||||
}
|
||||
|
||||
|
||||
function update() {
|
||||
var service = getService();
|
||||
var data = (service ? service.mapFeatures(projection) : []);
|
||||
const service = getService();
|
||||
let data = (service ? service.mapFeatures(projection) : []);
|
||||
data = filterData(data);
|
||||
|
||||
var selectedImageKey = service && service.getSelectedImageKey();
|
||||
var transform = svgPointTransform(projection);
|
||||
const transform = svgPointTransform(projection);
|
||||
|
||||
var mapFeatures = layer.selectAll('.icon-map-feature')
|
||||
.data(data, function(d) { return d.key; });
|
||||
const mapFeatures = layer.selectAll('.icon-map-feature')
|
||||
.data(data, function(d) { return d.id; });
|
||||
|
||||
// exit
|
||||
mapFeatures.exit()
|
||||
.remove();
|
||||
|
||||
// enter
|
||||
var enter = mapFeatures.enter()
|
||||
const enter = mapFeatures.enter()
|
||||
.append('g')
|
||||
.attr('class', 'icon-map-feature icon-detected')
|
||||
.on('click', click);
|
||||
@@ -173,32 +154,13 @@ export function svgMapillaryMapFeatures(projection, context, dispatch) {
|
||||
// update
|
||||
mapFeatures
|
||||
.merge(enter)
|
||||
.attr('transform', transform)
|
||||
.classed('currentView', function(d) {
|
||||
return d.detections.some(function(detection) {
|
||||
return detection.image_key === selectedImageKey;
|
||||
});
|
||||
})
|
||||
.sort(function(a, b) {
|
||||
var aSelected = a.detections.some(function(detection) {
|
||||
return detection.image_key === selectedImageKey;
|
||||
});
|
||||
var bSelected = b.detections.some(function(detection) {
|
||||
return detection.image_key === selectedImageKey;
|
||||
});
|
||||
if (aSelected === bSelected) {
|
||||
return b.loc[1] - a.loc[1]; // sort Y
|
||||
} else if (aSelected) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
});
|
||||
.attr('transform', transform);
|
||||
}
|
||||
|
||||
|
||||
function drawMapFeatures(selection) {
|
||||
var enabled = svgMapillaryMapFeatures.enabled;
|
||||
var service = getService();
|
||||
const enabled = svgMapillaryMapFeatures.enabled;
|
||||
const service = getService();
|
||||
|
||||
layer = selection.selectAll('.layer-mapillary-map-features')
|
||||
.data(service ? [0] : []);
|
||||
|
||||
@@ -6,12 +6,12 @@ import { services } from '../services';
|
||||
|
||||
|
||||
export function svgMapillaryPosition(projection, context) {
|
||||
var throttledRedraw = _throttle(function () { update(); }, 1000);
|
||||
var minZoom = 12;
|
||||
var minViewfieldZoom = 18;
|
||||
var layer = d3_select(null);
|
||||
var _mapillary;
|
||||
var viewerCompassAngle;
|
||||
const throttledRedraw = _throttle(function () { update(); }, 1000);
|
||||
const minZoom = 12;
|
||||
const minViewfieldZoom = 18;
|
||||
let layer = d3_select(null);
|
||||
let _mapillary;
|
||||
let viewerCompassAngle;
|
||||
|
||||
|
||||
function init() {
|
||||
@@ -23,15 +23,15 @@ export function svgMapillaryPosition(projection, context) {
|
||||
function getService() {
|
||||
if (services.mapillary && !_mapillary) {
|
||||
_mapillary = services.mapillary;
|
||||
_mapillary.event.on('nodeChanged', throttledRedraw);
|
||||
_mapillary.event.on('imageChanged', throttledRedraw);
|
||||
_mapillary.event.on('bearingChanged', function(e) {
|
||||
viewerCompassAngle = e;
|
||||
viewerCompassAngle = e.bearing;
|
||||
|
||||
if (context.map().isTransformed()) return;
|
||||
|
||||
layer.selectAll('.viewfield-group.currentView')
|
||||
.filter(function(d) {
|
||||
return d.pano;
|
||||
return d.is_pano;
|
||||
})
|
||||
.attr('transform', transform);
|
||||
});
|
||||
@@ -54,8 +54,8 @@ export function svgMapillaryPosition(projection, context) {
|
||||
|
||||
|
||||
function transform(d) {
|
||||
var t = svgPointTransform(projection)(d);
|
||||
if (d.pano && viewerCompassAngle !== null && isFinite(viewerCompassAngle)) {
|
||||
let t = svgPointTransform(projection)(d);
|
||||
if (d.is_pano && viewerCompassAngle !== null && isFinite(viewerCompassAngle)) {
|
||||
t += ' rotate(' + Math.floor(viewerCompassAngle) + ',0,0)';
|
||||
} else if (d.ca) {
|
||||
t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
|
||||
@@ -65,21 +65,21 @@ export function svgMapillaryPosition(projection, context) {
|
||||
|
||||
function update() {
|
||||
|
||||
var z = ~~context.map().zoom();
|
||||
var showViewfields = (z >= minViewfieldZoom);
|
||||
const z = ~~context.map().zoom();
|
||||
const showViewfields = (z >= minViewfieldZoom);
|
||||
|
||||
var service = getService();
|
||||
var node = service && service.getActiveImage();
|
||||
const service = getService();
|
||||
const image = service && service.getActiveImage();
|
||||
|
||||
var groups = layer.selectAll('.markers').selectAll('.viewfield-group')
|
||||
.data(node ? [node] : [], function(d) { return d.key; });
|
||||
const groups = layer.selectAll('.markers').selectAll('.viewfield-group')
|
||||
.data(image ? [image] : [], function(d) { return d.id; });
|
||||
|
||||
// exit
|
||||
groups.exit()
|
||||
.remove();
|
||||
|
||||
// enter
|
||||
var groupsEnter = groups.enter()
|
||||
const groupsEnter = groups.enter()
|
||||
.append('g')
|
||||
.attr('class', 'viewfield-group currentView highlighted');
|
||||
|
||||
@@ -89,7 +89,7 @@ export function svgMapillaryPosition(projection, context) {
|
||||
.attr('class', 'viewfield-scale');
|
||||
|
||||
// update
|
||||
var markers = groups
|
||||
const markers = groups
|
||||
.merge(groupsEnter)
|
||||
.attr('transform', transform)
|
||||
.select('.viewfield-scale');
|
||||
@@ -103,7 +103,7 @@ export function svgMapillaryPosition(projection, context) {
|
||||
.attr('dy', '0')
|
||||
.attr('r', '6');
|
||||
|
||||
var viewfields = markers.selectAll('.viewfield')
|
||||
const viewfields = markers.selectAll('.viewfield')
|
||||
.data(showViewfields ? [0] : []);
|
||||
|
||||
viewfields.exit()
|
||||
@@ -112,23 +112,13 @@ export function svgMapillaryPosition(projection, context) {
|
||||
viewfields.enter()
|
||||
.insert('path', 'circle')
|
||||
.attr('class', 'viewfield')
|
||||
.classed('pano', function() { return this.parentNode.__data__.pano; })
|
||||
.attr('transform', 'scale(1.5,1.5),translate(-8, -13)')
|
||||
.attr('d', viewfieldPath);
|
||||
|
||||
function viewfieldPath() {
|
||||
var d = this.parentNode.__data__;
|
||||
if (d.pano) {
|
||||
return 'M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0';
|
||||
} else {
|
||||
return 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z';
|
||||
}
|
||||
}
|
||||
.attr('d', 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z');
|
||||
}
|
||||
|
||||
|
||||
function drawImages(selection) {
|
||||
var service = getService();
|
||||
const service = getService();
|
||||
|
||||
layer = selection.selectAll('.layer-mapillary-position')
|
||||
.data(service ? [0] : []);
|
||||
@@ -136,7 +126,7 @@ export function svgMapillaryPosition(projection, context) {
|
||||
layer.exit()
|
||||
.remove();
|
||||
|
||||
var layerEnter = layer.enter()
|
||||
const layerEnter = layer.enter()
|
||||
.append('g')
|
||||
.attr('class', 'layer-mapillary-position');
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ import { services } from '../services';
|
||||
|
||||
|
||||
export function svgMapillarySigns(projection, context, dispatch) {
|
||||
var throttledRedraw = _throttle(function () { dispatch.call('change'); }, 1000);
|
||||
var minZoom = 12;
|
||||
var layer = d3_select(null);
|
||||
var _mapillary;
|
||||
const throttledRedraw = _throttle(function () { dispatch.call('change'); }, 1000);
|
||||
const minZoom = 12;
|
||||
let layer = d3_select(null);
|
||||
let _mapillary;
|
||||
|
||||
|
||||
function init() {
|
||||
@@ -30,7 +30,7 @@ export function svgMapillarySigns(projection, context, dispatch) {
|
||||
|
||||
|
||||
function showLayer() {
|
||||
var service = getService();
|
||||
const service = getService();
|
||||
if (!service) return;
|
||||
|
||||
service.loadSignResources(context);
|
||||
@@ -56,46 +56,37 @@ export function svgMapillarySigns(projection, context, dispatch) {
|
||||
|
||||
|
||||
function click(d3_event, d) {
|
||||
var service = getService();
|
||||
const service = getService();
|
||||
if (!service) return;
|
||||
|
||||
context.map().centerEase(d.loc);
|
||||
|
||||
var selectedImageKey = service.getSelectedImageKey();
|
||||
var imageKey;
|
||||
var highlightedDetection;
|
||||
// Pick one of the images the sign was detected in,
|
||||
// preference given to an image already selected.
|
||||
d.detections.forEach(function(detection) {
|
||||
if (!imageKey || selectedImageKey === detection.image_key) {
|
||||
imageKey = detection.image_key;
|
||||
highlightedDetection = detection;
|
||||
const selectedImageId = service.getActiveImage() && service.getActiveImage().id;
|
||||
|
||||
service.getDetections(d.id).then(detections => {
|
||||
if (detections.length) {
|
||||
const imageId = detections[0].image.id;
|
||||
if (imageId === selectedImageId) {
|
||||
service
|
||||
.highlightDetection(detections[0])
|
||||
.selectImage(context, imageId);
|
||||
} else {
|
||||
service.ensureViewerLoaded(context)
|
||||
.then(function() {
|
||||
service
|
||||
.highlightDetection(detections[0])
|
||||
.selectImage(context, imageId)
|
||||
.showViewer(context);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (imageKey === selectedImageKey) {
|
||||
service
|
||||
.highlightDetection(highlightedDetection)
|
||||
.selectImage(context, imageKey);
|
||||
} else {
|
||||
service.ensureViewerLoaded(context)
|
||||
.then(function() {
|
||||
service
|
||||
.highlightDetection(highlightedDetection)
|
||||
.selectImage(context, imageKey)
|
||||
.showViewer(context);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function filterData(detectedFeatures) {
|
||||
var service = getService();
|
||||
|
||||
var fromDate = context.photos().fromDate();
|
||||
var toDate = context.photos().toDate();
|
||||
var usernames = context.photos().usernames();
|
||||
|
||||
if (fromDate) {
|
||||
var fromTimestamp = new Date(fromDate).getTime();
|
||||
@@ -109,36 +100,27 @@ export function svgMapillarySigns(projection, context, dispatch) {
|
||||
return new Date(feature.first_seen_at).getTime() <= toTimestamp;
|
||||
});
|
||||
}
|
||||
if (usernames && service) {
|
||||
detectedFeatures = detectedFeatures.filter(function(feature) {
|
||||
return feature.detections.some(function(detection) {
|
||||
var imageKey = detection.image_key;
|
||||
var image = service.cachedImage(imageKey);
|
||||
return image && usernames.indexOf(image.captured_by) !== -1;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return detectedFeatures;
|
||||
}
|
||||
|
||||
|
||||
function update() {
|
||||
var service = getService();
|
||||
var data = (service ? service.signs(projection) : []);
|
||||
const service = getService();
|
||||
let data = (service ? service.signs(projection) : []);
|
||||
data = filterData(data);
|
||||
|
||||
var selectedImageKey = service.getSelectedImageKey();
|
||||
var transform = svgPointTransform(projection);
|
||||
const transform = svgPointTransform(projection);
|
||||
|
||||
var signs = layer.selectAll('.icon-sign')
|
||||
.data(data, function(d) { return d.key; });
|
||||
const signs = layer.selectAll('.icon-sign')
|
||||
.data(data, function(d) { return d.id; });
|
||||
|
||||
// exit
|
||||
signs.exit()
|
||||
.remove();
|
||||
|
||||
// enter
|
||||
var enter = signs.enter()
|
||||
const enter = signs.enter()
|
||||
.append('g')
|
||||
.attr('class', 'icon-sign icon-detected')
|
||||
.on('click', click);
|
||||
@@ -161,32 +143,13 @@ export function svgMapillarySigns(projection, context, dispatch) {
|
||||
// update
|
||||
signs
|
||||
.merge(enter)
|
||||
.attr('transform', transform)
|
||||
.classed('currentView', function(d) {
|
||||
return d.detections.some(function(detection) {
|
||||
return detection.image_key === selectedImageKey;
|
||||
});
|
||||
})
|
||||
.sort(function(a, b) {
|
||||
var aSelected = a.detections.some(function(detection) {
|
||||
return detection.image_key === selectedImageKey;
|
||||
});
|
||||
var bSelected = b.detections.some(function(detection) {
|
||||
return detection.image_key === selectedImageKey;
|
||||
});
|
||||
if (aSelected === bSelected) {
|
||||
return b.loc[1] - a.loc[1]; // sort Y
|
||||
} else if (aSelected) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
});
|
||||
.attr('transform', transform);
|
||||
}
|
||||
|
||||
|
||||
function drawSigns(selection) {
|
||||
var enabled = svgMapillarySigns.enabled;
|
||||
var service = getService();
|
||||
const enabled = svgMapillarySigns.enabled;
|
||||
const service = getService();
|
||||
|
||||
layer = selection.selectAll('.layer-mapillary-signs')
|
||||
.data(service ? [0] : []);
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@
|
||||
"js-yaml": "^4.0.0",
|
||||
"json-stringify-pretty-compact": "^3.0.0",
|
||||
"mapillary_sprite_source": "^1.8.0",
|
||||
"mapillary-js": "~3.1.0",
|
||||
"mapillary-js": "4.0.0",
|
||||
"minimist": "^1.2.3",
|
||||
"mocha": "^7.0.1",
|
||||
"mocha-phantomjs-core": "^2.1.0",
|
||||
|
||||
+55
-260
@@ -33,7 +33,8 @@ describe('iD.serviceMapillary', function() {
|
||||
var cache = mapillary.cache();
|
||||
expect(cache).to.have.property('images');
|
||||
expect(cache).to.have.property('image_detections');
|
||||
expect(cache).to.have.property('map_features');
|
||||
expect(cache).to.have.property('points');
|
||||
expect(cache).to.have.property('signs');
|
||||
expect(cache).to.have.property('sequences');
|
||||
|
||||
mapillary.init();
|
||||
@@ -42,6 +43,7 @@ describe('iD.serviceMapillary', function() {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('#reset', function() {
|
||||
it('resets cache and image', function() {
|
||||
mapillary.cache().foo = 'bar';
|
||||
@@ -49,227 +51,7 @@ describe('iD.serviceMapillary', function() {
|
||||
|
||||
mapillary.reset();
|
||||
expect(mapillary.cache()).to.not.have.property('foo');
|
||||
expect(mapillary.getSelectedImageKey()).to.be.null;
|
||||
});
|
||||
});
|
||||
|
||||
describe('#loadImages', function() {
|
||||
it('fires loadedImages when images are loaded', function(done) {
|
||||
var spy = sinon.spy();
|
||||
mapillary.on('loadedImages', spy);
|
||||
|
||||
mapillary.loadImages(context.projection);
|
||||
|
||||
var features = [{
|
||||
type: 'Feature',
|
||||
geometry: { type: 'Point', coordinates: [10,0] },
|
||||
properties: { ca: 90, key: '0' }
|
||||
}];
|
||||
var response = { type: 'FeatureCollection', features: features };
|
||||
|
||||
server.respondWith('GET', /images/,
|
||||
[200, { 'Content-Type': 'application/json' }, JSON.stringify(response) ]);
|
||||
server.respond();
|
||||
window.setTimeout(function() {
|
||||
expect(spy).to.have.been.called;
|
||||
expect(server.requests().length).to.eql(2);
|
||||
done();
|
||||
}, 500);
|
||||
});
|
||||
|
||||
it('does not load images around null island', function(done) {
|
||||
var spy = sinon.spy();
|
||||
context.projection.translate([0,0]);
|
||||
|
||||
mapillary.on('loadedImages', spy);
|
||||
mapillary.loadImages(context.projection);
|
||||
|
||||
var features = [{
|
||||
type: 'Feature',
|
||||
geometry: { type: 'Point', coordinates: [0,0] },
|
||||
properties: { ca: 90, key: '0' }
|
||||
}];
|
||||
var response = { type: 'FeatureCollection', features: features };
|
||||
|
||||
server.respondWith('GET', /images/,
|
||||
[200, { 'Content-Type': 'application/json' }, JSON.stringify(response) ]);
|
||||
server.respond();
|
||||
|
||||
window.setTimeout(function() {
|
||||
expect(spy).to.have.been.not.called;
|
||||
expect(server.requests().length).to.eql(0); // no tile requests of any kind
|
||||
done();
|
||||
}, 200);
|
||||
});
|
||||
|
||||
it('loads multiple pages of image results', function(done) {
|
||||
var calls = 0;
|
||||
mapillary.on('loadedImages', function() {
|
||||
server.respond(); // respond to new fetches
|
||||
if (++calls === 2) {
|
||||
expect(server.requests().length).to.eql(3); // 2 images, 1 sequences
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
mapillary.loadImages(context.projection);
|
||||
|
||||
var features0 = [];
|
||||
var features1 = [];
|
||||
var i, key;
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
key = String(i);
|
||||
features0.push({
|
||||
type: 'Feature',
|
||||
geometry: { type: 'Point', coordinates: [10,0] },
|
||||
properties: { ca: 90, key: key }
|
||||
});
|
||||
}
|
||||
for (i = 0; i < 500; i++) {
|
||||
key = String(1000 + i);
|
||||
features1.push({
|
||||
type: 'Feature',
|
||||
geometry: { type: 'Point', coordinates: [10,0] },
|
||||
properties: { ca: 90, key: key }
|
||||
});
|
||||
}
|
||||
|
||||
var response0 = { type: 'FeatureCollection', features: features0 };
|
||||
var response1 = { type: 'FeatureCollection', features: features1 };
|
||||
|
||||
server.respondWith('GET', /\/images\?.*&page=0/,
|
||||
[200, { 'Content-Type': 'application/json' }, JSON.stringify(response0) ]);
|
||||
server.respondWith('GET', /\/images\?.*&page=1/,
|
||||
[200, { 'Content-Type': 'application/json' }, JSON.stringify(response1) ]);
|
||||
server.respond();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('#loadSigns', function() {
|
||||
it('fires loadedSigns when signs are loaded', function(done) {
|
||||
var spy = sinon.spy();
|
||||
mapillary.on('loadedSigns', spy);
|
||||
|
||||
mapillary.loadSigns(context.projection);
|
||||
|
||||
var detections = [{ detection_key: '0', image_key: '0' }];
|
||||
var features = [{
|
||||
type: 'Feature',
|
||||
geometry: { type: 'Point', coordinates: [10,0] },
|
||||
properties: { detections: detections, key: '0', value: 'not-in-set' }
|
||||
}];
|
||||
var response = { type: 'FeatureCollection', features: features };
|
||||
|
||||
server.respondWith('GET', /map_features/,
|
||||
[200, { 'Content-Type': 'application/json' }, JSON.stringify(response) ]);
|
||||
server.respond();
|
||||
|
||||
window.setTimeout(function() {
|
||||
expect(spy).to.have.been.called;
|
||||
expect(server.requests().length).to.eql(1);
|
||||
done();
|
||||
}, 200);
|
||||
});
|
||||
|
||||
it('does not load signs around null island', function(done) {
|
||||
var spy = sinon.spy();
|
||||
context.projection.translate([0,0]);
|
||||
|
||||
mapillary.on('loadedSigns', spy);
|
||||
mapillary.loadSigns(context.projection);
|
||||
|
||||
var detections = [{ detection_key: '0', image_key: '0' }];
|
||||
var features = [{
|
||||
type: 'Feature',
|
||||
geometry: { type: 'Point', coordinates: [0,0] },
|
||||
properties: { detections: detections, key: '0', value: 'not-in-set' }
|
||||
}];
|
||||
var response = { type: 'FeatureCollection', features: features };
|
||||
|
||||
server.respondWith('GET', /map_features/,
|
||||
[200, { 'Content-Type': 'application/json' }, JSON.stringify(response) ]);
|
||||
server.respond();
|
||||
|
||||
window.setTimeout(function() {
|
||||
expect(spy).to.have.been.not.called;
|
||||
expect(server.requests().length).to.eql(0); // no tile requests of any kind
|
||||
done();
|
||||
}, 200);
|
||||
});
|
||||
|
||||
it.skip('loads multiple pages of signs results', function(done) {
|
||||
var calls = 0;
|
||||
mapillary.on('loadedSigns', function() {
|
||||
server.respond(); // respond to new fetches
|
||||
if (++calls === 2) {
|
||||
expect(server.requests().length).to.eql(4); // 2 images, 1 map_features, 1 image_detections
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
mapillary.loadSigns(context.projection);
|
||||
|
||||
var features0 = [];
|
||||
var features1 = [];
|
||||
var i, key, detections;
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
key = String(i);
|
||||
detections = [{ detection_key: key, image_key: key }];
|
||||
features0.push({
|
||||
type: 'Feature',
|
||||
geometry: { type: 'Point', coordinates: [10,0] },
|
||||
properties: { detections: detections, key: key, value: 'not-in-set' }
|
||||
});
|
||||
}
|
||||
for (i = 0; i < 500; i++) {
|
||||
key = String(1000 + i);
|
||||
detections = [{ detection_key: key, image_key: key }];
|
||||
features1.push({
|
||||
type: 'Feature',
|
||||
geometry: { type: 'Point', coordinates: [10,0] },
|
||||
properties: { detections: detections, key: key, value: 'not-in-set' }
|
||||
});
|
||||
}
|
||||
|
||||
var response0 = { type: 'FeatureCollection', features: features0 };
|
||||
var response1 = { type: 'FeatureCollection', features: features1 };
|
||||
|
||||
server.respondWith('GET', /\/map_features\?.*&page=0/,
|
||||
[200, { 'Content-Type': 'application/json' }, JSON.stringify(response0) ]);
|
||||
server.respondWith('GET', /\/map_features\?.*&page=1/,
|
||||
[200, { 'Content-Type': 'application/json' }, JSON.stringify(response1) ]);
|
||||
server.respond();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('#loadMapFeatures', function() {
|
||||
it('fires loadedMapFeatures when map features are loaded', function(done) {
|
||||
var spy = sinon.spy();
|
||||
mapillary.on('loadedMapFeatures', spy);
|
||||
|
||||
mapillary.loadMapFeatures(context.projection);
|
||||
|
||||
var detections = [{ detection_key: '0', image_key: '0' }];
|
||||
var features = [{
|
||||
type: 'Feature',
|
||||
geometry: { type: 'Point', coordinates: [10,0] },
|
||||
properties: { detections: detections, key: '0', value: 'not-in-set' }
|
||||
}];
|
||||
var response = { type: 'FeatureCollection', features: features };
|
||||
|
||||
server.respondWith('GET', /map_features/,
|
||||
[200, { 'Content-Type': 'application/json' }, JSON.stringify(response) ]);
|
||||
server.respond();
|
||||
|
||||
window.setTimeout(function() {
|
||||
expect(spy).to.have.been.called;
|
||||
expect(server.requests().length).to.eql(1);
|
||||
done();
|
||||
}, 500);
|
||||
expect(mapillary.getActiveImage()).to.be.null;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -310,26 +92,56 @@ describe('iD.serviceMapillary', function() {
|
||||
|
||||
describe('#signs', function() {
|
||||
it('returns signs in the visible map area', function() {
|
||||
var detections = [{
|
||||
detection_key: '78vqha63gs1upg15s823qckcmn',
|
||||
image_key: 'bwYs-uXLDvm_meo_EC5Nzw'
|
||||
}];
|
||||
var features = [
|
||||
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: { key: '0', loc: [10,0], detections: detections } },
|
||||
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: { key: '1', loc: [10,0], detections: detections } },
|
||||
{ minX: 10, minY: 1, maxX: 10, maxY: 1, data: { key: '2', loc: [10,1], detections: detections } }
|
||||
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: { key: '0', loc: [10,0] } },
|
||||
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: { key: '1', loc: [10,0] } },
|
||||
{ minX: 10, minY: 1, maxX: 10, maxY: 1, data: { key: '2', loc: [10,1] } }
|
||||
];
|
||||
|
||||
mapillary.cache().map_features.rtree.load(features);
|
||||
mapillary.cache().signs.rtree.load(features);
|
||||
var res = mapillary.signs(context.projection);
|
||||
|
||||
expect(res).to.deep.eql([
|
||||
{ key: '0', loc: [10,0], detections: detections },
|
||||
{ key: '1', loc: [10,0], detections: detections }
|
||||
{ key: '0', loc: [10,0] },
|
||||
{ key: '1', loc: [10,0] }
|
||||
]);
|
||||
});
|
||||
|
||||
it('limits results no more than 5 stacked signs in one spot', function() {
|
||||
var features = [
|
||||
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: { key: '0', loc: [10,0] } },
|
||||
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: { key: '1', loc: [10,0] } },
|
||||
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: { key: '2', loc: [10,0] } },
|
||||
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: { key: '3', loc: [10,0] } },
|
||||
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: { key: '4', loc: [10,0] } },
|
||||
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: { key: '5', loc: [10,0] } }
|
||||
];
|
||||
|
||||
mapillary.cache().signs.rtree.load(features);
|
||||
var res = mapillary.signs(context.projection);
|
||||
expect(res).to.have.length.of.at.most(5);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('#mapFeatures', function() {
|
||||
it('returns map features in the visible map area', function() {
|
||||
var features = [
|
||||
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: { key: '0', loc: [10,0] } },
|
||||
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: { key: '1', loc: [10,0] } },
|
||||
{ minX: 10, minY: 1, maxX: 10, maxY: 1, data: { key: '2', loc: [10,1] } }
|
||||
];
|
||||
|
||||
mapillary.cache().points.rtree.load(features);
|
||||
var res = mapillary.mapFeatures(context.projection);
|
||||
|
||||
expect(res).to.deep.eql([
|
||||
{ key: '0', loc: [10,0] },
|
||||
{ key: '1', loc: [10,0] }
|
||||
]);
|
||||
});
|
||||
|
||||
it('limits results no more than 5 stacked map features in one spot', function() {
|
||||
var detections = [{
|
||||
detection_key: '78vqha63gs1upg15s823qckcmn',
|
||||
image_key: 'bwYs-uXLDvm_meo_EC5Nzw'
|
||||
@@ -343,8 +155,8 @@ describe('iD.serviceMapillary', function() {
|
||||
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: { key: '5', loc: [10,0], detections: detections } }
|
||||
];
|
||||
|
||||
mapillary.cache().map_features.rtree.load(features);
|
||||
var res = mapillary.signs(context.projection);
|
||||
mapillary.cache().points.rtree.load(features);
|
||||
var res = mapillary.mapFeatures(context.projection);
|
||||
expect(res).to.have.length.of.at.most(5);
|
||||
});
|
||||
});
|
||||
@@ -353,9 +165,9 @@ describe('iD.serviceMapillary', function() {
|
||||
describe('#sequences', function() {
|
||||
it('returns sequence linestrings in the visible map area', function() {
|
||||
var features = [
|
||||
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: { key: '0', loc: [10,0], ca: 90 } },
|
||||
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: { key: '1', loc: [10,0], ca: 90 } },
|
||||
{ minX: 10, minY: 1, maxX: 10, maxY: 1, data: { key: '2', loc: [10,1], ca: 90 } }
|
||||
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: { key: '0', loc: [10,0], ca: 90, sequence_id: '-' } },
|
||||
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: { key: '1', loc: [10,0], ca: 90, sequence_id: '-' } },
|
||||
{ minX: 10, minY: 1, maxX: 10, maxY: 1, data: { key: '2', loc: [10,1], ca: 90, sequence_id: '-' } }
|
||||
];
|
||||
|
||||
mapillary.cache().images.rtree.load(features);
|
||||
@@ -376,40 +188,24 @@ describe('iD.serviceMapillary', function() {
|
||||
}
|
||||
};
|
||||
|
||||
mapillary.cache().sequences.lineString['-'] = gj;
|
||||
mapillary.cache().sequences.forImageKey['0'] = '-';
|
||||
mapillary.cache().sequences.forImageKey['1'] = '-';
|
||||
mapillary.cache().sequences.forImageKey['2'] = '-';
|
||||
mapillary.cache().sequences.lineString['-'] = [gj];
|
||||
|
||||
var res = mapillary.sequences(context.projection);
|
||||
expect(res).to.deep.eql([gj]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#selectImage', function() {
|
||||
|
||||
describe('#setActiveImage', function() {
|
||||
it('gets and sets the selected image', function() {
|
||||
var d = { key: 'baz', loc: [10,0] };
|
||||
mapillary.selectImage(context, d.key);
|
||||
expect(mapillary.getSelectedImageKey()).to.eql(d.key);
|
||||
var node = { id: 'baz', originalLngLat: {lng: 10, lat: 0}};
|
||||
mapillary.setActiveImage(node);
|
||||
expect(mapillary.getActiveImage().id).to.eql(node.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#parsePagination', function() {
|
||||
it('gets URL for next page of results from API', function() {
|
||||
var linkHeader = '<https://a.mapillary.com/v3/images?per_page=1000>; rel="first", <https://a.mapillary.com/v3/images?per_page=1000&_start_key_time=1476610926080>; rel="next"';
|
||||
var pagination = mapillary.parsePagination(linkHeader);
|
||||
expect(pagination.first).to.eql('https://a.mapillary.com/v3/images?per_page=1000');
|
||||
expect(pagination.next).to.eql('https://a.mapillary.com/v3/images?per_page=1000&_start_key_time=1476610926080');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#filterViewer', function() {
|
||||
it('filters images by username', function() {
|
||||
context.photos().setUsernameFilter('mapillary');
|
||||
var filter = mapillary.filterViewer(context);
|
||||
expect(filter.length).to.be.equal(2);
|
||||
});
|
||||
|
||||
it('filters images by dates', function() {
|
||||
context.photos().setDateFilter('fromDate', '2020-01-01');
|
||||
context.photos().setDateFilter('toDate', '2021-01-01');
|
||||
@@ -417,5 +213,4 @@ describe('iD.serviceMapillary', function() {
|
||||
expect(filter.length).to.be.equal(3);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user