mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-25 15:05:32 +00:00
Multipolygon relations report their geometry as 'area' and are rendered as such. However, they do not render a stroke. The stroke rendering will come from the individual lines, which are given the tag classes of their parent relations, allowing them to have a stroke style matching the style of simple areas with the same tags. Untagged circular ways are no longer considered areas. This prevents an untagged inner way of a multipolygon from rendering as an area and is consistent with how P2 and JOSM treat them. In the CSS, it's no longer necessary to deal with multipolygons explicitly in selectors. But keep in mind that area boundaries can now be rendered either as lines or as area strokes. In most cases the selector should be `path.stroke.tag-_____`, i.e. an explicit `.area` or `.line` classes should not be included. Finally, the parent ways of selected multipolygons are given the 'selected' class.
128 lines
3.4 KiB
JavaScript
128 lines
3.4 KiB
JavaScript
iD.Way = iD.Entity.way = function iD_Way() {
|
|
if (!(this instanceof iD_Way)) {
|
|
return (new iD_Way()).initialize(arguments);
|
|
} else if (arguments.length) {
|
|
this.initialize(arguments);
|
|
}
|
|
};
|
|
|
|
iD.Way.prototype = Object.create(iD.Entity.prototype);
|
|
|
|
_.extend(iD.Way.prototype, {
|
|
type: "way",
|
|
nodes: [],
|
|
|
|
extent: function(resolver) {
|
|
return resolver.transient(this, 'extent', function() {
|
|
return this.nodes.reduce(function (extent, id) {
|
|
return extent.extend(resolver.entity(id).extent(resolver));
|
|
}, iD.geo.Extent());
|
|
});
|
|
},
|
|
|
|
first: function() {
|
|
return this.nodes[0];
|
|
},
|
|
|
|
last: function() {
|
|
return this.nodes[this.nodes.length - 1];
|
|
},
|
|
|
|
contains: function(node) {
|
|
return this.nodes.indexOf(node) >= 0;
|
|
},
|
|
|
|
isOneWay: function() {
|
|
return this.tags.oneway === 'yes';
|
|
},
|
|
|
|
isClosed: function() {
|
|
return this.nodes.length > 0 && this.first() === this.last();
|
|
},
|
|
|
|
// a way is an area if:
|
|
//
|
|
// - area=yes
|
|
// - closed and
|
|
// - doesn't have area=no
|
|
// - doesn't have highway tag
|
|
isArea: function() {
|
|
return this.tags.area === 'yes' ||
|
|
(this.isClosed() &&
|
|
!_.isEmpty(this.tags) &&
|
|
this.tags.area !== 'no' &&
|
|
!this.tags.highway &&
|
|
!this.tags.barrier);
|
|
},
|
|
|
|
isDegenerate: function() {
|
|
return _.uniq(this.nodes).length < (this.isArea() ? 3 : 2);
|
|
},
|
|
|
|
geometry: function() {
|
|
return this.isArea() ? 'area' : 'line';
|
|
},
|
|
|
|
addNode: function(id, index) {
|
|
var nodes = this.nodes.slice();
|
|
nodes.splice(index === undefined ? nodes.length : index, 0, id);
|
|
return this.update({nodes: nodes});
|
|
},
|
|
|
|
updateNode: function(id, index) {
|
|
var nodes = this.nodes.slice();
|
|
nodes.splice(index, 1, id);
|
|
return this.update({nodes: nodes});
|
|
},
|
|
|
|
removeNode: function(id) {
|
|
var nodes = _.without(this.nodes, id);
|
|
|
|
// Preserve circularity
|
|
if (this.nodes.length > 1 && this.first() === id && this.last() === id) {
|
|
nodes.push(nodes[0]);
|
|
}
|
|
|
|
return this.update({nodes: nodes});
|
|
},
|
|
|
|
asJXON: function(changeset_id) {
|
|
var r = {
|
|
way: {
|
|
'@id': this.osmId(),
|
|
'@version': this.version || 0,
|
|
nd: _.map(this.nodes, function(id) {
|
|
return { keyAttributes: { ref: iD.Entity.id.toOSM(id) } };
|
|
}),
|
|
tag: _.map(this.tags, function(v, k) {
|
|
return { keyAttributes: { k: k, v: v } };
|
|
})
|
|
}
|
|
};
|
|
if (changeset_id) r.way['@changeset'] = changeset_id;
|
|
return r;
|
|
},
|
|
|
|
asGeoJSON: function(resolver) {
|
|
if (this.isArea()) {
|
|
return {
|
|
type: 'Feature',
|
|
properties: this.tags,
|
|
geometry: {
|
|
type: 'Polygon',
|
|
coordinates: [_.pluck(resolver.childNodes(this), 'loc')]
|
|
}
|
|
};
|
|
} else {
|
|
return {
|
|
type: 'Feature',
|
|
properties: this.tags,
|
|
geometry: {
|
|
type: 'LineString',
|
|
coordinates: _.pluck(resolver.childNodes(this), 'loc')
|
|
}
|
|
};
|
|
}
|
|
}
|
|
});
|