diff --git a/features/car/route_relations.feature b/features/car/route_relations.feature index dd305d4ce..104661775 100644 --- a/features/car/route_relations.feature +++ b/features/car/route_relations.feature @@ -3,66 +3,230 @@ Feature: Car - route relations Background: Given the profile "car" - @sliproads - Scenario: Cardinal direction assignment to refs + Scenario: Assignment using relation membership roles Given the node map """ - a b - | | - c------+--+------d - e------+--+------f - | | - g h - - i----------------j - k----------------l - - x----------------y - z----------------w + a----------------b + c----------------d """ And the ways | nodes | name | highway | ref | - | ag | southbound | motorway | I 80 | - | hb | northbound | motorway | I 80 | - | dc | westbound | motorway | I 85;CO 93 | - | ef | eastbound | motorway | I 85;US 12 | - | ij | westbound-2 | motorway | I 99 | - | ji | eastbound-2 | motorway | I 99 | - | kl | eastbound-2 | motorway | I 99 | - | lk | eastbound-2 | motorway | I 99 | - | xy | watermill | motorway | I 45M; US 3 | + | ba | westbound | motorway | I 80 | + | cd | eastbound | motorway | I 80;CO 93 | And the relations - | type | way:south | route | ref | - | route | ag | road | 80 | - | route | ef | road | 12 | + | type | way:east | way:west | route | ref | network | + | route | cd | ba | road | 80 | US:I | + | route | cd | ba | road | 93 | US:CO | - And the relations - | type | way:north | route | ref | - | route | hb | road | 80 | - | route | cd | road | 93 | - - And the relations - | type | way:west | route | ref | - | route | dc | road | 85 | - | route | ij | road | 99 | - | route | xy | road | I 45 | - - And the relations - | type | way:east | route | ref | - | route | lk | road | I 99 | - - And the relations - | type | way:east | route | ref | - | route | xy | road | US 3 | When I route I should get - | waypoints | route | ref | - | a,g | southbound,southbound | I 80 $south,I 80 $south | - | h,b | northbound,northbound | I 80 $north,I 80 $north | - | d,c | westbound,westbound | I 85 $west; CO 93 $north,I 85 $west; CO 93 $north | - | e,f | eastbound,eastbound | I 85; US 12 $south,I 85; US 12 $south | - | i,j | westbound-2,westbound-2 | I 99 $west,I 99 $west | - | l,k | eastbound-2,eastbound-2 | I 99 $east,I 99 $east | - | x,y | watermill,watermill | I 45M $west; US 3 $east,I 45M $west; US 3 $east | \ No newline at end of file + | waypoints | route | ref | + | b,a | westbound,westbound | I 80 $west,I 80 $west | + | c,d | eastbound,eastbound | I 80 $east; CO 93 $east,I 80 $east; CO 93 $east | + + Scenario: Assignment using relation direction property (no role on members) + Given the node map + """ + a----------------b + c----------------d + """ + + And the ways + | nodes | name | highway | ref | + | ba | westbound | motorway | I 80 | + | cd | eastbound | motorway | I 80;CO 93 | + + And the relations + | type | direction | way | route | ref | network | + | route | west | ba | road | 80 | US:I | + | route | east | cd | road | 80 | US:I | + | route | east | cd | road | 93 | US:CO | + + When I route I should get + | waypoints | route | ref | + | b,a | westbound,westbound | I 80 $west,I 80 $west | + | c,d | eastbound,eastbound | I 80 $east; CO 93 $east,I 80 $east; CO 93 $east | + + + Scenario: Forward assignment on one-way roads using relation direction property + Given the node map + """ + a----------------b + c----------------d + """ + + And the ways + | nodes | name | highway | ref | + | ba | westbound | motorway | I 80 | + | cd | eastbound | motorway | I 80;CO 93 | + + And the relations + | type | direction | way:forward | route | ref | network | + | route | west | ba | road | 80 | US:I | + | route | east | cd | road | 80 | US:I | + | route | east | cd | road | 93 | US:CO | + + When I route I should get + | waypoints | route | ref | + | b,a | westbound,westbound | I 80 $west,I 80 $west | + | c,d | eastbound,eastbound | I 80 $east; CO 93 $east,I 80 $east; CO 93 $east | + + + Scenario: Forward/backward assignment on non-divided roads with role direction tag + Given the node map + """ + a----------------b + """ + + And the ways + | nodes | name | highway | ref | oneway | + | ab | mainroad | motorway | I 80 | no | + + And the relations + | type | direction | way:forward | route | ref | network | + | route | west | ab | road | 80 | US:I | + + And the relations + | type | direction | way:backward | route | ref | network | + | route | east | ab | road | 80 | US:I | + + When I route I should get + | waypoints | route | ref | + | b,a | mainroad,mainroad | I 80 $west,I 80 $west | + | a,b | mainroad,mainroad | I 80 $east,I 80 $east | + + + Scenario: Conflict between role and direction + Given the node map + """ + a----------------b + """ + + And the ways + | nodes | name | highway | ref | + | ab | eastbound | motorway | I 80 | + + And the relations + | type | direction | way:east | route | ref | network | + | route | west | ab | road | 80 | US:I | + + When I route I should get + | waypoints | route | ref | + | a,b | eastbound,eastbound | I 80,I 80 | + + + Scenario: Conflict between role and superrelation direction + Given the node map + """ + a----------------b + """ + + And the ways + | nodes | name | highway | ref | + | ab | eastbound | motorway | I 80 | + + And the relations + | type | way:east | route | ref | network | name | + | route | ab | road | 80 | US:I | baserelation | + + And the relations + | type | direction | relation | route | ref | network | name | + | route | east | baserelation | road | 80 | US:I | superrelation | + + When I route I should get + | waypoints | route | ref | + | a,b | eastbound,eastbound | I 80,I 80 | + + Scenario: Conflict between role and superrelation role + Given the node map + """ + a----------------b + """ + + And the ways + | nodes | name | highway | ref | + | ab | eastbound | motorway | I 80 | + + And the relations + | type | way:east | route | ref | network | name | + | route | ab | road | 80 | US:I | baserelation | + + And the relations + | type | relation:west | route | ref | network | name | + | route | baserelation | road | 80 | US:I | superrelation | + + When I route I should get + | waypoints | route | ref | + | a,b | eastbound,eastbound | I 80,I 80 | + + Scenario: Direction only available via superrelation role + Given the node map + """ + a----------------b + """ + + And the ways + | nodes | name | highway | ref | + | ab | eastbound | motorway | I 80 | + + And the relations + | type | way:forward | route | ref | network | name | + | route | ab | road | 80 | US:I | baserelation | + + And the relations + | type | relation:east | route | ref | network | name | + | route | baserelation | road | 80 | US:I | superrelation | + + When I route I should get + | waypoints | route | ref | + | a,b | eastbound,eastbound | I 80 $east,I 80 $east | + + Scenario: Direction only available via superrelation direction + Given the node map + """ + a----------------b + """ + + And the ways + | nodes | name | highway | ref | + | ab | eastbound | motorway | I 80 | + + And the relations + | type | way:forward | route | ref | network | name | + | route | ab | road | 80 | US:I | baserelation | + + And the relations + | type | direction | relation | route | ref | network | name | + | route | east | baserelation | road | 80 | US:I | superrelation | + + When I route I should get + | waypoints | route | ref | + | a,b | eastbound,eastbound | I 80 $east,I 80 $east | + + Scenario: Three levels of indirection + Given the node map + """ + a----------------b + """ + + And the ways + | nodes | name | highway | ref | + | ab | eastbound | motorway | I 80 | + + And the relations + | type | way:forward | route | ref | network | name | + | route | ab | road | 80 | US:I | baserelation | + + And the relations + | type | relation | route | ref | network | name | + | route | baserelation | road | 80 | US:I | superrelation1 | + + And the relations + | type | direction | relation | route | ref | network | name | + | route | east | superrelation1 | road | 80 | US:I | superrelation2 | + + When I route I should get + | waypoints | route | ref | + | a,b | eastbound,eastbound | I 80 $east,I 80 $east | \ No newline at end of file diff --git a/features/lib/osm.js b/features/lib/osm.js index 5b03bd59d..18d688cfa 100644 --- a/features/lib/osm.js +++ b/features/lib/osm.js @@ -86,11 +86,12 @@ class DB { }); r.members.forEach((m) => { - relation.ele('member', { + var d = { type: m.type, - ref: m.id, - role: m.role - }); + ref: m.id + }; + if (m.role) d.role = m.role; + relation.ele('member', d); }); for (var k in r.tags) { diff --git a/features/step_definitions/data.js b/features/step_definitions/data.js index fdba9418a..c06fb14ce 100644 --- a/features/step_definitions/data.js +++ b/features/step_definitions/data.js @@ -188,9 +188,12 @@ module.exports = function () { let addRelation = (row, cb) => { let relation = new OSM.Relation(this.makeOSMId(), this.OSM_USER, this.OSM_TIMESTAMP, this.OSM_UID); + + var name = null; for (let key in row) { - let isNode = key.match(/^node:(.*)/), - isWay = key.match(/^way:(.*)/), + let isNode = key.match(/^node:?(.*)/), + isWay = key.match(/^way:?(.*)/), + isRelation = key.match(/^relation:?(.*)/), isColonSeparated = key.match(/^(.*):(.*)/); if (isNode) { row[key].split(',').map(function(v) { return v.trim(); }).forEach((nodeName) => { @@ -205,14 +208,26 @@ module.exports = function () { if (!way) throw new Error(util.format('*** unknown relation way member "%s"', wayName)); relation.addMember('way', way.id, isWay[1]); }); + } else if (isRelation) { + row[key].split(',').map(function(v) { return v.trim(); }).forEach((relName) => { + let otherrelation = this.findRelationByName(relName); + if (!otherrelation) throw new Error(util.format('*** unknown relation relation member "%s"', relName)); + relation.addMember('relation', otherrelation.id, isRelation[1]); + }); } else if (isColonSeparated && isColonSeparated[1] !== 'restriction') { throw new Error(util.format('*** unknown relation member type "%s:%s", must be either "node" or "way"', isColonSeparated[1], isColonSeparated[2])); } else { relation.addTag(key, row[key]); + if (key.match(/name/)) name = row[key]; } } relation.uid = this.OSM_UID; + + if (name) { + this.nameRelationHash[name] = relation; + } + this.OSMDB.addRelation(relation); cb(); diff --git a/features/support/data.js b/features/support/data.js index 2a5deb479..e9e1f06f4 100644 --- a/features/support/data.js +++ b/features/support/data.js @@ -144,6 +144,10 @@ module.exports = function () { return this.nameWayHash[s.toString()] || this.nameWayHash[s.toString().split('').reverse().join('')]; }; + this.findRelationByName = (s) => { + return this.nameRelationHash[s.toString()] || this.nameRelationHash[s.toString().split('').reverse().join('')]; + }; + this.makeOSMId = () => { this.osmID = this.osmID + 1; return this.osmID; @@ -155,6 +159,7 @@ module.exports = function () { this.locationHash = {}; this.shortcutsHash = {}; this.nameWayHash = {}; + this.nameRelationHash = {}; this.osmID = 0; };