Skip to content

Commit

Permalink
Store detections and signs in the same cache
Browse files Browse the repository at this point in the history
(closes #1538)

Before, by having them in different caches, it was possible for a point detection and
a sign detection to be in the same place (which we were trying to avoid with #1516)

Now by putting them in the same cache, the code that prevents coincident
detections can work to keep them spread a little bit apart.
  • Loading branch information
bhousel committed Sep 11, 2024
1 parent 8313630 commit 74758b6
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 27 deletions.
36 changes: 19 additions & 17 deletions modules/services/MapillaryService.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ export class MapillaryService extends AbstractSystem {

this._cache = {
images: { lastv: null, data: new Map(), rbush: new RBush() },
signs: { lastv: null, data: new Map(), rbush: new RBush() },
detections: { lastv: null, data: new Map(), rbush: new RBush() },
signs: { lastv: null /* signs are now stored in `detections` cache */ },
sequences: { data: new Map() }, // Map<sequenceID, Array<LineStrings>>
segmentations: { data: new Map() },
inflight: new Map(), // Map<url, {tileID, promise, controller}>
Expand Down Expand Up @@ -217,10 +217,7 @@ export class MapillaryService extends AbstractSystem {
* @return {Object?} The detection, or `undefined` if not found
*/
getDetection(detectionID) {
// Check both 'detections' and 'signs' caches
let detection = this._cache.detections.data.get(detectionID);
if (detection) return detection;
return this._cache.signs.data.get(detectionID);
return this._cache.detections.data.get(detectionID);
}


Expand All @@ -234,8 +231,16 @@ export class MapillaryService extends AbstractSystem {
if (!['images', 'signs', 'detections'].includes(datasetID)) return [];

const extent = this.context.viewport.visibleExtent();
const cache = this._cache[datasetID];
return cache.rbush.search(extent.bbox()).map(d => d.data);
if (datasetID === 'images') {
return this._cache.images.rbush.search(extent.bbox())
.map(d => d.data);

} else { // both signs and detections are now stored in the `detections` cache
const type = (datasetID === 'signs') ? 'traffic_sign' : 'point';
return this._cache.detections.rbush.search(extent.bbox())
.map(d => d.data)
.filter(d => d.object_type === type);
}
}


Expand Down Expand Up @@ -826,12 +831,11 @@ export class MapillaryService extends AbstractSystem {
}

// 'point' and 'traffic_sign' are both detection layers.
// We treat them the same, but their data gets stored in different caches.
// (This allows the user to toggle them on/off independently of each other)
// Both of these are stored in the `detections` cache.
for (const type of ['point', 'traffic_sign']) {
if (!vectorTile.layers.hasOwnProperty(type)) continue;

const cache = (type === 'traffic_sign') ? this._cache.signs : this._cache.detections;
const cache = this._cache.detections;
const layer = vectorTile.layers[type];

for (let i = 0; i < layer.length; i++) {
Expand Down Expand Up @@ -863,10 +867,7 @@ export class MapillaryService extends AbstractSystem {
*/
_loadDetectionAsync(detectionID) {
// Is data is cached already and includes the `images` Array? If so, resolve immediately.
const detection =
this._cache.detections.data.get(detectionID) ||
this._cache.signs.data.get(detectionID);

const detection = this._cache.detections.data.get(detectionID);
if (Array.isArray(detection?.images)) {
return Promise.resolve(detection);
}
Expand All @@ -882,8 +883,9 @@ export class MapillaryService extends AbstractSystem {
throw new Error('No Data');
}

const type = response.object_type; // Seems to be 'mvd_fast' or 'trafficsign' ??
const cache = (type === 'trafficsign') ? this._cache.signs : this._cache.detections;
// `response.object_type` seems to be 'mvd_fast' or 'trafficsign' ??
const type = (response.object_type === 'trafficsign') ? 'traffic_sign' : 'point';
const cache = this._cache.detections;

// Note that the graph API _does_ give us `images` and `aligned_direction`
// (but sometimes not `geometry`!? see Rapid#1557)
Expand All @@ -895,7 +897,7 @@ export class MapillaryService extends AbstractSystem {
last_seen_at: response.last_seen_at,
value: response.object_value,
aligned_direction: response.aligned_direction,
object_type: (type === 'trafficsign') ? 'traffic_sign' : 'point'
object_type: type
});

this.context.immediateRedraw();
Expand Down
20 changes: 10 additions & 10 deletions test/browser/services/MapillaryService.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ describe('MapillaryService', () => {
it('initializes cache', () => {
const cache = _mapillary._cache;
expect(cache).to.have.property('images');
expect(cache).to.have.property('signs');
expect(cache).to.have.property('detections');
expect(cache).to.have.property('signs');
expect(cache).to.have.property('sequences');
expect(cache).to.have.property('segmentations');
});
Expand Down Expand Up @@ -74,9 +74,9 @@ describe('MapillaryService', () => {

it('returns detections in the visible map area', () => {
const data = [
{ type: 'detection', id: 'detect0', loc: [10,0] },
{ type: 'detection', id: 'detect1', loc: [10,0] },
{ type: 'detection', id: 'detect2', loc: [10,1] }
{ type: 'detection', id: 'detect0', loc: [10,0], object_type: 'point' },
{ type: 'detection', id: 'detect1', loc: [10,0], object_type: 'point' },
{ type: 'detection', id: 'detect2', loc: [10,1], object_type: 'point' }
];
const boxes = [
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: data[0] },
Expand All @@ -96,23 +96,23 @@ describe('MapillaryService', () => {


it('returns signs in the visible map area', () => {
// signs are also detections, but stored in a different cache
const data = [
{ type: 'detection', id: 'sign0', loc: [10,0] },
{ type: 'detection', id: 'sign1', loc: [10,0] },
{ type: 'detection', id: 'sign2', loc: [10,1] }
{ type: 'detection', id: 'sign0', loc: [10,0], object_type: 'traffic_sign' },
{ type: 'detection', id: 'sign1', loc: [10,0], object_type: 'traffic_sign' },
{ type: 'detection', id: 'sign2', loc: [10,1], object_type: 'traffic_sign' }
];
const boxes = [
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: data[0] },
{ minX: 10, minY: 0, maxX: 10, maxY: 0, data: data[1] },
{ minX: 10, minY: 1, maxX: 10, maxY: 1, data: data[2] }
];

// signs are now also stored in the detections cache
const cache = _mapillary._cache;
for (const d of data) {
cache.signs.data.set(d.id, d);
cache.detections.data.set(d.id, d);
}
cache.signs.rbush.load(boxes);
cache.detections.rbush.load(boxes);

const result = _mapillary.getData('signs');
expect(result).to.deep.eql([data[0], data[1]]);
Expand Down

0 comments on commit 74758b6

Please sign in to comment.