Support multiple semicolon delimited direction values

(closes #4755)
This commit is contained in:
Bryan Housel
2018-01-29 17:49:08 -05:00
parent 660a7c09e5
commit 80a998e9c5
2 changed files with 69 additions and 28 deletions

View File

@@ -1,6 +1,7 @@
import _extend from 'lodash-es/extend';
import _map from 'lodash-es/map';
import _some from 'lodash-es/some';
import _uniq from 'lodash-es/uniq';
import { osmEntity } from './entity';
import { geoAngle, geoExtent } from '../geo';
@@ -73,7 +74,8 @@ _extend(osmNode.prototype, {
}
}
// swap cardinal for numeric directions
if (val === '') return [];
var cardinal = {
north: 0, n: 0,
northnortheast: 22, nne: 22,
@@ -92,41 +94,56 @@ _extend(osmNode.prototype, {
northwest: 315, nw: 315,
northnorthwest: 337, nnw: 337
};
if (cardinal[val] !== undefined) {
val = cardinal[val];
}
// if direction is numeric, return early
if (val !== '' && !isNaN(+val)) {
return [(+val)];
}
var lookBackward =
(this.tags['traffic_sign:backward'] || val === 'backward' || val === 'both' || val === 'all');
var lookForward =
(this.tags['traffic_sign:forward'] || val === 'forward' || val === 'both' || val === 'all');
var values = val.split(';');
var results = [];
if (!lookForward && !lookBackward) return [];
values.forEach(function(v) {
// swap cardinal for numeric directions
if (cardinal[v] !== undefined) {
v = cardinal[v];
}
var nodeIds = {};
resolver.parentWays(this).forEach(function(parent) {
var nodes = parent.nodes;
for (i = 0; i < nodes.length; i++) {
if (nodes[i] === this.id) { // match current entity
if (lookForward && i > 0) {
nodeIds[nodes[i - 1]] = true; // look back to prev node
}
if (lookBackward && i < nodes.length - 1) {
nodeIds[nodes[i + 1]] = true; // look ahead to next node
// numeric direction - just add to results
if (v !== '' && !isNaN(+v)) {
results.push(+v);
return;
}
// string direction - inspect parent ways
var lookBackward =
(this.tags['traffic_sign:backward'] || v === 'backward' || v === 'both' || v === 'all');
var lookForward =
(this.tags['traffic_sign:forward'] || v === 'forward' || v === 'both' || v === 'all');
if (!lookForward && !lookBackward) return;
var nodeIds = {};
resolver.parentWays(this).forEach(function(parent) {
var nodes = parent.nodes;
for (i = 0; i < nodes.length; i++) {
if (nodes[i] === this.id) { // match current entity
if (lookForward && i > 0) {
nodeIds[nodes[i - 1]] = true; // look back to prev node
}
if (lookBackward && i < nodes.length - 1) {
nodeIds[nodes[i + 1]] = true; // look ahead to next node
}
}
}
}
}, this);
Object.keys(nodeIds).forEach(function(nodeId) {
// +90 because geoAngle returns angle from X axis, not Y (north)
results.push(
(geoAngle(this, resolver.entity(nodeId), projection) * (180 / Math.PI)) + 90
);
}, this);
}, this);
return Object.keys(nodeIds).map(function(nodeId) {
// +90 because geoAngle returns angle from X axis, not Y (north)
return (geoAngle(this, resolver.entity(nodeId), projection) * (180 / Math.PI)) + 90;
}, this);
return _uniq(results);
},

View File

@@ -565,6 +565,30 @@ describe('iD.osmNode', function () {
expect(node2.directions(graph, projection)).to.eql([]);
});
it('supports multiple directions delimited by ;', function () {
var node1 = iD.osmNode({ loc: [0, 0], tags: { direction: '0;45' }});
var node2 = iD.osmNode({ loc: [0, 0], tags: { direction: '45;north' }});
var node3 = iD.osmNode({ loc: [0, 0], tags: { direction: 'north;east' }});
var node4 = iD.osmNode({ loc: [0, 0], tags: { direction: 'n;s;e;w' }});
var node5 = iD.osmNode({ loc: [0, 0], tags: { direction: 's;wat' }});
var graph = iD.coreGraph([node1, node2, node3, node4, node5]);
expect(node1.directions(graph, projection)).to.eql([0, 45], 'numeric 0, numeric 45');
expect(node2.directions(graph, projection)).to.eql([45, 0], 'numeric 45, cardinal north');
expect(node3.directions(graph, projection)).to.eql([0, 90], 'cardinal north and east');
expect(node4.directions(graph, projection)).to.eql([0, 180, 90, 270], 'cardinal n,s,e,w');
expect(node5.directions(graph, projection)).to.eql([180], 'cardinal 180 and nonsense');
});
it('supports mixing textual, cardinal, numeric directions, delimited by ;', function () {
var node1 = iD.osmNode({ id: 'n1', loc: [-1, 0] });
var node2 = iD.osmNode({ id: 'n2', loc: [0, 0], tags: { 'camera:direction': 'both;ne;60' }});
var node3 = iD.osmNode({ id: 'n3', loc: [1, 0] });
var way = iD.osmWay({ nodes: ['n1','n2','n3'] });
var graph = iD.coreGraph([node1, node2, node3, way]);
expect(node2.directions(graph, projection)).to.have.members([90, 270, 45, 60]);
});
});
describe('#asJXON', function () {