From 93758b7ab957a27ae64b17c7b55f0783f8dcf3be Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 9 May 2014 16:39:09 -0700 Subject: [PATCH 01/26] Add turn restriction presets --- data/presets.yaml | 14 +++++ data/presets/fields.json | 5 ++ data/presets/fields/except.json | 5 ++ data/presets/presets.json | 59 ++++++++++++++++++- data/presets/presets/type/restriction.json | 3 +- .../type/restriction/no_left_turn.json | 14 +++++ .../type/restriction/no_right_turn.json | 14 +++++ .../type/restriction/no_straight_on.json | 14 +++++ .../presets/type/restriction/no_u_turn.json | 14 +++++ dist/locales/en.json | 19 ++++++ 10 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 data/presets/fields/except.json create mode 100644 data/presets/presets/type/restriction/no_left_turn.json create mode 100644 data/presets/presets/type/restriction/no_right_turn.json create mode 100644 data/presets/presets/type/restriction/no_straight_on.json create mode 100644 data/presets/presets/type/restriction/no_u_turn.json diff --git a/data/presets.yaml b/data/presets.yaml index ceb5a3dba..1c661f7e4 100644 --- a/data/presets.yaml +++ b/data/presets.yaml @@ -138,6 +138,8 @@ en: label: Emergency entrance: label: Type + except: + label: Exceptions fax: label: Fax placeholder: +31 42 123 4567 @@ -1788,6 +1790,18 @@ en: type/restriction: name: Restriction terms: "" + type/restriction/no_left_turn: + name: No Left Turn + terms: "" + type/restriction/no_right_turn: + name: No Right Turn + terms: "" + type/restriction/no_straight_on: + name: No Straight On + terms: "" + type/restriction/no_u_turn: + name: No U Turn + terms: "" type/route: name: Route terms: "" diff --git a/data/presets/fields.json b/data/presets/fields.json index 65545df54..c25b151e9 100644 --- a/data/presets/fields.json +++ b/data/presets/fields.json @@ -320,6 +320,11 @@ "type": "typeCombo", "label": "Type" }, + "except": { + "key": "except", + "type": "combo", + "label": "Exceptions" + }, "fax": { "key": "fax", "type": "tel", diff --git a/data/presets/fields/except.json b/data/presets/fields/except.json new file mode 100644 index 000000000..38458d088 --- /dev/null +++ b/data/presets/fields/except.json @@ -0,0 +1,5 @@ +{ + "key": "except", + "type": "combo", + "label": "Exceptions" +} \ No newline at end of file diff --git a/data/presets/presets.json b/data/presets/presets.json index db8be2222..407d0418b 100644 --- a/data/presets/presets.json +++ b/data/presets/presets.json @@ -7964,9 +7964,66 @@ "name": "Restriction", "icon": "restriction", "fields": [ - "restriction" + "restriction", + "except" ] }, + "type/restriction/no_left_turn": { + "name": "No Left Turn", + "geometry": [ + "relation" + ], + "tags": { + "type": "restriction", + "restriction": "no_left_turn" + }, + "fields": [ + "except" + ], + "icon": "restriction" + }, + "type/restriction/no_right_turn": { + "name": "No Right Turn", + "geometry": [ + "relation" + ], + "tags": { + "type": "restriction", + "restriction": "no_right_turn" + }, + "fields": [ + "except" + ], + "icon": "restriction" + }, + "type/restriction/no_straight_on": { + "name": "No Straight On", + "geometry": [ + "relation" + ], + "tags": { + "type": "restriction", + "restriction": "no_straight_on" + }, + "fields": [ + "except" + ], + "icon": "restriction" + }, + "type/restriction/no_u_turn": { + "name": "No U Turn", + "geometry": [ + "relation" + ], + "tags": { + "type": "restriction", + "restriction": "no_u_turn" + }, + "fields": [ + "except" + ], + "icon": "restriction" + }, "type/route": { "geometry": [ "relation" diff --git a/data/presets/presets/type/restriction.json b/data/presets/presets/type/restriction.json index 416a0add1..3ebf5e58a 100644 --- a/data/presets/presets/type/restriction.json +++ b/data/presets/presets/type/restriction.json @@ -8,6 +8,7 @@ "name": "Restriction", "icon": "restriction", "fields": [ - "restriction" + "restriction", + "except" ] } \ No newline at end of file diff --git a/data/presets/presets/type/restriction/no_left_turn.json b/data/presets/presets/type/restriction/no_left_turn.json new file mode 100644 index 000000000..aa9bcaf95 --- /dev/null +++ b/data/presets/presets/type/restriction/no_left_turn.json @@ -0,0 +1,14 @@ +{ + "name": "No Left Turn", + "geometry": [ + "relation" + ], + "tags": { + "type": "restriction", + "restriction": "no_left_turn" + }, + "fields": [ + "except" + ], + "icon": "restriction" +} diff --git a/data/presets/presets/type/restriction/no_right_turn.json b/data/presets/presets/type/restriction/no_right_turn.json new file mode 100644 index 000000000..cb0f6698c --- /dev/null +++ b/data/presets/presets/type/restriction/no_right_turn.json @@ -0,0 +1,14 @@ +{ + "name": "No Right Turn", + "geometry": [ + "relation" + ], + "tags": { + "type": "restriction", + "restriction": "no_right_turn" + }, + "fields": [ + "except" + ], + "icon": "restriction" +} diff --git a/data/presets/presets/type/restriction/no_straight_on.json b/data/presets/presets/type/restriction/no_straight_on.json new file mode 100644 index 000000000..fe2927d79 --- /dev/null +++ b/data/presets/presets/type/restriction/no_straight_on.json @@ -0,0 +1,14 @@ +{ + "name": "No Straight On", + "geometry": [ + "relation" + ], + "tags": { + "type": "restriction", + "restriction": "no_straight_on" + }, + "fields": [ + "except" + ], + "icon": "restriction" +} diff --git a/data/presets/presets/type/restriction/no_u_turn.json b/data/presets/presets/type/restriction/no_u_turn.json new file mode 100644 index 000000000..6f1f40cd3 --- /dev/null +++ b/data/presets/presets/type/restriction/no_u_turn.json @@ -0,0 +1,14 @@ +{ + "name": "No U Turn", + "geometry": [ + "relation" + ], + "tags": { + "type": "restriction", + "restriction": "no_u_turn" + }, + "fields": [ + "except" + ], + "icon": "restriction" +} diff --git a/dist/locales/en.json b/dist/locales/en.json index ae9659154..8fff93692 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -598,6 +598,9 @@ "entrance": { "label": "Type" }, + "except": { + "label": "Exceptions" + }, "fax": { "label": "Fax", "placeholder": "+31 42 123 4567" @@ -2825,6 +2828,22 @@ "name": "Restriction", "terms": "" }, + "type/restriction/no_left_turn": { + "name": "No Left Turn", + "terms": "" + }, + "type/restriction/no_right_turn": { + "name": "No Right Turn", + "terms": "" + }, + "type/restriction/no_straight_on": { + "name": "No Straight On", + "terms": "" + }, + "type/restriction/no_u_turn": { + "name": "No U Turn", + "terms": "" + }, "type/route": { "name": "Route", "terms": "" From f5b29989f5f4c2309eb373bc2e58a1ac7b92c7f9 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 9 May 2014 16:45:29 -0700 Subject: [PATCH 02/26] Deselect before deleting an entity This avoids errors produced by attempts to generate turns for ways that were just deleted. --- js/id/operations/delete.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/id/operations/delete.js b/js/id/operations/delete.js index 13516c9cc..15c41c067 100644 --- a/js/id/operations/delete.js +++ b/js/id/operations/delete.js @@ -36,15 +36,15 @@ iD.operations.Delete = function(selectedIDs, context) { } } - context.perform( - action, - annotation); - if (nextSelectedID && context.hasEntity(nextSelectedID)) { context.enter(iD.modes.Select(context, [nextSelectedID])); } else { context.enter(iD.modes.Browse(context)); } + + context.perform( + action, + annotation); }; operation.available = function() { From 419d5f359f56315b95a7bd9f5b955b01755236cc Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 14 May 2014 16:39:41 -0700 Subject: [PATCH 03/26] field.geometry is a string, not an array --- js/id/presets/field.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/id/presets/field.js b/js/id/presets/field.js index afbb9f4cb..a82813243 100644 --- a/js/id/presets/field.js +++ b/js/id/presets/field.js @@ -4,7 +4,7 @@ iD.presets.Field = function(id, field) { field.id = id; field.matchGeometry = function(geometry) { - return !field.geometry || field.geometry.indexOf(geometry) >= 0; + return !field.geometry || field.geometry === geometry; }; field.t = function(scope, options) { From 90bc8dd70abdc01b55d584043456067f1422bf62 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 14 May 2014 17:53:47 -0700 Subject: [PATCH 04/26] Extract iD.geo.RawMercator --- index.html | 1 + js/id/geo/raw_mercator.js | 50 +++++++++++++++++++++++++++++++++++++++ js/id/id.js | 47 +----------------------------------- test/index.html | 1 + 4 files changed, 53 insertions(+), 46 deletions(-) create mode 100644 js/id/geo/raw_mercator.js diff --git a/index.html b/index.html index fec78cf5c..9f0c7a6f5 100644 --- a/index.html +++ b/index.html @@ -48,6 +48,7 @@ + diff --git a/js/id/geo/raw_mercator.js b/js/id/geo/raw_mercator.js new file mode 100644 index 000000000..f34cb5d96 --- /dev/null +++ b/js/id/geo/raw_mercator.js @@ -0,0 +1,50 @@ +/* + Bypasses features of D3's default projection stream pipeline that are unnecessary: + * Antimeridian clipping + * Spherical rotation + * Resampling +*/ +iD.geo.RawMercator = function () { + var project = d3.geo.mercator.raw, + k = 512 / Math.PI, // scale + x = 0, y = 0, // translate + clipExtent = [[0, 0], [0, 0]]; + + function projection(point) { + point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180); + return [point[0] * k + x, y - point[1] * k]; + } + + projection.invert = function(point) { + point = project.invert((point[0] - x) / k, (y - point[1]) / k); + return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI]; + }; + + projection.scale = function(_) { + if (!arguments.length) return k; + k = +_; + return projection; + }; + + projection.translate = function(_) { + if (!arguments.length) return [x, y]; + x = +_[0]; + y = +_[1]; + return projection; + }; + + projection.clipExtent = function(_) { + if (!arguments.length) return clipExtent; + clipExtent = _; + return projection; + }; + + projection.stream = d3.geo.transform({ + point: function(x, y) { + x = projection([x, y]); + this.stream.point(x[0], x[1]); + } + }).stream; + + return projection; +}; diff --git a/js/id/id.js b/js/id/id.js index 2dfc664d1..af51ef051 100644 --- a/js/id/id.js +++ b/js/id/id.js @@ -197,52 +197,7 @@ window.iD = function () { }; /* Projection */ - function rawMercator() { - var project = d3.geo.mercator.raw, - k = 512 / Math.PI, // scale - x = 0, y = 0, // translate - clipExtent = [[0, 0], [0, 0]]; - - function projection(point) { - point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180); - return [point[0] * k + x, y - point[1] * k]; - } - - projection.invert = function(point) { - point = project.invert((point[0] - x) / k, (y - point[1]) / k); - return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI]; - }; - - projection.scale = function(_) { - if (!arguments.length) return k; - k = +_; - return projection; - }; - - projection.translate = function(_) { - if (!arguments.length) return [x, y]; - x = +_[0]; - y = +_[1]; - return projection; - }; - - projection.clipExtent = function(_) { - if (!arguments.length) return clipExtent; - clipExtent = _; - return projection; - }; - - projection.stream = d3.geo.transform({ - point: function(x, y) { - x = projection([x, y]); - this.stream.point(x[0], x[1]); - } - }).stream; - - return projection; - } - - context.projection = rawMercator(); + context.projection = iD.geo.RawMercator(); /* Background */ var background = iD.Background(context); diff --git a/test/index.html b/test/index.html index 8fe2bc698..85dfeba68 100644 --- a/test/index.html +++ b/test/index.html @@ -46,6 +46,7 @@ + From be0126aba609ac02be681dd64e80f26d15653c7a Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 14 May 2014 16:54:11 -0700 Subject: [PATCH 05/26] Extract iD.svg.Defs from Surface Need to have a single defs for the entire document but multiple Surfaces. --- css/app.css | 7 +++ index.html | 5 +- js/id/svg/defs.js | 129 +++++++++++++++++++++++++++++++++++++++++++ js/id/svg/surface.js | 113 +------------------------------------ js/id/ui.js | 4 ++ 5 files changed, 145 insertions(+), 113 deletions(-) create mode 100644 js/id/svg/defs.js diff --git a/css/app.css b/css/app.css index e4fcec85a..256b7c91b 100644 --- a/css/app.css +++ b/css/app.css @@ -39,6 +39,13 @@ body { height: 100%; } +#defs { + /* Can't be display: none or the clippaths are ignored. */ + position: absolute; + width: 0; + height: 0; +} + .spacer { height: 40px; margin-right: 10px; diff --git a/index.html b/index.html index 9f0c7a6f5..4fd3ffbaf 100644 --- a/index.html +++ b/index.html @@ -59,14 +59,15 @@ + + + - - diff --git a/js/id/svg/defs.js b/js/id/svg/defs.js new file mode 100644 index 000000000..ad9182a41 --- /dev/null +++ b/js/id/svg/defs.js @@ -0,0 +1,129 @@ +/* + A standalone SVG element that contains only a `defs` sub-element. To be + used once globally, since defs IDs must be unique within a document. +*/ +iD.svg.Defs = function(context) { + function autosize(image) { + var img = document.createElement('img'); + img.src = image.attr('xlink:href'); + img.onload = function() { + image.attr({ + width: img.width, + height: img.height + }); + }; + } + + function SpriteDefinition(id, href, data) { + return function(defs) { + defs.append('image') + .attr('id', id) + .attr('xlink:href', href) + .call(autosize); + + defs.selectAll() + .data(data) + .enter().append('use') + .attr('id', function(d) { return d.key; }) + .attr('transform', function(d) { return 'translate(-' + d.value[0] + ',-' + d.value[1] + ')'; }) + .attr('xlink:href', '#' + id); + }; + } + + return function (selection) { + var defs = selection.append('defs'); + + defs.append('marker') + .attr({ + id: 'oneway-marker', + viewBox: '0 0 10 10', + refY: 2.5, + refX: 5, + markerWidth: 2, + markerHeight: 2, + orient: 'auto' + }) + .append('path') + .attr('d', 'M 5 3 L 0 3 L 0 2 L 5 2 L 5 0 L 10 2.5 L 5 5 z'); + + var patterns = defs.selectAll('pattern') + .data([ + // pattern name, pattern image name + ['wetland', 'wetland'], + ['construction', 'construction'], + ['cemetery', 'cemetery'], + ['orchard', 'orchard'], + ['farmland', 'farmland'], + ['beach', 'dots'], + ['scrub', 'dots'], + ['meadow', 'dots'] + ]) + .enter() + .append('pattern') + .attr({ + id: function (d) { + return 'pattern-' + d[0]; + }, + width: 32, + height: 32, + patternUnits: 'userSpaceOnUse' + }); + + patterns.append('rect') + .attr({ + x: 0, + y: 0, + width: 32, + height: 32, + 'class': function (d) { + return 'pattern-color-' + d[0]; + } + }); + + patterns.append('image') + .attr({ + x: 0, + y: 0, + width: 32, + height: 32 + }) + .attr('xlink:href', function (d) { + return context.imagePath('pattern/' + d[1] + '.png'); + }); + + defs.selectAll() + .data([12, 18, 20]) + .enter().append('clipPath') + .attr('id', function (d) { + return 'clip-square-' + d; + }) + .append('rect') + .attr('x', 0) + .attr('y', 0) + .attr('width', function (d) { + return d; + }) + .attr('height', function (d) { + return d; + }); + + var maki = []; + _.forEach(iD.data.featureIcons, function (dimensions, name) { + if (dimensions['12'] && dimensions['18'] && dimensions['24']) { + maki.push({key: 'maki-' + name + '-12', value: dimensions['12']}); + maki.push({key: 'maki-' + name + '-18', value: dimensions['18']}); + maki.push({key: 'maki-' + name + '-24', value: dimensions['24']}); + } + }); + + defs.call(SpriteDefinition( + 'sprite', + context.imagePath('sprite.svg'), + d3.entries(iD.data.operations))); + + defs.call(SpriteDefinition( + 'maki-sprite', + context.imagePath('maki-sprite.png'), + maki)); + }; +}; diff --git a/js/id/svg/surface.js b/js/id/svg/surface.js index cac731c69..3b11461dd 100644 --- a/js/id/svg/surface.js +++ b/js/id/svg/surface.js @@ -1,114 +1,5 @@ -iD.svg.Surface = function(context) { - function autosize(image) { - var img = document.createElement('img'); - img.src = image.attr('xlink:href'); - img.onload = function() { - image.attr({ - width: img.width, - height: img.height - }); - }; - } - - function SpriteDefinition(id, href, data) { - return function(defs) { - defs.append('image') - .attr('id', id) - .attr('xlink:href', href) - .call(autosize); - - defs.selectAll() - .data(data) - .enter().append('use') - .attr('id', function(d) { return d.key; }) - .attr('transform', function(d) { return 'translate(-' + d.value[0] + ',-' + d.value[1] + ')'; }) - .attr('xlink:href', '#' + id); - }; - } - - return function drawSurface(selection) { - var defs = selection.append('defs'); - - defs.append('marker') - .attr({ - id: 'oneway-marker', - viewBox: '0 0 10 10', - refY: 2.5, - refX: 5, - markerWidth: 2, - markerHeight: 2, - orient: 'auto' - }) - .append('path') - .attr('d', 'M 5 3 L 0 3 L 0 2 L 5 2 L 5 0 L 10 2.5 L 5 5 z'); - - var patterns = defs.selectAll('pattern') - .data([ - // pattern name, pattern image name - ['wetland', 'wetland'], - ['construction', 'construction'], - ['cemetery', 'cemetery'], - ['orchard', 'orchard'], - ['farmland', 'farmland'], - ['beach', 'dots'], - ['scrub', 'dots'], - ['meadow', 'dots']]) - .enter() - .append('pattern') - .attr({ - id: function(d) { return 'pattern-' + d[0]; }, - width: 32, - height: 32, - patternUnits: 'userSpaceOnUse' - }); - - patterns.append('rect') - .attr({ - x: 0, - y: 0, - width: 32, - height: 32, - 'class': function(d) { return 'pattern-color-' + d[0]; } - }); - - patterns.append('image') - .attr({ - x: 0, - y: 0, - width: 32, - height: 32 - }) - .attr('xlink:href', function(d) { return context.imagePath('pattern/' + d[1] + '.png'); }); - - defs.selectAll() - .data([12, 18, 20]) - .enter().append('clipPath') - .attr('id', function(d) { return 'clip-square-' + d; }) - .append('rect') - .attr('x', 0) - .attr('y', 0) - .attr('width', function(d) { return d; }) - .attr('height', function(d) { return d; }); - - var maki = []; - _.forEach(iD.data.featureIcons, function(dimensions, name) { - if (dimensions['12'] && dimensions['18'] && dimensions['24']) { - maki.push({key: 'maki-' + name + '-12', value: dimensions['12']}); - maki.push({key: 'maki-' + name + '-18', value: dimensions['18']}); - maki.push({key: 'maki-' + name + '-24', value: dimensions['24']}); - } - }); - - defs.call(SpriteDefinition( - 'sprite', - context.imagePath('sprite.svg'), - d3.entries(iD.data.operations))); - - defs.call(SpriteDefinition( - 'maki-sprite', - context.imagePath('maki-sprite.png'), - maki)); - +iD.svg.Surface = function() { + return function (selection) { var layers = selection.selectAll('.layer') .data(['fill', 'shadow', 'casing', 'stroke', 'oneway', 'hit', 'halo', 'label']); diff --git a/js/id/ui.js b/js/id/ui.js index 678c55ca4..01f8ed6df 100644 --- a/js/id/ui.js +++ b/js/id/ui.js @@ -12,6 +12,10 @@ iD.ui = function(context) { map.centerZoom([-77.02271, 38.90085], 20); } + container.append('svg') + .attr('id', 'defs') + .call(iD.svg.Defs(context)); + container.append('div') .attr('id', 'sidebar') .attr('class', 'col4') From 7cac179ce07d699092dbdac5fdbaeda72a5dc5d0 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 15 May 2014 11:49:10 -0700 Subject: [PATCH 06/26] Start work on turn restriction editing field --- css/app.css | 7 ++ data/presets.yaml | 2 + data/presets/fields.json | 9 +++ data/presets/fields/restrictions.json | 9 +++ data/presets/presets.json | 3 + .../presets/highway/traffic_signals.json | 3 + data/presets/schema/field.json | 3 +- dist/locales/en.json | 3 + index.html | 1 + js/id/ui/preset/restrictions.js | 71 +++++++++++++++++++ 10 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 data/presets/fields/restrictions.json create mode 100644 js/id/ui/preset/restrictions.js diff --git a/css/app.css b/css/app.css index 256b7c91b..3ac71d399 100644 --- a/css/app.css +++ b/css/app.css @@ -1534,6 +1534,13 @@ input[type=number] { border-bottom: 0; border-radius: 0 0 4px 0; } + +/* Restrictions editor */ + +.form-field-restrictions .preset-input-wrap { + height: 300px; +} + /* combobox dropdown */ div.combobox { diff --git a/data/presets.yaml b/data/presets.yaml index 1c661f7e4..7956ed495 100644 --- a/data/presets.yaml +++ b/data/presets.yaml @@ -296,6 +296,8 @@ en: taoist: Taoist restriction: label: Type + restrictions: + label: Turn Restrictions route: label: Type route_master: diff --git a/data/presets/fields.json b/data/presets/fields.json index c25b151e9..af125a0bb 100644 --- a/data/presets/fields.json +++ b/data/presets/fields.json @@ -721,6 +721,15 @@ "type": "combo", "label": "Type" }, + "restrictions": { + "type": "restrictions", + "geometry": "vertex", + "icon": "restrictions", + "reference": { + "rtype": "restriction" + }, + "label": "Turn Restrictions" + }, "route": { "key": "route", "type": "combo", diff --git a/data/presets/fields/restrictions.json b/data/presets/fields/restrictions.json new file mode 100644 index 000000000..4873601f9 --- /dev/null +++ b/data/presets/fields/restrictions.json @@ -0,0 +1,9 @@ +{ + "type": "restrictions", + "geometry": "vertex", + "icon": "restrictions", + "reference": { + "rtype": "restriction" + }, + "label": "Turn Restrictions" +} diff --git a/data/presets/presets.json b/data/presets/presets.json index 407d0418b..13e4dc6e5 100644 --- a/data/presets/presets.json +++ b/data/presets/presets.json @@ -4245,6 +4245,9 @@ "tags": { "highway": "traffic_signals" }, + "fields": [ + "restrictions" + ], "terms": [ "light", "stoplight", diff --git a/data/presets/presets/highway/traffic_signals.json b/data/presets/presets/highway/traffic_signals.json index 62e5d60e8..7f3fd4157 100644 --- a/data/presets/presets/highway/traffic_signals.json +++ b/data/presets/presets/highway/traffic_signals.json @@ -5,6 +5,9 @@ "tags": { "highway": "traffic_signals" }, + "fields": [ + "restrictions" + ], "terms": [ "light", "stoplight", diff --git a/data/presets/schema/field.json b/data/presets/schema/field.json index 12a45ee5f..3cc081660 100644 --- a/data/presets/schema/field.json +++ b/data/presets/schema/field.json @@ -63,7 +63,8 @@ "textarea", "localized", "wikipedia", - "typeCombo" + "typeCombo", + "restrictions" ], "required": true }, diff --git a/dist/locales/en.json b/dist/locales/en.json index 8fff93692..64d57639d 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -825,6 +825,9 @@ "restriction": { "label": "Type" }, + "restrictions": { + "label": "Turn Restrictions" + }, "route": { "label": "Type" }, diff --git a/index.html b/index.html index 4fd3ffbaf..aee983d3b 100644 --- a/index.html +++ b/index.html @@ -120,6 +120,7 @@ + diff --git a/js/id/ui/preset/restrictions.js b/js/id/ui/preset/restrictions.js new file mode 100644 index 000000000..a6d12953a --- /dev/null +++ b/js/id/ui/preset/restrictions.js @@ -0,0 +1,71 @@ +iD.ui.preset.restrictions = function(field, context) { + var event = d3.dispatch('change'), + entity; + + function restrictions(selection) { + var wrap = selection.selectAll('.preset-input-wrap') + .data([0]); + + // Enter + + var enter = wrap.enter().append('div') + .attr('class', 'preset-input-wrap'); + + enter.append('svg') + .call(iD.svg.Surface(context)) + .call(iD.behavior.Hover(context)); + + var d = wrap.dimensions(), + c = [d[0] / 2, d[1] / 2], + z = 21; + + var projection = iD.geo.RawMercator() + .scale(256 * Math.pow(2, z) / (2 * Math.PI)); + + var s = projection(entity ? entity.loc : [0, 0]); + + projection + .translate([c[0] - s[0], c[1] - s[1]]) + .clipExtent([[0, 0], d]); + + var surface = wrap.selectAll('svg'), + filter = function () { return true; }, + extent = iD.geo.Extent(), + entities = [], + graph = context.graph(), + lines = iD.svg.Lines(projection, context), + vertices = iD.svg.Vertices(projection, context); + + if (entity) { + entities = graph.parentWays(entity).filter(function (parent) { + return parent.type === 'way' && parent.tags.highway && !parent.isArea(); + }); + + entities.push(entity); + } + + surface + .call(vertices, graph, entities, filter, extent, z) + .call(lines, graph, entities, filter); + + context.history() + .on('change.restrictions', render); + + d3.select(window) + .on('resize.restrictions', render); + + function render() { + restrictions(selection); + } + } + + restrictions.tags = function() {}; + + restrictions.entity = function(_) { + entity = _; + }; + + restrictions.focus = function() {}; + + return d3.rebind(restrictions, event, 'on'); +}; From 495fcc1b11bc1f250e99c61513a3ef2ee648dbb4 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 9 May 2014 15:34:58 -0700 Subject: [PATCH 07/26] Include pick in lodash build --- Makefile | 3 +++ js/lib/lodash.js | 54 +++++++++++++++++++++++++++++++++++++++++++++++- package.json | 1 + 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 885df0a94..691a1a860 100644 --- a/Makefile +++ b/Makefile @@ -124,3 +124,6 @@ D3_FILES = \ js/lib/d3.v3.js: $(D3_FILES) node_modules/.bin/smash $(D3_FILES) > $@ @echo 'd3 rebuilt. Please reapply 7e2485d, 4da529f, and 223974d' + +js/lib/lodash.js: + node_modules/.bin/lodash --debug --output $@ include="any,assign,bind,clone,compact,contains,debounce,difference,each,every,extend,filter,find,first,forEach,groupBy,indexOf,intersection,isEmpty,isEqual,isFunction,keys,last,map,omit,pairs,pluck,reject,some,throttle,union,uniq,unique,values,without,flatten,value,chain,cloneDeep,merge,pick" exports="global,node" diff --git a/js/lib/lodash.js b/js/lib/lodash.js index cda72370c..4c8cb489e 100644 --- a/js/lib/lodash.js +++ b/js/lib/lodash.js @@ -1,7 +1,7 @@ /** * @license * Lo-Dash 2.3.0 (Custom Build) - * Build: `lodash include="any,assign,bind,clone,compact,contains,debounce,difference,each,every,extend,filter,find,first,forEach,groupBy,indexOf,intersection,isEmpty,isEqual,isFunction,keys,last,map,omit,pairs,pluck,reject,some,throttle,union,uniq,unique,values,without,flatten,value,chain,cloneDeep,merge" exports="global,node"` + * Build: `lodash --debug --output js/lib/lodash.js include="any,assign,bind,clone,compact,contains,debounce,difference,each,every,extend,filter,find,first,forEach,groupBy,indexOf,intersection,isEmpty,isEqual,isFunction,keys,last,map,omit,pairs,pluck,reject,some,throttle,union,uniq,unique,values,without,flatten,value,chain,cloneDeep,merge,pick" exports="global,node"` * Copyright 2012-2013 The Dojo Foundation * Based on Underscore.js 1.5.2 * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors @@ -2304,6 +2304,57 @@ return result; } + /** + * Creates a shallow clone of `object` composed of the specified properties. + * Property names may be specified as individual arguments or as arrays of + * property names. If a callback is provided it will be executed for each + * property of `object` picking the properties the callback returns truey + * for. The callback is bound to `thisArg` and invoked with three arguments; + * (value, key, object). + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The source object. + * @param {Function|...string|string[]} [callback] The function called per + * iteration or property names to pick, specified as individual property + * names or arrays of property names. + * @param {*} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns an object composed of the picked properties. + * @example + * + * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name'); + * // => { 'name': 'fred' } + * + * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) { + * return key.charAt(0) != '_'; + * }); + * // => { 'name': 'fred' } + */ + function pick(object, callback, thisArg) { + var result = {}; + if (typeof callback != 'function') { + var index = -1, + props = baseFlatten(arguments, true, false, 1), + length = isObject(object) ? props.length : 0; + + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + } else { + callback = lodash.createCallback(callback, thisArg, 3); + forIn(object, function(value, key, object) { + if (callback(value, key, object)) { + result[key] = value; + } + }); + } + return result; + } + /** * Creates an array composed of the own enumerable property values of `object`. * @@ -3830,6 +3881,7 @@ lodash.merge = merge; lodash.omit = omit; lodash.pairs = pairs; + lodash.pick = pick; lodash.pluck = pluck; lodash.reject = reject; lodash.throttle = throttle; diff --git a/package.json b/package.json index aa5f36818..92653c600 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "devDependencies": { "d3": "3.4.6", "smash": "0.0", + "lodash-cli": "2.3.0", "uglify-js": "~2.2.5", "maki": "0.4", "jshint": "2.3.0", From f39ae89177a5b077ed13e36c34b07b87716034b3 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 9 May 2014 14:58:27 -0700 Subject: [PATCH 08/26] Render turns of selected way --- css/map.css | 12 +++ index.html | 2 +- js/id/geo/turn.js | 22 ++++- js/id/svg/restrictions.js | 75 --------------- js/id/svg/turns.js | 31 +++++++ js/id/ui/preset/restrictions.js | 39 ++++++-- test/index.html | 2 +- test/spec/geo/turn.js | 160 +++++++++++++++++++------------- test/spec/svg/restrictions.js | 149 ----------------------------- 9 files changed, 197 insertions(+), 295 deletions(-) delete mode 100644 js/id/svg/restrictions.js create mode 100644 js/id/svg/turns.js diff --git a/css/map.css b/css/map.css index fd4509065..f3c540cc0 100644 --- a/css/map.css +++ b/css/map.css @@ -945,6 +945,18 @@ text.point { font-size: 10px; } +/* Turns */ + +g.turn path { + stroke: green; + stroke-width: 10px; + stroke-linecap: round; +} + +g.turn.restricted path { + stroke: red; +} + /* Cursors */ #map { diff --git a/index.html b/index.html index aee983d3b..7f192a48d 100644 --- a/index.html +++ b/index.html @@ -64,9 +64,9 @@ - + diff --git a/js/id/geo/turn.js b/js/id/geo/turn.js index 296a43e31..5776000e9 100644 --- a/js/id/geo/turn.js +++ b/js/id/geo/turn.js @@ -1,3 +1,23 @@ +iD.geo.Turn = function(turn) { + turn = _.clone(turn); + + turn.key = function() { + var components = [turn.from, turn.to, turn.via, turn.toward]; + if (turn.restriction) + components.push(turn.restriction); + return components.map(iD.Entity.key).join('-'); + }; + + turn.angle = function(projection) { + var v = projection(turn.via.loc), + t = projection(turn.toward.loc); + + return Math.atan2(t[1] - v[1], t[0] - v[0]); + }; + + return turn; +}; + iD.geo.turns = function(graph, entityID) { var way = graph.entity(entityID); if (way.type !== 'way' || !way.tags.highway || way.isArea()) @@ -19,7 +39,7 @@ iD.geo.turns = function(graph, entityID) { } }); - return turn; + return iD.geo.Turn(turn); } var turns = []; diff --git a/js/id/svg/restrictions.js b/js/id/svg/restrictions.js deleted file mode 100644 index 66c8289c5..000000000 --- a/js/id/svg/restrictions.js +++ /dev/null @@ -1,75 +0,0 @@ -iD.svg.Restrictions = function(context) { - var projection = context.projection; - - function drawRestrictions(surface) { - var turns = drawRestrictions.turns(context.graph(), context.selectedIDs()); - - var groups = surface.select('.layer-hit').selectAll('g.restriction') - .data(turns, iD.Entity.key); - - var enter = groups.enter().append('g') - .attr('class', 'restriction'); - - enter.append('circle') - .attr('class', 'restriction') - .attr('r', 4); - - groups - .attr('transform', function(restriction) { - var via = context.entity(restriction.memberByRole('via').id); - return iD.svg.PointTransform(projection)(via); - }); - - groups.exit() - .remove(); - - return this; - } - - drawRestrictions.turns = function (graph, selectedIDs) { - if (selectedIDs.length !== 1) - return []; - - var from = graph.entity(selectedIDs[0]); - if (from.type !== 'way') - return []; - - return graph.parentRelations(from).filter(function(relation) { - var f = relation.memberById(from.id), - t = relation.memberByRole('to'), - v = relation.memberByRole('via'); - - return relation.tags.type === 'restriction' && f.role === 'from' && - t && t.type === 'way' && graph.hasEntity(t.id) && - v && v.type === 'node' && graph.hasEntity(v.id) && - !graph.entity(t.id).isDegenerate() && - !graph.entity(f.id).isDegenerate() && - graph.entity(t.id).affix(v.id) && - graph.entity(f.id).affix(v.id); - }); - }; - - drawRestrictions.datum = function(graph, from, restriction, projection) { - var to = graph.entity(restriction.memberByRole('to').id), - a = graph.entity(restriction.memberByRole('via').id), - b; - - if (to.first() === a.id) { - b = graph.entity(to.nodes[1]); - } else { - b = graph.entity(to.nodes[to.nodes.length - 2]); - } - - a = projection(a.loc); - b = projection(b.loc); - - return { - from: from, - to: to, - restriction: restriction, - angle: Math.atan2(b[1] - a[1], b[0] - a[0]) - }; - }; - - return drawRestrictions; -}; diff --git a/js/id/svg/turns.js b/js/id/svg/turns.js new file mode 100644 index 000000000..f86518ce3 --- /dev/null +++ b/js/id/svg/turns.js @@ -0,0 +1,31 @@ +iD.svg.Turns = function(projection) { + return function(surface, graph, wayID) { + var turns = wayID ? iD.geo.turns(graph, wayID) : []; + + var groups = surface.select('.layer-hit').selectAll('g.turn') + .data(turns, function(turn) { return turn.key(); }); + + var enter = groups.enter().append('g') + .attr('class', 'turn'); + + enter.append('path') + .attr('class', 'turn') + .attr('d', function() { + return 'M20 0 L50 0 M40 10 L50 0 M40 -10 L50 0'; + }); + + groups + .classed('restricted', function(turn) { + return turn.restriction; + }) + .attr('transform', function(turn) { + return iD.svg.PointTransform(projection)(turn.via) + + 'rotate(' + turn.angle(projection) * 180 / Math.PI + ')'; + }); + + groups.exit() + .remove(); + + return this; + }; +}; diff --git a/js/id/ui/preset/restrictions.js b/js/id/ui/preset/restrictions.js index a6d12953a..9d72bd406 100644 --- a/js/id/ui/preset/restrictions.js +++ b/js/id/ui/preset/restrictions.js @@ -1,6 +1,7 @@ iD.ui.preset.restrictions = function(field, context) { var event = d3.dispatch('change'), - entity; + entity, + selectedID; function restrictions(selection) { var wrap = selection.selectAll('.preset-input-wrap') @@ -34,7 +35,8 @@ iD.ui.preset.restrictions = function(field, context) { entities = [], graph = context.graph(), lines = iD.svg.Lines(projection, context), - vertices = iD.svg.Vertices(projection, context); + vertices = iD.svg.Vertices(projection, context), + turns = iD.svg.Turns(projection, context); if (entity) { entities = graph.parentWays(entity).filter(function (parent) { @@ -44,9 +46,32 @@ iD.ui.preset.restrictions = function(field, context) { entities.push(entity); } + if (!selectedID && entities.length) { + selectedID = entities[0].id; + } + surface .call(vertices, graph, entities, filter, extent, z) - .call(lines, graph, entities, filter); + .call(lines, graph, entities, filter) + .call(turns, graph, selectedID); + + surface.on('click.select', function() { + var datum = d3.event.target.__data__; + if (datum instanceof iD.Entity) { + selectedID = datum.id; + render(); + } + }); + + surface + .selectAll('.selected') + .classed('selected', false); + + if (selectedID) { + surface + .selectAll('.' + selectedID) + .classed('selected', true); + } context.history() .on('change.restrictions', render); @@ -59,12 +84,14 @@ iD.ui.preset.restrictions = function(field, context) { } } - restrictions.tags = function() {}; - restrictions.entity = function(_) { - entity = _; + if (!entity || entity.id !== _.id) { + selectedID = null; + entity = _; + } }; + restrictions.tags = function() {}; restrictions.focus = function() {}; return d3.rebind(restrictions, event, 'on'); diff --git a/test/index.html b/test/index.html index 85dfeba68..708e20622 100644 --- a/test/index.html +++ b/test/index.html @@ -258,7 +258,7 @@ - + diff --git a/test/spec/geo/turn.js b/test/spec/geo/turn.js index 4d0c87cac..44f95dc92 100644 --- a/test/spec/geo/turn.js +++ b/test/spec/geo/turn.js @@ -1,4 +1,23 @@ +describe('iD.geo.Turn', function() { + describe('#angle', function() { + it("calculates the angle of via to toward", function() { + function projection(x) { return x; } + + var turn = iD.geo.Turn({ + via: iD.Node({id: 'v', loc: [1, 0]}), + toward: iD.Node({id: 'w', loc: [1, 1]}) + }); + + expect(turn.angle(projection)).to.eql(Math.PI / 2); + }); + }); +}); + describe("iD.geo.turns", function() { + function properties(turns) { + return turns.map(function (turn) { return _.pick(turn, 'from', 'to', 'via', 'toward', 'restriction') }); + } + it("returns an empty array for non-ways", function() { var graph = iD.Graph([ iD.Node({id: 'n'}) @@ -73,13 +92,15 @@ describe("iD.geo.turns", function() { it("permits turns onto a way forward", function() { // u====v--->w var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential'}}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([{ + iD.Node({id: 'u'}), + iD.Node({id: 'v'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential'}}) + ]), + turns = iD.geo.turns(graph, '='); + + expect(properties(turns)).to.eql([{ from: graph.entity('='), to: graph.entity('-'), via: graph.entity('v'), @@ -90,13 +111,15 @@ describe("iD.geo.turns", function() { it("permits turns onto a way backward", function() { // u====v<---w var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['w', 'v'], tags: {highway: 'residential'}}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([{ + iD.Node({id: 'u'}), + iD.Node({id: 'v'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['w', 'v'], tags: {highway: 'residential'}}) + ]), + turns = iD.geo.turns(graph, '='); + + expect(properties(turns)).to.eql([{ from: graph.entity('='), to: graph.entity('-'), via: graph.entity('v'), @@ -111,14 +134,16 @@ describe("iD.geo.turns", function() { // | // x var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Node({id: 'x'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['w', 'v', 'x'], tags: {highway: 'residential'}}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([{ + iD.Node({id: 'u'}), + iD.Node({id: 'v'}), + iD.Node({id: 'w'}), + iD.Node({id: 'x'}), + iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['w', 'v', 'x'], tags: {highway: 'residential'}}) + ]), + turns = iD.geo.turns(graph, '='); + + expect(properties(turns)).to.eql([{ from: graph.entity('='), to: graph.entity('-'), via: graph.entity('v'), @@ -134,13 +159,15 @@ describe("iD.geo.turns", function() { it("permits turns from a oneway forward", function() { // u===>v----w var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential', oneway: 'yes'}}), - iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential'}}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([{ + iD.Node({id: 'u'}), + iD.Node({id: 'v'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential', oneway: 'yes'}}), + iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential'}}) + ]), + turns = iD.geo.turns(graph, '='); + + expect(properties(turns)).to.eql([{ from: graph.entity('='), to: graph.entity('-'), via: graph.entity('v'), @@ -151,13 +178,15 @@ describe("iD.geo.turns", function() { it("permits turns from a reverse oneway backward", function() { // u<===v----w var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['v', 'u'], tags: {highway: 'residential', oneway: '-1'}}), - iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential'}}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([{ + iD.Node({id: 'u'}), + iD.Node({id: 'v'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['v', 'u'], tags: {highway: 'residential', oneway: '-1'}}), + iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential'}}) + ]), + turns = iD.geo.turns(graph, '='); + + expect(properties(turns)).to.eql([{ from: graph.entity('='), to: graph.entity('-'), via: graph.entity('v'), @@ -192,13 +221,15 @@ describe("iD.geo.turns", function() { it("permits turns onto a oneway forward", function() { // u====v--->w var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential', oneway: 'yes'}}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([{ + iD.Node({id: 'u'}), + iD.Node({id: 'v'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential', oneway: 'yes'}}) + ]), + turns = iD.geo.turns(graph, '='); + + expect(properties(turns)).to.eql([{ from: graph.entity('='), to: graph.entity('-'), via: graph.entity('v'), @@ -209,13 +240,15 @@ describe("iD.geo.turns", function() { it("permits turns onto a reverse oneway backward", function() { // u====v<---w var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['w', 'v'], tags: {highway: 'residential', oneway: '-1'}}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([{ + iD.Node({id: 'u'}), + iD.Node({id: 'v'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['w', 'v'], tags: {highway: 'residential', oneway: '-1'}}) + ]), + turns = iD.geo.turns(graph, '='); + + expect(properties(turns)).to.eql([{ from: graph.entity('='), to: graph.entity('-'), via: graph.entity('v'), @@ -250,18 +283,20 @@ describe("iD.geo.turns", function() { it("restricts turns with a restriction relation", function() { // u====v--->w var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential'}}), - iD.Relation({id: 'r', tags: {type: 'restriction'}, members: [ - {id: '=', role: 'from', type: 'way'}, - {id: '-', role: 'to', type: 'way'}, - {id: 'v', role: 'via', type: 'node'} - ]}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([{ + iD.Node({id: 'u'}), + iD.Node({id: 'v'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential'}}), + iD.Relation({id: 'r', tags: {type: 'restriction'}, members: [ + {id: '=', role: 'from', type: 'way'}, + {id: '-', role: 'to', type: 'way'}, + {id: 'v', role: 'via', type: 'node'} + ]}) + ]), + turns = iD.geo.turns(graph, '='); + + expect(properties(turns)).to.eql([{ from: graph.entity('='), to: graph.entity('-'), via: graph.entity('v'), @@ -270,6 +305,7 @@ describe("iD.geo.turns", function() { }]); }); + // 'no' vs 'only' // U-turns // Self-intersections // Split point diff --git a/test/spec/svg/restrictions.js b/test/spec/svg/restrictions.js index 38f3bf1b9..5d4f5e5e3 100644 --- a/test/spec/svg/restrictions.js +++ b/test/spec/svg/restrictions.js @@ -1,151 +1,2 @@ describe("iD.svg.Restrictions", function() { - var restrictions = iD.svg.Restrictions({}); - - describe("#turns", function() { - it("returns an empty array with no selection", function() { - var graph = iD.Graph(); - expect(restrictions.turns(graph, [])).to.eql([]); - }); - - it("returns an empty array with a multiselection", function() { - var graph = iD.Graph(); - expect(restrictions.turns(graph, ['a', 'b'])).to.eql([]); - }); - - var valid = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: 'f', nodes: ['u', 'v']}), - iD.Way({id: 't', nodes: ['v', 'w']}), - iD.Relation({id: 'r', tags: {type: 'restriction'}, members: [ - { role: 'via', id: 'v', type: 'node' }, - { role: 'from', id: 'f', type: 'way' }, - { role: 'to', id: 't', type: 'way' } - ]}) - ]); - - it("returns a valid restriction when the selected way has role 'from'", function() { - expect(restrictions.turns(valid, ['f'])).to.eql([valid.entity('r')]); - }); - - it("returns an empty array when the selected way has role 'to'", function() { - expect(restrictions.turns(valid, ['t'])).to.eql([]); - }); - - it("ignores restrictions missing a 'to' role", function() { - var graph = valid.replace(valid.entity('r').removeMembersWithID('t')); - expect(restrictions.turns(graph, ['f'])).to.eql([]); - }); - - it("ignores restrictions with an incomplete 'to' role", function() { - var graph = valid.remove(valid.entity('t')); - expect(restrictions.turns(graph, ['f'])).to.eql([]); - }); - - it("ignores restrictions missing a 'via' role", function() { - var graph = valid.replace(valid.entity('r').removeMembersWithID('v')); - expect(restrictions.turns(graph, ['f'])).to.eql([]); - }); - - it("ignores restrictions with an incomplete 'via' role", function() { - var graph = valid.remove(valid.entity('v')); - expect(restrictions.turns(graph, ['f'])).to.eql([]); - }); - - it("ignores restrictions whose 'from' role is not a way", function() { - var graph = valid.replace(iD.Node({id: 'f2'})) - .replace(valid.entity('r').replaceMember({id: 'f'}, {id: 'f2', type: 'node'})); - expect(restrictions.turns(graph, ['f2'])).to.eql([]); - }); - - it("ignores restrictions whose 'to' role is not a way", function() { - var graph = valid.replace(iD.Node({id: 't2'})) - .replace(valid.entity('r').replaceMember({id: 't'}, {id: 't2', type: 'node'})); - expect(restrictions.turns(graph, ['f'])).to.eql([]); - }); - - it("ignores restrictions whose 'via' role is not a node", function() { - var graph = valid.replace(iD.Way({id: 'v2'})) - .replace(valid.entity('r').replaceMember({id: 'v'}, {id: 'v2', type: 'way'})); - expect(restrictions.turns(graph, ['f'])).to.eql([]); - }); - - it("ignores restrictions whose 'from' role does not start or end with the via node", function() { - var graph = valid.replace(valid.entity('f').update({nodes: ['o']})); - expect(restrictions.turns(graph, ['f'])).to.eql([]); - }); - - it("ignores restrictions whose 'to' role does not start or end with the via node", function() { - var graph = valid.replace(valid.entity('t').update({nodes: ['o']})); - expect(restrictions.turns(graph, ['f'])).to.eql([]); - }); - - it("ignores restrictions whose 'from' role has less than two nodes", function() { - var graph = valid.replace(valid.entity('f').update({nodes: ['v']})); - expect(restrictions.turns(graph, ['f'])).to.eql([]); - }); - - it("ignores restrictions whose 'to' role has less than two nodes", function() { - var graph = valid.replace(valid.entity('t').update({nodes: ['v']})); - expect(restrictions.turns(graph, ['f'])).to.eql([]); - }); - - it("ignores restriction subtypes", function() { - var graph = valid.replace(valid.entity('r').update({tags: {type: 'restriction:hgv'}})); - expect(restrictions.turns(graph, ['f'])).to.eql([]); - }); - }); - - describe("#datum", function() { - function projection(x) { return x; } - - it("calculates the angle of a forward 'to' role", function() { - // w---x--->y - // | - // u====>v - // From = to - via v - - var graph = iD.Graph([ - iD.Node({id: 'u', loc: [0, 0]}), - iD.Node({id: 'v', loc: [1, 0]}), - iD.Node({id: 'w', loc: [1, 1]}), - iD.Node({id: 'x', loc: [2, 1]}), - iD.Node({id: 'y', loc: [3, 1]}), - iD.Way({id: '=', nodes: ['u', 'v']}), - iD.Way({id: '-', nodes: ['v', 'w', 'x', 'y']}), - iD.Relation({id: 'r', tags: {type: 'restriction'}, members: [ - { role: 'via', id: 'v', type: 'node' }, - { role: 'from', id: '=', type: 'way' }, - { role: 'to', id: '-', type: 'way' } - ]}) - ]); - - expect(restrictions.datum(graph, graph.entity('='), graph.entity('r'), projection).angle).to.eql(Math.PI / 2); - }); - - it("calculates the angle of a reverse 'to' role", function() { - // w<---x---y - // | - // u====>v - // From = to - via v - - var graph = iD.Graph([ - iD.Node({id: 'u', loc: [0, 0]}), - iD.Node({id: 'v', loc: [1, 0]}), - iD.Node({id: 'w', loc: [1, 1]}), - iD.Node({id: 'x', loc: [2, 1]}), - iD.Node({id: 'y', loc: [3, 1]}), - iD.Way({id: '=', nodes: ['u', 'v']}), - iD.Way({id: '-', nodes: ['y', 'x', 'w', 'v']}), - iD.Relation({id: 'r', tags: {type: 'restriction'}, members: [ - { role: 'via', id: 'v', type: 'node' }, - { role: 'from', id: '=', type: 'way' }, - { role: 'to', id: '-', type: 'way' } - ]}) - ]); - - expect(restrictions.datum(graph, graph.entity('='), graph.entity('r'), projection).angle).to.eql(Math.PI / 2); - }); - }); }); From 3b26e8d5111759c1764e6e7518fdcb5cb1c316a1 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 15 May 2014 14:33:29 -0700 Subject: [PATCH 09/26] Show turn restriction editor for any intersection --- data/presets/presets.json | 3 --- data/presets/presets/highway/traffic_signals.json | 3 --- js/id/ui/inspector.js | 7 ++++++- js/id/ui/preset.js | 6 +++++- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/data/presets/presets.json b/data/presets/presets.json index 13e4dc6e5..407d0418b 100644 --- a/data/presets/presets.json +++ b/data/presets/presets.json @@ -4245,9 +4245,6 @@ "tags": { "highway": "traffic_signals" }, - "fields": [ - "restrictions" - ], "terms": [ "light", "stoplight", diff --git a/data/presets/presets/highway/traffic_signals.json b/data/presets/presets/highway/traffic_signals.json index 7f3fd4157..62e5d60e8 100644 --- a/data/presets/presets/highway/traffic_signals.json +++ b/data/presets/presets/highway/traffic_signals.json @@ -5,9 +5,6 @@ "tags": { "highway": "traffic_signals" }, - "fields": [ - "restrictions" - ], "terms": [ "light", "stoplight", diff --git a/js/id/ui/inspector.js b/js/id/ui/inspector.js index 0f53ef62c..5c4bff46a 100644 --- a/js/id/ui/inspector.js +++ b/js/id/ui/inspector.js @@ -31,7 +31,12 @@ iD.ui.Inspector = function(context) { var $presetPane = $wrap.select('.preset-list-pane'); var $editorPane = $wrap.select('.entity-editor-pane'); - var showEditor = state === 'hover' || context.entity(entityID).isUsed(context.graph()); + var graph = context.graph(), + entity = context.entity(entityID), + showEditor = state === 'hover' || + entity.isUsed(graph) || + entity.isIntersection(graph); + if (showEditor) { $wrap.style('right', '0%'); $editorPane.call(entityEditor); diff --git a/js/id/ui/preset.js b/js/id/ui/preset.js index 99ae2ff54..de3f550b3 100644 --- a/js/id/ui/preset.js +++ b/js/id/ui/preset.js @@ -72,6 +72,10 @@ iD.ui.preset = function(context) { } }); + if (geometry === 'vertex' && entity.isIntersection(context.graph())) { + fields.push(UIField(context.presets().field('restrictions'), entity, true)); + } + context.presets().universal().forEach(function(field) { if (preset.fields.indexOf(field) < 0) { fields.push(UIField(field, entity)); @@ -177,7 +181,7 @@ iD.ui.preset = function(context) { function show(field) { field.show = true; - presets(selection); + context.presets()(selection); field.input.focus(); } From 26422d9c9a02a8c8b8baa220dcf60204f1c2c858 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 15 May 2014 16:46:38 -0700 Subject: [PATCH 10/26] Show ways in restriction editor as if they were split --- index.html | 2 +- js/id/geo/intersection.js | 114 ++++++++++++ js/id/geo/turn.js | 82 --------- js/id/svg/turns.js | 4 +- js/id/ui/preset/restrictions.js | 30 +-- test/index.html | 9 +- test/index_packaged.html | 3 +- test/spec/geo/intersection.js | 276 ++++++++++++++++++++++++++++ test/spec/geo/turn.js | 312 -------------------------------- test/spec/svg/restrictions.js | 2 - 10 files changed, 406 insertions(+), 428 deletions(-) create mode 100644 js/id/geo/intersection.js delete mode 100644 js/id/geo/turn.js create mode 100644 test/spec/geo/intersection.js delete mode 100644 test/spec/geo/turn.js delete mode 100644 test/spec/svg/restrictions.js diff --git a/index.html b/index.html index 7f192a48d..aa156ee5e 100644 --- a/index.html +++ b/index.html @@ -47,9 +47,9 @@ + - diff --git a/js/id/geo/intersection.js b/js/id/geo/intersection.js new file mode 100644 index 000000000..c53e6db2a --- /dev/null +++ b/js/id/geo/intersection.js @@ -0,0 +1,114 @@ +iD.geo.Turn = function(turn) { + turn = _.clone(turn); + + turn.key = function() { + var components = [turn.from, turn.to, turn.via, turn.toward]; + if (turn.restriction) + components.push(turn.restriction); + return components.map(iD.Entity.key).join('-'); + }; + + turn.angle = function(projection) { + var v = projection(turn.via.loc), + t = projection(turn.toward.loc); + + return Math.atan2(t[1] - v[1], t[0] - v[0]); + }; + + return turn; +}; + +iD.geo.Intersection = function(graph, vertexId) { + var vertex = graph.entity(vertexId), + highways = []; + + // Pre-split ways that would need to be split in + // order to add a restriction. The real split will + // happen when the restriction is added. + graph.parentWays(vertex).forEach(function(way) { + if (!way.tags.highway || way.isArea() || way.isDegenerate()) + return; + + if (way.affix(vertexId)) { + highways.push(way); + } else { + var idx = _.indexOf(way.nodes, vertex.id, 1), + wayA = iD.Way({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, idx + 1)}), + wayB = iD.Way({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(idx)}); + + graph = graph.replace(wayA); + graph = graph.replace(wayB); + + highways.push(wayA); + highways.push(wayB); + } + }); + + var intersection = { + highways: highways, + graph: graph + }; + + intersection.turns = function(wayId) { + if (!wayId) + return []; + + var way = graph.entity(wayId); + if (way.first() === vertex.id && way.tags.oneway === 'yes') + return []; + if (way.last() === vertex.id && way.tags.oneway === '-1') + return []; + + function withRestriction(turn) { + graph.parentRelations(turn.from).forEach(function(relation) { + if (relation.tags.type !== 'restriction') + return; + + var f = relation.memberByRole('from'), + t = relation.memberByRole('to'), + v = relation.memberByRole('via'); + + if (f && f.id === turn.from.id && + t && t.id === turn.to.id && + v && v.id === turn.via.id) { + turn.restriction = relation; + } + }); + + return iD.geo.Turn(turn); + } + + var turns = []; + + highways.forEach(function(parent) { + if (parent === way) + return; + + var index = parent.nodes.indexOf(vertex.id); + + // backward + if (parent.first() !== vertex.id && parent.tags.oneway !== 'yes') { + turns.push(withRestriction({ + from: way, + to: parent, + via: vertex, + toward: graph.entity(parent.nodes[index - 1]) + })); + } + + // forward + if (parent.last() !== vertex.id && parent.tags.oneway !== '-1') { + turns.push(withRestriction({ + from: way, + to: parent, + via: vertex, + toward: graph.entity(parent.nodes[index + 1]) + })); + } + }); + + return turns; + }; + + return intersection; +}; diff --git a/js/id/geo/turn.js b/js/id/geo/turn.js deleted file mode 100644 index 5776000e9..000000000 --- a/js/id/geo/turn.js +++ /dev/null @@ -1,82 +0,0 @@ -iD.geo.Turn = function(turn) { - turn = _.clone(turn); - - turn.key = function() { - var components = [turn.from, turn.to, turn.via, turn.toward]; - if (turn.restriction) - components.push(turn.restriction); - return components.map(iD.Entity.key).join('-'); - }; - - turn.angle = function(projection) { - var v = projection(turn.via.loc), - t = projection(turn.toward.loc); - - return Math.atan2(t[1] - v[1], t[0] - v[0]); - }; - - return turn; -}; - -iD.geo.turns = function(graph, entityID) { - var way = graph.entity(entityID); - if (way.type !== 'way' || !way.tags.highway || way.isArea()) - return []; - - function withRestriction(turn) { - graph.parentRelations(turn.from).forEach(function(relation) { - if (relation.tags.type !== 'restriction') - return; - - var f = relation.memberByRole('from'), - t = relation.memberByRole('to'), - v = relation.memberByRole('via'); - - if (f && f.id === turn.from.id && - t && t.id === turn.to.id && - v && v.id === turn.via.id) { - turn.restriction = relation; - } - }); - - return iD.geo.Turn(turn); - } - - var turns = []; - - [way.first(), way.last()].forEach(function(nodeID) { - var node = graph.entity(nodeID); - graph.parentWays(node).forEach(function(parent) { - if (parent === way || parent.isDegenerate() || !parent.tags.highway) - return; - if (way.first() === node.id && way.tags.oneway === 'yes') - return; - if (way.last() === node.id && way.tags.oneway === '-1') - return; - - var index = parent.nodes.indexOf(node.id); - - // backward - if (parent.first() !== node.id && parent.tags.oneway !== 'yes') { - turns.push(withRestriction({ - from: way, - to: parent, - via: node, - toward: graph.entity(parent.nodes[index - 1]) - })); - } - - // forward - if (parent.last() !== node.id && parent.tags.oneway !== '-1') { - turns.push(withRestriction({ - from: way, - to: parent, - via: node, - toward: graph.entity(parent.nodes[index + 1]) - })); - } - }); - }); - - return turns; -}; diff --git a/js/id/svg/turns.js b/js/id/svg/turns.js index f86518ce3..dce3ca924 100644 --- a/js/id/svg/turns.js +++ b/js/id/svg/turns.js @@ -1,7 +1,5 @@ iD.svg.Turns = function(projection) { - return function(surface, graph, wayID) { - var turns = wayID ? iD.geo.turns(graph, wayID) : []; - + return function(surface, graph, turns) { var groups = surface.select('.layer-hit').selectAll('g.turn') .data(turns, function(turn) { return turn.key(); }); diff --git a/js/id/ui/preset/restrictions.js b/js/id/ui/preset/restrictions.js index 9d72bd406..c604d04bd 100644 --- a/js/id/ui/preset/restrictions.js +++ b/js/id/ui/preset/restrictions.js @@ -1,6 +1,6 @@ iD.ui.preset.restrictions = function(field, context) { var event = d3.dispatch('change'), - entity, + vertex, selectedID; function restrictions(selection) { @@ -23,7 +23,7 @@ iD.ui.preset.restrictions = function(field, context) { var projection = iD.geo.RawMercator() .scale(256 * Math.pow(2, z) / (2 * Math.PI)); - var s = projection(entity ? entity.loc : [0, 0]); + var s = projection(vertex.loc); projection .translate([c[0] - s[0], c[1] - s[1]]) @@ -32,28 +32,16 @@ iD.ui.preset.restrictions = function(field, context) { var surface = wrap.selectAll('svg'), filter = function () { return true; }, extent = iD.geo.Extent(), - entities = [], - graph = context.graph(), + intersection = iD.geo.Intersection(context.graph(), vertex.id), + graph = intersection.graph, lines = iD.svg.Lines(projection, context), vertices = iD.svg.Vertices(projection, context), turns = iD.svg.Turns(projection, context); - if (entity) { - entities = graph.parentWays(entity).filter(function (parent) { - return parent.type === 'way' && parent.tags.highway && !parent.isArea(); - }); - - entities.push(entity); - } - - if (!selectedID && entities.length) { - selectedID = entities[0].id; - } - surface - .call(vertices, graph, entities, filter, extent, z) - .call(lines, graph, entities, filter) - .call(turns, graph, selectedID); + .call(vertices, graph, [vertex], filter, extent, z) + .call(lines, graph, intersection.highways, filter) + .call(turns, graph, intersection.turns(selectedID)); surface.on('click.select', function() { var datum = d3.event.target.__data__; @@ -85,9 +73,9 @@ iD.ui.preset.restrictions = function(field, context) { } restrictions.entity = function(_) { - if (!entity || entity.id !== _.id) { + if (!vertex || vertex.id !== _.id) { selectedID = null; - entity = _; + vertex = _; } }; diff --git a/test/index.html b/test/index.html index 708e20622..5b6469948 100644 --- a/test/index.html +++ b/test/index.html @@ -45,9 +45,9 @@ + - @@ -57,14 +57,14 @@ + + - - @@ -234,8 +234,8 @@ + - @@ -258,7 +258,6 @@ - diff --git a/test/index_packaged.html b/test/index_packaged.html index 55c067b52..0f83951a5 100644 --- a/test/index_packaged.html +++ b/test/index_packaged.html @@ -49,8 +49,8 @@ + - @@ -73,7 +73,6 @@ - diff --git a/test/spec/geo/intersection.js b/test/spec/geo/intersection.js new file mode 100644 index 000000000..c77b50c78 --- /dev/null +++ b/test/spec/geo/intersection.js @@ -0,0 +1,276 @@ +describe('iD.geo.Turn', function() { + describe('#angle', function() { + it("calculates the angle of via to toward", function() { + function projection(x) { return x; } + + var turn = iD.geo.Turn({ + via: iD.Node({id: 'v', loc: [1, 0]}), + toward: iD.Node({id: 'w', loc: [1, 1]}) + }); + + expect(turn.angle(projection)).to.eql(Math.PI / 2); + }); + }); +}); + +describe("iD.geo.Intersection", function() { + describe('highways', function() { + it('excludes non-highways', function() { + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', '*']}), + iD.Way({id: '-', nodes: ['*', 'w']}) + ]); + expect(iD.geo.Intersection(graph, '*').highways).to.eql([]); + }); + + it("excludes degenerate highways", function() { + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['*'], tags: {highway: 'residential'}}) + ]); + expect(_.pluck(iD.geo.Intersection(graph, '*').highways, 'id')).to.eql(['=']); + }); + + it('includes line highways', function() { + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['*', 'w']}) + ]); + expect(_.pluck(iD.geo.Intersection(graph, '*').highways, 'id')).to.eql(['=']); + }); + + it('excludes area highways', function() { + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', '*', 'w'], tags: {highway: 'pedestrian', area: 'yes'}}) + ]); + expect(iD.geo.Intersection(graph, '*').highways).to.eql([]); + }); + + it('auto-splits highways at the intersection', function() { + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', '*', 'w'], tags: {highway: 'residential'}}) + ]); + expect(_.pluck(iD.geo.Intersection(graph, '*').highways, 'id')).to.eql(['=-a', '=-b']); + }); + }); + + describe('#turns', function() { + function ids(turns) { + return turns.map(function (turn) { + var result = { + from: turn.from.id, + to: turn.to.id, + via: turn.via.id, + toward: turn.toward.id + }; + + if (turn.restriction) + result.restriction = turn.restriction.id; + + return result; + }); + } + + it("permits turns onto a way forward", function() { + // u====*--->w + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential'}}) + ]), + turns = iD.geo.Intersection(graph, '*').turns('='); + + expect(ids(turns)).to.eql([{ + from: '=', + to: '-', + via: '*', + toward: 'w' + }]); + }); + + it("permits turns onto a way backward", function() { + // u====*<---w + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['w', '*'], tags: {highway: 'residential'}}) + ]), + turns = iD.geo.Intersection(graph, '*').turns('='); + + expect(ids(turns)).to.eql([{from: '=', to: '-', via: '*', toward: 'w'}]); + }); + + it("permits turns onto a way in both directions", function() { + // w + // | + // u===* + // | + // x + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Node({id: 'x'}), + iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['w', '*', 'x'], tags: {highway: 'residential'}}) + ]), + turns = iD.geo.Intersection(graph, '*').turns('='); + + expect(ids(turns)).to.eql([ + {from: '=', to: '--a', via: '*', toward: 'w'}, + {from: '=', to: '--b', via: '*', toward: 'x'} + ]); + }); + + it("permits turns from a oneway forward", function() { + // u===>v----w + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential', oneway: 'yes'}}), + iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential'}}) + ]), + turns = iD.geo.Intersection(graph, '*').turns('='); + + expect(ids(turns)).to.eql([{from: '=', to: '-', via: '*', toward: 'w'}]); + }); + + it("permits turns from a reverse oneway backward", function() { + // u<===*----w + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['*', 'u'], tags: {highway: 'residential', oneway: '-1'}}), + iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential'}}) + ]), + turns = iD.geo.Intersection(graph, '*').turns('='); + + expect(ids(turns)).to.eql([{from: '=', to: '-', via: '*', toward: 'w'}]); + }); + + it("omits turns from a oneway backward", function() { + // u<===*----w + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['*', 'u'], tags: {highway: 'residential', oneway: 'yes'}}), + iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential'}}) + ]); + expect(iD.geo.Intersection(graph, '*').turns('=')).to.eql([]); + }); + + it("omits turns from a reverse oneway forward", function() { + // u===>*----w + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential', oneway: '-1'}}), + iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential'}}) + ]); + expect(iD.geo.Intersection(graph, '*').turns('=')).to.eql([]); + }); + + it("permits turns onto a oneway forward", function() { + // u====*--->w + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential', oneway: 'yes'}}) + ]), + turns = iD.geo.Intersection(graph, '*').turns('='); + + expect(ids(turns)).to.eql([{from: '=', to: '-', via: '*', toward: 'w'}]); + }); + + it("permits turns onto a reverse oneway backward", function() { + // u====*<---w + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['w', '*'], tags: {highway: 'residential', oneway: '-1'}}) + ]), + turns = iD.geo.Intersection(graph, '*').turns('='); + + expect(ids(turns)).to.eql([{from: '=', to: '-', via: '*', toward: 'w'}]); + }); + + it("omits turns onto a oneway backward", function() { + // u====*<---w + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['w', '*'], tags: {highway: 'residential', oneway: 'yes'}}) + ]); + expect(iD.geo.Intersection(graph, '*').turns('=')).to.eql([]); + }); + + it("omits turns onto a reverse oneway forward", function() { + // u====*--->w + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential', oneway: '-1'}}) + ]); + expect(iD.geo.Intersection(graph, '*').turns('=')).to.eql([]); + }); + + it("restricts turns with a restriction relation", function() { + // u====*--->w + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential'}}), + iD.Relation({id: 'r', tags: {type: 'restriction'}, members: [ + {id: '=', role: 'from', type: 'way'}, + {id: '-', role: 'to', type: 'way'}, + {id: '*', role: 'via', type: 'node'} + ]}) + ]), + turns = iD.geo.Intersection(graph, '*').turns('='); + + expect(ids(turns)).to.eql([{ + from: '=', + to: '-', + via: '*', + toward: 'w', + restriction: 'r' + }]); + }); + }); + + // 'no' vs 'only' + // U-turns + // Self-intersections +}); diff --git a/test/spec/geo/turn.js b/test/spec/geo/turn.js deleted file mode 100644 index 44f95dc92..000000000 --- a/test/spec/geo/turn.js +++ /dev/null @@ -1,312 +0,0 @@ -describe('iD.geo.Turn', function() { - describe('#angle', function() { - it("calculates the angle of via to toward", function() { - function projection(x) { return x; } - - var turn = iD.geo.Turn({ - via: iD.Node({id: 'v', loc: [1, 0]}), - toward: iD.Node({id: 'w', loc: [1, 1]}) - }); - - expect(turn.angle(projection)).to.eql(Math.PI / 2); - }); - }); -}); - -describe("iD.geo.turns", function() { - function properties(turns) { - return turns.map(function (turn) { return _.pick(turn, 'from', 'to', 'via', 'toward', 'restriction') }); - } - - it("returns an empty array for non-ways", function() { - var graph = iD.Graph([ - iD.Node({id: 'n'}) - ]); - expect(iD.geo.turns(graph, 'n')).to.eql([]); - }); - - it("returns an empty array for non-lines", function() { - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential', area: 'yes'}}), - iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential'}}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([]); - }); - - it("returns an empty array for an unconnected way", function() { - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Way({id: '=', nodes: ['u', 'v']}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([]); - }); - - it("omits turns onto degenerate ways", function() { - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['v'], tags: {highway: 'residential'}}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([]); - }); - - it("omits turns from non-highways", function() { - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v']}), - iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential'}}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([]); - }); - - it("omits turns onto non-highways", function() { - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['v', 'w']}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([]); - }); - - it("omits turns onto non-lines", function() { - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Node({id: 'x'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['v', 'w', 'x', 'v'], tags: {highway: 'residential', area: 'yes'}}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([]); - }); - - it("permits turns onto a way forward", function() { - // u====v--->w - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential'}}) - ]), - turns = iD.geo.turns(graph, '='); - - expect(properties(turns)).to.eql([{ - from: graph.entity('='), - to: graph.entity('-'), - via: graph.entity('v'), - toward: graph.entity('w') - }]); - }); - - it("permits turns onto a way backward", function() { - // u====v<---w - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['w', 'v'], tags: {highway: 'residential'}}) - ]), - turns = iD.geo.turns(graph, '='); - - expect(properties(turns)).to.eql([{ - from: graph.entity('='), - to: graph.entity('-'), - via: graph.entity('v'), - toward: graph.entity('w') - }]); - }); - - it("permits turns onto a way in both directions", function() { - // w - // | - // u===v - // | - // x - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Node({id: 'x'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['w', 'v', 'x'], tags: {highway: 'residential'}}) - ]), - turns = iD.geo.turns(graph, '='); - - expect(properties(turns)).to.eql([{ - from: graph.entity('='), - to: graph.entity('-'), - via: graph.entity('v'), - toward: graph.entity('w') - }, { - from: graph.entity('='), - to: graph.entity('-'), - via: graph.entity('v'), - toward: graph.entity('x') - }]); - }); - - it("permits turns from a oneway forward", function() { - // u===>v----w - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential', oneway: 'yes'}}), - iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential'}}) - ]), - turns = iD.geo.turns(graph, '='); - - expect(properties(turns)).to.eql([{ - from: graph.entity('='), - to: graph.entity('-'), - via: graph.entity('v'), - toward: graph.entity('w') - }]); - }); - - it("permits turns from a reverse oneway backward", function() { - // u<===v----w - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['v', 'u'], tags: {highway: 'residential', oneway: '-1'}}), - iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential'}}) - ]), - turns = iD.geo.turns(graph, '='); - - expect(properties(turns)).to.eql([{ - from: graph.entity('='), - to: graph.entity('-'), - via: graph.entity('v'), - toward: graph.entity('w') - }]); - }); - - it("omits turns from a oneway backward", function() { - // u<===v----w - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['v', 'u'], tags: {highway: 'residential', oneway: 'yes'}}), - iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential'}}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([]); - }); - - it("omits turns from a reverse oneway forward", function() { - // u===>v----w - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential', oneway: '-1'}}), - iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential'}}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([]); - }); - - it("permits turns onto a oneway forward", function() { - // u====v--->w - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential', oneway: 'yes'}}) - ]), - turns = iD.geo.turns(graph, '='); - - expect(properties(turns)).to.eql([{ - from: graph.entity('='), - to: graph.entity('-'), - via: graph.entity('v'), - toward: graph.entity('w') - }]); - }); - - it("permits turns onto a reverse oneway backward", function() { - // u====v<---w - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['w', 'v'], tags: {highway: 'residential', oneway: '-1'}}) - ]), - turns = iD.geo.turns(graph, '='); - - expect(properties(turns)).to.eql([{ - from: graph.entity('='), - to: graph.entity('-'), - via: graph.entity('v'), - toward: graph.entity('w') - }]); - }); - - it("omits turns onto a oneway backward", function() { - // u====v<---w - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['w', 'v'], tags: {highway: 'residential', oneway: 'yes'}}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([]); - }); - - it("omits turns onto a reverse oneway forward", function() { - // u====v--->w - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential', oneway: '-1'}}) - ]); - expect(iD.geo.turns(graph, '=')).to.eql([]); - }); - - it("restricts turns with a restriction relation", function() { - // u====v--->w - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: 'v'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', 'v'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['v', 'w'], tags: {highway: 'residential'}}), - iD.Relation({id: 'r', tags: {type: 'restriction'}, members: [ - {id: '=', role: 'from', type: 'way'}, - {id: '-', role: 'to', type: 'way'}, - {id: 'v', role: 'via', type: 'node'} - ]}) - ]), - turns = iD.geo.turns(graph, '='); - - expect(properties(turns)).to.eql([{ - from: graph.entity('='), - to: graph.entity('-'), - via: graph.entity('v'), - toward: graph.entity('w'), - restriction: graph.entity('r') - }]); - }); - - // 'no' vs 'only' - // U-turns - // Self-intersections - // Split point -}); diff --git a/test/spec/svg/restrictions.js b/test/spec/svg/restrictions.js deleted file mode 100644 index 5d4f5e5e3..000000000 --- a/test/spec/svg/restrictions.js +++ /dev/null @@ -1,2 +0,0 @@ -describe("iD.svg.Restrictions", function() { -}); From 0afb5002cf567e4d39751d39b8799a68291fc111 Mon Sep 17 00:00:00 2001 From: samanpwbb Date: Fri, 16 May 2014 14:29:33 -0400 Subject: [PATCH 11/26] adding turn restriction assets --- dist/img/relation-presets.png | Bin 17817 -> 22869 bytes svg/relation-presets.svg | 245 +++++++++++++++++++++++++++++++--- svg/resitriction-no-u.svg | 76 +++++++++++ svg/restriction-no.svg | 78 +++++++++++ svg/restriction-yes-u.svg | 76 +++++++++++ svg/restriction-yes.svg | 77 +++++++++++ 6 files changed, 533 insertions(+), 19 deletions(-) create mode 100644 svg/resitriction-no-u.svg create mode 100644 svg/restriction-no.svg create mode 100644 svg/restriction-yes-u.svg create mode 100644 svg/restriction-yes.svg diff --git a/dist/img/relation-presets.png b/dist/img/relation-presets.png index 00c922b757c8c414452ff2eeb09af1bdd5d0f42e..47f1d6e30c30e7dad2567653c9334cfcc2284a2d 100644 GIT binary patch literal 22869 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 literal 17817 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 + inkscape:version="0.48.2 r9819" + sodipodi:docname="relation-presets.svg" + inkscape:export-filename="/Users/saman/work_repos/iD/css/img/relation-presets@2x.png" + inkscape:export-xdpi="180" + inkscape:export-ydpi="180"> + + + + + + @@ -369,7 +396,7 @@ image/svg+xml - + @@ -1505,7 +1532,7 @@ id="path23512" transform="translate(-400,12.362183)" d="M 110 39.5 C 101.43958 39.5 94.5 46.439584 94.5 55 C 94.5 63.560416 101.43958 70.5 110 70.5 C 118.56042 70.5 125.5 63.560416 125.5 55 C 125.5 46.439584 118.56042 39.5 110 39.5 z M 110 43.5 C 116.35127 43.5 121.5 48.648725 121.5 55 C 121.5 57.454314 120.71623 59.726293 119.40625 61.59375 L 103.40625 45.59375 C 105.27371 44.283773 107.54569 43.5 110 43.5 z M 100.59375 48.40625 L 116.59375 64.40625 C 114.72629 65.716227 112.45431 66.5 110 66.5 C 103.64873 66.5 98.5 61.351275 98.5 55 C 98.5 52.545686 99.283773 50.273707 100.59375 48.40625 z " - style="color:#000000;fill:#e06d5f;fill-opacity:1;fill-rule:nonzero;stroke:#70372f;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> + style="color:#000000;fill:#e06d5f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/svg/resitriction-no-u.svg b/svg/resitriction-no-u.svg new file mode 100644 index 000000000..af584a552 --- /dev/null +++ b/svg/resitriction-no-u.svg @@ -0,0 +1,76 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/svg/restriction-no.svg b/svg/restriction-no.svg new file mode 100644 index 000000000..512ad5616 --- /dev/null +++ b/svg/restriction-no.svg @@ -0,0 +1,78 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/svg/restriction-yes-u.svg b/svg/restriction-yes-u.svg new file mode 100644 index 000000000..854f8761d --- /dev/null +++ b/svg/restriction-yes-u.svg @@ -0,0 +1,76 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/svg/restriction-yes.svg b/svg/restriction-yes.svg new file mode 100644 index 000000000..a0b088a31 --- /dev/null +++ b/svg/restriction-yes.svg @@ -0,0 +1,77 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + From 15fb547bcc9887d57db16dc86201ea48c631a588 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 15 May 2014 17:29:57 -0700 Subject: [PATCH 12/26] Let preset editor preserve field state The turn restrictions field wants to have selected state. --- js/id/ui/entity_editor.js | 7 ++++--- js/id/ui/preset.js | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/js/id/ui/entity_editor.js b/js/id/ui/entity_editor.js index 4f59f209e..272f3555a 100644 --- a/js/id/ui/entity_editor.js +++ b/js/id/ui/entity_editor.js @@ -5,6 +5,8 @@ iD.ui.EntityEditor = function(context) { preset, reference; + var presetEditor = iD.ui.preset(context) + .on('change', changeTags); var rawTagEditor = iD.ui.RawTagEditor(context) .on('change', changeTags); @@ -91,12 +93,11 @@ iD.ui.EntityEditor = function(context) { .text(preset.name()); $body.select('.inspector-preset') - .call(iD.ui.preset(context) + .call(presetEditor .preset(preset) .entityID(id) .tags(tags) - .state(state) - .on('change', changeTags)); + .state(state)); $body.select('.raw-tag-editor') .call(rawTagEditor diff --git a/js/id/ui/preset.js b/js/id/ui/preset.js index de3f550b3..b0a372bc3 100644 --- a/js/id/ui/preset.js +++ b/js/id/ui/preset.js @@ -200,6 +200,7 @@ iD.ui.preset = function(context) { presets.preset = function(_) { if (!arguments.length) return preset; + if (preset && preset.id === _.id) return presets; preset = _; fields = null; return presets; @@ -220,6 +221,7 @@ iD.ui.preset = function(context) { presets.entityID = function(_) { if (!arguments.length) return id; + if (id === _) return presets; id = _; fields = null; return presets; From f74f6ad54ace2d0a63c42fdae0de41f28db02b4b Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 16 May 2014 13:43:13 -0700 Subject: [PATCH 13/26] Use restriction preset icons --- css/feature-icons.css | 11 ++-- data/feature-icons.json | 2 +- data/presets.yaml | 15 ++++- data/presets/categories.json | 15 +++++ data/presets/categories/restriction.json | 15 +++++ data/presets/defaults.json | 2 +- data/presets/presets.json | 52 ++++++++++++++++-- .../type/restriction/no_left_turn.json | 2 +- .../type/restriction/no_right_turn.json | 2 +- .../type/restriction/no_straight_on.json | 2 +- .../presets/type/restriction/no_u_turn.json | 4 +- .../type/restriction/only_left_turn.json | 14 +++++ .../type/restriction/only_right_turn.json | 14 +++++ .../type/restriction/only_straight_ahead.json | 14 +++++ data/relation-icons.json | 9 ++- dist/img/maki-sprite.png | Bin 113751 -> 109414 bytes dist/locales/en.json | 17 +++++- 17 files changed, 170 insertions(+), 20 deletions(-) create mode 100644 data/presets/categories/restriction.json create mode 100644 data/presets/presets/type/restriction/only_left_turn.json create mode 100644 data/presets/presets/type/restriction/only_right_turn.json create mode 100644 data/presets/presets/type/restriction/only_straight_ahead.json diff --git a/css/feature-icons.css b/css/feature-icons.css index 6d3c638ea..9b7926f17 100644 --- a/css/feature-icons.css +++ b/css/feature-icons.css @@ -113,10 +113,6 @@ .feature-laundry{background-position:-108px -504px;} .feature-car{background-position:-162px -504px;} .feature-suitcase{background-position:-216px -504px;} -.feature-hairdresser{background-position:-0px -528px;} -.feature-chemist{background-position:-54px -528px;} -.feature-mobilephone{background-position:-108px -528px;} -.feature-scooter{background-position:-162px -528px;} .preset-icon-line.feature-highway-motorway{background-position:-20px -25px;} .preset-icon-line.feature-highway-trunk{background-position:-80px -25px;} .preset-icon-line.feature-highway-primary{background-position:-140px -25px;} @@ -172,3 +168,10 @@ .preset-icon-relation.feature-route-power{background-position:-800px -25px;} .preset-icon-relation.feature-route-pipeline{background-position:-860px -25px;} .preset-icon-relation.feature-route-master{background-position:-920px -25px;} +.preset-icon-relation.feature-restriction-no-straight-on{background-position:-980px -25px;} +.preset-icon-relation.feature-restriction-no-u-turn{background-position:-1040px -25px;} +.preset-icon-relation.feature-restriction-no-left-turn{background-position:-1100px -25px;} +.preset-icon-relation.feature-restriction-no-right-turn{background-position:-1160px -25px;} +.preset-icon-relation.feature-restriction-only-straight-ahead{background-position:-1220px -25px;} +.preset-icon-relation.feature-restriction-only-left-turn{background-position:-1280px -25px;} +.preset-icon-relation.feature-restriction-only-right-turn{background-position:-1340px -25px;} diff --git a/data/feature-icons.json b/data/feature-icons.json index 001e6aecc..750d11baf 100644 --- a/data/feature-icons.json +++ b/data/feature-icons.json @@ -1 +1 @@ -{"circle-stroked":{"12":[42,0],"18":[24,0],"24":[0,0]},"circle":{"12":[96,0],"18":[78,0],"24":[54,0]},"square-stroked":{"12":[150,0],"18":[132,0],"24":[108,0]},"square":{"12":[204,0],"18":[186,0],"24":[162,0]},"triangle-stroked":{"12":[258,0],"18":[240,0],"24":[216,0]},"triangle":{"12":[42,24],"18":[24,24],"24":[0,24]},"star-stroked":{"12":[96,24],"18":[78,24],"24":[54,24]},"star":{"12":[150,24],"18":[132,24],"24":[108,24]},"cross":{"12":[204,24],"18":[186,24],"24":[162,24]},"marker-stroked":{"12":[258,24],"18":[240,24],"24":[216,24]},"marker":{"12":[42,48],"18":[24,48],"24":[0,48]},"religious-jewish":{"12":[96,48],"18":[78,48],"24":[54,48]},"religious-christian":{"12":[150,48],"18":[132,48],"24":[108,48]},"religious-muslim":{"12":[204,48],"18":[186,48],"24":[162,48]},"cemetery":{"12":[258,48],"18":[240,48],"24":[216,48]},"rocket":{"12":[42,72],"18":[24,72],"24":[0,72]},"airport":{"12":[96,72],"18":[78,72],"24":[54,72]},"heliport":{"12":[150,72],"18":[132,72],"24":[108,72]},"rail":{"12":[204,72],"18":[186,72],"24":[162,72]},"rail-metro":{"12":[258,72],"18":[240,72],"24":[216,72]},"rail-light":{"12":[42,96],"18":[24,96],"24":[0,96]},"bus":{"12":[96,96],"18":[78,96],"24":[54,96]},"fuel":{"12":[150,96],"18":[132,96],"24":[108,96]},"parking":{"12":[204,96],"18":[186,96],"24":[162,96]},"parking-garage":{"12":[258,96],"18":[240,96],"24":[216,96]},"airfield":{"12":[42,120],"18":[24,120],"24":[0,120]},"roadblock":{"12":[96,120],"18":[78,120],"24":[54,120]},"ferry":{"12":[150,120],"18":[132,120],"24":[108,120],"line":[2240,25]},"harbor":{"12":[204,120],"18":[186,120],"24":[162,120]},"bicycle":{"12":[258,120],"18":[240,120],"24":[216,120]},"park":{"12":[42,144],"18":[24,144],"24":[0,144]},"park2":{"12":[96,144],"18":[78,144],"24":[54,144]},"museum":{"12":[150,144],"18":[132,144],"24":[108,144]},"lodging":{"12":[204,144],"18":[186,144],"24":[162,144]},"monument":{"12":[258,144],"18":[240,144],"24":[216,144]},"zoo":{"12":[42,168],"18":[24,168],"24":[0,168]},"garden":{"12":[96,168],"18":[78,168],"24":[54,168]},"campsite":{"12":[150,168],"18":[132,168],"24":[108,168]},"theatre":{"12":[204,168],"18":[186,168],"24":[162,168]},"art-gallery":{"12":[258,168],"18":[240,168],"24":[216,168]},"pitch":{"12":[42,192],"18":[24,192],"24":[0,192]},"soccer":{"12":[96,192],"18":[78,192],"24":[54,192]},"america-football":{"12":[150,192],"18":[132,192],"24":[108,192]},"tennis":{"12":[204,192],"18":[186,192],"24":[162,192]},"basketball":{"12":[258,192],"18":[240,192],"24":[216,192]},"baseball":{"12":[42,216],"18":[24,216],"24":[0,216]},"golf":{"12":[96,216],"18":[78,216],"24":[54,216]},"swimming":{"12":[150,216],"18":[132,216],"24":[108,216]},"cricket":{"12":[204,216],"18":[186,216],"24":[162,216]},"skiing":{"12":[258,216],"18":[240,216],"24":[216,216]},"school":{"12":[42,240],"18":[24,240],"24":[0,240]},"college":{"12":[96,240],"18":[78,240],"24":[54,240]},"library":{"12":[150,240],"18":[132,240],"24":[108,240]},"post":{"12":[204,240],"18":[186,240],"24":[162,240]},"fire-station":{"12":[258,240],"18":[240,240],"24":[216,240]},"town-hall":{"12":[42,264],"18":[24,264],"24":[0,264]},"police":{"12":[96,264],"18":[78,264],"24":[54,264]},"prison":{"12":[150,264],"18":[132,264],"24":[108,264]},"embassy":{"12":[204,264],"18":[186,264],"24":[162,264]},"beer":{"12":[258,264],"18":[240,264],"24":[216,264]},"restaurant":{"12":[42,288],"18":[24,288],"24":[0,288]},"cafe":{"12":[96,288],"18":[78,288],"24":[54,288]},"shop":{"12":[150,288],"18":[132,288],"24":[108,288]},"fast-food":{"12":[204,288],"18":[186,288],"24":[162,288]},"bar":{"12":[258,288],"18":[240,288],"24":[216,288]},"bank":{"12":[42,312],"18":[24,312],"24":[0,312]},"grocery":{"12":[96,312],"18":[78,312],"24":[54,312]},"cinema":{"12":[150,312],"18":[132,312],"24":[108,312]},"pharmacy":{"12":[204,312],"18":[186,312],"24":[162,312]},"hospital":{"12":[258,312],"18":[240,312],"24":[216,312]},"danger":{"12":[42,336],"18":[24,336],"24":[0,336]},"industrial":{"12":[96,336],"18":[78,336],"24":[54,336]},"warehouse":{"12":[150,336],"18":[132,336],"24":[108,336]},"commercial":{"12":[204,336],"18":[186,336],"24":[162,336]},"building":{"12":[258,336],"18":[240,336],"24":[216,336]},"place-of-worship":{"12":[42,360],"18":[24,360],"24":[0,360]},"alcohol-shop":{"12":[96,360],"18":[78,360],"24":[54,360]},"logging":{"12":[150,360],"18":[132,360],"24":[108,360]},"oil-well":{"12":[204,360],"18":[186,360],"24":[162,360]},"slaughterhouse":{"12":[258,360],"18":[240,360],"24":[216,360]},"dam":{"12":[42,384],"18":[24,384],"24":[0,384]},"water":{"12":[96,384],"18":[78,384],"24":[54,384]},"wetland":{"12":[150,384],"18":[132,384],"24":[108,384]},"disability":{"12":[204,384],"18":[186,384],"24":[162,384]},"telephone":{"12":[258,384],"18":[240,384],"24":[216,384]},"emergency-telephone":{"12":[42,408],"18":[24,408],"24":[0,408]},"toilets":{"12":[96,408],"18":[78,408],"24":[54,408]},"waste-basket":{"12":[150,408],"18":[132,408],"24":[108,408]},"music":{"12":[204,408],"18":[186,408],"24":[162,408]},"land-use":{"12":[258,408],"18":[240,408],"24":[216,408]},"city":{"12":[42,432],"18":[24,432],"24":[0,432]},"town":{"12":[96,432],"18":[78,432],"24":[54,432]},"village":{"12":[150,432],"18":[132,432],"24":[108,432]},"farm":{"12":[204,432],"18":[186,432],"24":[162,432]},"bakery":{"12":[258,432],"18":[240,432],"24":[216,432]},"dog-park":{"12":[42,456],"18":[24,456],"24":[0,456]},"lighthouse":{"12":[96,456],"18":[78,456],"24":[54,456]},"clothing-store":{"12":[150,456],"18":[132,456],"24":[108,456]},"polling-place":{"12":[204,456],"18":[186,456],"24":[162,456]},"playground":{"12":[258,456],"18":[240,456],"24":[216,456]},"entrance":{"12":[42,480],"18":[24,480],"24":[0,480]},"heart":{"12":[96,480],"18":[78,480],"24":[54,480]},"london-underground":{"12":[150,480],"18":[132,480],"24":[108,480]},"minefield":{"12":[204,480],"18":[186,480],"24":[162,480]},"rail-underground":{"12":[258,480],"18":[240,480],"24":[216,480]},"rail-above":{"12":[42,504],"18":[24,504],"24":[0,504]},"camera":{"12":[96,504],"18":[78,504],"24":[54,504]},"laundry":{"12":[150,504],"18":[132,504],"24":[108,504]},"car":{"12":[204,504],"18":[186,504],"24":[162,504]},"suitcase":{"12":[258,504],"18":[240,504],"24":[216,504]},"hairdresser":{"12":[42,528],"18":[24,528],"24":[0,528]},"chemist":{"12":[96,528],"18":[78,528],"24":[54,528]},"mobilephone":{"12":[150,528],"18":[132,528],"24":[108,528]},"scooter":{"12":[204,528],"18":[186,528],"24":[162,528]},"highway-motorway":{"line":[20,25]},"highway-trunk":{"line":[80,25]},"highway-primary":{"line":[140,25]},"highway-secondary":{"line":[200,25]},"highway-tertiary":{"line":[260,25]},"highway-motorway-link":{"line":[320,25]},"highway-trunk-link":{"line":[380,25]},"highway-primary-link":{"line":[440,25]},"highway-secondary-link":{"line":[500,25]},"highway-tertiary-link":{"line":[560,25]},"highway-residential":{"line":[620,25]},"highway-unclassified":{"line":[680,25]},"highway-service":{"line":[740,25]},"highway-road":{"line":[800,25]},"highway-track":{"line":[860,25]},"highway-living-street":{"line":[920,25]},"highway-path":{"line":[980,25]},"highway-cycleway":{"line":[1040,25]},"highway-footway":{"line":[1100,25]},"highway-bridleway":{"line":[1160,25]},"highway-steps":{"line":[1220,25]},"railway-rail":{"line":[1280,25]},"railway-disused":{"line":[1340,25]},"railway-abandoned":{"line":[1400,25]},"railway-subway":{"line":[1460,25]},"railway-light-rail":{"line":[1520,25]},"railway-monorail":{"line":[1580,25]},"waterway-river":{"line":[1640,25]},"waterway-stream":{"line":[1700,25]},"waterway-canal":{"line":[1760,25]},"waterway-ditch":{"line":[1820,25]},"power-line":{"line":[1880,25]},"other-line":{"line":[1940,25]},"category-roads":{"line":[2000,25]},"category-rail":{"line":[2060,25]},"category-path":{"line":[2120,25]},"category-water":{"line":[2180,25]},"pipeline":{"line":[2300,25]},"relation":{"relation":[20,25]},"restriction":{"relation":[80,25]},"multipolygon":{"relation":[140,25]},"boundary":{"relation":[200,25]},"route":{"relation":[260,25]},"route-road":{"relation":[320,25]},"route-bicycle":{"relation":[380,25]},"route-foot":{"relation":[440,25]},"route-bus":{"relation":[500,25]},"route-train":{"relation":[560,25]},"route-detour":{"relation":[620,25]},"route-tram":{"relation":[680,25]},"route-ferry":{"relation":[740,25]},"route-power":{"relation":[800,25]},"route-pipeline":{"relation":[860,25]},"route-master":{"relation":[920,25]}} \ No newline at end of file +{"circle-stroked":{"12":[42,0],"18":[24,0],"24":[0,0]},"circle":{"12":[96,0],"18":[78,0],"24":[54,0]},"square-stroked":{"12":[150,0],"18":[132,0],"24":[108,0]},"square":{"12":[204,0],"18":[186,0],"24":[162,0]},"triangle-stroked":{"12":[258,0],"18":[240,0],"24":[216,0]},"triangle":{"12":[42,24],"18":[24,24],"24":[0,24]},"star-stroked":{"12":[96,24],"18":[78,24],"24":[54,24]},"star":{"12":[150,24],"18":[132,24],"24":[108,24]},"cross":{"12":[204,24],"18":[186,24],"24":[162,24]},"marker-stroked":{"12":[258,24],"18":[240,24],"24":[216,24]},"marker":{"12":[42,48],"18":[24,48],"24":[0,48]},"religious-jewish":{"12":[96,48],"18":[78,48],"24":[54,48]},"religious-christian":{"12":[150,48],"18":[132,48],"24":[108,48]},"religious-muslim":{"12":[204,48],"18":[186,48],"24":[162,48]},"cemetery":{"12":[258,48],"18":[240,48],"24":[216,48]},"rocket":{"12":[42,72],"18":[24,72],"24":[0,72]},"airport":{"12":[96,72],"18":[78,72],"24":[54,72]},"heliport":{"12":[150,72],"18":[132,72],"24":[108,72]},"rail":{"12":[204,72],"18":[186,72],"24":[162,72]},"rail-metro":{"12":[258,72],"18":[240,72],"24":[216,72]},"rail-light":{"12":[42,96],"18":[24,96],"24":[0,96]},"bus":{"12":[96,96],"18":[78,96],"24":[54,96]},"fuel":{"12":[150,96],"18":[132,96],"24":[108,96]},"parking":{"12":[204,96],"18":[186,96],"24":[162,96]},"parking-garage":{"12":[258,96],"18":[240,96],"24":[216,96]},"airfield":{"12":[42,120],"18":[24,120],"24":[0,120]},"roadblock":{"12":[96,120],"18":[78,120],"24":[54,120]},"ferry":{"12":[150,120],"18":[132,120],"24":[108,120],"line":[2240,25]},"harbor":{"12":[204,120],"18":[186,120],"24":[162,120]},"bicycle":{"12":[258,120],"18":[240,120],"24":[216,120]},"park":{"12":[42,144],"18":[24,144],"24":[0,144]},"park2":{"12":[96,144],"18":[78,144],"24":[54,144]},"museum":{"12":[150,144],"18":[132,144],"24":[108,144]},"lodging":{"12":[204,144],"18":[186,144],"24":[162,144]},"monument":{"12":[258,144],"18":[240,144],"24":[216,144]},"zoo":{"12":[42,168],"18":[24,168],"24":[0,168]},"garden":{"12":[96,168],"18":[78,168],"24":[54,168]},"campsite":{"12":[150,168],"18":[132,168],"24":[108,168]},"theatre":{"12":[204,168],"18":[186,168],"24":[162,168]},"art-gallery":{"12":[258,168],"18":[240,168],"24":[216,168]},"pitch":{"12":[42,192],"18":[24,192],"24":[0,192]},"soccer":{"12":[96,192],"18":[78,192],"24":[54,192]},"america-football":{"12":[150,192],"18":[132,192],"24":[108,192]},"tennis":{"12":[204,192],"18":[186,192],"24":[162,192]},"basketball":{"12":[258,192],"18":[240,192],"24":[216,192]},"baseball":{"12":[42,216],"18":[24,216],"24":[0,216]},"golf":{"12":[96,216],"18":[78,216],"24":[54,216]},"swimming":{"12":[150,216],"18":[132,216],"24":[108,216]},"cricket":{"12":[204,216],"18":[186,216],"24":[162,216]},"skiing":{"12":[258,216],"18":[240,216],"24":[216,216]},"school":{"12":[42,240],"18":[24,240],"24":[0,240]},"college":{"12":[96,240],"18":[78,240],"24":[54,240]},"library":{"12":[150,240],"18":[132,240],"24":[108,240]},"post":{"12":[204,240],"18":[186,240],"24":[162,240]},"fire-station":{"12":[258,240],"18":[240,240],"24":[216,240]},"town-hall":{"12":[42,264],"18":[24,264],"24":[0,264]},"police":{"12":[96,264],"18":[78,264],"24":[54,264]},"prison":{"12":[150,264],"18":[132,264],"24":[108,264]},"embassy":{"12":[204,264],"18":[186,264],"24":[162,264]},"beer":{"12":[258,264],"18":[240,264],"24":[216,264]},"restaurant":{"12":[42,288],"18":[24,288],"24":[0,288]},"cafe":{"12":[96,288],"18":[78,288],"24":[54,288]},"shop":{"12":[150,288],"18":[132,288],"24":[108,288]},"fast-food":{"12":[204,288],"18":[186,288],"24":[162,288]},"bar":{"12":[258,288],"18":[240,288],"24":[216,288]},"bank":{"12":[42,312],"18":[24,312],"24":[0,312]},"grocery":{"12":[96,312],"18":[78,312],"24":[54,312]},"cinema":{"12":[150,312],"18":[132,312],"24":[108,312]},"pharmacy":{"12":[204,312],"18":[186,312],"24":[162,312]},"hospital":{"12":[258,312],"18":[240,312],"24":[216,312]},"danger":{"12":[42,336],"18":[24,336],"24":[0,336]},"industrial":{"12":[96,336],"18":[78,336],"24":[54,336]},"warehouse":{"12":[150,336],"18":[132,336],"24":[108,336]},"commercial":{"12":[204,336],"18":[186,336],"24":[162,336]},"building":{"12":[258,336],"18":[240,336],"24":[216,336]},"place-of-worship":{"12":[42,360],"18":[24,360],"24":[0,360]},"alcohol-shop":{"12":[96,360],"18":[78,360],"24":[54,360]},"logging":{"12":[150,360],"18":[132,360],"24":[108,360]},"oil-well":{"12":[204,360],"18":[186,360],"24":[162,360]},"slaughterhouse":{"12":[258,360],"18":[240,360],"24":[216,360]},"dam":{"12":[42,384],"18":[24,384],"24":[0,384]},"water":{"12":[96,384],"18":[78,384],"24":[54,384]},"wetland":{"12":[150,384],"18":[132,384],"24":[108,384]},"disability":{"12":[204,384],"18":[186,384],"24":[162,384]},"telephone":{"12":[258,384],"18":[240,384],"24":[216,384]},"emergency-telephone":{"12":[42,408],"18":[24,408],"24":[0,408]},"toilets":{"12":[96,408],"18":[78,408],"24":[54,408]},"waste-basket":{"12":[150,408],"18":[132,408],"24":[108,408]},"music":{"12":[204,408],"18":[186,408],"24":[162,408]},"land-use":{"12":[258,408],"18":[240,408],"24":[216,408]},"city":{"12":[42,432],"18":[24,432],"24":[0,432]},"town":{"12":[96,432],"18":[78,432],"24":[54,432]},"village":{"12":[150,432],"18":[132,432],"24":[108,432]},"farm":{"12":[204,432],"18":[186,432],"24":[162,432]},"bakery":{"12":[258,432],"18":[240,432],"24":[216,432]},"dog-park":{"12":[42,456],"18":[24,456],"24":[0,456]},"lighthouse":{"12":[96,456],"18":[78,456],"24":[54,456]},"clothing-store":{"12":[150,456],"18":[132,456],"24":[108,456]},"polling-place":{"12":[204,456],"18":[186,456],"24":[162,456]},"playground":{"12":[258,456],"18":[240,456],"24":[216,456]},"entrance":{"12":[42,480],"18":[24,480],"24":[0,480]},"heart":{"12":[96,480],"18":[78,480],"24":[54,480]},"london-underground":{"12":[150,480],"18":[132,480],"24":[108,480]},"minefield":{"12":[204,480],"18":[186,480],"24":[162,480]},"rail-underground":{"12":[258,480],"18":[240,480],"24":[216,480]},"rail-above":{"12":[42,504],"18":[24,504],"24":[0,504]},"camera":{"12":[96,504],"18":[78,504],"24":[54,504]},"laundry":{"12":[150,504],"18":[132,504],"24":[108,504]},"car":{"12":[204,504],"18":[186,504],"24":[162,504]},"suitcase":{"12":[258,504],"18":[240,504],"24":[216,504]},"highway-motorway":{"line":[20,25]},"highway-trunk":{"line":[80,25]},"highway-primary":{"line":[140,25]},"highway-secondary":{"line":[200,25]},"highway-tertiary":{"line":[260,25]},"highway-motorway-link":{"line":[320,25]},"highway-trunk-link":{"line":[380,25]},"highway-primary-link":{"line":[440,25]},"highway-secondary-link":{"line":[500,25]},"highway-tertiary-link":{"line":[560,25]},"highway-residential":{"line":[620,25]},"highway-unclassified":{"line":[680,25]},"highway-service":{"line":[740,25]},"highway-road":{"line":[800,25]},"highway-track":{"line":[860,25]},"highway-living-street":{"line":[920,25]},"highway-path":{"line":[980,25]},"highway-cycleway":{"line":[1040,25]},"highway-footway":{"line":[1100,25]},"highway-bridleway":{"line":[1160,25]},"highway-steps":{"line":[1220,25]},"railway-rail":{"line":[1280,25]},"railway-disused":{"line":[1340,25]},"railway-abandoned":{"line":[1400,25]},"railway-subway":{"line":[1460,25]},"railway-light-rail":{"line":[1520,25]},"railway-monorail":{"line":[1580,25]},"waterway-river":{"line":[1640,25]},"waterway-stream":{"line":[1700,25]},"waterway-canal":{"line":[1760,25]},"waterway-ditch":{"line":[1820,25]},"power-line":{"line":[1880,25]},"other-line":{"line":[1940,25]},"category-roads":{"line":[2000,25]},"category-rail":{"line":[2060,25]},"category-path":{"line":[2120,25]},"category-water":{"line":[2180,25]},"pipeline":{"line":[2300,25]},"relation":{"relation":[20,25]},"restriction":{"relation":[80,25]},"multipolygon":{"relation":[140,25]},"boundary":{"relation":[200,25]},"route":{"relation":[260,25]},"route-road":{"relation":[320,25]},"route-bicycle":{"relation":[380,25]},"route-foot":{"relation":[440,25]},"route-bus":{"relation":[500,25]},"route-train":{"relation":[560,25]},"route-detour":{"relation":[620,25]},"route-tram":{"relation":[680,25]},"route-ferry":{"relation":[740,25]},"route-power":{"relation":[800,25]},"route-pipeline":{"relation":[860,25]},"route-master":{"relation":[920,25]},"restriction-no-straight-on":{"relation":[980,25]},"restriction-no-u-turn":{"relation":[1040,25]},"restriction-no-left-turn":{"relation":[1100,25]},"restriction-no-right-turn":{"relation":[1160,25]},"restriction-only-straight-ahead":{"relation":[1220,25]},"restriction-only-left-turn":{"relation":[1280,25]},"restriction-only-right-turn":{"relation":[1340,25]}} \ No newline at end of file diff --git a/data/presets.yaml b/data/presets.yaml index 7956ed495..47c7f7e29 100644 --- a/data/presets.yaml +++ b/data/presets.yaml @@ -11,6 +11,8 @@ en: name: Path "category-rail": name: Rail + "category-restriction": + name: Restriction "category-road": name: Road "category-route": @@ -1802,8 +1804,17 @@ en: name: No Straight On terms: "" type/restriction/no_u_turn: - name: No U Turn - terms: "" + name: "No U-turn" + terms: "" + type/restriction/only_left_turn: + name: Left Turn Only + terms: "" + type/restriction/only_right_turn: + name: Right Turn Only + terms: "" + type/restriction/only_straight_ahead: + name: No Turns + terms: "" type/route: name: Route terms: "" diff --git a/data/presets/categories.json b/data/presets/categories.json index 20e9ea3d7..ff320f113 100644 --- a/data/presets/categories.json +++ b/data/presets/categories.json @@ -68,6 +68,21 @@ "railway/abandoned" ] }, + "category-restriction": { + "geometry": "relation", + "name": "Restriction", + "icon": "restriction", + "members": [ + "type/restriction/no_left_turn", + "type/restriction/no_right_turn", + "type/restriction/no_straight_on", + "type/restriction/no_u_turn", + "type/restriction/only_left_turn", + "type/restriction/only_right_turn", + "type/restriction/only_straight_ahead", + "type/restriction" + ] + }, "category-road": { "geometry": "line", "name": "Road", diff --git a/data/presets/categories/restriction.json b/data/presets/categories/restriction.json new file mode 100644 index 000000000..9403d50e1 --- /dev/null +++ b/data/presets/categories/restriction.json @@ -0,0 +1,15 @@ +{ + "geometry": "relation", + "name": "Restriction", + "icon": "restriction", + "members": [ + "type/restriction/no_left_turn", + "type/restriction/no_right_turn", + "type/restriction/no_straight_on", + "type/restriction/no_u_turn", + "type/restriction/only_left_turn", + "type/restriction/only_right_turn", + "type/restriction/only_straight_ahead", + "type/restriction" + ] +} diff --git a/data/presets/defaults.json b/data/presets/defaults.json index 2fdd42049..00a385aca 100644 --- a/data/presets/defaults.json +++ b/data/presets/defaults.json @@ -40,8 +40,8 @@ ], "relation": [ "category-route", + "category-restriction", "type/boundary", - "type/restriction", "type/multipolygon", "relation" ] diff --git a/data/presets/presets.json b/data/presets/presets.json index 407d0418b..94de478d4 100644 --- a/data/presets/presets.json +++ b/data/presets/presets.json @@ -7980,7 +7980,7 @@ "fields": [ "except" ], - "icon": "restriction" + "icon": "restriction-no-left-turn" }, "type/restriction/no_right_turn": { "name": "No Right Turn", @@ -7994,7 +7994,7 @@ "fields": [ "except" ], - "icon": "restriction" + "icon": "restriction-no-right-turn" }, "type/restriction/no_straight_on": { "name": "No Straight On", @@ -8008,10 +8008,10 @@ "fields": [ "except" ], - "icon": "restriction" + "icon": "restriction-no-straight-on" }, "type/restriction/no_u_turn": { - "name": "No U Turn", + "name": "No U-turn", "geometry": [ "relation" ], @@ -8022,7 +8022,49 @@ "fields": [ "except" ], - "icon": "restriction" + "icon": "restriction-no-u-turn" + }, + "type/restriction/only_left_turn": { + "name": "Left Turn Only", + "geometry": [ + "relation" + ], + "tags": { + "type": "restriction", + "restriction": "only_left_turn" + }, + "fields": [ + "except" + ], + "icon": "restriction-only-left-turn" + }, + "type/restriction/only_right_turn": { + "name": "Right Turn Only", + "geometry": [ + "relation" + ], + "tags": { + "type": "restriction", + "restriction": "only_right_turn" + }, + "fields": [ + "except" + ], + "icon": "restriction-only-right-turn" + }, + "type/restriction/only_straight_ahead": { + "name": "No Turns", + "geometry": [ + "relation" + ], + "tags": { + "type": "restriction", + "restriction": "only_straight_ahead" + }, + "fields": [ + "except" + ], + "icon": "restriction-only-straight-ahead" }, "type/route": { "geometry": [ diff --git a/data/presets/presets/type/restriction/no_left_turn.json b/data/presets/presets/type/restriction/no_left_turn.json index aa9bcaf95..68a035964 100644 --- a/data/presets/presets/type/restriction/no_left_turn.json +++ b/data/presets/presets/type/restriction/no_left_turn.json @@ -10,5 +10,5 @@ "fields": [ "except" ], - "icon": "restriction" + "icon": "restriction-no-left-turn" } diff --git a/data/presets/presets/type/restriction/no_right_turn.json b/data/presets/presets/type/restriction/no_right_turn.json index cb0f6698c..1fe2b3eb7 100644 --- a/data/presets/presets/type/restriction/no_right_turn.json +++ b/data/presets/presets/type/restriction/no_right_turn.json @@ -10,5 +10,5 @@ "fields": [ "except" ], - "icon": "restriction" + "icon": "restriction-no-right-turn" } diff --git a/data/presets/presets/type/restriction/no_straight_on.json b/data/presets/presets/type/restriction/no_straight_on.json index fe2927d79..b6e20e952 100644 --- a/data/presets/presets/type/restriction/no_straight_on.json +++ b/data/presets/presets/type/restriction/no_straight_on.json @@ -10,5 +10,5 @@ "fields": [ "except" ], - "icon": "restriction" + "icon": "restriction-no-straight-on" } diff --git a/data/presets/presets/type/restriction/no_u_turn.json b/data/presets/presets/type/restriction/no_u_turn.json index 6f1f40cd3..ce526a5f6 100644 --- a/data/presets/presets/type/restriction/no_u_turn.json +++ b/data/presets/presets/type/restriction/no_u_turn.json @@ -1,5 +1,5 @@ { - "name": "No U Turn", + "name": "No U-turn", "geometry": [ "relation" ], @@ -10,5 +10,5 @@ "fields": [ "except" ], - "icon": "restriction" + "icon": "restriction-no-u-turn" } diff --git a/data/presets/presets/type/restriction/only_left_turn.json b/data/presets/presets/type/restriction/only_left_turn.json new file mode 100644 index 000000000..516f178f1 --- /dev/null +++ b/data/presets/presets/type/restriction/only_left_turn.json @@ -0,0 +1,14 @@ +{ + "name": "Left Turn Only", + "geometry": [ + "relation" + ], + "tags": { + "type": "restriction", + "restriction": "only_left_turn" + }, + "fields": [ + "except" + ], + "icon": "restriction-only-left-turn" +} diff --git a/data/presets/presets/type/restriction/only_right_turn.json b/data/presets/presets/type/restriction/only_right_turn.json new file mode 100644 index 000000000..428d274e7 --- /dev/null +++ b/data/presets/presets/type/restriction/only_right_turn.json @@ -0,0 +1,14 @@ +{ + "name": "Right Turn Only", + "geometry": [ + "relation" + ], + "tags": { + "type": "restriction", + "restriction": "only_right_turn" + }, + "fields": [ + "except" + ], + "icon": "restriction-only-right-turn" +} diff --git a/data/presets/presets/type/restriction/only_straight_ahead.json b/data/presets/presets/type/restriction/only_straight_ahead.json new file mode 100644 index 000000000..dcad31ab0 --- /dev/null +++ b/data/presets/presets/type/restriction/only_straight_ahead.json @@ -0,0 +1,14 @@ +{ + "name": "No Turns", + "geometry": [ + "relation" + ], + "tags": { + "type": "restriction", + "restriction": "only_straight_ahead" + }, + "fields": [ + "except" + ], + "icon": "restriction-only-straight-ahead" +} diff --git a/data/relation-icons.json b/data/relation-icons.json index 79d4f115f..2715cc804 100644 --- a/data/relation-icons.json +++ b/data/relation-icons.json @@ -14,5 +14,12 @@ "route-ferry": [740, 25], "route-power": [800, 25], "route-pipeline": [860, 25], - "route-master": [920, 25] + "route-master": [920, 25], + "restriction-no-straight-on": [980, 25], + "restriction-no-u-turn": [1040, 25], + "restriction-no-left-turn": [1100, 25], + "restriction-no-right-turn": [1160, 25], + "restriction-only-straight-ahead": [1220, 25], + "restriction-only-left-turn": [1280, 25], + "restriction-only-right-turn": [1340, 25] } diff --git a/dist/img/maki-sprite.png b/dist/img/maki-sprite.png index e4028833d114b4327157bbc9a5c7bd648e43fc96..af7b5322cc8f4e499846629b22ab7e4d71ffba51 100644 GIT binary patch literal 109414 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�x#;7u$NSYbNn=6b!^jgl6OD`HdHQtOB;6uRZ)&5n!zapV#~-4p#3pKf_ms zThAEr(cUB1f9DRoSE`7Oig)Let(6t?;@`h9$PHB<0cy4YK}$C|9G5|-wV!$G z=r1I~U$%F@IWs-Y!AqO*m37_d%$nCEdO6_}F7{3c6@ucTqxTJ?z1oUa)xHFK04sde z+Vp)x<*i?A@IkBBi+(Z%CNKM)vI9o0TVgj<%GcefS)ZEO8{d>i{Vq(um&{C1x&Jiu~D-ZuXgpS@&^40pi zV0vQFpsWnxng{PtR4m#}Z}E3ZRSnsW`_lnnSv^$5c+~;H*;lK0qPx9Xaw>Hx!)4fJ zaRsu#M}#b?OMqT#6vx%X*J@yC$KduYyOoh`=%u*E40No6W&&5|7Z9!ekU z_^YO_zHQK#jR`g~lhlLkAdy+pBMSz5d{eU}w2w(dh?RzG=nRw(QW^Rg%9F*OBH!e=$ zV`ZfiRshr2;Ungv3hWv~KF;-w?2WYKy<$3TFwNbA@5B?r*A5hf^(3_r3WM<@>;*m= znIYEtaJ{nMgGcUL|4V6ZYb*1@`riP|n##x;4Tgzn%U29RJii@>*(J`iFl7~@WzCN26LM{fAG zDairAyy2c(hW_R<8oy5YEnA-Cz^TpIqVUa3 z@I#77tcH->&Sr0_3&Vl4N1`Lv+D-IG12YppQ@Z`H zLS!Q|JT^tj$%JZ7V-J@fUTXj>M+HcE@*9-dD;2z}-OUs#c|;U9%#n#wI4z6GSS(wS z%brh_W$DT>y9M=2H-ySE4z08~1aHMFoMIiXCKKy9$5twLgQ-XV@GpUL_r!Osq8SZ> zj}spP#P3s(rP;~xL~sTJJaG?F3lY=@6y6rv2x~@G-6J60{|~O$E`vuyAsWs#{Nt< z`fF9p&>8j~PL$lxN9OP63b2Z&(aXnY=LO8u;R{WybGR2gI6OsD)oM}m6%)`JKAH2`@o;@INfYLoAa zvw86|tlA`C@DH#3PE}}}kZe4?h`E0kV8xLr$ZO7ktP2FddLiQK)q@BP(C$E$(2dL( zZ~Yg!_Wm{3b!>O1G{ZkGNO2!g5RPZW4j#^!KhN!1^HSRl*ohR(t{J}u2Au9-hs|TW zeS^S^c(c>ec$sX>b|mQ-ri~|OehIyTEmo)*7EO@uh+_UXi!WLS_%IA$n6O({iQfY1 zDl5M4k2q;(M-#R?iUAi;E<>v8YK@ng>oCy%ho`KyZLp+NtV8MQlzO=W>%ykY(@Nd_yrE$eK&%;&!G=KE&FtR85XfqAAA=YWBI zvA5d?fW4Kb2@1W*z_Grd%tez5Xs&Gz4^xAl&eGYb$LC3W75P4L03tO%oaT%2%J1W~nZyoAtto$ClANo; zm2KlQGdb&%>f;ilkFU+BcQxnX;8?45^7H*Z=n|h_K9XU1MmJqVSlDG9esF#pS?aj- zI(I!JtCfJBp54R!Fow+L3pD+X?9}zYbQG30r;{pwDH38wh-K7v>iwNmz1zH>7tyR% zlD~Qn7_>I;wfjTym(x9yW#4C|M$Eo2oWI}~&rZF8*MkhsakWH4=D?)8W}Ox)uo8E< zk%L1w14+N5Q(z*Zj~D)7J~c?Re)#@9uopn{AOtf(U5IMXp#HQm+50?{HxFp_E=1Y5 zlccG-?_?Sibpw-T#VCtK=0^%ULdSou4!H!o#Pdy^?FK`1BKl#~MHr0?29z>TGBjUq#&znUO7+zAa){k`|A7Oju$_!h*wbkF@VOOG^L zVCV>1sBpZQK7M$yc>FFxk}!>^LoZ)+s8mV2cvrm2+Q@9}0O01YD43Mtq|Qv$4CP~?7*$Vl%a(o3?d?`;v<+k<`DjHK?Jp0$abFOL(-#1+Zuy zajQ!_)SnC?3P%%DL{{TUbMnOs+>s11Jj_q1Lu~E^IdJL{Rs?0DjI*k#s@lnfzP}{X z*Xwoo0%k+I1;9?5IyE3N+W~>&dNhO=MAbar3#_R5UleKjIpuKAny$9r_Oes$wjMt2 zj#`Ml%P|l~@J{pXP&>dLd*L|Y5`X88H)bw{Z z#JBbT8XI$C4cWM!*>hr1DcB)ou5%1fWd0DE9w}T0k5!_oamExs)(eLkdGfWJICVcI z@JhZrmiHSU?=`si2+{cmwjHHsf6OT|Bj3~Q4b#(>J!t(3GOY?Yj?_@2&0}(#j z1~sWzGV_&ONXiyM{u*9X&He}OE%)iqNz+~Yty?aH4yNH8ZYmVD5(y<_J7|S<3YNs~kHu81SSwIXF(gc%gU#jM-pX znuIy@*4Vp7SfZzl#>sdMyr7$tqvOrUwX_oUl)xvuL52-NR<)1x4vgZEp2S$k#7><^ zoN2xF;`)rfi>-~#Hvkpyh5!~hjV8q7mV{w_bAsxTaw7Plz#F!>>RCoTaT3SGOW5ss zN|Z=L){XA|{o4X@99_|=+I)_NmpkzcXbf%VlP5*?P>dP3>Ts~womOgO-0csLY`2)E zufhz@j~LC!12B)+{R4Wi2{pfr+)Fta8YiE|a(Yd=K!^{Xs8gQkZWz$RHDeRww~$rZ zgHa$*xm$>bsHtNk72X-GmT*{lT zGMnNuj6%l>0B8)-r~kA9|ANoo(c%gmV;O)*B>Xeyj>)c`n|@@2yQ?JtZc-XM=4Kdf z{hgnWj>ZybMgl0kIr0MRx7nAdt`Ervt|bUy!2_x;R|{w9K?5IHwVDCK$AHt%2FvPJ z**XF$ip+T`wzIJ*isRe=5lVt#LY0l{8t~v#%>dyZv;$(B=zLTc#BF~mGsyt!VRxQK zw0iPd{ZU-x?~rS(jAGS`GgQ2>#06g30iBI}1IluA;;$%(uxbq6Pmuz07Yfqx{DOk5 zfExE#kx*s-;NUMJ4dvDXVlImU1SYYQ+o8aRaY}}2GB>`3ORnzi+oLl;DFaB%69%G8T(RO~1f+z%UlsLcTZ7@|@BzcD$kQK95dE^yD*@1wH?(VyST1_)5 zN=Zq%b^SUW>9<)1xM$IA7;0eD|4S|@6aXRdLp6(V1?uNr4E%inw>e-OSL8dA^)-+0 z2>p}HSITw8Wf1Du^Qw?^J;ww|ca7B4l?6-b2}|c)0Ic!YlsM80(hiv7+1z{{n}|NeA8Mf%&_kB1+orRh|GT0V_6+Qp1aOqS!_Wo5BwkcBp$ zkc$1IzYCE=hN!~R0H;0zBr0`-97zAjku>h*8JCCn18!L6`7iJJbF&{%^3)>Et_BrI z45GBk&71^PkMvA^7n$4ne3+sJHQ)A-e;W9#b9ng2d1<@M1aDW-Klvo4!Pg`S#5N}} zF;QUAO1F}JCnMv>pOc2b=gQKG45*JXG7i{TS!GWmk^h^pu&`Ys^2_OH9F%e1ODza{ z7m-|R1rFIU5{rxEm0SSAa+3H7oTE4$r%C!He6(EwO`0a!o9N58EFl zU>|*zg_&8ze|RtsnVHG5XkA-mz;vPLGu~T~}kMOc~tQHs7_Q1fl3%iJM79QUar$w349BSr6=Yrn~^&(jdwo1&caM;_&TwQ%_bWV_bC!cE@e?mp!K zxy~i%-6rHc!FBHshUGUoDyp^%Rs=ERJ(Mx4r!o;64!=5gRC;K2xJtQ?W8yLV#%YFZ zNLT~P?x1vVv-DJ5wlk2zp;(2-)(w^a03nN+z4Hao*j&hBsG{`(K7j{Ne|`MpjSk|?UWoY)uv3RIE2iF&cUW#ga}(EG$tlCfdzp-9t1Ik0H}b!YHA#fbd@|Bnd|1#x$G!dDY!mGK8PyOfcnP83pw~* zq>i9=;ml0AMtEwzLE+A4Zo#5pd9qcSQEQGu5x9{;JqF`_u3@yWy9j}v)JKU*J=zK7 zfjU3!xUNr<>cf}-s7~tZ0<`b&Dh{9}4s@zdn%(IV_0lM1Z_5?(%w`qyvlLO@d6Dk1|{NNI^f`&1;CGGb1me_*yU<(Y6Ym}*8 z$_iC8HNAElAS1kea}dv|$_ePq+3?U@1%Z_gcI`YA5#2N2Q00SJ+ys8Q+ODPkY(+WM zW|(AhOLMx|z&CTf)TrW4LJ>SdGhauIp{WhS17pQVK*86UwJ_vPv$Yz`R$(MFNpp=K-Es43cz{NeP@gHv@040 zDa;KD@p;Rf*N(mmA3KcSZUVBviV}2m1NOC+EP(rP!1|_VXTRlt+>Qv%SFUfXa={sUdQdXem=(9;E(N%F&~^Yfu9-n%KfPr=Ekf|m0U2uO<0nsC|A9oijsxm9+nD(DRbI)P zz%$iw-t@phunZ9GZva#mCTRkE=4r|?Jo_#`CIU8o>F@QQWJ;hfaZ)#Y#q-?kfPjhW z@87>qq8)sAX;c(KZ5FWP@#Lh6_489IL(HF*7s8K|iUmCku1m-ye1K_c?^g{Bk6w%f zrUOAJFbgPDj%&9i5_AX1NTOZfsvapc1HqGHT_x(vtUVC>6#c(ozK^^6SGQxwUVO*8 z850CQhvHoQimLZrKl##{$2mFLLi$G8_y=444|_`s^m|h+>X@@{kY(%{4))hzQM}s` zc61tYBOY3~+C3o+zi>o~nSgcN?z;FRlwF|f+#2DXXY7s}QO0f>&@CR2|8?@YJUi1I z=hQI1)@B`_8Vbmv3D0yGcM3*FU0G<(C5$d#WXMkHb@FPm#T*t=sy;bNBqd?tnsQ6e7Osu&SCu6GpQ zI3uRT+(Kx;+sn(3?D8y8Sal*7g{2pckgpLaZtrj$&XSIg1R$u-afWXuPGHW~1+ufd z?WwI0%PML+W$GAI!>e%x{s{{T?$`z8#Sx@-D2>x__=iEF_K8dk!pxy*z;s~tHgt*L z6^gk;RVO3z^Ur@om9-=tVv$z$w!y){hK+S6D>8VsA70Mp_Q0<@zPgqUhV=x1hVNaN z0PKjy=H^;hqQ1;wBEI0BJA{LwGUQ4z!^`_Cn0bHiJAXc3g!DrP#lbqwTU>`}pDi!g z2b-nqpq@)@Z56P-q&ECVZ5>rl9jcXY@18^S0PC$WT=;>D;p7s}go#A;^A_H|mAHHWVw~h|KIdkCNjh*?M?C#qapBWBj$}B@Z@w zzWbCWUHl&7D~Imjp#_;e-%-0g{dFnEim2Pw$MW)pIaVh8+`u3Olw;Wp!o;_+lv~o9 zFSfG6IE;bn*^}MHFBm#kME=CFdD#4S=3k8MIS5kv$p=yOrqMg-uzmsl-UddmzPGar z{j*QcMAq+CY-hTE`7#r(x|5dQ^znWi^W11!9YJ;!K`HhNCV{UwzLa1(*hptPTHVZ0 zhZC5hlhX!nhY6aM<$cEKEaniz{s0i-h$sRBCUPI}Gq9$cf$P+e>ka4dpUx(*1|cS| zn6YP3akGG7#rnPc!I&lF8(Ed^)f#YLMB>$VJoawft5(IV+Z8Y`g7}OF=z51vgY~~1 zKT;cY;;vA_Bf5Ifz9Y;;e@`iwt?hk4#-p!-SC*&O9%AsNA?D%;5(cj<*ljM>dPJaG z`a$XkWI~P*5BAwyFr4Xw$gP1V&A&ME~sH^MzQRzXhK zN&a`n)L|BVx-=3z?CtHp;w0n5OSLv0n#o=qjgAPpEGtCl0>;87h;y8Gu}l_j3-__V zw0jX8Pw795XSckKhE(Y36*91IVqCfMHr=@!=Xckb)P@K=m(W zQ67s1^&_|SBR2aR=eeiCOQ$e+n^OFcK3wt(N&(xq!k*{}z8^)toAx|WisfWXRSw7S zU-3QJC%^SBX`nMoMDyMtquu?9TRIvQt1qgAI<*+49any>ZGL$=`fNp7QN*jIfLa}9H$R>53WD=L4{n=8Bz)J3r zW1QUR(KGP&IgknrYa$Vwlc$Rz5Im-#QEawD@$Fj|o$aA<`B0ygBJt&{7i1aBXbMG= z?%nH(ZFbPvx9`b51lH;U923Vi*CzjE^H6`mlWz{XmwVlGbV8&?#BvUZdtd!)(1|W# z{7vx68*|7q?Haf1ZpKy52bC|09&c(Gkj9vll+-NA5r(OS4-F5eAh_e};mJwAUKRt@ z9abB>3i>zGj0`crdjU_g&&Q_gUpO#VYFCSJ(yG&dagFaWH5KncvZ8N!2*V&V%R%Ks z3cXe9p~^Xr#ajwgOzcO<9HQmFzjABAiA?BTk&eIYJ>|wOVVH0**`ZU$xUpozH^6ZM z_>`}=LBW9v-%|qsx)6J??U~}3B?{8rj7@rYD$hRtgckM+hP0*wX4#iWeE`(zbCAsS zY!9(S2pRETPa{Cw&vi&|PeH-3?`b%0Lb(o{HKh;-Z6EUGBKi@X_J z>MM`e4!vGxv)9!t6A)&56qKf1exR{r?Qk}AOEJ5)P-vVsZuxJ>>AAsqewM}xXb9Z0 zZ^Kn@34Po=-VemCzP+@FRk=OVw1_28FI$m)`Fj?R;i1_N7A>JN zOTjF=KepZB{d|*GF`D<-`+z^k3wQ1rF}kibMxnZX`L|i0UcoG`{Qt-=B)O44y%doh z-?&(3Vvwfdf!}d^;}MF&Z@ENjP=Lvg{^3wR4X%I7P{B5 z!XYeXt81tH2>jgAYEkZFp-tTC>D!8Dg0oM)zDoUkvg%k~(W|1O{V~ze$ymAUBk1!O^lN!)xSO~!2VRTEP&vHVatLC_ZquFU?gA}#r@RORI%8J zD?PhMYFRx^Z7&B|B4^1@`l8sDn%6Za8Dx*z)l!d_j!ijuxTj0{COUp$SYk-x8ru{hu3b0ghW*2vZ0H|VNW3zqUR`#x<;tnLzF-kaQ55vxELMX>HMmLUd zc6G9e(BUz1$0wFQE^&h_Z=L+_YrVOc`Wd5diO!}$SeKl+*iKGo8Crvl^rZ` z*A@b2G~&#U09fHh5mT&(R`oU**7eZiJpw-EAQh^2X;s@<_OzQ2-{@dNTpMwT`LN)- zw~q(0Hb6mDwcP?DF;f4BIIgy|%)EmPE=<*ZePzvycr@NYLBnlsZa#}T5O@Y?h$Z+f zIV2CWL25c#5^i(;%$fTflN%2xVWc*P3M#V?l&~tyWiINmho$jSi-7ol1rx=J@5`Or zup-qM#geD7CAq@nps>Rgd%*4Ct}4zbutx|!LH&M;Ih#2TOPUF~A7`2Tz-@Q8u1_0o zCA-WT9MD#f9cc|Ei-qRITvbj1Hhh|9SIdh+b};$9zAJX{{x4|{s#%NnLU()dtjcl& zV5l3Yxu@r`cV^XKf4>*~z=23DV89+w$xLplbz))@Hkc@K?W31*g3Vsz zxVfMKzWLG~&2a}NRZm>mi)a%+$HHt5ydYz1Zjo=nUPxOmgFAnec3L770v?f+LFJ4# z=D7${x}a&g5k+J>cJDZrR7}05V(wGJutU|S|9L$kd;}~|ED%Dpc|vpEFotZTMOYya zz(G)7ODNm@c|kPv_V%E^t=p z#?~kj9P7Y=W3qk64$UHfh7yy)53nxaXYHnQ?WClT+-eXO_enP~zL6lDip%0=&t=~F z^gH9>rUYh}tgT@fdW#WDmbZeUS3y(@&{!|EhP>Ln=nv=R1wsdvUn@kztFw}O42i{c zt9W>J76Xb&CWEQ7d;b%eZ~XI8%j$L6=~wYdr0Z?T8)&e1hhe75C*w$4VaVvTLB_ZP zf>U0#zl7WYOOH7A0ngSjo{}-Wr>VW$SKqq-$O@zJOY9Ag#n6=CJ<>AF7CTNtR`A_% zVCi4|PjgFm4Bm?T0s>W@JRz6~OW*Da&+X}HQA`-BJtdNZwkup+Rdwi^@b(|iOG^V4 zsCvRmI@8`33NrN-g!F=Rxjvo8 zNT~mZ6MkLZPRMh**~|ni!<;ZY`p6lOt{eCvQg)r|3Au|xz*#Q6B&+)PBCq13!j4my zpitYSAuUnXy&}#Be+GxnUjU~h8GPIr(Tr%njuP|QXYU}+$Hu^b72+0U9RbTJ6WcwM zlksqUu@e|FKTD`CSYHL+&q@R=FIfwe^U@x7^d*iRshQ%)kq6S#zezP=EI>Kt4Qh+I z-${|B@&|!-jOCV*FTz-}!pndCr%>@AMiy|qQO^T=q{eJWo3n6d2MDuktgr7fV9{li zsH5b+UlaE;dPS`_KH+lwc>V;)Cr)(Ts}q{+(td51FK}pgs|fM5shaptp{?rQzZ`gk zL{GT52%Fj2ZCTCFf6U(ejHo?a*lN_DeW0njFAg;QW0puXo%#U|I*Uo?%$aBEr(%dZ zjx`t6_NP_89sdn0^s3~gjLsfG#!jz%*RMCSdX5y%tQH*sZWD{9j%C|*_K+flFjZyd zpt9F*hyVL@FW5c!Wi5N2um1Q)&U3I07WR8Z~pzbXvr-N+Eyju}qnT1<>e|DWQAeW#E1xts&x=dBg8lh}Zh z#sSCiT4XzWN5U2Q3b#rjG=N9A?}b8O_!pS7b`a<@%-9-ZcqJRV-ri#JOqRHo3GK1D zY=b2TiZ_=s(Ku?du)RzvyXJ_|I2aoK+3*O+zXO4`4A*CfZDjmwWovtvU5?B#8tCu8 z&DKNb_6mfNpoE3M(WkU|%NEz~@Lc=^V*FRBLp##rXejRkwDQ{lmE}NpsD7ig6p*1Q z7}4*z#)H^j(6|?^^frR`Q?3~7?7yKKu~UPlq*!*)S@<=vv@?mb`02HA)n5c2_? z1#(&BT|9nV@HtSeY(Uv6-T1#wsMxmmyvPCVWO#Al65m=u{XhnSW^^Mb=QMu^XPsBx zCh=baPqdfkrPik@dtq2juMn#i-Dq}hXlRJyRf^$Y@U-X{N=7(zyXt=;oiWQXbH;q5 zTq_dY$S4P3afv!h{!~2;(UprEhAahyp(SO>%rZXs9R*!U=tx7ddtBxi($_@*76=j zSv4kJAh)4=dVWo$Yj_ivBoXkXt<7?BW@hm`3X28?1{*r6Oc6M)31AM4_|2*5thR9> ziG4?DuqQtS- zkYX2;0$JZ3WI*LX3gXI0z^@yD_Gr8-&+&>0usL~e5#kj(<2AZoQ${JWf)uLY;;~;N z7fdL0gcYnS1X{P1M7sTMr^`OB04zBGeBc|<%LFonZ7Uo{wEK#UWa!-c*GJLmS7Gpk-rc0BgyVB^&3>hoF-2xn$VL{~?7iqv zciX?vfYST!t+kH+_qFd`8|HO75PC7jB%zjAF3P8 z_4+?ly$Li{>l-(`%`=a=q#_YAl`%u{ps37A$(TYYN|`dHMO?6NLL?c#-~NB!THpJwv#e82N6+5--uHc7zv=Q|92{YfH-qV_%~0EoX;gK3A%bz& zzzrN_qDWDfCljZRc1-MtMf0$O!^#ZslpTfy=ne8&-0Qs7MP?i(RJ~{DWvgr`HavxIeOp;vC@OM$7dIg^(la z!rPCPu0;knI3TCXJOFa6^@QJ)Y#-&Md-V51QhS=0FI9ft9d5f;eT;1&WCtyhvQyM6 z7_PX`E>zq(jUNRpm{Jq7Oj8)E_Pm_~Kn)_3{eN~A_*>R9&daJuK^ZFuc=CfMnhbuR z`9VDuw_iS#eQR{fWu0W`^vuGq|L?Ouxf1RWU)-Bm_HbT7gH`-3S{HjVPSW0bBtHHM z_IeO?1;gU6?1ynPt_aH=no6W3emZnUm$eC8W(Z(VNl*k;gEo%)AGTn+STI+l*OS?}V_)y&_8?G^axcTG_6=A};FjGu`5)NR! zu35^viBufO&n%kgczJqBd%d~Cr1k5^lYI*>cw!azROjUlUx#R-QS~OG;ezkv^sObGSkj#WgtY6LPKnVA3Dv7Q z`}|)5&#A>PPjZ4>^41l$m)p?2VxAHS-{3wsDi?Fdp=X8D#GO^?{@3&iHai3id;MPp z@rUv;o<^>9hVmVXu5$cjCk}~Y=`S?Hhna3hC9F?+*3sZc$!T~`N&co|pS)ZZ>^`W9 zAgE-e^R*C4$cG}rX$gym{e@BQd$ER>&$-=Jayxu!6v3{}-8Wr)h1`!E^y6w?IgQ&p z-PqWuPX+-&3-bz0lRlfcx=7mk@l|D3@&EK#&a!j1up~&oqI|%JsQFB6ymIPlYCGGf zYk?)PW|dsM+6h5)Ruxi-RiF9DbE+WCp!g9(&KjY6#)wcLF5;d#39Vhb;|Ej|`wZP5 zzs2X0LJE?~qM^DSlP*tJ#LbQG#~qh65BGu9Uq9mN?WX)hxuq_WPmGqJmKCY#Z&`5F z>#Ydy$1PUo=1RwU3$5osShaGxF-UIRn&vy$K*vKhVjVi(%5#!|fuR}L?Mx+5lj9It zCYP80p`zh-@A@Gas--mPd8F%N`u5R|-MUZDGgaL_RWjr+7JQ#Iw< zYUIET$HsEjnP#DiRYd6W1QQ!~%tUwN9}_zF5d^OO#uyCGo`JLZr2Ab5PSE?iFEkoj zjqvD_F>&R2Ln0I%C=5QKsbHSknuXbGpD=F`%2PHKee3Nu)eLM7G8@4X{4d^&96yEh z;G^q2d_HcWmDRx*+XG$QaU4?v7uiVx0s5X5eby>O|8FlyA;#g z0Z8Y8g)znG&+|MRPRqtJ_iqfpgQKJr_dt>`GB&ox0VBv@zM00!M45XWf>ZG|T^YT} zhr6_&liTQC|GUOD2soxn`-3Xt4g=5Z-{0PaIefnWFH%-<)kYouzW3o+3lr7revZ3<@vqzg0RQNZm z5MmM%F5#&6nTRro1Kxo4+C*y`XNI#Q%r!`=edgy`?8cI4)oOsV{>`}W2PjzIG;?R| zF?|2ppxNCvo>tt1|46?doi@&X8fBAJ{451r$YO?IOW8QXHu?j=ypTxr|T-HJ6k56-=4$Jhf<=dA!r&!eNejSR^}cr%-B zT3UYVc+IsTBO~s;00DK$FS>BC zxw58?j^ZX67i|aau_3rR!#GnP@gR~_D7ec(Ijx&o%(Tx8#-HQ!n z*U_VAbi~Ckc#9-J7?7V`Exs0~6T%5G6tN$Z(921_pemt+K%;X8#ws;r-DdjB#4NNH zaT;1ovWZ(_b5j5~6E?G#0)5^=HBi8}pvL^1BmGk+v)d4>`2b18JZJ*I3EZ*M4Q}cu zjl3EFCXx}XtTUp%xRhR)5p5)j019WnjwoJ<-J;AV#XKEZoM+#*we5>IB3R7h!#uss zk9|*%c#rnZowpxYhdlA7P#5SM5V}X&mkK2}qro?EVKn94b>YPtxAXMwbKl#9Ri(CM zhWQgjIALs{cc3*~7eZ@ObMUZ990?hiX9Mt2dwIb)G}{;I#+(}q1@&t)hPH}5FtBq&pvTH5x3 zD1KLa&YEe+aK1;2k6MdJ7@Xg*IyxlH3+a2{J+l zbYs_!GKOs(9DKZ`Bq-1yaj|89k0UEYevHA;BIVQCqMsb&D%Y@G#{eT*rB1b8)`j%! zHs(DqXkeO~Z$VwE7)J9I3FCCXlvWSOc1LSppZb4IOjY zZlG)D&AyAPD*M$oZK7`ey9AL}91`kVzt+z(z9sKn+`IPBUxfZ^R3aWH80JriEUjSD z<7tiXp+P>;Sm(zPHu*x~vI-ZHf8b!*uzvk(8~t~^y(VfFHG;sc+;*Xd9T%x*lm|F5wYEsg zyWjj=Wh&M&~zzVxAl4%dV+6C>(~1?%kW- z?i9*mXn_c)X^4L=V?^tMPoh9%)YDmbk z3m^_*-H+LfQj8Kbclyy^6BGaO6R;GWS2+CWZZd_>(Bgos*dd>qCr_U6Ai-4C1&lj7 z17oZb@vH|A%Y{Vg&BeTur#mlE+T9~jCUr7BxDN^S&eJ|Vtjtr%T4UNS`GNFVssUQz zk{pMMZ-9BZ-)ngmLwXA_{y-(*qt-V7a)w8f-CBJ`GzaW!gL*|H1|G8$lT$MZM^Bwv zc?qsrATEbq^q*sLZ`4OTMz+DuM}m&m-Q)}{-hfZXMYkX**K4@U7!Ax#6z^@vQI0%8 z_>oZgwf%*(5g>N25r!&+gVc`kq>|9+5h|+%7YB#(ECO1Z<3)CzpSzDKb5rNR7a-a* zO~5dBUysk%9yBlYKnuDdBl*KY+-slH)Y-8!;5@7W6Q7>z1~=sW*jM6wB*ZxaXRt2B zgZ_iI{Z8Zjua}mW?P&#jxOKgWT?QYvM`Wul6>i6ICtI$;-F|xeV6Cl0T3XuH#FvdX zR(GCxcS#|!wC})Wjhhtn^%h^shLr5qkf3j%^P@I6a&Cg+F&h#36w54DCL~6912cO8 zj+u;CQiCuM2rB7EAUqdIUNw?jw*xI=Nu*dfJq;sn2gRn@PkR?U^sf-ZYaFER@{-eg>3!94c*0)Owr$$Jm1lA6AK!75t{!$z zMwo^*LOYDkAbn;N8+Tst$sI@fN4G&Y8+UH{oYTe9p{ebz`G3ayyI0Yxx<=5V$V3m| z$jfiSYwpIHYy!e!iJ7tce*!-n0|4X)9Lj-#GX41Xb00f1weWSSH;asYqM^w)qQgh* z@G7xTU3I(wcRAgVsUzzkKhLcRT7y(~QAhg6G1|V*Nf);l_t+cY6fV z{_Z_?D~E$OTtaz2<6(<3W=K@zRmQ5QC|#yVXgh#k^}v8vejt)&bT!3Sx||N`lvhkt^94rC~iV#uL$ctt>l_1FYf^AL>;cdVaLlN>QJorppz(YV3`(O;w5WH_&Tr0Cr zJ@-~FLjV|NWPfH65^4{1-Dh*r>vCie{+*zBdZ%fA5icdhJ6*T4{&1#1xo*ow-j|4+ z10c+;$q)tSF-!;yV9GL$faBYX$|`yEtMqLWp)G#!`12$?HTna#>6ggCIyG`urxOWN z!H7IsM1QQHqO3e4Micn$yP2O^l|3GBoFU;<=cyvab~zgRjb=oJk*|VY-JidI-4s{f zanx$L)buchlT=2rp`cgio0oexN?Y04*==oX6m2&1snI}rEkv9*DA>-T8=zBm&)nEp zMh!Q1-^r~Qe-iUzmC{(sS|Ebq;=duAVk(`xm2<&LS1o!F92`r7#D9i@eyDv~a z1hnvQ9qYNTXw>&DqlKsawDw6+0YgE$fTb%R1iVq5e1lhepQnU2j<};H`}fBWs<%v7 zWjZZ%{kgQ$EG`1^byQv=d2->cMyM2RyTfmN1`*XUj_u{S0#5No`=b3XhTkbrq$O~m z%Hu7_$Ui0SzKi`@)t*o_v`)IsWd)~CPBMt`tLPof=}z~sv%XhY$j3koAE_CZT_e%h2t#AA!mCt`%Kz6s;r~G zRg)Z^b&BZGo8f)#6O_5lAvCCc;MJ>Ig1|GxzN|E8|3S}gem zTBml+>#|x9=CX2Ml%9RRL$8~D<@(GM25|#!m61X@cYR;(jqgea*!R1KsCSj_k?V4e zIWV`f@QVKdSdg)n!{c97*(+9 zdl7WKlP&Ih&SoKyD*oG zh<(}X{VV@Hy(!GSLHj-F47LZk;Cm;2#D*b*Pgk(4)Wm%QCpDUHjWdQ@eH0fH%i4n( zyN7U-58xoFMm3xXQP1j;r9EF6sL>kXri2PQXj>*`=DGMQSH=)F`1vWAG7Ctoi;Aem3egV^7`^k^gmqlO9IgmUW> zMlsTacN<*PGBSeJhoGyuj3bemyfjQ#I*iy9OISB<>1EllX&Aee!3Hk{5mN{`l4lQb z1LsK!%;(1t>*5%3Pxfe?+jg7H>%VMeghb7$$AMc-IhB``Xzb)hK!Tmgkc}5?? zm-!e1uXbR&dVT@W!b(F~T$~pk#H&>LR+>?{G@I>K za~55&x$hQXNW2JCxo3~Pz0T*}UR7jHoiG4{c@#@369~am9)OB$53C@^pVJjx&Ej1TdpQWJihFiv1)FEWq;3J@!@L9|Otn12n3C2f?NdAnq6l zIRz#ES;7M3*fAm`qFrpWgr_h=XBU|e!JylRhgo&TZw1Fm1z7Qui0+%e{%4JcIa@(qKI0AaQCeBor7lNQd$9b8JhfyQ{V->+zdLC%B1h_k#HLWCJYv)h zGYFHeUzgbbR+0#Z{P`n3i6(tz%V(kW>rcuurUj}tZrVFC{1Ru;FqyWoimyA3Y178! z^yB>ZKQ?$Yp@{IN3t+ch?+AWx3m2WDK)XN_ZFr#@Of#N&PEPhx%ZRKpsq~SMw zcM56HlXr7->n{l98GhQ0yofVw;>J*K*@9|Ih5j<%801!=AD`OVG9tS7hSwFYymaZ! zANZEaw8d3fP6%C*B*SHFP;1A+>G=nsY3!xZQ%jpXSw0QsluvDKs~h=bYZ518@V;B9 zV_mmN56y6?p)Hx-wwvNI5-Z3IqNH1Yxw1+f(BRiMA2v7AjRs2#7&1-w+XHJ&NJdnc z)%%5jW0%@Qz;}N`s~Gu!o|rH=3*gHE1=^2Apcj`g+pD|=el>oAocRhb(egZ20S6@F zf~1QJ1^=RH%J%QW2w<>`OqL49WY1Y1PR_EV#6;Ot$P!pUpCDQ$C~*8def9MU*PTxD zn*(<9&hSxIIqVeRzEFlXf5%17nQ2EKnO*MkH4Vl#4f;j*t_4Mys5Z)I7?>V<&QlXB zLv#VGG}7zlJT;Z-r=;h$lCHQuU+F9VtE8ekclgMBDS4E%QV`M>kDTby!pIH~e zw7;Ho{*66{v=&m=Vwhn*s$)oE33gB!q^WHVAF{7L%Z4!&2Yw;ztqoFvS{S+GL?P&A z4d)EqD#n=zaCQ?O{)1~s!D)n~Izs8>m%dAyte0i+>64Uf5&xsXp%QrY;VXnrjiumi zef{T?@qpzYEHh76o^dH{F%dkD&_tZIxaah;U z9)3E4Osz#(eMme?EX))}y`!Yml+t&g3$RTmeqZRR!=@878;zjmALH0=Sb}y;Ud1NmJq|Q} z%aq#NTp$NKSMcgYW13d&{KB82aj=nQXKp%=YV6yZ)wzzsuW9;%JXaEjSLv>2K#s=CcvDHv|2wpa0}L*^&UY^VYd=Q^Y}_ zznf%r5w#Oa3EbPbn~T{hDJG_MokdnuQAjy(+zVy%omm-4;Ow)V}RxDOws zJ+2>##xo7QEunm$Gk5sD)n_ZA(4G#u z1DO?5O`QUwH&OL?|EmqJq0w+u969jUzkuURPj9cw*byHkF`RfCv5>5k$%MLlYF|<0 z7yK{ZfZFi!poJpE@ccZNjYGOU|l_D?hEJ z`Fb@LFSL#O{qg~WEOgeH5%~v2qQq`imKHV$7?#2*VW`T?-o3$3su(A6v8$TlTr{+birs+vhwbTQ1Y^xNC~ zx^%nQ9q9K8G)ho*v2r^*)V-7yrRl=DJ~N6=(w5_V_`@7&LyI4S(|4vnu4sj41dQ1@ z?qT@)9iF0_?1OxvoV}gQQLhL6^-W&Bu8y$siBA6!yD{Lwq8eW?QaW4`ko7@@l%$80 zl%MhU=lQ1aZE#R2(q%PJWlH)3&5=Rs_19IEv>^QpRz3%O)gMTN9{PKd6OCggB?3C; zd&n1)B}dlKrGq9(w!cI<`pPAYpKYc@U-gzR2ts8LI4SrF1i7*|eR@y1&kk=nck}ZG z`h!mg-Q9chc*ToQQQdkk!W1sY`&V79$JWa0d8+u9!m4zeg9lqn58YRjJNT!qIJYg( zg>Kh*gPe82{qteXJNB|(W6pT1Cs<}4{cV56f$o);%+zREcaO#o?lE$NcYwi|nn-jL z;p*ijx1He-zem)ne?$&j{T3045%>R-KNjJupEwXnc`KwV+{OHvohSuUfzHq)+;5J> zL{09%{CWORZdUOyVw9cEqF$AeXj;5*WJHm1S%aZt&E* zd}U4AZl0c#3^)21B(m#n8+A)+E3X~9YkWO^W@xQ*0b}TqMvLy51<8nu zlsls9*Xz7QK8PU}Y&~pqCm?II4GM$UB}-%j`2@8TuPV4%aky zHJ>g76Ngk^T3xsBZap!lxmb5E|{?a=7-a81_{fWUgAe%)w#O-*KyC(-=GN> zxc_DMbH*dm(l;z@m5cc0Gf}wp&9;%{e-pQFna2X)T}w6cC&QPcd1w9ung|@ zViKCtOYj=b*cL+JFTI8Q$6+@prjcr{bm@z^fFL_|CVg_o3&`3@A{@2%dQvGz-V#E< zL!*wmd$&}^k7yva+XNFY#s4S8w0r)~_dgrMgM)$=h+(E1!jDX2D0j|7_%1^*Q>fLS z>%+pf6V47@b&w$^dt;+T9{9OYGAHR#m~Tc-Zq{B_ad}|LdlV2U>&Ud;eva~pi8AT&4aT(xrozx4K-RVb4U{)p>Gr7 z-?gi{j{+~5g|jwp1W#ZKg{pb^jLsi6hYWiGx`tn)pXwuPO6n(O_=>*Jr{?D8^T6G< zavNIdDzFQhSb5vYe`BNeMdWP#79E`sG4Z=x*!zGD+-2rNn&v6bto_DB%UwzKln>L-PiH*ZgYj}e8bZ2pYX)cA<=6J zto52_Yi@aZ2ph8g@FO)K07q{_zgesC7rA?XA3-)z1BGq?)kvMn`lPgW2rr)>4qEr= z!g^FDo&b5ZbluwcS^eCG`&v9b8NT-R8}bt6y&9o^N35@V48X$Bg7AxnIwctx_BDan zC^-b0{ARkt+j9eG!WPg_ab#%n9)<>pC?+@vNR-)#`E92?$w*pK!f_KhAdVZf{O+H3 zcQ5FNPjw0Is2K1y!$4R*lcVX?uBORy>rNtZ^defBKJ*VK7^bSB@iXXH-BfnL-g^cc zIvuX;%Fx%Zc??-u_N+6;S+CK18uJUAVKO|+vg+Q` z1G2lCnTaU{l}+m*l=Nay_kTw{FI9qX*y!nrJ0l;dc>da??grgmaJ9FfR<~`eKxlJi z?C?_OjpYlhQ4(%aihsRoF+SOQKay;lK2HHY6&xR^*{zJfs|!%?DeC%v25TGdPEJhd z%puig43G;g^&ol*41&2+C=sgdo%C7Bfs=n@e{niMULH+K%n>G;QVZW!DJu1&0LP=r8v|R3 zLBxjI%JR%#NDWT{Xpz}bH4T3IUHU3ht$}F&k4mklmWVTUa{kcCEOG3oKxF%KpII1> zQ|2JDu21IOTA-#eM@2%lVEtY>sZ#G}yCChp?n302X*-I=$P`eJQ& zmZUQ7A%_qB3PYF?V?90AT{VyH`>LSh=xlE#C$H&-Tj4o2DVFNW%5-aU^C?AX>4d4@ zzeQH?p2}b^I0;?RGrf`5gS24)N9maSv9SjE3ieR%#4=4hdDDbCp$$JEKOLFR3^{>5 z)L385x2(K@XaQePyo}^o8u}F?QJHh=>4e|Qx7{G>;ITD7VUT4*cl=rI2Vz(L6`W3= zy!9xj*LsLTw`)0&?V`wSVa2-)svPmr=uA%jhmv3nwOs$1Ntgw`6_duMs40Qz5(tJ) zu3xj}{SXjItBpu;{fGD9A2M))7XX{+p{tDnlo$HY{mmVF5R%^061$F)sowhu8RDx< z%u%;sGf7(Tr^jw)qTyCqI_6>P5Q)!qXU3>T3!Iz>vHe_NW6G_&jH+997g`JrcB?te zU8%Hn*b=^wQP`t5H2BLY*KW0n>8n|oL-~b=b9v|)ZuNZ=CbF?F-5Qb9z?{yojb*~e z;8j#~eJp0y=0%*wbjE9lgw@8Fxh>a|lGHQ+9tI#R!Mh_>b*mA~SRRO_b=0f3>;1{w zgKUi$U50Ek<4`rY!R&_PWba8QUDMC5$ zcSE>M{esl;Dfa?yhjnp7{(AbkO#d926dT12S+Bk7?3@h1Yov-^?FKVmJs&=#1DjGT*^k>5r=H1!}+Q!$*$nLN1~a@u0tq zjg|EwI?I8F7=pH+Of-te>RjQzU@wO~(7faO`_!y^_twTR-yP@2x)Q3lG*am~kjqxi zpx8LwIxsLmYF_`tHmCGI=P^)!azK)+$B7e>KY#qtxf~lSnhu-`x-(>8JA4ADR0Pnm zekY`@YgmVkk9Bfz=xw=bI(+DAyaeqzvRa-aS(z3duR6c}Eqjeq@OFd44#%@sw)ZTD z2aOM^u5AsK9xy-Y;bnDmcTDD7O(;b)_F}gL)u;zDryL~9p7{-{#%{1hGvt}Fge!YS zr+e_=oF~wO612ukeh}m#+ie|RvT%7`ptyv=&(yo~`4Q7AUILf1`wJA~hQg9p^_^IT zN+8wEsq+gKIi!s|I4M{$?*mZSxE5GoX0D- z4oR{Cz^Jyuru#1dQT{e;;yltZ9$w6^HMgWKm{_tA?i%a%xaeKCAL_e!>*X7m4fs3o zpwEbQUrQjJstiWx{BBX+LJw?c2=HzNhkEulWCrlp!`MOo@#WX;?XD|7cTYE@1sSQm zpr0DHQK$8tJI!I}9QkZ=Gv{j5)UInRQMU$-QsKDrg;sDDyFw;F zM@vX1Vf6$EZ!X0jU@`O8XcIU71{r}s)ChxcbwUXA= zO`*-AvYed;o?UZ~5SZa{Z04&bch-8ku(sfm{jow@)>F3|TJY8{REvnz%a!c4Z+s|v zjya1vb$aVBn~w)I5@(6>eXnMYd^dOYeW0nOW!BN!>Vfg~u^*ehReaIrCQu;-YzVg8 zy>wS?mad^?C4)=+_W*^OisUli1jrrq=G2gvf0LGAup#hJCK+ZJwf^w2iQx_ z)Z6(eNnDk3&ncA7F%844eM=i<}c0Zl1uRu z+*w?Ok7sP?=BaR)$a@=`k-kklVApXjh+$VCcsx(^-2HO`G71})J3L4;);#s8axrTr zdFh~&XAOwmk8Q23-=G(^;s5>YP&&h4Zh^7Odx>D?@W1Dbg`V}ua5*KEluU{t@H3y5 zkl$3((0;nm>t{X0%cmZemxo9lbL;*LSUVQ!>Ag6+wBZh4;yU{~XMu1_++gwRfl9a@ zPJUOy3D83Y!Z@hTlTigDU&hPu`RMTZg0CB}SzX0Mpa#4FvryMm`#wqYbs}_BSH3J| zIlfHo=>Lt9EC zdgXIIiKBqJRb2dwSqE2pn7j(bkvY@v6|sh1bCrW`3L=2N1_k8Nts4?Ahr@LxaK3zAi?}-({l--qt$)7~Y@D=E*3J3|v*rh|ZxQi*j=@&zI{SJ)RA;YV_|MMxJM842eziWYJTRxoS zocqJ=ZfqV|c{Rugl`B5t|L|gyH@9wxOG)f#IODAW(f#MOQMpq}iq#h5Q_##YI z_*%X!rh+p5D+Wio%eS9K*qc17xO3Lw)=-Mb_<%M|*U_&Z{UQMn-)I9hXZHhy9i{-8 z*91+lv1AzvvSswNM>w*@ee{)OWn;FyQF**fKd+_Yfd#$FM!;_OgJ@0m2Ag#l;uz)P zxy6}e_8vxuz|-X$b_Tx(6Kep3;>(X8frw|Za+0i3F}W0K{-Ldn1MmQS?bS#@QT9&? zk6;#FHurt0S|>&;JC9vml_e9IW}cYfXd!U3VdSAmToiSU@J&?hH;M3n2Y0X6W4+di zvv=g@&jlUh8*sU3A|PCj`YPm7#`rDWgf0^B7*w|&)K)+fUPew#0C6FOgI1AGOr

Ff(TXXV)^EiH^EPoyRe00w78os_xsi9;ht` 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
3foXFugT5xqOcdp3BO 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 literal 113751 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

J* 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 diff --git a/dist/locales/en.json b/dist/locales/en.json index 64d57639d..2c5a525fe 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -416,6 +416,9 @@ "category-rail": { "name": "Rail" }, + "category-restriction": { + "name": "Restriction" + }, "category-road": { "name": "Road" }, @@ -2844,7 +2847,19 @@ "terms": "" }, "type/restriction/no_u_turn": { - "name": "No U Turn", + "name": "No U-turn", + "terms": "" + }, + "type/restriction/only_left_turn": { + "name": "Left Turn Only", + "terms": "" + }, + "type/restriction/only_right_turn": { + "name": "Right Turn Only", + "terms": "" + }, + "type/restriction/only_straight_ahead": { + "name": "No Turns", "terms": "" }, "type/route": { From 3d210ac3c1d6167fd4ba41692691758f1615dc7c Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 16 May 2014 17:03:55 -0700 Subject: [PATCH 14/26] Implement basic restriction toggling --- data/core.yaml | 4 + dist/locales/en.json | 6 + index.html | 10 +- js/id/actions/restrict_turn.js | 88 ++++++++++ js/id/actions/unrestrict_turn.js | 23 +++ js/id/geo.js | 8 + js/id/geo/intersection.js | 52 +++--- js/id/svg/turns.js | 10 +- js/id/ui/preset/restrictions.js | 12 +- test/index.html | 12 +- test/index_packaged.html | 1 + test/spec/actions/restrict_turn.js | 239 +++++++++++++++++++++++++++ test/spec/actions/unrestrict_turn.js | 24 +++ test/spec/geo/intersection.js | 95 +++++------ 14 files changed, 487 insertions(+), 97 deletions(-) create mode 100644 js/id/actions/restrict_turn.js create mode 100644 js/id/actions/unrestrict_turn.js create mode 100644 test/spec/actions/restrict_turn.js create mode 100644 test/spec/actions/unrestrict_turn.js diff --git a/data/core.yaml b/data/core.yaml index 2c4edca74..048a433dc 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -145,6 +145,10 @@ en: multiple: "Split {n} lines/area boundaries." not_eligible: Lines can't be split at their beginning or end. multiple_ways: There are too many lines here to split. + restriction: + annotation: + create: Added a turn restriction + delete: Deleted a turn restriction undo: tooltip: "Undo: {action}" nothing: Nothing to undo. diff --git a/dist/locales/en.json b/dist/locales/en.json index 2c5a525fe..cd29e7272 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -182,6 +182,12 @@ }, "not_eligible": "Lines can't be split at their beginning or end.", "multiple_ways": "There are too many lines here to split." + }, + "restriction": { + "annotation": { + "create": "Added a turn restriction", + "delete": "Deleted a turn restriction" + } } }, "undo": { diff --git a/index.html b/index.html index aa156ee5e..48cd10b82 100644 --- a/index.html +++ b/index.html @@ -138,6 +138,7 @@ + @@ -151,13 +152,14 @@ - - - - + + + + + diff --git a/js/id/actions/restrict_turn.js b/js/id/actions/restrict_turn.js new file mode 100644 index 000000000..e6786e6e6 --- /dev/null +++ b/js/id/actions/restrict_turn.js @@ -0,0 +1,88 @@ +// Create a restriction relation for `turn`, which must have the following structure: +// +// { +// from: { node: , way: }, +// via: { node: }, +// to: { node: , way: }, +// restriction: <'no_right_turn', 'no_left_turn', etc.> +// } +// +// This specifies a restriction of type `restriction` when traveling from +// `from.node` in `from.way` toward `to.node` in `to.way` via `via.node`. +// (The action does not check that these entities form a valid intersection.) +// +// If `restriction` is not provided, it is automatically determined by the +// angle of the turn: +// +// 0-23 degrees: no_u_turn +// 23-158 degrees: no_right_turn +// 158-202 degrees: no_straight_on +// 202-326 degrees: no_left_turn +// 336-360 degrees: no_u_turn +// +// If necessary, the `from` and `to` ways are split. In these cases, `from.node` +// and `to.node` are used to determine which portion of the split ways become +// members of the restriction. +// +// For testing convenience, accepts an ID to assign to the new relation. +// Normally, this will be undefined and the relation will automatically +// be assigned a new ID. +// +iD.actions.RestrictTurn = function(turn, projection, restrictionId) { + return function(graph) { + var from = graph.entity(turn.from.way), + via = graph.entity(turn.via.node), + to = graph.entity(turn.to.way); + + if (!from.affix(via.id)) { + var newFromId = turn.from.newID || iD.Way().id; + + graph = iD.actions.Split(via.id, [newFromId]) + .limitWays([from.id])(graph); + + var newFrom = graph.entity(newFromId); + if (newFrom.nodes.indexOf(turn.from.node) !== -1) + from = newFrom; + } + + if (turn.from.way === turn.to.way) { + to = from; + } else if (!to.affix(via.id)) { + var newToId = turn.to.newID || iD.Way().id; + + graph = iD.actions.Split(via.id, [newToId]) + .limitWays([to.id])(graph); + + var newTo = graph.entity(newToId); + if (newTo.nodes.indexOf(turn.to.node) !== -1) + to = newTo; + } + + return graph.replace(iD.Relation({ + id: restrictionId, + tags: { + type: 'restriction', + restriction: turn.restriction || guessRestriction() + }, + members: [ + {id: from.id, type: 'way', role: 'from'}, + {id: via.id, type: 'node', role: 'via'}, + {id: to.id, type: 'way', role: 'to'} + ] + })); + + function guessRestriction() { + var angle = iD.geo.angle(via, graph.entity(turn.from.node), projection) - + iD.geo.angle(via, graph.entity(turn.to.node), projection); + + if (angle > 158 || angle < -158) + return 'no_straight_on'; + if (angle > 23) + return 'no_right_turn'; + if (angle < -22) + return 'no_left_turn'; + + return 'no_u_turn'; + } + }; +}; diff --git a/js/id/actions/unrestrict_turn.js b/js/id/actions/unrestrict_turn.js new file mode 100644 index 000000000..f57186d7a --- /dev/null +++ b/js/id/actions/unrestrict_turn.js @@ -0,0 +1,23 @@ +// Remove the effects of `turn.restriction` on `turn`, which must have the +// following structure: +// +// { +// from: { node: , way: }, +// via: { node: }, +// to: { node: , way: }, +// restriction: +// } +// +// In the simple case, `restriction` is a reference to a `no_*` restriction +// on the turn itself. In this case, it is simply deleted. +// +// The more complex case is where `restriction` references an `only_*` +// restriction on a different turn in the same intersection. In that case, +// that restriction is also deleted, but at the same time restrictions on +// the turns other than the first two are created. +// +iD.actions.UnrestrictTurn = function(turn) { + return function(graph) { + return iD.actions.DeleteRelation(turn.restriction)(graph); + }; +}; diff --git a/js/id/geo.js b/js/id/geo.js index 2fa2e2ace..f667ca100 100644 --- a/js/id/geo.js +++ b/js/id/geo.js @@ -33,6 +33,14 @@ iD.geo.edgeEqual = function(a, b) { (a[0] === b[1] && a[1] === b[0]); }; +// Return the counterclockwise angle in the range (-180, 180) degrees +// between the positive X axis and the line intersecting a and b. +iD.geo.angle = function(a, b, projection) { + a = projection(a.loc); + b = projection(b.loc); + return Math.atan2(b[1] - a[1], b[0] - a[0]) * 180 / Math.PI; +}; + // Choose the edge with the minimal distance from `point` to its orthogonal // projection onto that edge, if such a projection exists, or the distance to // the closest vertex on that edge. Returns an object with the `index` of the diff --git a/js/id/geo/intersection.js b/js/id/geo/intersection.js index c53e6db2a..c76405e08 100644 --- a/js/id/geo/intersection.js +++ b/js/id/geo/intersection.js @@ -1,21 +1,7 @@ iD.geo.Turn = function(turn) { - turn = _.clone(turn); - - turn.key = function() { - var components = [turn.from, turn.to, turn.via, turn.toward]; - if (turn.restriction) - components.push(turn.restriction); - return components.map(iD.Entity.key).join('-'); - }; - - turn.angle = function(projection) { - var v = projection(turn.via.loc), - t = projection(turn.toward.loc); - - return Math.atan2(t[1] - v[1], t[0] - v[0]); - }; - - return turn; + if (!(this instanceof iD.geo.Turn)) + return new iD.geo.Turn(turn); + _.extend(this, turn); }; iD.geo.Intersection = function(graph, vertexId) { @@ -33,8 +19,8 @@ iD.geo.Intersection = function(graph, vertexId) { highways.push(way); } else { var idx = _.indexOf(way.nodes, vertex.id, 1), - wayA = iD.Way({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, idx + 1)}), - wayB = iD.Way({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(idx)}); + wayA = iD.Way({id: way.id + '.a', tags: way.tags, nodes: way.nodes.slice(0, idx + 1)}), + wayB = iD.Way({id: way.id + '.b', tags: way.tags, nodes: way.nodes.slice(idx)}); graph = graph.replace(wayA); graph = graph.replace(wayB); @@ -60,7 +46,7 @@ iD.geo.Intersection = function(graph, vertexId) { return []; function withRestriction(turn) { - graph.parentRelations(turn.from).forEach(function(relation) { + graph.parentRelations(graph.entity(turn.from.way)).forEach(function(relation) { if (relation.tags.type !== 'restriction') return; @@ -68,17 +54,19 @@ iD.geo.Intersection = function(graph, vertexId) { t = relation.memberByRole('to'), v = relation.memberByRole('via'); - if (f && f.id === turn.from.id && - t && t.id === turn.to.id && - v && v.id === turn.via.id) { - turn.restriction = relation; + if (f && f.id === turn.from.way && + v && v.id === turn.via.node && + t && t.id === turn.to.way) { + turn.restriction = relation.id; } }); return iD.geo.Turn(turn); } - var turns = []; + var from = {node: way.nodes[way.first() === vertex.id ? 1 : way.nodes.length - 2], way: way.id}, + via = {node: vertex.id}, + turns = []; highways.forEach(function(parent) { if (parent === way) @@ -89,20 +77,18 @@ iD.geo.Intersection = function(graph, vertexId) { // backward if (parent.first() !== vertex.id && parent.tags.oneway !== 'yes') { turns.push(withRestriction({ - from: way, - to: parent, - via: vertex, - toward: graph.entity(parent.nodes[index - 1]) + from: from, + via: via, + to: {node: parent.nodes[index - 1], way: parent.id.split('.')[0]} })); } // forward if (parent.last() !== vertex.id && parent.tags.oneway !== '-1') { turns.push(withRestriction({ - from: way, - to: parent, - via: vertex, - toward: graph.entity(parent.nodes[index + 1]) + from: from, + via: via, + to: {node: parent.nodes[index + 1], way: parent.id.split('.')[0]} })); } }); diff --git a/js/id/svg/turns.js b/js/id/svg/turns.js index dce3ca924..f20f20a3d 100644 --- a/js/id/svg/turns.js +++ b/js/id/svg/turns.js @@ -1,7 +1,7 @@ iD.svg.Turns = function(projection) { return function(surface, graph, turns) { var groups = surface.select('.layer-hit').selectAll('g.turn') - .data(turns, function(turn) { return turn.key(); }); + .data(turns); var enter = groups.enter().append('g') .attr('class', 'turn'); @@ -17,10 +17,14 @@ iD.svg.Turns = function(projection) { return turn.restriction; }) .attr('transform', function(turn) { - return iD.svg.PointTransform(projection)(turn.via) + - 'rotate(' + turn.angle(projection) * 180 / Math.PI + ')'; + var v = graph.entity(turn.via.node), + t = graph.entity(turn.to.node); + return iD.svg.PointTransform(projection)(v) + + 'rotate(' + iD.geo.angle(v, t, projection) + ')'; }); + groups.select('path'); // Propagate updated data. + groups.exit() .remove(); diff --git a/js/id/ui/preset/restrictions.js b/js/id/ui/preset/restrictions.js index c604d04bd..61baebc88 100644 --- a/js/id/ui/preset/restrictions.js +++ b/js/id/ui/preset/restrictions.js @@ -7,8 +7,6 @@ iD.ui.preset.restrictions = function(field, context) { var wrap = selection.selectAll('.preset-input-wrap') .data([0]); - // Enter - var enter = wrap.enter().append('div') .attr('class', 'preset-input-wrap'); @@ -48,6 +46,16 @@ iD.ui.preset.restrictions = function(field, context) { if (datum instanceof iD.Entity) { selectedID = datum.id; render(); + } else if (datum instanceof iD.geo.Turn) { + if (datum.restriction) { + context.perform( + iD.actions.UnrestrictTurn(datum, projection), + t('operations.restriction.annotation.delete')); + } else { + context.perform( + iD.actions.RestrictTurn(datum, projection), + t('operations.restriction.annotation.create')); + } } }); diff --git a/test/index.html b/test/index.html index 5b6469948..dec049083 100644 --- a/test/index.html +++ b/test/index.html @@ -118,6 +118,7 @@ + @@ -131,13 +132,14 @@ - - - - + + + + + @@ -230,8 +232,10 @@ + + diff --git a/test/index_packaged.html b/test/index_packaged.html index 0f83951a5..b22e812ee 100644 --- a/test/index_packaged.html +++ b/test/index_packaged.html @@ -47,6 +47,7 @@ + diff --git a/test/spec/actions/restrict_turn.js b/test/spec/actions/restrict_turn.js new file mode 100644 index 000000000..302f14cad --- /dev/null +++ b/test/spec/actions/restrict_turn.js @@ -0,0 +1,239 @@ +describe("iD.actions.RestrictTurn", function() { + var projection = d3.geo.mercator().scale(250 / Math.PI); + + it('adds a restriction to an unrestricted turn', function() { + // u====*--->w + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', '*']}), + iD.Way({id: '-', nodes: ['*', 'w']}) + ]), + action = iD.actions.RestrictTurn({ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'w', way: '-'}, + restriction: 'no_right_turn' + }, projection, 'r'); + + graph = action(graph); + + var r = graph.entity('r'); + expect(r.tags).to.eql({type: 'restriction', restriction: 'no_right_turn'}); + expect(_.pick(r.memberByRole('from'), 'id', 'type')).to.eql({id: '=', type: 'way'}); + expect(_.pick(r.memberByRole('via'), 'id', 'type')).to.eql({id: '*', type: 'node'}); + expect(_.pick(r.memberByRole('to'), 'id', 'type')).to.eql({id: '-', type: 'way'}); + }); + + it('splits the from way when necessary (forward)', function() { + // u====*===>w + // | + // x + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Node({id: 'x'}), + iD.Way({id: '=', nodes: ['u', '*', 'w']}), + iD.Way({id: '-', nodes: ['*', 'x']}) + ]), + action = iD.actions.RestrictTurn({ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'x', way: '-'}, + restriction: 'no_right_turn' + }, projection, 'r'); + + graph = action(graph); + + var r = graph.entity('r'); + expect(r.tags).to.eql({type: 'restriction', restriction: 'no_right_turn'}); + expect(_.pick(r.memberByRole('from'), 'id', 'type')).to.eql({id: '=', type: 'way'}); + expect(_.pick(r.memberByRole('via'), 'id', 'type')).to.eql({id: '*', type: 'node'}); + expect(_.pick(r.memberByRole('to'), 'id', 'type')).to.eql({id: '-', type: 'way'}); + }); + + it('splits the from way when necessary (backward)', function() { + // u====*===>w + // | + // x + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Node({id: 'x'}), + iD.Way({id: '=', nodes: ['u', '*', 'w']}), + iD.Way({id: '-', nodes: ['*', 'x']}) + ]), + action = iD.actions.RestrictTurn({ + from: {node: 'w', way: '=', newID: '=='}, + via: {node: '*'}, + to: {node: 'x', way: '-'}, + restriction: 'no_left_turn' + }, projection, 'r'); + + graph = action(graph); + + var r = graph.entity('r'); + expect(r.tags).to.eql({type: 'restriction', restriction: 'no_left_turn'}); + expect(_.pick(r.memberByRole('from'), 'id', 'type')).to.eql({id: '==', type: 'way'}); + expect(_.pick(r.memberByRole('via'), 'id', 'type')).to.eql({id: '*', type: 'node'}); + expect(_.pick(r.memberByRole('to'), 'id', 'type')).to.eql({id: '-', type: 'way'}); + }); + + it('splits the to way when necessary (forward)', function() { + // u====*===>w + // | + // x + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Node({id: 'x'}), + iD.Way({id: '=', nodes: ['u', '*', 'w']}), + iD.Way({id: '-', nodes: ['*', 'x']}) + ]), + action = iD.actions.RestrictTurn({ + from: {node: 'x', way: '-'}, + via: {node: '*'}, + to: {node: 'w', way: '=', newID: '=='}, + restriction: 'no_right_turn' + }, projection, 'r'); + + graph = action(graph); + + var r = graph.entity('r'); + expect(r.tags).to.eql({type: 'restriction', restriction: 'no_right_turn'}); + expect(_.pick(r.memberByRole('from'), 'id', 'type')).to.eql({id: '-', type: 'way'}); + expect(_.pick(r.memberByRole('via'), 'id', 'type')).to.eql({id: '*', type: 'node'}); + expect(_.pick(r.memberByRole('to'), 'id', 'type')).to.eql({id: '==', type: 'way'}); + }); + + it('splits the to way when necessary (backward)', function() { + // u====*===>w + // | + // x + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Node({id: 'x'}), + iD.Way({id: '=', nodes: ['u', '*', 'w']}), + iD.Way({id: '-', nodes: ['*', 'x']}) + ]), + action = iD.actions.RestrictTurn({ + from: {node: 'x', way: '-'}, + via: {node: '*'}, + to: {node: 'u', way: '='}, + restriction: 'no_left_turn' + }, projection, 'r'); + + graph = action(graph); + + var r = graph.entity('r'); + expect(r.tags).to.eql({type: 'restriction', restriction: 'no_left_turn'}); + expect(_.pick(r.memberByRole('from'), 'id', 'type')).to.eql({id: '-', type: 'way'}); + expect(_.pick(r.memberByRole('via'), 'id', 'type')).to.eql({id: '*', type: 'node'}); + expect(_.pick(r.memberByRole('to'), 'id', 'type')).to.eql({id: '=', type: 'way'}); + }); + + it('splits the from/to way of a U-turn (forward)', function() { + // u====*===>w + // | + // x + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Node({id: 'x'}), + iD.Way({id: '=', nodes: ['u', '*', 'w']}), + iD.Way({id: '-', nodes: ['*', 'x']}) + ]), + action = iD.actions.RestrictTurn({ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'u', way: '='}, + restriction: 'no_u_turn' + }, projection, 'r'); + + graph = action(graph); + + var r = graph.entity('r'); + expect(r.tags).to.eql({type: 'restriction', restriction: 'no_u_turn'}); + expect(_.pick(r.memberByRole('from'), 'id', 'type')).to.eql({id: '=', type: 'way'}); + expect(_.pick(r.memberByRole('via'), 'id', 'type')).to.eql({id: '*', type: 'node'}); + expect(_.pick(r.memberByRole('to'), 'id', 'type')).to.eql({id: '=', type: 'way'}); + }); + + it('splits the from/to way of a U-turn (backward)', function() { + // u====*===>w + // | + // x + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Node({id: 'x'}), + iD.Way({id: '=', nodes: ['u', '*', 'w']}), + iD.Way({id: '-', nodes: ['*', 'x']}) + ]), + action = iD.actions.RestrictTurn({ + from: {node: 'w', way: '=', newID: '=='}, + via: {node: '*'}, + to: {node: 'w', way: '=', newID: '~~'}, + restriction: 'no_u_turn' + }, projection, 'r'); + + graph = action(graph); + + var r = graph.entity('r'); + expect(r.tags).to.eql({type: 'restriction', restriction: 'no_u_turn'}); + expect(_.pick(r.memberByRole('from'), 'id', 'type')).to.eql({id: '==', type: 'way'}); + expect(_.pick(r.memberByRole('via'), 'id', 'type')).to.eql({id: '*', type: 'node'}); + expect(_.pick(r.memberByRole('to'), 'id', 'type')).to.eql({id: '==', type: 'way'}); + }); + + it('guesses the restriction type based on the turn angle', function() { + // u====*~~~~w + // | + // x + var graph = iD.Graph([ + iD.Node({id: 'u', loc: [-1, 0]}), + iD.Node({id: '*', loc: [ 0, 0]}), + iD.Node({id: 'w', loc: [ 0, 1]}), + iD.Node({id: 'x', loc: [ 0, -1]}), + iD.Way({id: '=', nodes: ['u', '*']}), + iD.Way({id: '-', nodes: ['*', 'x']}), + iD.Way({id: '~', nodes: ['*', 'w']}) + ]); + + var r = iD.actions.RestrictTurn({ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'x', way: '-'} + }, projection, 'r')(graph); + expect(r.entity('r').tags.restriction).to.equal('no_right_turn'); + + var l = iD.actions.RestrictTurn({ + from: {node: 'x', way: '-'}, + via: {node: '*'}, + to: {node: 'u', way: '='} + }, projection, 'r')(graph); + expect(l.entity('r').tags.restriction).to.equal('no_left_turn'); + + var s = iD.actions.RestrictTurn({ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'w', way: '~'} + }, projection, 'r')(graph); + expect(s.entity('r').tags.restriction).to.equal('no_straight_on'); + + var u = iD.actions.RestrictTurn({ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'u', way: '='} + }, projection, 'r')(graph); + expect(u.entity('r').tags.restriction).to.equal('no_u_turn'); + }); +}); diff --git a/test/spec/actions/unrestrict_turn.js b/test/spec/actions/unrestrict_turn.js new file mode 100644 index 000000000..f7c5a6830 --- /dev/null +++ b/test/spec/actions/unrestrict_turn.js @@ -0,0 +1,24 @@ +describe("iD.actions.UnrestrictTurn", function() { + it('removes a restriction from a restricted turn', function() { + // u====*--->w + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential'}}), + iD.Relation({id: 'r', tags: {type: 'restriction'}, members: [ + {id: '=', role: 'from', type: 'way'}, + {id: '-', role: 'to', type: 'way'}, + {id: '*', role: 'via', type: 'node'} + ]}) + ]), + action = iD.actions.UnrestrictTurn({ + restriction: 'r' + }); + + graph = action(graph); + + expect(graph.hasEntity('r')).to.be.undefined; + }); +}); diff --git a/test/spec/geo/intersection.js b/test/spec/geo/intersection.js index c77b50c78..68def534d 100644 --- a/test/spec/geo/intersection.js +++ b/test/spec/geo/intersection.js @@ -1,18 +1,3 @@ -describe('iD.geo.Turn', function() { - describe('#angle', function() { - it("calculates the angle of via to toward", function() { - function projection(x) { return x; } - - var turn = iD.geo.Turn({ - via: iD.Node({id: 'v', loc: [1, 0]}), - toward: iD.Node({id: 'w', loc: [1, 1]}) - }); - - expect(turn.angle(projection)).to.eql(Math.PI / 2); - }); - }); -}); - describe("iD.geo.Intersection", function() { describe('highways', function() { it('excludes non-highways', function() { @@ -64,27 +49,11 @@ describe("iD.geo.Intersection", function() { iD.Node({id: 'w'}), iD.Way({id: '=', nodes: ['u', '*', 'w'], tags: {highway: 'residential'}}) ]); - expect(_.pluck(iD.geo.Intersection(graph, '*').highways, 'id')).to.eql(['=-a', '=-b']); + expect(_.pluck(iD.geo.Intersection(graph, '*').highways, 'id')).to.eql(['=.a', '=.b']); }); }); describe('#turns', function() { - function ids(turns) { - return turns.map(function (turn) { - var result = { - from: turn.from.id, - to: turn.to.id, - via: turn.via.id, - toward: turn.toward.id - }; - - if (turn.restriction) - result.restriction = turn.restriction.id; - - return result; - }); - } - it("permits turns onto a way forward", function() { // u====*--->w var graph = iD.Graph([ @@ -96,11 +65,10 @@ describe("iD.geo.Intersection", function() { ]), turns = iD.geo.Intersection(graph, '*').turns('='); - expect(ids(turns)).to.eql([{ - from: '=', - to: '-', - via: '*', - toward: 'w' + expect(turns).to.eql([{ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'w', way: '-'} }]); }); @@ -115,7 +83,11 @@ describe("iD.geo.Intersection", function() { ]), turns = iD.geo.Intersection(graph, '*').turns('='); - expect(ids(turns)).to.eql([{from: '=', to: '-', via: '*', toward: 'w'}]); + expect(turns).to.eql([{ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'w', way: '-'} + }]); }); it("permits turns onto a way in both directions", function() { @@ -134,10 +106,15 @@ describe("iD.geo.Intersection", function() { ]), turns = iD.geo.Intersection(graph, '*').turns('='); - expect(ids(turns)).to.eql([ - {from: '=', to: '--a', via: '*', toward: 'w'}, - {from: '=', to: '--b', via: '*', toward: 'x'} - ]); + expect(turns).to.eql([{ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'w', way: '-'} + }, { + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'x', way: '-'} + }]); }); it("permits turns from a oneway forward", function() { @@ -151,7 +128,11 @@ describe("iD.geo.Intersection", function() { ]), turns = iD.geo.Intersection(graph, '*').turns('='); - expect(ids(turns)).to.eql([{from: '=', to: '-', via: '*', toward: 'w'}]); + expect(turns).to.eql([{ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'w', way: '-'} + }]); }); it("permits turns from a reverse oneway backward", function() { @@ -165,7 +146,11 @@ describe("iD.geo.Intersection", function() { ]), turns = iD.geo.Intersection(graph, '*').turns('='); - expect(ids(turns)).to.eql([{from: '=', to: '-', via: '*', toward: 'w'}]); + expect(turns).to.eql([{ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'w', way: '-'} + }]); }); it("omits turns from a oneway backward", function() { @@ -203,7 +188,11 @@ describe("iD.geo.Intersection", function() { ]), turns = iD.geo.Intersection(graph, '*').turns('='); - expect(ids(turns)).to.eql([{from: '=', to: '-', via: '*', toward: 'w'}]); + expect(turns).to.eql([{ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'w', way: '-'} + }]); }); it("permits turns onto a reverse oneway backward", function() { @@ -217,7 +206,11 @@ describe("iD.geo.Intersection", function() { ]), turns = iD.geo.Intersection(graph, '*').turns('='); - expect(ids(turns)).to.eql([{from: '=', to: '-', via: '*', toward: 'w'}]); + expect(turns).to.eql([{ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'w', way: '-'} + }]); }); it("omits turns onto a oneway backward", function() { @@ -260,11 +253,10 @@ describe("iD.geo.Intersection", function() { ]), turns = iD.geo.Intersection(graph, '*').turns('='); - expect(ids(turns)).to.eql([{ - from: '=', - to: '-', - via: '*', - toward: 'w', + expect(turns).to.eql([{ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'w', way: '-'}, restriction: 'r' }]); }); @@ -273,4 +265,5 @@ describe("iD.geo.Intersection", function() { // 'no' vs 'only' // U-turns // Self-intersections + // Incomplete relations }); From d4d80b2d6ec5f2ba28d62812f4cb87313868422f Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sat, 17 May 2014 08:15:22 -0700 Subject: [PATCH 15/26] Use turn restriction icons --- css/app.css | 4 -- css/map.css | 14 +++++ data/operations-sprite.json | 7 ++- dist/img/sprite.svg | 110 +++++++++++++++++++++++++++++++-- js/id/actions/restrict_turn.js | 2 + js/id/geo.js | 4 +- js/id/svg/defs.js | 2 +- js/id/svg/turns.js | 34 +++++++--- svg/resitriction-no-u.svg | 76 ----------------------- svg/restriction-no.svg | 78 ----------------------- svg/restriction-yes-u.svg | 76 ----------------------- svg/restriction-yes.svg | 77 ----------------------- 12 files changed, 154 insertions(+), 330 deletions(-) delete mode 100644 svg/resitriction-no-u.svg delete mode 100644 svg/restriction-no.svg delete mode 100644 svg/restriction-yes-u.svg delete mode 100644 svg/restriction-yes.svg diff --git a/css/app.css b/css/app.css index 3ac71d399..44cc8998a 100644 --- a/css/app.css +++ b/css/app.css @@ -2763,10 +2763,6 @@ img.wiki-image { fill: rgba(255,255,255,.5); } -.radial-menu .icon { - pointer-events: none; -} - .lasso-box { fill-opacity:0.1; stroke: #fff; diff --git a/css/map.css b/css/map.css index f3c540cc0..9654a56cf 100644 --- a/css/map.css +++ b/css/map.css @@ -957,6 +957,11 @@ g.turn.restricted path { stroke: red; } +g.turn rect { + fill: none; + pointer-events: all; +} + /* Cursors */ #map { @@ -1104,6 +1109,15 @@ g.turn.restricted path { ) 9 9, crosshair; } +.turn rect { + cursor: pointer; /* Opera */ + cursor: url(img/cursor-pointer.png) 6 1, pointer; /* FF */ + cursor: -webkit-image-set( + url(img/cursor-pointer.png) 1x, + url(img/cursor-pointer2x.png) 2x + ) 6 1, pointer; +} + .lasso #map { pointer-events: visibleStroke; } diff --git a/data/operations-sprite.json b/data/operations-sprite.json index 23c5a816d..9eab70d5c 100644 --- a/data/operations-sprite.json +++ b/data/operations-sprite.json @@ -23,5 +23,10 @@ "icon-operation-disabled-orthogonalize": [160, 160], "icon-operation-disabled-rotate": [180, 160], "icon-operation-disabled-simplify": [200, 160], - "icon-operation-disabled-continue": [220, 160] + "icon-operation-disabled-continue": [220, 160], + + "icon-restriction-yes": [50, 80], + "icon-restriction-no": [95, 80], + "icon-restriction-yes-u": [140, 80], + "icon-restriction-no-u": [185, 80] } \ No newline at end of file diff --git a/dist/img/sprite.svg b/dist/img/sprite.svg index f93948414..5fc64cbb9 100644 --- a/dist/img/sprite.svg +++ b/dist/img/sprite.svg @@ -27,12 +27,12 @@ inkscape:window-width="1440" inkscape:window-height="856" id="namedview392" - showgrid="false" - inkscape:zoom="11.313708" - inkscape:cx="19.712517" - inkscape:cy="454.54715" - inkscape:window-x="298" - inkscape:window-y="6" + showgrid="true" + inkscape:zoom="2.8284271" + inkscape:cx="124.86957" + inkscape:cy="471.44031" + inkscape:window-x="305" + inkscape:window-y="95" inkscape:window-maximized="0" inkscape:current-layer="svg12393" showguides="false" @@ -48,6 +48,22 @@ visible="true" enabled="true" snapvisiblegridlinesonly="true" /> + + + + @@ -1881,4 +1897,86 @@ transform="matrix(0,1,-1,0,0,0)" rx="0.5" ry="0.5" /> + + + + + + + + + + + + + + + + + + + + diff --git a/js/id/actions/restrict_turn.js b/js/id/actions/restrict_turn.js index e6786e6e6..0b4ebd02f 100644 --- a/js/id/actions/restrict_turn.js +++ b/js/id/actions/restrict_turn.js @@ -75,6 +75,8 @@ iD.actions.RestrictTurn = function(turn, projection, restrictionId) { var angle = iD.geo.angle(via, graph.entity(turn.from.node), projection) - iD.geo.angle(via, graph.entity(turn.to.node), projection); + angle = angle * 180 / Math.PI; + if (angle > 158 || angle < -158) return 'no_straight_on'; if (angle > 23) diff --git a/js/id/geo.js b/js/id/geo.js index f667ca100..8978828b0 100644 --- a/js/id/geo.js +++ b/js/id/geo.js @@ -33,12 +33,12 @@ iD.geo.edgeEqual = function(a, b) { (a[0] === b[1] && a[1] === b[0]); }; -// Return the counterclockwise angle in the range (-180, 180) degrees +// Return the counterclockwise angle in the range (-pi, pi) // between the positive X axis and the line intersecting a and b. iD.geo.angle = function(a, b, projection) { a = projection(a.loc); b = projection(b.loc); - return Math.atan2(b[1] - a[1], b[0] - a[0]) * 180 / Math.PI; + return Math.atan2(b[1] - a[1], b[0] - a[0]); }; // Choose the edge with the minimal distance from `point` to its orthogonal diff --git a/js/id/svg/defs.js b/js/id/svg/defs.js index ad9182a41..7789e9d6e 100644 --- a/js/id/svg/defs.js +++ b/js/id/svg/defs.js @@ -92,7 +92,7 @@ iD.svg.Defs = function(context) { }); defs.selectAll() - .data([12, 18, 20]) + .data([12, 18, 20, 45]) .enter().append('clipPath') .attr('id', function (d) { return 'clip-square-' + d; diff --git a/js/id/svg/turns.js b/js/id/svg/turns.js index f20f20a3d..b49dd435d 100644 --- a/js/id/svg/turns.js +++ b/js/id/svg/turns.js @@ -3,14 +3,21 @@ iD.svg.Turns = function(projection) { var groups = surface.select('.layer-hit').selectAll('g.turn') .data(turns); + // Enter + var enter = groups.enter().append('g') .attr('class', 'turn'); - enter.append('path') - .attr('class', 'turn') - .attr('d', function() { - return 'M20 0 L50 0 M40 10 L50 0 M40 -10 L50 0'; - }); + enter.append('rect') + .attr('transform', 'translate(-12, -12)') + .attr('width', '45') + .attr('height', '25'); + + enter.append('use') + .attr('transform', 'translate(-12, -12)') + .attr('clip-path', 'url(#clip-square-45)'); + + // Update groups .classed('restricted', function(turn) { @@ -18,12 +25,21 @@ iD.svg.Turns = function(projection) { }) .attr('transform', function(turn) { var v = graph.entity(turn.via.node), - t = graph.entity(turn.to.node); - return iD.svg.PointTransform(projection)(v) + - 'rotate(' + iD.geo.angle(v, t, projection) + ')'; + t = graph.entity(turn.to.node), + a = iD.geo.angle(v, t, projection), + p = projection(v.loc), + r = 60; + + return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ')' + + 'rotate(' + a * 180 / Math.PI + ')'; }); - groups.select('path'); // Propagate updated data. + groups.select('use') + .attr('xlink:href', function(turn) { return '#icon-restriction-' + (turn.restriction ? 'no' : 'yes'); }); + + groups.select('rect'); + + // Exit groups.exit() .remove(); diff --git a/svg/resitriction-no-u.svg b/svg/resitriction-no-u.svg deleted file mode 100644 index af584a552..000000000 --- a/svg/resitriction-no-u.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - diff --git a/svg/restriction-no.svg b/svg/restriction-no.svg deleted file mode 100644 index 512ad5616..000000000 --- a/svg/restriction-no.svg +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - diff --git a/svg/restriction-yes-u.svg b/svg/restriction-yes-u.svg deleted file mode 100644 index 854f8761d..000000000 --- a/svg/restriction-yes-u.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - diff --git a/svg/restriction-yes.svg b/svg/restriction-yes.svg deleted file mode 100644 index a0b088a31..000000000 --- a/svg/restriction-yes.svg +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - From 573237e94e458d89066284720787edc3315dda62 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sat, 17 May 2014 08:42:47 -0700 Subject: [PATCH 16/26] Render U-turns --- css/map.css | 16 +++------- dist/img/sprite.svg | 4 +-- js/id/geo/intersection.js | 10 ++++++ js/id/svg/defs.js | 2 +- js/id/svg/turns.js | 40 +++++++++++++++++------- test/spec/geo/intersection.js | 58 +++++++++++++++++++++++++---------- 6 files changed, 88 insertions(+), 42 deletions(-) diff --git a/css/map.css b/css/map.css index 9654a56cf..eeac2efc2 100644 --- a/css/map.css +++ b/css/map.css @@ -947,17 +947,8 @@ text.point { /* Turns */ -g.turn path { - stroke: green; - stroke-width: 10px; - stroke-linecap: round; -} - -g.turn.restricted path { - stroke: red; -} - -g.turn rect { +g.turn rect, +g.turn circle { fill: none; pointer-events: all; } @@ -1109,7 +1100,8 @@ g.turn rect { ) 9 9, crosshair; } -.turn rect { +.turn rect, +.turn circle { cursor: pointer; /* Opera */ cursor: url(img/cursor-pointer.png) 6 1, pointer; /* FF */ cursor: -webkit-image-set( diff --git a/dist/img/sprite.svg b/dist/img/sprite.svg index 5fc64cbb9..4362cd91b 100644 --- a/dist/img/sprite.svg +++ b/dist/img/sprite.svg @@ -1941,7 +1941,7 @@ + transform="matrix(0,1,1,0,71.9905,-80.00893)"> + transform="matrix(0,1,1,0,122,-115)"> Date: Sat, 17 May 2014 08:47:21 -0700 Subject: [PATCH 17/26] Vertex in turn restriction editor isn't selectable --- css/map.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/css/map.css b/css/map.css index eeac2efc2..b57f7fb1a 100644 --- a/css/map.css +++ b/css/map.css @@ -953,6 +953,11 @@ g.turn circle { pointer-events: all; } +.form-field-restrictions .vertex { + pointer-events: none; + cursor: auto !important; +} + /* Cursors */ #map { From 047fbb128274a8598854a3d9aa0b534972f0b91a Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sat, 17 May 2014 08:54:09 -0700 Subject: [PATCH 18/26] Fix rendering when dragging intersection vertex --- js/id/ui/preset/restrictions.js | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/js/id/ui/preset/restrictions.js b/js/id/ui/preset/restrictions.js index 61baebc88..c0e9b66a9 100644 --- a/js/id/ui/preset/restrictions.js +++ b/js/id/ui/preset/restrictions.js @@ -1,6 +1,6 @@ iD.ui.preset.restrictions = function(field, context) { var event = d3.dispatch('change'), - vertex, + vertexID, selectedID; function restrictions(selection) { @@ -14,11 +14,22 @@ iD.ui.preset.restrictions = function(field, context) { .call(iD.svg.Surface(context)) .call(iD.behavior.Hover(context)); + var intersection = iD.geo.Intersection(context.graph(), vertexID), + graph = intersection.graph, + vertex = graph.entity(vertexID), + surface = wrap.selectAll('svg'), + filter = function () { return true; }, + extent = iD.geo.Extent(), + projection = iD.geo.RawMercator(), + lines = iD.svg.Lines(projection, context), + vertices = iD.svg.Vertices(projection, context), + turns = iD.svg.Turns(projection, context); + var d = wrap.dimensions(), c = [d[0] / 2, d[1] / 2], z = 21; - var projection = iD.geo.RawMercator() + projection .scale(256 * Math.pow(2, z) / (2 * Math.PI)); var s = projection(vertex.loc); @@ -27,15 +38,6 @@ iD.ui.preset.restrictions = function(field, context) { .translate([c[0] - s[0], c[1] - s[1]]) .clipExtent([[0, 0], d]); - var surface = wrap.selectAll('svg'), - filter = function () { return true; }, - extent = iD.geo.Extent(), - intersection = iD.geo.Intersection(context.graph(), vertex.id), - graph = intersection.graph, - lines = iD.svg.Lines(projection, context), - vertices = iD.svg.Vertices(projection, context), - turns = iD.svg.Turns(projection, context); - surface .call(vertices, graph, [vertex], filter, extent, z) .call(lines, graph, intersection.highways, filter) @@ -81,9 +83,9 @@ iD.ui.preset.restrictions = function(field, context) { } restrictions.entity = function(_) { - if (!vertex || vertex.id !== _.id) { + if (!vertexID || vertexID !== _.id) { selectedID = null; - vertex = _; + vertexID = _.id; } }; From eaaff52d6264f4ca6f1e08fd39d5180304fe391d Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sat, 17 May 2014 10:22:54 -0700 Subject: [PATCH 19/26] Help text --- css/app.css | 13 ++++++ data/core.yaml | 5 +++ dist/locales/en.json | 6 +++ js/id/actions/restrict_turn.js | 23 +++-------- js/id/geo/intersection.js | 16 ++++++++ js/id/ui/preset/restrictions.js | 71 ++++++++++++++++++++++++++------- 6 files changed, 102 insertions(+), 32 deletions(-) diff --git a/css/app.css b/css/app.css index 44cc8998a..096c4d1d2 100644 --- a/css/app.css +++ b/css/app.css @@ -1538,9 +1538,22 @@ input[type=number] { /* Restrictions editor */ .form-field-restrictions .preset-input-wrap { + position: relative; height: 300px; } +.form-field-restrictions .restriction-help { + z-index: 1; + position: absolute; + top: 0; + left: 0; + right: 0; + padding: 2px 6px; + background-color: rgba(255, 255, 255, .8); + color: #999; + text-align: center; +} + /* combobox dropdown */ div.combobox { diff --git a/data/core.yaml b/data/core.yaml index 048a433dc..5de2517ba 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -146,6 +146,11 @@ en: not_eligible: Lines can't be split at their beginning or end. multiple_ways: There are too many lines here to split. restriction: + help: + select: Click to select a road segment. + toggle: Click to toggle turn restrictions. + toggle_on: 'Click to add a "{restriction}" restriction.' + toggle_off: 'Click to remove the "{restriction}" restriction.' annotation: create: Added a turn restriction delete: Deleted a turn restriction diff --git a/dist/locales/en.json b/dist/locales/en.json index cd29e7272..f89e6f236 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -184,6 +184,12 @@ "multiple_ways": "There are too many lines here to split." }, "restriction": { + "help": { + "select": "Click to select a road segment.", + "toggle": "Click to toggle turn restrictions.", + "toggle_on": "Click to add a \"{restriction}\" restriction.", + "toggle_off": "Click to remove the \"{restriction}\" restriction." + }, "annotation": { "create": "Added a turn restriction", "delete": "Deleted a turn restriction" diff --git a/js/id/actions/restrict_turn.js b/js/id/actions/restrict_turn.js index 0b4ebd02f..eeefee3e6 100644 --- a/js/id/actions/restrict_turn.js +++ b/js/id/actions/restrict_turn.js @@ -62,7 +62,12 @@ iD.actions.RestrictTurn = function(turn, projection, restrictionId) { id: restrictionId, tags: { type: 'restriction', - restriction: turn.restriction || guessRestriction() + restriction: turn.restriction || + iD.geo.inferRestriction( + graph.entity(turn.from.node), + via, + graph.entity(turn.to.node), + projection) }, members: [ {id: from.id, type: 'way', role: 'from'}, @@ -70,21 +75,5 @@ iD.actions.RestrictTurn = function(turn, projection, restrictionId) { {id: to.id, type: 'way', role: 'to'} ] })); - - function guessRestriction() { - var angle = iD.geo.angle(via, graph.entity(turn.from.node), projection) - - iD.geo.angle(via, graph.entity(turn.to.node), projection); - - angle = angle * 180 / Math.PI; - - if (angle > 158 || angle < -158) - return 'no_straight_on'; - if (angle > 23) - return 'no_right_turn'; - if (angle < -22) - return 'no_left_turn'; - - return 'no_u_turn'; - } }; }; diff --git a/js/id/geo/intersection.js b/js/id/geo/intersection.js index 7d29b8f05..1451b1dd2 100644 --- a/js/id/geo/intersection.js +++ b/js/id/geo/intersection.js @@ -108,3 +108,19 @@ iD.geo.Intersection = function(graph, vertexId) { return intersection; }; + +iD.geo.inferRestriction = function(from, via, to, projection) { + var angle = iD.geo.angle(via, from, projection) - + iD.geo.angle(via, to, projection); + + angle = angle * 180 / Math.PI; + + if (angle > 158 || angle < -158) + return 'no_straight_on'; + if (angle > 23) + return 'no_right_turn'; + if (angle < -22) + return 'no_left_turn'; + + return 'no_u_turn'; +}; diff --git a/js/id/ui/preset/restrictions.js b/js/id/ui/preset/restrictions.js index c0e9b66a9..45f137f36 100644 --- a/js/id/ui/preset/restrictions.js +++ b/js/id/ui/preset/restrictions.js @@ -10,6 +10,9 @@ iD.ui.preset.restrictions = function(field, context) { var enter = wrap.enter().append('div') .attr('class', 'preset-input-wrap'); + enter.append('div') + .attr('class', 'restriction-help'); + enter.append('svg') .call(iD.svg.Surface(context)) .call(iD.behavior.Hover(context)); @@ -43,7 +46,30 @@ iD.ui.preset.restrictions = function(field, context) { .call(lines, graph, intersection.highways, filter) .call(turns, graph, intersection.turns(selectedID)); - surface.on('click.select', function() { + surface + .on('click.restrictions', click) + .on('mouseover.restrictions', mouseover) + .on('mouseout.restrictions', mouseout); + + surface + .selectAll('.selected') + .classed('selected', false); + + if (selectedID) { + surface + .selectAll('.' + selectedID) + .classed('selected', true); + } + + mouseout(); + + context.history() + .on('change.restrictions', render); + + d3.select(window) + .on('resize.restrictions', render); + + function click() { var datum = d3.event.target.__data__; if (datum instanceof iD.Entity) { selectedID = datum.id; @@ -59,23 +85,38 @@ iD.ui.preset.restrictions = function(field, context) { t('operations.restriction.annotation.create')); } } - }); - - surface - .selectAll('.selected') - .classed('selected', false); - - if (selectedID) { - surface - .selectAll('.' + selectedID) - .classed('selected', true); } - context.history() - .on('change.restrictions', render); + function mouseover() { + var datum = d3.event.target.__data__; + if (datum instanceof iD.geo.Turn) { + var graph = context.graph(), + presets = context.presets(), + preset; - d3.select(window) - .on('resize.restrictions', render); + if (datum.restriction) { + preset = presets.match(graph.entity(datum.restriction), graph); + } else { + preset = presets.item('type/restriction/' + + iD.geo.inferRestriction( + graph.entity(datum.from.node), + graph.entity(datum.via.node), + graph.entity(datum.to.node), + projection)); + } + + wrap.selectAll('.restriction-help') + .text(t('operations.restriction.help.' + + (datum.restriction ? 'toggle_off' : 'toggle_on'), + {restriction: preset.name()})); + } + } + + function mouseout() { + wrap.selectAll('.restriction-help') + .text(t('operations.restriction.help.' + + (selectedID ? 'toggle' : 'select'))); + } function render() { restrictions(selection); From 9d5df793b5c1a6f58146d1ba3525523eb321bfa5 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sat, 17 May 2014 21:27:51 -0700 Subject: [PATCH 20/26] Fix turn generation from ways that need splitting --- js/id/geo/intersection.js | 73 +++++++++++++++++++++-------------- test/spec/geo/intersection.js | 55 +++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 32 deletions(-) diff --git a/js/id/geo/intersection.js b/js/id/geo/intersection.js index 1451b1dd2..dab5b2fb2 100644 --- a/js/id/geo/intersection.js +++ b/js/id/geo/intersection.js @@ -19,8 +19,8 @@ iD.geo.Intersection = function(graph, vertexId) { highways.push(way); } else { var idx = _.indexOf(way.nodes, vertex.id, 1), - wayA = iD.Way({id: way.id + '.a', tags: way.tags, nodes: way.nodes.slice(0, idx + 1)}), - wayB = iD.Way({id: way.id + '.b', tags: way.tags, nodes: way.nodes.slice(idx)}); + wayA = iD.Way({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, idx + 1)}), + wayB = iD.Way({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(idx)}); graph = graph.replace(wayA); graph = graph.replace(wayB); @@ -64,45 +64,58 @@ iD.geo.Intersection = function(graph, vertexId) { return iD.geo.Turn(turn); } - var from = {node: way.nodes[way.first() === vertex.id ? 1 : way.nodes.length - 2], way: way.id}, - via = {node: vertex.id}, + var via = {node: vertex.id}, + ways = [], turns = []; - highways.forEach(function(parent) { - if (parent === way) - return; + if (way.affix(vertexId)) { + ways = [way]; + } else { + ways = [graph.entity(way.id + '-a'), graph.entity(way.id + '-b')]; + } - var index = parent.nodes.indexOf(vertex.id); + ways.forEach(function(way) { + var from = { + node: way.nodes[way.first() === vertex.id ? 1 : way.nodes.length - 2], + way: way.id.split(/-(a|b)/)[0] + }; - // backward - if (parent.first() !== vertex.id && parent.tags.oneway !== 'yes') { + highways.forEach(function(parent) { + if (parent === way) + return; + + var index = parent.nodes.indexOf(vertex.id); + + // backward + if (parent.first() !== vertex.id && parent.tags.oneway !== 'yes') { + turns.push(withRestriction({ + from: from, + via: via, + to: {node: parent.nodes[index - 1], way: parent.id.split(/-(a|b)/)[0]} + })); + } + + // forward + if (parent.last() !== vertex.id && parent.tags.oneway !== '-1') { + turns.push(withRestriction({ + from: from, + via: via, + to: {node: parent.nodes[index + 1], way: parent.id.split(/-(a|b)/)[0]} + })); + } + }); + + // U-turn + if (way.tags.oneway !== 'yes' && way.tags.oneway !== '-1') { turns.push(withRestriction({ from: from, via: via, - to: {node: parent.nodes[index - 1], way: parent.id.split('.')[0]} - })); - } - - // forward - if (parent.last() !== vertex.id && parent.tags.oneway !== '-1') { - turns.push(withRestriction({ - from: from, - via: via, - to: {node: parent.nodes[index + 1], way: parent.id.split('.')[0]} + to: from, + u: true })); } }); - // U-turn - if (way.tags.oneway !== 'yes' && way.tags.oneway !== '-1') { - turns.push(withRestriction({ - from: from, - via: via, - to: from, - u: true - })); - } - return turns; }; diff --git a/test/spec/geo/intersection.js b/test/spec/geo/intersection.js index fc7dbcd46..bcef423b5 100644 --- a/test/spec/geo/intersection.js +++ b/test/spec/geo/intersection.js @@ -49,7 +49,7 @@ describe("iD.geo.Intersection", function() { iD.Node({id: 'w'}), iD.Way({id: '=', nodes: ['u', '*', 'w'], tags: {highway: 'residential'}}) ]); - expect(_.pluck(iD.geo.Intersection(graph, '*').highways, 'id')).to.eql(['=.a', '=.b']); + expect(_.pluck(iD.geo.Intersection(graph, '*').highways, 'id')).to.eql(['=-a', '=-b']); }); }); @@ -92,7 +92,58 @@ describe("iD.geo.Intersection", function() { }); }); - it("permits turns onto a way in both directions", function() { + it("permits turns fom a way in both directions", function() { + // w + // | + // u===* + // | + // x + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Node({id: 'x'}), + iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['w', '*', 'x'], tags: {highway: 'residential'}}) + ]), + turns = iD.geo.Intersection(graph, '*').turns('-'); + + expect(turns.length).to.eql(6); + expect(turns[0]).to.eql({ + from: {node: 'w', way: '-'}, + via: {node: '*'}, + to: {node: 'u', way: '='} + }); + expect(turns[1]).to.eql({ + from: {node: 'w', way: '-'}, + via: {node: '*'}, + to: {node: 'x', way: '-'} + }); + expect(turns[2]).to.eql({ + from: {node: 'w', way: '-'}, + via: {node: '*'}, + to: {node: 'w', way: '-'}, + u: true + }); + expect(turns[3]).to.eql({ + from: {node: 'x', way: '-'}, + via: {node: '*'}, + to: {node: 'u', way: '='} + }); + expect(turns[4]).to.eql({ + from: {node: 'x', way: '-'}, + via: {node: '*'}, + to: {node: 'w', way: '-'} + }); + expect(turns[5]).to.eql({ + from: {node: 'x', way: '-'}, + via: {node: '*'}, + to: {node: 'x', way: '-'}, + u: true + }); + }); + + it("permits turns to a way in both directions", function() { // w // | // u===* From 243e86b277acb6eb3864702652abb783bdfe80fa Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sat, 17 May 2014 21:49:54 -0700 Subject: [PATCH 21/26] Update selected segment after splits --- js/id/actions/restrict_turn.js | 12 +++++++++-- js/id/ui/preset/restrictions.js | 11 +++++++++- test/spec/actions/restrict_turn.js | 34 ++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/js/id/actions/restrict_turn.js b/js/id/actions/restrict_turn.js index eeefee3e6..aaac9b734 100644 --- a/js/id/actions/restrict_turn.js +++ b/js/id/actions/restrict_turn.js @@ -29,7 +29,9 @@ // be assigned a new ID. // iD.actions.RestrictTurn = function(turn, projection, restrictionId) { - return function(graph) { + var dispatch = d3.dispatch('split'); + + function action(graph) { var from = graph.entity(turn.from.way), via = graph.entity(turn.via.node), to = graph.entity(turn.to.way); @@ -40,6 +42,8 @@ iD.actions.RestrictTurn = function(turn, projection, restrictionId) { graph = iD.actions.Split(via.id, [newFromId]) .limitWays([from.id])(graph); + dispatch.split(from.id, newFromId, graph); + var newFrom = graph.entity(newFromId); if (newFrom.nodes.indexOf(turn.from.node) !== -1) from = newFrom; @@ -53,6 +57,8 @@ iD.actions.RestrictTurn = function(turn, projection, restrictionId) { graph = iD.actions.Split(via.id, [newToId]) .limitWays([to.id])(graph); + dispatch.split(to.id, newToId, graph); + var newTo = graph.entity(newToId); if (newTo.nodes.indexOf(turn.to.node) !== -1) to = newTo; @@ -75,5 +81,7 @@ iD.actions.RestrictTurn = function(turn, projection, restrictionId) { {id: to.id, type: 'way', role: 'to'} ] })); - }; + } + + return d3.rebind(action, dispatch, 'on'); }; diff --git a/js/id/ui/preset/restrictions.js b/js/id/ui/preset/restrictions.js index 45f137f36..10e3c4ed7 100644 --- a/js/id/ui/preset/restrictions.js +++ b/js/id/ui/preset/restrictions.js @@ -81,8 +81,17 @@ iD.ui.preset.restrictions = function(field, context) { t('operations.restriction.annotation.delete')); } else { context.perform( - iD.actions.RestrictTurn(datum, projection), + iD.actions.RestrictTurn(datum, projection) + .on('split', split), t('operations.restriction.annotation.create')); + + function split(oldID, newID, graph) { + if (graph.entity(newID).contains(datum.from.node)) { + selectedID = newID; + } else if (graph.entity(oldID).contains(datum.from.node)) { + selectedID = oldID; + } + } } } } diff --git a/test/spec/actions/restrict_turn.js b/test/spec/actions/restrict_turn.js index 302f14cad..a403a8a17 100644 --- a/test/spec/actions/restrict_turn.js +++ b/test/spec/actions/restrict_turn.js @@ -236,4 +236,38 @@ describe("iD.actions.RestrictTurn", function() { }, projection, 'r')(graph); expect(u.entity('r').tags.restriction).to.equal('no_u_turn'); }); + + it('emits split events', function() { + // x + // | + // u====*====w + // | + // y + var graph = iD.Graph([ + iD.Node({id: '*'}), + iD.Node({id: 'u'}), + iD.Node({id: 'w'}), + iD.Node({id: 'x'}), + iD.Node({id: 'y'}), + iD.Way({id: '=', nodes: ['u', '*', 'w']}), + iD.Way({id: '-', nodes: ['x', '*', 'y']}) + ]), + action = iD.actions.RestrictTurn({ + from: {node: 'u', way: '=', newID: '=='}, + via: {node: '*'}, + to: {node: 'x', way: '-', newID: '--'}, + restriction: 'no_left_turn' + }); + + var splits = []; + + action.on('split', function(a, b, graph) { + expect(graph).to.be.instanceOf(iD.Graph); + splits.push([a, b]); + }); + + action(graph); + + expect(splits).to.eql([['=', '=='], ['-', '--']]); + }); }); From 6089a6aaea975c115c41d924c960042ae1813117 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sun, 18 May 2014 13:27:15 -0700 Subject: [PATCH 22/26] Better solution for maintaining selection --- js/id/actions/restrict_turn.js | 12 +---- js/id/geo/intersection.js | 78 +++++++++++++----------------- js/id/ui/preset/restrictions.js | 25 +++------- test/spec/actions/restrict_turn.js | 34 ------------- test/spec/geo/intersection.js | 56 +++++++++------------ 5 files changed, 67 insertions(+), 138 deletions(-) diff --git a/js/id/actions/restrict_turn.js b/js/id/actions/restrict_turn.js index aaac9b734..eeefee3e6 100644 --- a/js/id/actions/restrict_turn.js +++ b/js/id/actions/restrict_turn.js @@ -29,9 +29,7 @@ // be assigned a new ID. // iD.actions.RestrictTurn = function(turn, projection, restrictionId) { - var dispatch = d3.dispatch('split'); - - function action(graph) { + return function(graph) { var from = graph.entity(turn.from.way), via = graph.entity(turn.via.node), to = graph.entity(turn.to.way); @@ -42,8 +40,6 @@ iD.actions.RestrictTurn = function(turn, projection, restrictionId) { graph = iD.actions.Split(via.id, [newFromId]) .limitWays([from.id])(graph); - dispatch.split(from.id, newFromId, graph); - var newFrom = graph.entity(newFromId); if (newFrom.nodes.indexOf(turn.from.node) !== -1) from = newFrom; @@ -57,8 +53,6 @@ iD.actions.RestrictTurn = function(turn, projection, restrictionId) { graph = iD.actions.Split(via.id, [newToId]) .limitWays([to.id])(graph); - dispatch.split(to.id, newToId, graph); - var newTo = graph.entity(newToId); if (newTo.nodes.indexOf(turn.to.node) !== -1) to = newTo; @@ -81,7 +75,5 @@ iD.actions.RestrictTurn = function(turn, projection, restrictionId) { {id: to.id, type: 'way', role: 'to'} ] })); - } - - return d3.rebind(action, dispatch, 'on'); + }; }; diff --git a/js/id/geo/intersection.js b/js/id/geo/intersection.js index dab5b2fb2..e2dace3d6 100644 --- a/js/id/geo/intersection.js +++ b/js/id/geo/intersection.js @@ -35,11 +35,11 @@ iD.geo.Intersection = function(graph, vertexId) { graph: graph }; - intersection.turns = function(wayId) { - if (!wayId) + intersection.turns = function(fromNodeID) { + if (!fromNodeID) return []; - var way = graph.entity(wayId); + var way = _.find(highways, function(way) { return way.contains(fromNodeID); }); if (way.first() === vertex.id && way.tags.oneway === 'yes') return []; if (way.last() === vertex.id && way.tags.oneway === '-1') @@ -64,58 +64,48 @@ iD.geo.Intersection = function(graph, vertexId) { return iD.geo.Turn(turn); } - var via = {node: vertex.id}, - ways = [], + var from = { + node: way.nodes[way.first() === vertex.id ? 1 : way.nodes.length - 2], + way: way.id.split(/-(a|b)/)[0] + }, + via = {node: vertex.id}, turns = []; - if (way.affix(vertexId)) { - ways = [way]; - } else { - ways = [graph.entity(way.id + '-a'), graph.entity(way.id + '-b')]; - } + highways.forEach(function(parent) { + if (parent === way) + return; - ways.forEach(function(way) { - var from = { - node: way.nodes[way.first() === vertex.id ? 1 : way.nodes.length - 2], - way: way.id.split(/-(a|b)/)[0] - }; + var index = parent.nodes.indexOf(vertex.id); - highways.forEach(function(parent) { - if (parent === way) - return; - - var index = parent.nodes.indexOf(vertex.id); - - // backward - if (parent.first() !== vertex.id && parent.tags.oneway !== 'yes') { - turns.push(withRestriction({ - from: from, - via: via, - to: {node: parent.nodes[index - 1], way: parent.id.split(/-(a|b)/)[0]} - })); - } - - // forward - if (parent.last() !== vertex.id && parent.tags.oneway !== '-1') { - turns.push(withRestriction({ - from: from, - via: via, - to: {node: parent.nodes[index + 1], way: parent.id.split(/-(a|b)/)[0]} - })); - } - }); - - // U-turn - if (way.tags.oneway !== 'yes' && way.tags.oneway !== '-1') { + // backward + if (parent.first() !== vertex.id && parent.tags.oneway !== 'yes') { turns.push(withRestriction({ from: from, via: via, - to: from, - u: true + to: {node: parent.nodes[index - 1], way: parent.id.split(/-(a|b)/)[0]} + })); + } + + // forward + if (parent.last() !== vertex.id && parent.tags.oneway !== '-1') { + turns.push(withRestriction({ + from: from, + via: via, + to: {node: parent.nodes[index + 1], way: parent.id.split(/-(a|b)/)[0]} })); } }); + // U-turn + if (way.tags.oneway !== 'yes' && way.tags.oneway !== '-1') { + turns.push(withRestriction({ + from: from, + via: via, + to: from, + u: true + })); + } + return turns; }; diff --git a/js/id/ui/preset/restrictions.js b/js/id/ui/preset/restrictions.js index 10e3c4ed7..ef31b77aa 100644 --- a/js/id/ui/preset/restrictions.js +++ b/js/id/ui/preset/restrictions.js @@ -1,7 +1,7 @@ iD.ui.preset.restrictions = function(field, context) { var event = d3.dispatch('change'), vertexID, - selectedID; + fromNodeID; function restrictions(selection) { var wrap = selection.selectAll('.preset-input-wrap') @@ -44,7 +44,7 @@ iD.ui.preset.restrictions = function(field, context) { surface .call(vertices, graph, [vertex], filter, extent, z) .call(lines, graph, intersection.highways, filter) - .call(turns, graph, intersection.turns(selectedID)); + .call(turns, graph, intersection.turns(fromNodeID)); surface .on('click.restrictions', click) @@ -55,9 +55,9 @@ iD.ui.preset.restrictions = function(field, context) { .selectAll('.selected') .classed('selected', false); - if (selectedID) { + if (fromNodeID) { surface - .selectAll('.' + selectedID) + .selectAll('.' + _.find(intersection.highways, function(way) { return way.contains(fromNodeID); }).id) .classed('selected', true); } @@ -72,7 +72,7 @@ iD.ui.preset.restrictions = function(field, context) { function click() { var datum = d3.event.target.__data__; if (datum instanceof iD.Entity) { - selectedID = datum.id; + fromNodeID = datum.nodes[(datum.first() === vertexID) ? 1 : datum.nodes.length - 2]; render(); } else if (datum instanceof iD.geo.Turn) { if (datum.restriction) { @@ -81,17 +81,8 @@ iD.ui.preset.restrictions = function(field, context) { t('operations.restriction.annotation.delete')); } else { context.perform( - iD.actions.RestrictTurn(datum, projection) - .on('split', split), + iD.actions.RestrictTurn(datum, projection), t('operations.restriction.annotation.create')); - - function split(oldID, newID, graph) { - if (graph.entity(newID).contains(datum.from.node)) { - selectedID = newID; - } else if (graph.entity(oldID).contains(datum.from.node)) { - selectedID = oldID; - } - } } } } @@ -124,7 +115,7 @@ iD.ui.preset.restrictions = function(field, context) { function mouseout() { wrap.selectAll('.restriction-help') .text(t('operations.restriction.help.' + - (selectedID ? 'toggle' : 'select'))); + (fromNodeID ? 'toggle' : 'select'))); } function render() { @@ -134,7 +125,7 @@ iD.ui.preset.restrictions = function(field, context) { restrictions.entity = function(_) { if (!vertexID || vertexID !== _.id) { - selectedID = null; + fromNodeID = null; vertexID = _.id; } }; diff --git a/test/spec/actions/restrict_turn.js b/test/spec/actions/restrict_turn.js index a403a8a17..302f14cad 100644 --- a/test/spec/actions/restrict_turn.js +++ b/test/spec/actions/restrict_turn.js @@ -236,38 +236,4 @@ describe("iD.actions.RestrictTurn", function() { }, projection, 'r')(graph); expect(u.entity('r').tags.restriction).to.equal('no_u_turn'); }); - - it('emits split events', function() { - // x - // | - // u====*====w - // | - // y - var graph = iD.Graph([ - iD.Node({id: '*'}), - iD.Node({id: 'u'}), - iD.Node({id: 'w'}), - iD.Node({id: 'x'}), - iD.Node({id: 'y'}), - iD.Way({id: '=', nodes: ['u', '*', 'w']}), - iD.Way({id: '-', nodes: ['x', '*', 'y']}) - ]), - action = iD.actions.RestrictTurn({ - from: {node: 'u', way: '=', newID: '=='}, - via: {node: '*'}, - to: {node: 'x', way: '-', newID: '--'}, - restriction: 'no_left_turn' - }); - - var splits = []; - - action.on('split', function(a, b, graph) { - expect(graph).to.be.instanceOf(iD.Graph); - splits.push([a, b]); - }); - - action(graph); - - expect(splits).to.eql([['=', '=='], ['-', '--']]); - }); }); diff --git a/test/spec/geo/intersection.js b/test/spec/geo/intersection.js index bcef423b5..62170e601 100644 --- a/test/spec/geo/intersection.js +++ b/test/spec/geo/intersection.js @@ -63,7 +63,7 @@ describe("iD.geo.Intersection", function() { iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential'}}) ]), - turns = iD.geo.Intersection(graph, '*').turns('='); + turns = iD.geo.Intersection(graph, '*').turns('u'); expect(turns.length).to.eql(2); expect(turns[0]).to.eql({ @@ -82,7 +82,7 @@ describe("iD.geo.Intersection", function() { iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), iD.Way({id: '-', nodes: ['w', '*'], tags: {highway: 'residential'}}) ]), - turns = iD.geo.Intersection(graph, '*').turns('='); + turns = iD.geo.Intersection(graph, '*').turns('u'); expect(turns.length).to.eql(2); expect(turns[0]).to.eql({ @@ -92,7 +92,7 @@ describe("iD.geo.Intersection", function() { }); }); - it("permits turns fom a way in both directions", function() { + it("permits turns from a way that must be split", function() { // w // | // u===* @@ -106,9 +106,9 @@ describe("iD.geo.Intersection", function() { iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), iD.Way({id: '-', nodes: ['w', '*', 'x'], tags: {highway: 'residential'}}) ]), - turns = iD.geo.Intersection(graph, '*').turns('-'); + turns = iD.geo.Intersection(graph, '*').turns('w'); - expect(turns.length).to.eql(6); + expect(turns.length).to.eql(3); expect(turns[0]).to.eql({ from: {node: 'w', way: '-'}, via: {node: '*'}, @@ -125,25 +125,9 @@ describe("iD.geo.Intersection", function() { to: {node: 'w', way: '-'}, u: true }); - expect(turns[3]).to.eql({ - from: {node: 'x', way: '-'}, - via: {node: '*'}, - to: {node: 'u', way: '='} - }); - expect(turns[4]).to.eql({ - from: {node: 'x', way: '-'}, - via: {node: '*'}, - to: {node: 'w', way: '-'} - }); - expect(turns[5]).to.eql({ - from: {node: 'x', way: '-'}, - via: {node: '*'}, - to: {node: 'x', way: '-'}, - u: true - }); }); - it("permits turns to a way in both directions", function() { + it("permits turns to a way that must be split", function() { // w // | // u===* @@ -157,7 +141,7 @@ describe("iD.geo.Intersection", function() { iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), iD.Way({id: '-', nodes: ['w', '*', 'x'], tags: {highway: 'residential'}}) ]), - turns = iD.geo.Intersection(graph, '*').turns('='); + turns = iD.geo.Intersection(graph, '*').turns('u'); expect(turns.length).to.eql(3); expect(turns[0]).to.eql({ @@ -170,6 +154,12 @@ describe("iD.geo.Intersection", function() { via: {node: '*'}, to: {node: 'x', way: '-'} }); + expect(turns[2]).to.eql({ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'u', way: '='}, + u: true + }); }); it("permits turns from a oneway forward", function() { @@ -181,7 +171,7 @@ describe("iD.geo.Intersection", function() { iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential', oneway: 'yes'}}), iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential'}}) ]), - turns = iD.geo.Intersection(graph, '*').turns('='); + turns = iD.geo.Intersection(graph, '*').turns('u'); expect(turns).to.eql([{ from: {node: 'u', way: '='}, @@ -199,7 +189,7 @@ describe("iD.geo.Intersection", function() { iD.Way({id: '=', nodes: ['*', 'u'], tags: {highway: 'residential', oneway: '-1'}}), iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential'}}) ]), - turns = iD.geo.Intersection(graph, '*').turns('='); + turns = iD.geo.Intersection(graph, '*').turns('u'); expect(turns).to.eql([{ from: {node: 'u', way: '='}, @@ -217,7 +207,7 @@ describe("iD.geo.Intersection", function() { iD.Way({id: '=', nodes: ['*', 'u'], tags: {highway: 'residential', oneway: 'yes'}}), iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential'}}) ]); - expect(iD.geo.Intersection(graph, '*').turns('=')).to.eql([]); + expect(iD.geo.Intersection(graph, '*').turns('u')).to.eql([]); }); it("omits turns from a reverse oneway forward", function() { @@ -229,7 +219,7 @@ describe("iD.geo.Intersection", function() { iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential', oneway: '-1'}}), iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential'}}) ]); - expect(iD.geo.Intersection(graph, '*').turns('=')).to.eql([]); + expect(iD.geo.Intersection(graph, '*').turns('u')).to.eql([]); }); it("permits turns onto a oneway forward", function() { @@ -241,7 +231,7 @@ describe("iD.geo.Intersection", function() { iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential', oneway: 'yes'}}) ]), - turns = iD.geo.Intersection(graph, '*').turns('='); + turns = iD.geo.Intersection(graph, '*').turns('u'); expect(turns.length).to.eql(2); expect(turns[0]).to.eql({ @@ -260,7 +250,7 @@ describe("iD.geo.Intersection", function() { iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), iD.Way({id: '-', nodes: ['w', '*'], tags: {highway: 'residential', oneway: '-1'}}) ]), - turns = iD.geo.Intersection(graph, '*').turns('='); + turns = iD.geo.Intersection(graph, '*').turns('u'); expect(turns.length).to.eql(2); expect(turns[0]).to.eql({ @@ -279,7 +269,7 @@ describe("iD.geo.Intersection", function() { iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), iD.Way({id: '-', nodes: ['w', '*'], tags: {highway: 'residential', oneway: 'yes'}}) ]); - expect(iD.geo.Intersection(graph, '*').turns('=').length).to.eql(1); + expect(iD.geo.Intersection(graph, '*').turns('u').length).to.eql(1); }); it("omits turns onto a reverse oneway forward", function() { @@ -291,7 +281,7 @@ describe("iD.geo.Intersection", function() { iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential', oneway: '-1'}}) ]); - expect(iD.geo.Intersection(graph, '*').turns('=').length).to.eql(1); + expect(iD.geo.Intersection(graph, '*').turns('u').length).to.eql(1); }); it("includes U-turns", function() { @@ -303,7 +293,7 @@ describe("iD.geo.Intersection", function() { iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential'}}) ]), - turns = iD.geo.Intersection(graph, '*').turns('='); + turns = iD.geo.Intersection(graph, '*').turns('u'); expect(turns.length).to.eql(2); expect(turns[1]).to.eql({ @@ -328,7 +318,7 @@ describe("iD.geo.Intersection", function() { {id: '*', role: 'via', type: 'node'} ]}) ]), - turns = iD.geo.Intersection(graph, '*').turns('='); + turns = iD.geo.Intersection(graph, '*').turns('u'); expect(turns.length).to.eql(2); expect(turns[0]).to.eql({ From f811c19cdc75331572bff138cdd41bce6e68db77 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sun, 18 May 2014 12:08:26 -0700 Subject: [PATCH 23/26] Fix straight on restricting with splits --- js/id/actions/restrict_turn.js | 44 ++++++++++++++--------- test/spec/actions/restrict_turn.js | 56 ++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 17 deletions(-) diff --git a/js/id/actions/restrict_turn.js b/js/id/actions/restrict_turn.js index eeefee3e6..b5837eb57 100644 --- a/js/id/actions/restrict_turn.js +++ b/js/id/actions/restrict_turn.js @@ -34,28 +34,38 @@ iD.actions.RestrictTurn = function(turn, projection, restrictionId) { via = graph.entity(turn.via.node), to = graph.entity(turn.to.way); - if (!from.affix(via.id)) { - var newFromId = turn.from.newID || iD.Way().id; + function split(toOrFrom) { + var newID = toOrFrom.newID || iD.Way().id; + graph = iD.actions.Split(via.id, [newID]) + .limitWays([toOrFrom.way])(graph); - graph = iD.actions.Split(via.id, [newFromId]) - .limitWays([from.id])(graph); + var a = graph.entity(newID), + b = graph.entity(toOrFrom.way); - var newFrom = graph.entity(newFromId); - if (newFrom.nodes.indexOf(turn.from.node) !== -1) - from = newFrom; + if (a.nodes.indexOf(toOrFrom.node) !== -1) { + return [a, b]; + } else { + return [b, a]; + } } - if (turn.from.way === turn.to.way) { - to = from; - } else if (!to.affix(via.id)) { - var newToId = turn.to.newID || iD.Way().id; + if (!from.affix(via.id)) { + if (turn.from.node === turn.to.node) { + // U-turn + from = to = split(turn.from)[0]; + } else if (turn.from.way === turn.to.way) { + // Straight-on + var s = split(turn.from); + from = s[0]; + to = s[1]; + } else { + // Other + from = split(turn.from)[0]; + } + } - graph = iD.actions.Split(via.id, [newToId]) - .limitWays([to.id])(graph); - - var newTo = graph.entity(newToId); - if (newTo.nodes.indexOf(turn.to.node) !== -1) - to = newTo; + if (!to.affix(via.id)) { + to = split(turn.to)[0]; } return graph.replace(iD.Relation({ diff --git a/test/spec/actions/restrict_turn.js b/test/spec/actions/restrict_turn.js index 302f14cad..a147470cb 100644 --- a/test/spec/actions/restrict_turn.js +++ b/test/spec/actions/restrict_turn.js @@ -82,6 +82,62 @@ describe("iD.actions.RestrictTurn", function() { expect(_.pick(r.memberByRole('to'), 'id', 'type')).to.eql({id: '-', type: 'way'}); }); + it('splits the from way when necessary (straight on forward)', function() { + // u====*===>w + // | + // x + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Node({id: 'x'}), + iD.Way({id: '=', nodes: ['u', '*', 'w']}), + iD.Way({id: '-', nodes: ['*', 'x']}) + ]), + action = iD.actions.RestrictTurn({ + from: {node: 'u', way: '=', newID: '=='}, + via: {node: '*'}, + to: {node: 'w', way: '='}, + restriction: 'no_straight_on' + }, projection, 'r'); + + graph = action(graph); + + var r = graph.entity('r'); + expect(r.tags).to.eql({type: 'restriction', restriction: 'no_straight_on'}); + expect(_.pick(r.memberByRole('from'), 'id', 'type')).to.eql({id: '=', type: 'way'}); + expect(_.pick(r.memberByRole('via'), 'id', 'type')).to.eql({id: '*', type: 'node'}); + expect(_.pick(r.memberByRole('to'), 'id', 'type')).to.eql({id: '==', type: 'way'}); + }); + + it('splits the from way when necessary (straight on backward)', function() { + // u<===*====w + // | + // x + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: '*'}), + iD.Node({id: 'w'}), + iD.Node({id: 'x'}), + iD.Way({id: '=', nodes: ['w', '*', 'u']}), + iD.Way({id: '-', nodes: ['*', 'x']}) + ]), + action = iD.actions.RestrictTurn({ + from: {node: 'u', way: '=', newID: '=='}, + via: {node: '*'}, + to: {node: 'w', way: '='}, + restriction: 'no_straight_on' + }, projection, 'r'); + + graph = action(graph); + + var r = graph.entity('r'); + expect(r.tags).to.eql({type: 'restriction', restriction: 'no_straight_on'}); + expect(_.pick(r.memberByRole('from'), 'id', 'type')).to.eql({id: '==', type: 'way'}); + expect(_.pick(r.memberByRole('via'), 'id', 'type')).to.eql({id: '*', type: 'node'}); + expect(_.pick(r.memberByRole('to'), 'id', 'type')).to.eql({id: '=', type: 'way'}); + }); + it('splits the to way when necessary (forward)', function() { // u====*===>w // | From 3ac705b67ee5643e584744338cd1d68e4757fba2 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sun, 18 May 2014 16:26:31 -0700 Subject: [PATCH 24/26] Fix flicker --- js/id/svg/turns.js | 75 +++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/js/id/svg/turns.js b/js/id/svg/turns.js index 48c3823bc..45f09fc7b 100644 --- a/js/id/svg/turns.js +++ b/js/id/svg/turns.js @@ -1,65 +1,64 @@ iD.svg.Turns = function(projection) { return function(surface, graph, turns) { - var layer = surface.select('.layer-hit'), - nTurns = turns.filter(function (d) { return !d.u; }), - uTurns = turns.filter(function (d) { return d.u; }); + function key(turn) { + return iD.Entity.key(graph.entity(turn.from.node)) + ',' + + iD.Entity.key(graph.entity(turn.via.node)) + ',' + + iD.Entity.key(graph.entity(turn.to.node)) + ',' + + turn.restriction; + } - var nGroups = layer.selectAll('g.turn.turn-n') - .data(nTurns); - var uGroups = layer.selectAll('g.turn.turn-u') - .data(uTurns); + var groups = surface.select('.layer-hit').selectAll('g.turn') + .data(turns, key); // Enter - var nEnter = nGroups.enter().append('g') - .attr('class', 'turn turn-n'); - var uEnter = uGroups.enter().append('g') - .attr('class', 'turn turn-u'); + var enter = groups.enter().append('g') + .attr('class', 'turn') + .classed('restricted', function (turn) { + return turn.restriction; + }); + + var nEnter = enter.filter(function (turn) { return !turn.u; }); nEnter.append('rect') .attr('transform', 'translate(-12, -12)') .attr('width', '45') .attr('height', '25'); - uEnter.append('circle') - .attr('r', '16'); nEnter.append('use') .attr('transform', 'translate(-12, -12)') - .attr('clip-path', 'url(#clip-square-45)'); + .attr('clip-path', 'url(#clip-square-45)') + .attr('xlink:href', function(turn) { return '#icon-restriction-' + (turn.restriction ? 'no' : 'yes'); }); + + var uEnter = enter.filter(function (turn) { return turn.u; }); + + uEnter.append('circle') + .attr('r', '16'); + uEnter.append('use') .attr('transform', 'translate(-16, -16)') - .attr('clip-path', 'url(#clip-square-32)'); + .attr('clip-path', 'url(#clip-square-32)') + .attr('xlink:href', function(turn) { return '#icon-restriction-' + (turn.restriction ? 'no' : 'yes') + '-u'; }); // Update - layer.selectAll('g.turn') - .classed('restricted', function(turn) { - return turn.restriction; - }) - .attr('transform', function(turn) { - var v = graph.entity(turn.via.node), - t = graph.entity(turn.to.node), - a = iD.geo.angle(v, t, projection), - p = projection(v.loc), - r = turn.u ? 0 : 60; + groups.attr('transform', function (turn) { + var v = graph.entity(turn.via.node), + t = graph.entity(turn.to.node), + a = iD.geo.angle(v, t, projection), + p = projection(v.loc), + r = turn.u ? 0 : 60; - return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ')' + - 'rotate(' + a * 180 / Math.PI + ')'; - }); + return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ')' + + 'rotate(' + a * 180 / Math.PI + ')'; + }); - nGroups.select('use') - .attr('xlink:href', function(turn) { return '#icon-restriction-' + (turn.restriction ? 'no' : 'yes'); }); - uGroups.select('use') - .attr('xlink:href', function(turn) { return '#icon-restriction-' + (turn.restriction ? 'no' : 'yes') + '-u'; }); - - nGroups.select('rect'); - uGroups.select('circle'); + groups.select('rect'); + groups.select('circle'); // Exit - nGroups.exit() - .remove(); - uGroups.exit() + groups.exit() .remove(); return this; From 67e7380980daccb24609c85c76095258eb09bd13 Mon Sep 17 00:00:00 2001 From: samanpwbb Date: Mon, 19 May 2014 15:55:24 -0400 Subject: [PATCH 25/26] add blue arrow --- dist/img/sprite.svg | 60 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/dist/img/sprite.svg b/dist/img/sprite.svg index 4362cd91b..d27db5d95 100644 --- a/dist/img/sprite.svg +++ b/dist/img/sprite.svg @@ -13,7 +13,7 @@ width="800" height="560" id="svg12393" - inkscape:version="0.48.4 r" + inkscape:version="0.48.2 r9819" sodipodi:docname="sprite.svg"> + inkscape:snap-nodes="true"> image/svg+xml - + @@ -1911,7 +1911,7 @@ inkscape:connector-curvature="0" id="path12188" d="m -111,-45 -8,9.01282 1,1 4,0 0,10.59375 c -2.92023,1.19221 -4.99998,4.05725 -5,7.40625 4e-5,4.41829 3.58172,7.98721 8,7.98718 4.41827,10e-6 8,-3.5689 8,-7.98718 2e-5,-3.36351 -2.05966,-6.25472 -5,-7.4375 l 0,-10.5625 4,0 1,-1 z" - style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#8cd05f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.25;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" /> + style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#8cd05f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.25000000000000000;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" /> + style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:8;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" + d="M 156 80 C 147.21084 80.00001 140 87.21083 140 96 C 140.00001 104.78916 147.21083 112 156 112 C 164.78916 111.99999 172 104.78917 172 96 C 171.99999 87.21084 164.78917 80 156 80 z " + id="path4163" + transform="matrix(0,1,1,0,80.00893,-71.9905)" /> @@ -1979,4 +1979,36 @@ d="m 215.5,72.13782 -5,5 -2,2 -4,4 0,1 1,1 1,0 4,-4 2,-2 5,-5 0,-1 -1,-1 -1,0 z m -6.5,0.875 -2,1 -1,1 -1,2 0,4.1875 2.78125,-2.78125 0.21875,-0.21875 0,-1.1875 1,-1 1.1875,0 2.59375,-2.59375 L 212,73.01282 l -3,0 z m 7,4.03125 -2.78125,2.78125 -0.21875,0.1875 -1.5625,1.59375 3.0625,3.40625 4.5,-5 -3,0 0,-2.96875 z" style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> + + + + + + ONLY From 8b6ce214a2c0cb389db6e5f68f1a50f05be53ba8 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 19 May 2014 15:53:46 -0700 Subject: [PATCH 26/26] Initial support for only_* restrictions --- data/operations-sprite.json | 6 ++-- dist/img/sprite.svg | 52 +++++++++++++++++++++++++---------- js/id/geo/intersection.js | 6 ++++ js/id/svg/turns.js | 47 +++++++++++++++---------------- test/spec/geo/intersection.js | 48 +++++++++++++++++++++++++++++--- 5 files changed, 115 insertions(+), 44 deletions(-) diff --git a/data/operations-sprite.json b/data/operations-sprite.json index 9eab70d5c..f9ae5a12c 100644 --- a/data/operations-sprite.json +++ b/data/operations-sprite.json @@ -27,6 +27,8 @@ "icon-restriction-yes": [50, 80], "icon-restriction-no": [95, 80], - "icon-restriction-yes-u": [140, 80], - "icon-restriction-no-u": [185, 80] + "icon-restriction-only": [140, 80], + "icon-restriction-yes-u": [185, 80], + "icon-restriction-no-u": [230, 80], + "icon-restriction-only-u": [275, 80] } \ No newline at end of file diff --git a/dist/img/sprite.svg b/dist/img/sprite.svg index d27db5d95..e6c15a29b 100644 --- a/dist/img/sprite.svg +++ b/dist/img/sprite.svg @@ -13,7 +13,7 @@ width="800" height="560" id="svg12393" - inkscape:version="0.48.2 r9819" + inkscape:version="0.48.4 r" sodipodi:docname="sprite.svg"> image/svg+xml - + @@ -1941,14 +1941,15 @@ + transform="matrix(0,1,1,0,116.9905,-80.00893)"> + transform="matrix(0,1,1,0,80.00893,-71.9905)" + inkscape:connector-curvature="0" /> @@ -1961,7 +1962,7 @@ + transform="matrix(0,1,1,0,167,-115)"> ONLY + + + + + diff --git a/js/id/geo/intersection.js b/js/id/geo/intersection.js index e2dace3d6..1697cc7d4 100644 --- a/js/id/geo/intersection.js +++ b/js/id/geo/intersection.js @@ -58,6 +58,12 @@ iD.geo.Intersection = function(graph, vertexId) { v && v.id === turn.via.node && t && t.id === turn.to.way) { turn.restriction = relation.id; + } else if (/^only_/.test(relation.tags.restriction) && + f && f.id === turn.from.way && + v && v.id === turn.via.node && + t && t.id !== turn.to.way) { + turn.restriction = relation.id; + turn.indirect_restriction = true; } }); diff --git a/js/id/svg/turns.js b/js/id/svg/turns.js index 45f09fc7b..555b75eef 100644 --- a/js/id/svg/turns.js +++ b/js/id/svg/turns.js @@ -1,22 +1,21 @@ iD.svg.Turns = function(projection) { return function(surface, graph, turns) { - function key(turn) { - return iD.Entity.key(graph.entity(turn.from.node)) + ',' + - iD.Entity.key(graph.entity(turn.via.node)) + ',' + - iD.Entity.key(graph.entity(turn.to.node)) + ',' + - turn.restriction; + function icon(turn) { + if (!turn.restriction) + return '#icon-restriction-yes'; + var restriction = graph.entity(turn.restriction).tags.restriction; + return '#icon-restriction-' + + (!turn.indirect_restriction && /^only_/.test(restriction) ? 'only' : 'no') + + (turn.u ? '-u' : ''); } var groups = surface.select('.layer-hit').selectAll('g.turn') - .data(turns, key); + .data(turns); // Enter var enter = groups.enter().append('g') - .attr('class', 'turn') - .classed('restricted', function (turn) { - return turn.restriction; - }); + .attr('class', 'turn'); var nEnter = enter.filter(function (turn) { return !turn.u; }); @@ -27,8 +26,7 @@ iD.svg.Turns = function(projection) { nEnter.append('use') .attr('transform', 'translate(-12, -12)') - .attr('clip-path', 'url(#clip-square-45)') - .attr('xlink:href', function(turn) { return '#icon-restriction-' + (turn.restriction ? 'no' : 'yes'); }); + .attr('clip-path', 'url(#clip-square-45)'); var uEnter = enter.filter(function (turn) { return turn.u; }); @@ -37,21 +35,24 @@ iD.svg.Turns = function(projection) { uEnter.append('use') .attr('transform', 'translate(-16, -16)') - .attr('clip-path', 'url(#clip-square-32)') - .attr('xlink:href', function(turn) { return '#icon-restriction-' + (turn.restriction ? 'no' : 'yes') + '-u'; }); + .attr('clip-path', 'url(#clip-square-32)'); // Update - groups.attr('transform', function (turn) { - var v = graph.entity(turn.via.node), - t = graph.entity(turn.to.node), - a = iD.geo.angle(v, t, projection), - p = projection(v.loc), - r = turn.u ? 0 : 60; + groups + .attr('transform', function (turn) { + var v = graph.entity(turn.via.node), + t = graph.entity(turn.to.node), + a = iD.geo.angle(v, t, projection), + p = projection(v.loc), + r = turn.u ? 0 : 60; - return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ')' + - 'rotate(' + a * 180 / Math.PI + ')'; - }); + return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ')' + + 'rotate(' + a * 180 / Math.PI + ')'; + }); + + groups.select('use') + .attr('xlink:href', icon); groups.select('rect'); groups.select('circle'); diff --git a/test/spec/geo/intersection.js b/test/spec/geo/intersection.js index 62170e601..bcf083542 100644 --- a/test/spec/geo/intersection.js +++ b/test/spec/geo/intersection.js @@ -328,9 +328,49 @@ describe("iD.geo.Intersection", function() { restriction: 'r' }); }); - }); - // 'no' vs 'only' - // Self-intersections - // Incomplete relations + it("restricts turns affected by an only_* restriction relation", function() { + // u====*~~~~v + // | + // w + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: 'v'}), + iD.Node({id: 'w'}), + iD.Node({id: '*'}), + iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), + iD.Way({id: '~', nodes: ['v', '*'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['w', '*'], tags: {highway: 'residential'}}), + iD.Relation({id: 'r', tags: {type: 'restriction', restriction: 'only_right_turn'}, members: [ + {id: '=', role: 'from', type: 'way'}, + {id: '-', role: 'to', type: 'way'}, + {id: '*', role: 'via', type: 'node'} + ]}) + ]), + turns = iD.geo.Intersection(graph, '*').turns('u'); + + expect(turns.length).to.eql(3); + expect(turns[0]).to.eql({ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'v', way: '~'}, + restriction: 'r', + indirect_restriction: true + }); + expect(turns[1]).to.eql({ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'w', way: '-'}, + restriction: 'r' + }); + expect(turns[2]).to.eql({ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'u', way: '='}, + restriction: 'r', + indirect_restriction: true, + u: true + }); + }); + }); });