/**
* @license
* Lo-Dash 2.3.0 (Custom Build) <http://lodash.com/>
- * 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 <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
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`.
*
lodash.merge = merge;
lodash.omit = omit;
lodash.pairs = pairs;
+ lodash.pick = pick;
lodash.pluck = pluck;
lodash.reject = reject;
lodash.throttle = throttle;
};
/* 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);
return d3.rebind(context, dispatch, 'on');
};
-iD.version = '1.3.10';
+iD.version = '1.4.0';
(function() {
var detected = {};
(a[0] === b[1] && a[1] === b[0]);
};
+// 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]);
+};
+
// 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
return [this[0][0], this[0][1], this[1][0], this[1][1]].join(',');
}
});
+iD.geo.Turn = function(turn) {
+ if (!(this instanceof iD.geo.Turn))
+ return new iD.geo.Turn(turn);
+ _.extend(this, 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(fromNodeID) {
+ if (!fromNodeID)
+ return [];
+
+ 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')
+ return [];
+
+ function withRestriction(turn) {
+ graph.parentRelations(graph.entity(turn.from.way)).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.way &&
+ 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;
+ }
+ });
+
+ return iD.geo.Turn(turn);
+ }
+
+ 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 = [];
+
+ 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: from,
+ u: true
+ }));
+ }
+
+ return turns;
+ };
+
+ 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;
+
+ while (angle < 0)
+ angle += 360;
+
+ if (angle < 23)
+ return 'no_u_turn';
+ if (angle < 158)
+ return 'no_right_turn';
+ if (angle < 202)
+ return 'no_straight_on';
+ if (angle < 336)
+ return 'no_left_turn';
+
+ return 'no_u_turn';
+};
// For fixing up rendering of multipolygons with tags on the outer member.
// https://github.com/openstreetmap/iD/issues/613
iD.geo.isSimpleMultipolygonOuterMember = function(entity, graph) {
return joined;
};
-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;
- }
- });
+/*
+ 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]];
- return turn;
+ function projection(point) {
+ point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
+ return [point[0] * k + x, y - point[1] * k];
}
- var turns = [];
+ 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];
+ };
- [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;
+ projection.scale = function(_) {
+ if (!arguments.length) return k;
+ k = +_;
+ return projection;
+ };
- var index = parent.nodes.indexOf(node.id);
+ projection.translate = function(_) {
+ if (!arguments.length) return [x, y];
+ x = +_[0];
+ y = +_[1];
+ return projection;
+ };
- // 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])
- }));
- }
+ projection.clipExtent = function(_) {
+ if (!arguments.length) return clipExtent;
+ clipExtent = _;
+ return projection;
+ };
- // 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])
- }));
- }
- });
- });
+ projection.stream = d3.geo.transform({
+ point: function(x, y) {
+ x = projection([x, y]);
+ this.stream.point(x[0], x[1]);
+ }
+ }).stream;
- return turns;
+ return projection;
};
iD.actions = {};
iD.actions.AddEntity = function(way) {
return action;
};
+// Create a restriction relation for `turn`, which must have the following structure:
+//
+// {
+// from: { node: <node ID>, way: <way ID> },
+// via: { node: <node ID> },
+// to: { node: <node ID>, way: <way ID> },
+// 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);
+
+ function split(toOrFrom) {
+ var newID = toOrFrom.newID || iD.Way().id;
+ graph = iD.actions.Split(via.id, [newID])
+ .limitWays([toOrFrom.way])(graph);
+
+ var a = graph.entity(newID),
+ b = graph.entity(toOrFrom.way);
+
+ if (a.nodes.indexOf(toOrFrom.node) !== -1) {
+ return [a, b];
+ } else {
+ return [b, a];
+ }
+ }
+
+ 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];
+ }
+ }
+
+ if (!to.affix(via.id)) {
+ to = split(turn.to)[0];
+ }
+
+ return graph.replace(iD.Relation({
+ id: restrictionId,
+ tags: {
+ type: 'restriction',
+ 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'},
+ {id: via.id, type: 'node', role: 'via'},
+ {id: to.id, type: 'way', role: 'to'}
+ ]
+ }));
+ };
+};
/*
Order the nodes of a way in reverse order and reverse any direction dependent tags
other than `oneway`. (We assume that correcting a backwards oneway is the primary
return action;
};
+// Remove the effects of `turn.restriction` on `turn`, which must have the
+// following structure:
+//
+// {
+// from: { node: <node ID>, way: <way ID> },
+// via: { node: <node ID> },
+// to: { node: <node ID>, way: <way ID> },
+// restriction: <relation ID>
+// }
+//
+// 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);
+ };
+};
iD.behavior = {};
iD.behavior.AddWay = function(context) {
var event = d3.dispatch('start', 'startFromWay', 'startFromNode'),
.on('mouseup.lasso', mouseup);
d3.event.stopPropagation();
- d3.event.preventDefault();
-
}
}
}
}
- 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() {
connection.changesetTags = function(comment, imageryUsed) {
var tags = {
- imagery_used: imageryUsed.join(';'),
+ imagery_used: imageryUsed.join(';').substr(0, 255),
created_by: 'iD ' + iD.version
};
});
},
+ isHighwayIntersection: function() {
+ return false;
+ },
+
deprecatedTags: function() {
var tags = _.pairs(this.tags);
var deprecated = {};
});
},
+ isHighwayIntersection: function(resolver) {
+ return resolver.transient(this, 'isHighwayIntersection', function() {
+ return resolver.parentWays(this).filter(function(parent) {
+ return parent.tags.highway && parent.geometry(resolver) === 'line';
+ }).length > 1;
+ });
+ },
+
asJXON: function(changeset_id) {
var r = {
node: {
};
}
});
+iD.oneWayTags = {
+ 'aerialway': {
+ 'chair_lift': true,
+ 'mixed_lift': true,
+ 't-bar': true,
+ 'j-bar': true,
+ 'platter': true,
+ 'rope_tow': true,
+ 'magic_carpet': true,
+ 'yes': true
+ },
+ 'highway': {
+ 'motorway': true,
+ 'motorway_link': true
+ },
+ 'junction': {
+ 'roundabout': true
+ },
+ 'man_made': {
+ 'piste:halfpipe': true,
+ 'pipeline': true
+ },
+ 'piste:type': {
+ 'downhill': true,
+ 'sled': true,
+ 'yes': true
+ },
+ 'waterway': {
+ 'river': true,
+ 'stream': true
+ }
+};
iD.Relation = iD.Entity.relation = function iD_Relation() {
if (!(this instanceof iD_Relation)) {
return (new iD_Relation()).initialize(arguments);
if (['no', '0'].indexOf(this.tags.oneway) !== -1) { return false; }
// implied oneway tag..
- return this.tags.waterway === 'river' ||
- this.tags.waterway === 'stream' ||
- this.tags.highway === 'motorway' ||
- this.tags.highway === 'motorway_link' ||
- this.tags.junction === 'roundabout';
+ for (var key in this.tags) {
+ if (key in iD.oneWayTags && (this.tags[key] in iD.oneWayTags[key]))
+ return true;
+ }
+ return false;
},
isClosed: function() {
if (difference) {
var complete = difference.complete(map.extent());
all = _.compact(_.values(complete));
- filter = function(d) {
- if (d.type === 'midpoint') {
-
- var a = d.edge[0],
- b = d.edge[1];
-
- // redraw a midpoint if it needs to be
- // - moved (either edge node moved)
- // - deleted (edge nodes not consecutive in any parent way)
- if (a in complete || b in complete) return true;
-
- var parentsWays = graph.parentWays({ id: a });
- for (var i = 0; i < parentsWays.length; i++) {
- var nodes = parentsWays[i].nodes;
- for (var n = 0; n < nodes.length; n++) {
- if (nodes[n] === a && (nodes[n - 1] === b || nodes[n + 1] === b)) return false;
- }
- }
- return true;
-
- } else {
- return d.id in complete;
- }
- };
+ filter = function(d) { return d.id in complete; };
} else if (extent) {
all = context.intersects(map.extent().intersection(extent));
.attr('d', path);
};
};
+/*
+ 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, 32, 45])
+ .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.Labels = function(projection, context) {
var path = d3.geo.path().projection(projection);
for (var i = 0; i < entities.length; i++) {
var entity = entities[i];
- if (entity.type !== 'way') continue;
- if (context.selectedIDs().indexOf(entity.id) < 0) continue;
+ if (entity.type !== 'way')
+ continue;
+ if (!filter(entity))
+ continue;
+ if (context.selectedIDs().indexOf(entity.id) < 0)
+ continue;
var nodes = graph.childNodes(entity);
-
- // skip the last node because it is always repeated
for (var j = 0; j < nodes.length - 1; j++) {
var a = nodes[j],
b = nodes[j + 1],
id = [a.id, b.id].sort().join('-');
- // Redraw midpoints in two cases:
- // 1. One of the two endpoint nodes changed (e.g. was moved).
- // 2. A node was deleted. The midpoint between the two new
- // endpoints needs to be redrawn. In this case only the
- // way will be in the diff.
- if (!midpoints[id] && (filter(a) || filter(b) || filter(entity))) {
+ if (midpoints[id]) {
+ midpoints[id].parents.push(entity);
+ } else {
var loc = iD.geo.interp(a.loc, b.loc, 0.5);
if (extent.intersects(loc) && iD.geo.euclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
midpoints[id] = {
type: 'midpoint',
id: id,
loc: loc,
- edge: [a.id, b.id]
+ edge: [a.id, b.id],
+ parents: [entity]
};
}
}
}
}
+ function midpointFilter(d) {
+ if (midpoints[d.id])
+ return true;
+
+ for (var i = 0; i < d.parents.length; i++)
+ if (filter(d.parents[i]))
+ return true;
+
+ return false;
+ }
+
var groups = surface.select('.layer-hit').selectAll('g.midpoint')
- .filter(filter)
+ .filter(midpointFilter)
.data(_.values(midpoints), function(d) { return d.id; });
var group = groups.enter()
return drawPoints;
};
-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;
-};
-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']);
return tagClasses;
};
+iD.svg.Turns = function(projection) {
+ return function(surface, graph, turns) {
+ function key(turn) {
+ return [turn.from.node + turn.via.node + turn.to.node].join('-');
+ }
+
+ function icon(turn) {
+ var u = turn.u ? '-u' : '';
+ if (!turn.restriction)
+ return '#icon-restriction-yes' + u;
+ var restriction = graph.entity(turn.restriction).tags.restriction;
+ return '#icon-restriction-' +
+ (!turn.indirect_restriction && /^only_/.test(restriction) ? 'only' : 'no') + u;
+ }
+
+ var groups = surface.select('.layer-hit').selectAll('g.turn')
+ .data(turns, key);
+
+ // Enter
+
+ var enter = groups.enter().append('g')
+ .attr('class', 'turn');
+
+ var nEnter = enter.filter(function (turn) { return !turn.u; });
+
+ nEnter.append('rect')
+ .attr('transform', 'translate(-12, -12)')
+ .attr('width', '45')
+ .attr('height', '25');
+
+ nEnter.append('use')
+ .attr('transform', 'translate(-12, -12)')
+ .attr('clip-path', 'url(#clip-square-45)');
+
+ 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)');
+
+ // 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;
+
+ 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');
+
+ // Exit
+
+ groups.exit()
+ .remove();
+
+ return this;
+ };
+};
iD.svg.Vertices = function(projection, context) {
var radiuses = {
// z16-, z17, z18+, tagged
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')
preset,
reference;
+ var presetEditor = iD.ui.preset(context)
+ .on('change', changeTags);
var rawTagEditor = iD.ui.RawTagEditor(context)
.on('change', changeTags);
.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
function clean(o) {
var out = {}, k, v;
+ /*jshint -W083 */
for (k in o) {
if (k && (v = o[k]) !== undefined) {
- out[k] = v.trim();
+ out[k] = v.split(';').map(function(s) { return s.trim(); }).join(';');
}
}
+ /*jshint +W083 */
return out;
}
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.isHighwayIntersection(graph);
+
if (showEditor) {
$wrap.style('right', '0%');
$editorPane.call(entityEditor);
}
});
+ if (entity.isHighwayIntersection(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));
function show(field) {
field.show = true;
- presets(selection);
+ context.presets()(selection);
field.input.focus();
}
presets.preset = function(_) {
if (!arguments.length) return preset;
+ if (preset && preset.id === _.id) return presets;
preset = _;
fields = null;
return presets;
presets.entityID = function(_) {
if (!arguments.length) return id;
+ if (id === _) return presets;
id = _;
fields = null;
return presets;
sidebar.hide = function() {
featureListWrap.classed('inspector-hidden', false);
+ inspectorWrap.classed('inspector-hidden', true);
if (current) current.remove();
current = null;
};
city = wrap.select('.addr-city');
postcode = wrap.select('.addr-postcode');
- wrap.selectAll('input')
- .on('blur', change)
- .on('change', change);
-
street
.call(d3.combobox()
.fetcher(function(value, callback) {
.fetcher(function(value, callback) {
callback(getPostCodes());
}));
+
+ wrap.selectAll('input')
+ .on('blur', change)
+ .on('change', change);
}
function change() {
iD.ui.preset.check =
iD.ui.preset.defaultcheck = function(field) {
var event = d3.dispatch('change'),
- values = field.type === 'check' ?
- [undefined, 'yes', 'no'] :
- [undefined, 'yes'],
- value,
- box,
- text,
- label;
+ options = field.strings && field.strings.options,
+ values = [],
+ texts = [],
+ entity, value, box, text, label;
+
+ if (options) {
+ for (var k in options) {
+ values.push(k === 'undefined' ? undefined : k);
+ texts.push(field.t('check.' + k, { 'default': options[k] }));
+ }
+ } else {
+ values = [undefined, 'yes'];
+ texts = [t('inspector.unknown'), t('inspector.check.yes')];
+ if (field.type === 'check') {
+ values.push('no');
+ texts.push(t('inspector.check.no'));
+ }
+ }
var check = function(selection) {
+ // hack: pretend oneway field is a oneway_yes field
+ // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841
+ if (field.id === 'oneway') {
+ for (var key in entity.tags) {
+ if (key in iD.oneWayTags && (entity.tags[key] in iD.oneWayTags[key])) {
+ texts.shift();
+ texts.unshift(t('presets.fields.oneway_yes.check.undefined', { 'default': 'Assumed to be Yes' }));
+ break;
+ }
+ }
+ }
+
selection.classed('checkselect', 'true');
label = selection.selectAll('.preset-input-wrap')
.attr('id', 'preset-input-' + field.id);
enter.append('span')
- .text(t('inspector.unknown'))
+ .text(texts[0])
.attr('class', 'value');
box = label.select('input')
text = label.select('span.value');
};
+ check.entity = function(_) {
+ if (!arguments.length) return entity;
+ entity = _;
+ return check;
+ };
+
check.tags = function(tags) {
value = tags[field.key];
box.property('indeterminate', field.type === 'check' && !value);
box.property('checked', value === 'yes');
- text.text(value ? t('inspector.check.' + value, {default: value}) :
- field.type === 'check' ? t('inspector.unknown') : t('inspector.check.no'));
+ text.text(texts[values.indexOf(value)]);
label.classed('set', !!value);
};
.attr('id', 'preset-input-' + field.id);
input
+ .call(combobox)
.on('change', change)
.on('blur', change)
.each(function() {
if (!err) options(_.pluck(data, 'value'));
});
}
- })
- .call(combobox);
+ });
function options(opts) {
combobox.data(opts.map(function(d) {
var o = {};
- o.title = o.value = d.replace('_', ' ');
+ o.title = o.value = d.replace(/_+/g, ' ');
return o;
}));
}
function change() {
- var value = input.value().replace(' ', '_');
+ var value = input.value()
+ .split(';')
+ .map(function(s) { return s.trim(); })
+ .join(';')
+ .replace(/\s+/g, '_');
+
if (field.type === 'typeCombo' && !value) value = 'yes';
var t = {};
.attr('class', 'localized-main')
.attr('placeholder', field.placeholder());
- input
- .on('blur', change)
- .on('change', change);
-
if (field.id === 'name') {
var preset = context.presets().match(entity, context.graph());
input.call(d3.combobox().fetcher(
));
}
+ input
+ .on('blur', change)
+ .on('change', change);
+
var translateButton = selection.selectAll('.localized-add')
.data([0]);
.attr('placeholder', field.placeholder());
input
+ .call(combobox)
.on('change', change)
- .on('blur', change)
- .call(combobox);
+ .on('blur', change);
var childNodes = context.graph().childNodes(context.entity(entity.id)),
loc = childNodes[~~(childNodes.length/2)].loc;
return d3.rebind(radio, event, 'on');
};
+iD.ui.preset.restrictions = function(field, context) {
+ var event = d3.dispatch('change'),
+ vertexID,
+ fromNodeID;
+
+ function restrictions(selection) {
+ var wrap = selection.selectAll('.preset-input-wrap')
+ .data([0]);
+
+ 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));
+
+ 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;
+
+ projection
+ .scale(256 * Math.pow(2, z) / (2 * Math.PI));
+
+ var s = projection(vertex.loc);
+
+ projection
+ .translate([c[0] - s[0], c[1] - s[1]])
+ .clipExtent([[0, 0], d]);
+
+ surface
+ .call(vertices, graph, [vertex], filter, extent, z)
+ .call(lines, graph, intersection.highways, filter)
+ .call(turns, graph, intersection.turns(fromNodeID));
+
+ surface
+ .on('click.restrictions', click)
+ .on('mouseover.restrictions', mouseover)
+ .on('mouseout.restrictions', mouseout);
+
+ surface
+ .selectAll('.selected')
+ .classed('selected', false);
+
+ if (fromNodeID) {
+ surface
+ .selectAll('.' + _.find(intersection.highways, function(way) { return way.contains(fromNodeID); }).id)
+ .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) {
+ fromNodeID = datum.nodes[(datum.first() === vertexID) ? 1 : datum.nodes.length - 2];
+ 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'));
+ }
+ }
+ }
+
+ function mouseover() {
+ var datum = d3.event.target.__data__;
+ if (datum instanceof iD.geo.Turn) {
+ var graph = context.graph(),
+ presets = context.presets(),
+ preset;
+
+ 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.' +
+ (fromNodeID ? 'toggle' : 'select')));
+ }
+
+ function render() {
+ if (context.hasEntity(vertexID)) {
+ restrictions(selection);
+ }
+ }
+ }
+
+ restrictions.entity = function(_) {
+ if (!vertexID || vertexID !== _.id) {
+ fromNodeID = null;
+ vertexID = _.id;
+ }
+ };
+
+ restrictions.tags = function() {};
+ restrictions.focus = function() {};
+
+ return d3.rebind(restrictions, event, 'on');
+};
iD.ui.preset.textarea = function(field) {
var event = d3.dispatch('change'),
.value('English');
lang
+ .call(langcombo)
.on('blur', changeLang)
- .on('change', changeLang)
- .call(langcombo);
+ .on('change', changeLang);
title = selection.selectAll('input.wiki-title')
.data([0]);
.attr('id', 'preset-input-' + field.id);
title
+ .call(titlecombo)
.on('blur', change)
- .on('change', change)
- .call(titlecombo);
+ .on('change', change);
link = selection.selectAll('a.wiki-link')
.data([0]);
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) {
"opening_hours"
]
},
+ "amenity/dojo": {
+ "icon": "pitch",
+ "geometry": [
+ "point",
+ "area"
+ ],
+ "terms": [
+ "martial arts",
+ "dojo",
+ "dojang"
+ ],
+ "tags": {
+ "amenity": "dojo"
+ },
+ "fields": [
+ "address",
+ "sport"
+ ],
+ "name": "Dojo / Martial Arts Academy"
+ },
"amenity/drinking_water": {
"icon": "water",
"geometry": [
"fields": [
"crossing",
"access",
- "surface"
+ "surface",
+ "sloped_curb",
+ "tactile_paving"
],
"geometry": [
"line"
"highway": "footway",
"footway": "crossing"
},
+ "terms": [],
+ "name": "Crossing"
+ },
+ "footway/crosswalk": {
+ "fields": [
+ "crossing",
+ "access",
+ "surface",
+ "sloped_curb",
+ "tactile_paving"
+ ],
+ "geometry": [
+ "line"
+ ],
+ "tags": {
+ "highway": "footway",
+ "footway": "crossing",
+ "crossing": "zebra"
+ },
"terms": [
"crosswalk",
"zebra crossing"
],
- "name": "Crossing"
+ "name": "Crosswalk"
},
"footway/sidewalk": {
"fields": [
"tags": {
"highway": "crossing"
},
+ "terms": [],
+ "name": "Crossing"
+ },
+ "highway/crosswalk": {
+ "fields": [
+ "crossing",
+ "sloped_curb",
+ "tactile_paving"
+ ],
+ "geometry": [
+ "vertex"
+ ],
+ "tags": {
+ "highway": "crossing",
+ "crossing": "zebra"
+ },
"terms": [
"crosswalk",
"zebra crossing"
],
- "name": "Crossing"
+ "name": "Crosswalk"
},
"highway/cycleway": {
"icon": "highway-cycleway",
"highway/motorway": {
"icon": "highway-motorway",
"fields": [
- "oneway",
+ "oneway_yes",
"maxspeed",
"structure",
"access",
"fields": [
"ref"
],
- "name": "Motorway Junction"
+ "name": "Motorway Junction / Exit"
},
"highway/motorway_link": {
"icon": "highway-motorway-link",
"name": "Slipway"
},
"leisure/sports_center": {
+ "icon": "pitch",
"geometry": [
"point",
"area"
"terms": [
"gym"
],
- "icon": "sports",
- "name": "Sports Center"
+ "fields": [
+ "sport"
+ ],
+ "name": "Sports Center / Gym"
},
"leisure/stadium": {
+ "icon": "pitch",
"geometry": [
"point",
"area"
"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-no-left-turn"
+ },
+ "type/restriction/no_right_turn": {
+ "name": "No Right Turn",
+ "geometry": [
+ "relation"
+ ],
+ "tags": {
+ "type": "restriction",
+ "restriction": "no_right_turn"
+ },
+ "fields": [
+ "except"
+ ],
+ "icon": "restriction-no-right-turn"
+ },
+ "type/restriction/no_straight_on": {
+ "name": "No Straight On",
+ "geometry": [
+ "relation"
+ ],
+ "tags": {
+ "type": "restriction",
+ "restriction": "no_straight_on"
+ },
+ "fields": [
+ "except"
+ ],
+ "icon": "restriction-no-straight-on"
+ },
+ "type/restriction/no_u_turn": {
+ "name": "No U-turn",
+ "geometry": [
+ "relation"
+ ],
+ "tags": {
+ "type": "restriction",
+ "restriction": "no_u_turn"
+ },
+ "fields": [
+ "except"
+ ],
+ "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_on": {
+ "name": "No Turns",
+ "geometry": [
+ "relation"
+ ],
+ "tags": {
+ "type": "restriction",
+ "restriction": "only_straight_on"
+ },
+ "fields": [
+ "except"
+ ],
+ "icon": "restriction-only-straight-on"
+ },
"type/route": {
"geometry": [
"relation"
],
"suggestion": true
},
- "amenity/fuel/Sainsbury's": {
- "tags": {
- "name": "Sainsbury's",
- "amenity": "fuel"
- },
- "name": "Sainsbury's",
- "icon": "fuel",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "address",
- "building_area"
- ],
- "suggestion": true
- },
"amenity/fuel/OMV": {
"tags": {
"name": "OMV",
],
"suggestion": true
},
- "amenity/fuel/Tesco": {
- "tags": {
- "name": "Tesco",
- "amenity": "fuel"
- },
- "name": "Tesco",
- "icon": "fuel",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "address",
- "building_area"
- ],
- "suggestion": true
- },
"amenity/fuel/JET": {
"tags": {
"name": "JET",
],
"suggestion": true
},
- "amenity/fuel/Morrisons": {
- "tags": {
- "name": "Morrisons",
- "amenity": "fuel"
- },
- "name": "Morrisons",
- "icon": "fuel",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "address",
- "building_area"
- ],
- "suggestion": true
- },
"amenity/fuel/United": {
"tags": {
"name": "United",
],
"suggestion": true
},
- "amenity/fuel/Canadian Tire": {
- "tags": {
- "name": "Canadian Tire",
- "amenity": "fuel"
- },
- "name": "Canadian Tire",
- "icon": "fuel",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "address",
- "building_area"
- ],
- "suggestion": true
- },
"amenity/fuel/Mobil": {
"tags": {
"name": "Mobil",
],
"suggestion": true
},
- "amenity/fuel/ABC": {
- "tags": {
- "name": "ABC",
- "amenity": "fuel"
- },
- "name": "ABC",
- "icon": "fuel",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "address",
- "building_area"
- ],
- "suggestion": true
- },
"amenity/fuel/ARAL": {
"tags": {
"name": "ARAL",
],
"suggestion": true
},
- "amenity/fuel/Intermarché": {
- "tags": {
- "name": "Intermarché",
- "amenity": "fuel"
- },
- "name": "Intermarché",
- "icon": "fuel",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "address",
- "building_area"
- ],
- "suggestion": true
- },
"amenity/fuel/Total Access": {
"tags": {
"name": "Total Access",
],
"suggestion": true
},
- "amenity/fuel/Super U": {
- "tags": {
- "name": "Super U",
- "amenity": "fuel"
- },
- "name": "Super U",
- "icon": "fuel",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "address",
- "building_area"
- ],
- "suggestion": true
- },
- "amenity/fuel/Auchan": {
- "tags": {
- "name": "Auchan",
- "amenity": "fuel"
- },
- "name": "Auchan",
- "icon": "fuel",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "address",
- "building_area"
- ],
- "suggestion": true
- },
"amenity/fuel/Elf": {
"tags": {
"name": "Elf",
],
"suggestion": true
},
- "amenity/fuel/Carrefour": {
- "tags": {
- "name": "Carrefour",
- "amenity": "fuel"
- },
- "name": "Carrefour",
- "icon": "fuel",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "address",
- "building_area"
- ],
- "suggestion": true
- },
"amenity/fuel/Station Service E. Leclerc": {
"tags": {
"name": "Station Service E. Leclerc",
],
"suggestion": true
},
- "amenity/fuel/Raiffeisenbank": {
- "tags": {
- "name": "Raiffeisenbank",
- "amenity": "fuel"
- },
- "name": "Raiffeisenbank",
- "icon": "fuel",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "address",
- "building_area"
- ],
- "suggestion": true
- },
"amenity/fuel/Tamoil": {
"tags": {
"name": "Tamoil",
],
"suggestion": true
},
- "amenity/fuel/Coop": {
- "tags": {
- "name": "Coop",
- "amenity": "fuel"
- },
- "name": "Coop",
- "icon": "fuel",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "address",
- "building_area"
- ],
- "suggestion": true
- },
"amenity/fuel/Orlen": {
"tags": {
"name": "Orlen",
],
"suggestion": true
},
- "amenity/fuel/7-Eleven": {
- "tags": {
- "name": "7-Eleven",
- "amenity": "fuel"
- },
- "name": "7-Eleven",
- "icon": "fuel",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "address",
- "building_area"
- ],
- "suggestion": true
- },
"amenity/fuel/Agrola": {
"tags": {
"name": "Agrola",
],
"suggestion": true
},
- "amenity/fuel/Wawa": {
- "tags": {
- "name": "Wawa",
- "amenity": "fuel"
- },
- "name": "Wawa",
- "icon": "fuel",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "address",
- "building_area"
- ],
- "suggestion": true
- },
"amenity/fuel/Pertamina": {
"tags": {
"name": "Pertamina",
],
"suggestion": true
},
- "amenity/fuel/Circle K": {
- "tags": {
- "name": "Circle K",
- "amenity": "fuel"
- },
- "name": "Circle K",
- "icon": "fuel",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "address",
- "building_area"
- ],
- "suggestion": true
- },
"amenity/fuel/Posto Ipiranga": {
"tags": {
"name": "Posto Ipiranga",
],
"suggestion": true
},
- "amenity/fuel/Stewart's": {
- "tags": {
- "name": "Stewart's",
- "amenity": "fuel"
- },
- "name": "Stewart's",
- "icon": "fuel",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "address",
- "building_area"
- ],
- "suggestion": true
- },
"amenity/fuel/Posto BR": {
"tags": {
"name": "Posto BR",
],
"suggestion": true
},
- "amenity/fuel/H-E-B": {
- "tags": {
- "name": "H-E-B",
- "amenity": "fuel"
- },
- "name": "H-E-B",
- "icon": "fuel",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "address",
- "building_area"
- ],
- "suggestion": true
- },
"amenity/fuel/Укрнафта": {
"tags": {
"name": "Укрнафта",
],
"suggestion": true
},
+ "amenity/fast_food/Subway": {
+ "tags": {
+ "name": "Subway",
+ "cuisine": "sandwich",
+ "amenity": "fast_food"
+ },
+ "name": "Subway",
+ "icon": "fast-food",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "cuisine",
+ "building_area",
+ "address",
+ "opening_hours",
+ "smoking"
+ ],
+ "suggestion": true
+ },
"amenity/fast_food/Burger King": {
"tags": {
"name": "Burger King",
],
"suggestion": true
},
+ "amenity/bank/Raiffeisenbank": {
+ "tags": {
+ "name": "Raiffeisenbank",
+ "amenity": "bank"
+ },
+ "name": "Raiffeisenbank",
+ "icon": "bank",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "atm",
+ "building_area",
+ "address",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"amenity/bank/Yorkshire Bank": {
"tags": {
"name": "Yorkshire Bank",
],
"suggestion": true
},
- "amenity/pharmacy/Радуга": {
- "tags": {
- "name": "Радуга",
- "amenity": "pharmacy"
- },
- "name": "Радуга",
- "icon": "pharmacy",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "building_area",
- "address",
- "opening_hours"
- ],
- "suggestion": true
- },
"amenity/pharmacy/サンドラッグ": {
"tags": {
"name": "サンドラッグ",
],
"suggestion": true
},
+ "shop/supermarket/Morrisons": {
+ "tags": {
+ "name": "Morrisons",
+ "shop": "supermarket"
+ },
+ "name": "Morrisons",
+ "icon": "grocery",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "operator",
+ "building_area",
+ "address"
+ ],
+ "suggestion": true
+ },
"shop/supermarket/Interspar": {
"tags": {
"name": "Interspar",
],
"suggestion": true
},
+ "shop/supermarket/Sainsbury's": {
+ "tags": {
+ "name": "Sainsbury's",
+ "shop": "supermarket"
+ },
+ "name": "Sainsbury's",
+ "icon": "grocery",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "operator",
+ "building_area",
+ "address"
+ ],
+ "suggestion": true
+ },
"shop/supermarket/Lidl": {
"tags": {
"name": "Lidl",
],
"suggestion": true
},
+ "shop/supermarket/Coop": {
+ "tags": {
+ "name": "Coop",
+ "shop": "supermarket"
+ },
+ "name": "Coop",
+ "icon": "grocery",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "operator",
+ "building_area",
+ "address"
+ ],
+ "suggestion": true
+ },
+ "shop/supermarket/Tesco": {
+ "tags": {
+ "name": "Tesco",
+ "shop": "supermarket"
+ },
+ "name": "Tesco",
+ "icon": "grocery",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "operator",
+ "building_area",
+ "address"
+ ],
+ "suggestion": true
+ },
"shop/supermarket/Woolworths": {
"tags": {
"name": "Woolworths",
],
"suggestion": true
},
- "shop/supermarket/Tesco Express": {
- "tags": {
- "name": "Tesco Express",
- "shop": "supermarket"
- },
- "name": "Tesco Express",
- "icon": "grocery",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "building_area",
- "address"
- ],
- "suggestion": true
- },
"shop/supermarket/King Soopers": {
"tags": {
"name": "King Soopers",
],
"suggestion": true
},
+ "shop/supermarket/Carrefour": {
+ "tags": {
+ "name": "Carrefour",
+ "shop": "supermarket"
+ },
+ "name": "Carrefour",
+ "icon": "grocery",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "operator",
+ "building_area",
+ "address"
+ ],
+ "suggestion": true
+ },
"shop/supermarket/Waitrose": {
"tags": {
"name": "Waitrose",
],
"suggestion": true
},
+ "shop/supermarket/Super U": {
+ "tags": {
+ "name": "Super U",
+ "shop": "supermarket"
+ },
+ "name": "Super U",
+ "icon": "grocery",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "operator",
+ "building_area",
+ "address"
+ ],
+ "suggestion": true
+ },
"shop/supermarket/Metro": {
"tags": {
"name": "Metro",
],
"suggestion": true
},
- "shop/supermarket/COOP Jednota": {
- "tags": {
- "name": "COOP Jednota",
- "shop": "supermarket"
- },
- "name": "COOP Jednota",
- "icon": "grocery",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "building_area",
- "address"
- ],
- "suggestion": true
- },
"shop/supermarket/Rema 1000": {
"tags": {
"name": "Rema 1000",
],
"suggestion": true
},
+ "shop/supermarket/Auchan": {
+ "tags": {
+ "name": "Auchan",
+ "shop": "supermarket"
+ },
+ "name": "Auchan",
+ "icon": "grocery",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "operator",
+ "building_area",
+ "address"
+ ],
+ "suggestion": true
+ },
"shop/supermarket/Mercadona": {
"tags": {
"name": "Mercadona",
],
"suggestion": true
},
- "shop/supermarket/Costcutter": {
- "tags": {
- "name": "Costcutter",
- "shop": "supermarket"
- },
- "name": "Costcutter",
- "icon": "grocery",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "building_area",
- "address"
- ],
- "suggestion": true
- },
"shop/supermarket/Maxi": {
"tags": {
"name": "Maxi",
],
"suggestion": true
},
+ "shop/supermarket/Intermarché": {
+ "tags": {
+ "name": "Intermarché",
+ "shop": "supermarket"
+ },
+ "name": "Intermarché",
+ "icon": "grocery",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "operator",
+ "building_area",
+ "address"
+ ],
+ "suggestion": true
+ },
"shop/supermarket/Delhaize": {
"tags": {
"name": "Delhaize",
],
"suggestion": true
},
- "shop/supermarket/dm": {
- "tags": {
- "name": "dm",
- "shop": "supermarket"
- },
- "name": "dm",
- "icon": "grocery",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "building_area",
- "address"
- ],
- "suggestion": true
- },
"shop/supermarket/Kvickly": {
"tags": {
"name": "Kvickly",
],
"suggestion": true
},
- "shop/supermarket/Petit Casino": {
- "tags": {
- "name": "Petit Casino",
- "shop": "supermarket"
- },
- "name": "Petit Casino",
- "icon": "grocery",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "building_area",
- "address"
- ],
- "suggestion": true
- },
"shop/supermarket/Wasgau": {
"tags": {
"name": "Wasgau",
],
"suggestion": true
},
- "shop/supermarket/Fressnapf": {
- "tags": {
- "name": "Fressnapf",
- "shop": "supermarket"
- },
- "name": "Fressnapf",
- "icon": "grocery",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "building_area",
- "address"
- ],
- "suggestion": true
- },
"shop/supermarket/Coop Konsum": {
"tags": {
"name": "Coop Konsum",
],
"suggestion": true
},
- "shop/supermarket/Centra": {
- "tags": {
- "name": "Centra",
- "shop": "supermarket"
- },
- "name": "Centra",
- "icon": "grocery",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "building_area",
- "address"
- ],
- "suggestion": true
- },
"shop/supermarket/Квартал": {
"tags": {
"name": "Квартал",
],
"suggestion": true
},
- "shop/supermarket/Атак": {
+ "shop/supermarket/H-E-B": {
"tags": {
- "name": "Атак",
+ "name": "H-E-B",
"shop": "supermarket"
},
- "name": "Атак",
+ "name": "H-E-B",
"icon": "grocery",
"geometry": [
"point",
],
"suggestion": true
},
- "shop/supermarket/Ð\9fолÑ\83Ñ\88ка": {
+ "shop/supermarket/Ð\90Ñ\82ак": {
"tags": {
- "name": "Ð\9fолÑ\83Ñ\88ка",
+ "name": "Ð\90Ñ\82ак",
"shop": "supermarket"
},
- "name": "Ð\9fолÑ\83Ñ\88ка",
+ "name": "Ð\90Ñ\82ак",
"icon": "grocery",
"geometry": [
"point",
],
"suggestion": true
},
- "shop/supermarket/Extra": {
+ "shop/supermarket/Полушка": {
"tags": {
- "name": "Extra",
+ "name": "Полушка",
"shop": "supermarket"
},
- "name": "Extra",
+ "name": "Полушка",
"icon": "grocery",
"geometry": [
"point",
],
"suggestion": true
},
- "shop/supermarket/Lewiatan": {
+ "shop/supermarket/Extra": {
"tags": {
- "name": "Lewiatan",
+ "name": "Extra",
"shop": "supermarket"
},
- "name": "Lewiatan",
+ "name": "Extra",
"icon": "grocery",
"geometry": [
"point",
],
"suggestion": true
},
- "shop/supermarket/Społem": {
- "tags": {
- "name": "Społem",
- "shop": "supermarket"
- },
- "name": "Społem",
- "icon": "grocery",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "building_area",
- "address"
- ],
- "suggestion": true
- },
"shop/supermarket/Bodega Aurrera": {
"tags": {
"name": "Bodega Aurrera",
],
"suggestion": true
},
- "shop/supermarket/Магазин": {
- "tags": {
- "name": "Магазин",
- "shop": "supermarket"
- },
- "name": "Магазин",
- "icon": "grocery",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "operator",
- "building_area",
- "address"
- ],
- "suggestion": true
- },
"shop/supermarket/Монетка": {
"tags": {
"name": "Монетка",
],
"suggestion": true
},
+ "shop/convenience/Tesco Express": {
+ "tags": {
+ "name": "Tesco Express",
+ "shop": "convenience"
+ },
+ "name": "Tesco Express",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/convenience/One Stop": {
"tags": {
"name": "One Stop",
],
"suggestion": true
},
+ "shop/convenience/7-Eleven": {
+ "tags": {
+ "name": "7-Eleven",
+ "shop": "convenience"
+ },
+ "name": "7-Eleven",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/convenience/Sale": {
"tags": {
"name": "Sale",
],
"suggestion": true
},
+ "shop/convenience/COOP Jednota": {
+ "tags": {
+ "name": "COOP Jednota",
+ "shop": "convenience"
+ },
+ "name": "COOP Jednota",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/convenience/Mac's": {
"tags": {
"name": "Mac's",
],
"suggestion": true
},
+ "shop/convenience/Costcutter": {
+ "tags": {
+ "name": "Costcutter",
+ "shop": "convenience"
+ },
+ "name": "Costcutter",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/convenience/Valintatalo": {
"tags": {
"name": "Valintatalo",
],
"suggestion": true
},
+ "shop/convenience/Circle K": {
+ "tags": {
+ "name": "Circle K",
+ "shop": "convenience"
+ },
+ "name": "Circle K",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/convenience/セブンイレブン": {
"tags": {
"name": "セブンイレブン",
],
"suggestion": true
},
+ "shop/convenience/Petit Casino": {
+ "tags": {
+ "name": "Petit Casino",
+ "shop": "convenience"
+ },
+ "name": "Petit Casino",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/convenience/Mace": {
"tags": {
"name": "Mace",
],
"suggestion": true
},
+ "shop/convenience/ABC": {
+ "tags": {
+ "name": "ABC",
+ "shop": "convenience"
+ },
+ "name": "ABC",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/convenience/ミニストップ": {
"tags": {
"name": "ミニストップ",
],
"suggestion": true
},
+ "shop/convenience/Магазин": {
+ "tags": {
+ "name": "Магазин",
+ "shop": "convenience"
+ },
+ "name": "Магазин",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/convenience/Гастроном": {
"tags": {
"name": "Гастроном",
],
"suggestion": true
},
+ "shop/convenience/Centra": {
+ "tags": {
+ "name": "Centra",
+ "shop": "convenience"
+ },
+ "name": "Centra",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/convenience/サークルK": {
"tags": {
"name": "サークルK",
],
"suggestion": true
},
+ "shop/convenience/Wawa": {
+ "tags": {
+ "name": "Wawa",
+ "shop": "convenience"
+ },
+ "name": "Wawa",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/convenience/Proxi": {
"tags": {
"name": "Proxi",
],
"suggestion": true
},
+ "shop/convenience/Społem": {
+ "tags": {
+ "name": "Społem",
+ "shop": "convenience"
+ },
+ "name": "Społem",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/convenience/Cumberland Farms": {
"tags": {
"name": "Cumberland Farms",
],
"suggestion": true
},
+ "shop/convenience/Kiosk": {
+ "tags": {
+ "name": "Kiosk",
+ "shop": "convenience"
+ },
+ "name": "Kiosk",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/convenience/24 часа": {
"tags": {
"name": "24 часа",
],
"suggestion": true
},
+ "shop/convenience/Stewart's": {
+ "tags": {
+ "name": "Stewart's",
+ "shop": "convenience"
+ },
+ "name": "Stewart's",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/convenience/Продукти": {
"tags": {
"name": "Продукти",
],
"suggestion": true
},
+ "shop/convenience/Радуга": {
+ "tags": {
+ "name": "Радуга",
+ "shop": "convenience"
+ },
+ "name": "Радуга",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/convenience/ローソンストア100": {
"tags": {
"name": "ローソンストア100",
],
"suggestion": true
},
+ "shop/convenience/Lewiatan": {
+ "tags": {
+ "name": "Lewiatan",
+ "shop": "convenience"
+ },
+ "name": "Lewiatan",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/convenience/Продуктовый магазин": {
"tags": {
"name": "Продуктовый магазин",
],
"suggestion": true
},
+ "shop/convenience/Boutique": {
+ "tags": {
+ "name": "Boutique",
+ "shop": "convenience"
+ },
+ "name": "Boutique",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/convenience/მარკეტი (Market)": {
"tags": {
"name": "მარკეტი (Market)",
],
"suggestion": true
},
+ "shop/chemist/dm": {
+ "tags": {
+ "name": "dm",
+ "shop": "chemist"
+ },
+ "name": "dm",
+ "icon": "chemist",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/chemist/Müller": {
"tags": {
"name": "Müller",
],
"suggestion": true
},
- "shop/car_repair/Peugeot": {
- "tags": {
- "name": "Peugeot",
- "shop": "car_repair"
- },
- "name": "Peugeot",
- "icon": "car",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "address",
- "building_area",
- "opening_hours"
- ],
- "suggestion": true
- },
"shop/car_repair/Kwik Fit": {
"tags": {
"name": "Kwik Fit",
],
"suggestion": true
},
- "shop/car_repair/Автозапчасти": {
- "tags": {
- "name": "Автозапчасти",
- "shop": "car_repair"
- },
- "name": "Автозапчасти",
- "icon": "car",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "address",
- "building_area",
- "opening_hours"
- ],
- "suggestion": true
- },
- "shop/car_repair/Renault": {
- "tags": {
- "name": "Renault",
- "shop": "car_repair"
- },
- "name": "Renault",
- "icon": "car",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "address",
- "building_area",
- "opening_hours"
- ],
- "suggestion": true
- },
"shop/car_repair/Pit Stop": {
"tags": {
"name": "Pit Stop",
],
"suggestion": true
},
- "shop/car_repair/Citroen": {
- "tags": {
- "name": "Citroen",
- "shop": "car_repair"
- },
- "name": "Citroen",
- "icon": "car",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "address",
- "building_area",
- "opening_hours"
- ],
- "suggestion": true
- },
"shop/car_repair/Euromaster": {
"tags": {
"name": "Euromaster",
],
"suggestion": true
},
+ "shop/doityourself/Canadian Tire": {
+ "tags": {
+ "name": "Canadian Tire",
+ "shop": "doityourself"
+ },
+ "name": "Canadian Tire",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/doityourself/Leroy Merlin": {
"tags": {
"name": "Leroy Merlin",
],
"suggestion": true
},
- "shop/doityourself/Хозтовары": {
- "tags": {
- "name": "Хозтовары",
- "shop": "doityourself"
- },
- "name": "Хозтовары",
- "icon": "shop",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "address",
- "building_area",
- "opening_hours"
- ],
- "suggestion": true
- },
"shop/doityourself/Стройматериалы": {
"tags": {
"name": "Стройматериалы",
],
"suggestion": true
},
+ "shop/car/Citroen": {
+ "tags": {
+ "name": "Citroen",
+ "shop": "car"
+ },
+ "name": "Citroen",
+ "icon": "car",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
+ "shop/car/Renault": {
+ "tags": {
+ "name": "Renault",
+ "shop": "car"
+ },
+ "name": "Renault",
+ "icon": "car",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/car/Mercedes-Benz": {
"tags": {
"name": "Mercedes-Benz",
],
"suggestion": true
},
+ "shop/car/Ford": {
+ "tags": {
+ "name": "Ford",
+ "shop": "car"
+ },
+ "name": "Ford",
+ "icon": "car",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/car/Volkswagen": {
"tags": {
"name": "Volkswagen",
],
"suggestion": true
},
+ "shop/car/Автозапчасти": {
+ "tags": {
+ "name": "Автозапчасти",
+ "shop": "car"
+ },
+ "name": "Автозапчасти",
+ "icon": "car",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/car/Opel": {
"tags": {
"name": "Opel",
],
"suggestion": true
},
+ "shop/car/Peugeot": {
+ "tags": {
+ "name": "Peugeot",
+ "shop": "car"
+ },
+ "name": "Peugeot",
+ "icon": "car",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/car/Hyundai": {
"tags": {
"name": "Hyundai",
],
"suggestion": true
},
- "shop/clothes/Deichmann": {
- "tags": {
- "name": "Deichmann",
- "shop": "clothes"
- },
- "name": "Deichmann",
- "icon": "clothing-store",
- "geometry": [
- "point",
- "vertex",
- "area"
- ],
- "fields": [
- "address",
- "building_area",
- "opening_hours"
- ],
- "suggestion": true
- },
"shop/clothes/Lindex": {
"tags": {
"name": "Lindex",
],
"suggestion": true
},
+ "shop/pet/Fressnapf": {
+ "tags": {
+ "name": "Fressnapf",
+ "shop": "pet"
+ },
+ "name": "Fressnapf",
+ "icon": "dog-park",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/pet/PetSmart": {
"tags": {
"name": "PetSmart",
],
"suggestion": true
},
+ "shop/shoes/Deichmann": {
+ "tags": {
+ "name": "Deichmann",
+ "shop": "shoes"
+ },
+ "name": "Deichmann",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/shoes/Reno": {
"tags": {
"name": "Reno",
],
"suggestion": true
},
+ "shop/hardware/Хозтовары": {
+ "tags": {
+ "name": "Хозтовары",
+ "shop": "hardware"
+ },
+ "name": "Хозтовары",
+ "icon": "shop",
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "fields": [
+ "address",
+ "building_area",
+ "opening_hours"
+ ],
+ "suggestion": true
+ },
"shop/motorcycle/Yamaha": {
"tags": {
"name": "Yamaha",
"point"
],
"vertex": [
- "highway/crossing",
+ "highway/crosswalk",
"railway/level_crossing",
"highway/traffic_signals",
"highway/turning_circle",
],
"relation": [
"category-route",
+ "category-restriction",
"type/boundary",
- "type/restriction",
"type/multipolygon",
"relation"
]
"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_on",
+ "type/restriction"
+ ]
+ },
"category-road": {
"geometry": "line",
"name": "Road",
"type": "typeCombo",
"label": "Type"
},
+ "except": {
+ "key": "except",
+ "type": "combo",
+ "label": "Exceptions"
+ },
"fax": {
"key": "fax",
"type": "tel",
"oneway": {
"key": "oneway",
"type": "check",
- "label": "One Way"
+ "label": "One Way",
+ "strings": {
+ "options": {
+ "undefined": "Assumed to be No",
+ "yes": "Yes",
+ "no": "No"
+ }
+ }
},
"oneway_yes": {
"key": "oneway",
"type": "check",
"default": "yes",
- "label": "One Way"
+ "label": "One Way",
+ "strings": {
+ "options": {
+ "undefined": "Assumed to be Yes",
+ "yes": "Yes",
+ "no": "No"
+ }
+ }
},
"opening_hours": {
"key": "opening_hours",
"type": "combo",
"label": "Type"
},
+ "restrictions": {
+ "type": "restrictions",
+ "geometry": "vertex",
+ "icon": "restrictions",
+ "reference": {
+ "rtype": "restriction"
+ },
+ "label": "Turn Restrictions"
+ },
"route": {
"key": "route",
"type": "combo",
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-on": {
+ "relation": [
+ 1220,
+ 25
+ ]
+ },
+ "restriction-only-left-turn": {
+ "relation": [
+ 1280,
+ 25
+ ]
+ },
+ "restriction-only-right-turn": {
+ "relation": [
+ 1340,
+ 25
+ ]
}
},
"operations": {
"icon-operation-disabled-continue": [
220,
160
+ ],
+ "icon-restriction-yes": [
+ 50,
+ 80
+ ],
+ "icon-restriction-no": [
+ 95,
+ 80
+ ],
+ "icon-restriction-only": [
+ 140,
+ 80
+ ],
+ "icon-restriction-yes-u": [
+ 185,
+ 80
+ ],
+ "icon-restriction-no-u": [
+ 230,
+ 80
+ ],
+ "icon-restriction-only-u": [
+ 275,
+ 80
]
},
"locales": [
},
"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"
+ }
}
},
"undo": {
"category-rail": {
"name": "Rail"
},
+ "category-restriction": {
+ "name": "Restriction"
+ },
"category-road": {
"name": "Road"
},
"entrance": {
"label": "Type"
},
+ "except": {
+ "label": "Exceptions"
+ },
"fax": {
"label": "Fax",
"placeholder": "+31 42 123 4567"
"label": "Type"
},
"oneway": {
- "label": "One Way"
+ "label": "One Way",
+ "options": {
+ "undefined": "Assumed to be No",
+ "yes": "Yes",
+ "no": "No"
+ }
},
"oneway_yes": {
- "label": "One Way"
+ "label": "One Way",
+ "options": {
+ "undefined": "Assumed to be Yes",
+ "yes": "Yes",
+ "no": "No"
+ }
},
"opening_hours": {
"label": "Hours"
"restriction": {
"label": "Type"
},
+ "restrictions": {
+ "label": "Turn Restrictions"
+ },
"route": {
"label": "Type"
},
"name": "Doctor",
"terms": "doctor,doctor's office"
},
+ "amenity/dojo": {
+ "name": "Dojo / Martial Arts Academy",
+ "terms": "martial arts,dojo,dojang"
+ },
"amenity/drinking_water": {
"name": "Drinking Water",
"terms": "water fountain,potable water"
},
"footway/crossing": {
"name": "Crossing",
+ "terms": ""
+ },
+ "footway/crosswalk": {
+ "name": "Crosswalk",
"terms": "crosswalk,zebra crossing"
},
"footway/sidewalk": {
},
"highway/crossing": {
"name": "Crossing",
+ "terms": ""
+ },
+ "highway/crosswalk": {
+ "name": "Crosswalk",
"terms": "crosswalk,zebra crossing"
},
"highway/cycleway": {
"terms": ""
},
"highway/motorway_junction": {
- "name": "Motorway Junction",
+ "name": "Motorway Junction / Exit",
"terms": ""
},
"highway/motorway_link": {
"terms": ""
},
"leisure/sports_center": {
- "name": "Sports Center",
+ "name": "Sports Center / Gym",
"terms": "gym"
},
"leisure/stadium": {
"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/restriction/only_left_turn": {
+ "name": "Left Turn Only",
+ "terms": ""
+ },
+ "type/restriction/only_right_turn": {
+ "name": "Right Turn Only",
+ "terms": ""
+ },
+ "type/restriction/only_straight_on": {
+ "name": "No Turns",
+ "terms": ""
+ },
"type/route": {
"name": "Route",
"terms": ""