mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-15 13:38:26 +02:00
Replace Graph#fetch with Graph#childNodes
Having two kinds of Ways (fetched and non-fetched) introduced some accidental complexity. This brings things more in line with how parentWays/parentRelations work. Fixes #73.
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
iD.actions.Circular = function(wayId, map) {
|
||||
|
||||
var action = function(graph) {
|
||||
var way = graph.fetch(wayId),
|
||||
var way = graph.entity(wayId),
|
||||
nodes = graph.childNodes(way),
|
||||
tags = {}, key, role;
|
||||
|
||||
var points = way.nodes.map(function(n) {
|
||||
var points = nodes.map(function(n) {
|
||||
return map.projection(n.loc);
|
||||
}),
|
||||
centroid = d3.geom.polygon(points).centroid(),
|
||||
@@ -22,21 +23,21 @@ iD.actions.Circular = function(wayId, map) {
|
||||
|
||||
circular_nodes.push(circular_nodes[0]);
|
||||
|
||||
for (i = 0; i < way.nodes.length; i++) {
|
||||
if (graph.parentWays(way.nodes[i]).length > 1) {
|
||||
for (i = 0; i < nodes.length; i++) {
|
||||
if (graph.parentWays(nodes[i]).length > 1) {
|
||||
var closest, closest_dist = Infinity, dist;
|
||||
for (var j = 0; j < circular_nodes.length; j++) {
|
||||
dist = iD.geo.dist(circular_nodes[j].loc, way.nodes[i].loc);
|
||||
dist = iD.geo.dist(circular_nodes[j].loc, nodes[i].loc);
|
||||
if (dist < closest_dist) {
|
||||
closest_dist = dist;
|
||||
closest = j;
|
||||
}
|
||||
}
|
||||
circular_nodes.splice(closest, 1, way.nodes[i]);
|
||||
if (closest === 0) circular_nodes.splice(circular_nodes.length - 1, 1, way.nodes[i]);
|
||||
else if (closest === circular_nodes.length - 1) circular_nodes.splice(0, 1, way.nodes[i]);
|
||||
circular_nodes.splice(closest, 1, nodes[i]);
|
||||
if (closest === 0) circular_nodes.splice(circular_nodes.length - 1, 1, nodes[i]);
|
||||
else if (closest === circular_nodes.length - 1) circular_nodes.splice(0, 1, nodes[i]);
|
||||
} else {
|
||||
graph = graph.remove(way.nodes[i]);
|
||||
graph = graph.remove(nodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ iD.behavior.DragWay = function(mode) {
|
||||
return d && d.id === mode.entity.id;
|
||||
})
|
||||
.origin(function(entity) {
|
||||
return projection(entity.nodes[0].loc);
|
||||
return projection(history.graph().entity(entity.nodes[0]).loc);
|
||||
})
|
||||
.on('start', function() {
|
||||
history.perform(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
iD.format.GeoJSON = {
|
||||
mapping: function(entity) {
|
||||
mapping: function(entity, graph) {
|
||||
if (this.mappings[entity.type]) {
|
||||
return this.mappings[entity.type](entity);
|
||||
return this.mappings[entity.type](entity, graph);
|
||||
}
|
||||
},
|
||||
mappings: {
|
||||
@@ -15,15 +15,13 @@ iD.format.GeoJSON = {
|
||||
}
|
||||
};
|
||||
},
|
||||
way: function(entity) {
|
||||
way: function(entity, graph) {
|
||||
return {
|
||||
type: 'Feature',
|
||||
properties: entity.tags,
|
||||
geometry: {
|
||||
'type': 'LineString',
|
||||
'coordinates': entity.nodes.map(function(node) {
|
||||
return node.loc;
|
||||
})
|
||||
'coordinates': _.pluck(graph.childNodes(entity), 'loc')
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+2
-2
@@ -86,8 +86,8 @@ iD.format.XML = {
|
||||
var r = {
|
||||
way: {
|
||||
'@id': entity.id.replace('w', ''),
|
||||
nd: entity.nodes.map(function(e) {
|
||||
return { keyAttributes: { ref: e.id.replace('n', '') } };
|
||||
nd: entity.nodes.map(function(id) {
|
||||
return { keyAttributes: { ref: id.replace('n', '') } };
|
||||
}),
|
||||
'@version': (entity.version || 0),
|
||||
tag: _.map(entity.tags, function(v, k) {
|
||||
|
||||
+4
-4
@@ -16,9 +16,9 @@ iD.geo.dist = function(a, b) {
|
||||
|
||||
iD.geo.chooseIndex = function(way, point, map) {
|
||||
var dist = iD.geo.dist,
|
||||
projNodes = way.nodes.map(function(n) {
|
||||
return map.projection(n.loc);
|
||||
});
|
||||
graph = map.history().graph(),
|
||||
nodes = graph.childNodes(way),
|
||||
projNodes = nodes.map(function(n) { return map.projection(n.loc); });
|
||||
|
||||
for (var i = 0, changes = []; i < projNodes.length - 1; i++) {
|
||||
changes[i] =
|
||||
@@ -28,7 +28,7 @@ iD.geo.chooseIndex = function(way, point, map) {
|
||||
|
||||
var idx = _.indexOf(changes, _.min(changes)),
|
||||
ratio = dist(projNodes[idx], point) / dist(projNodes[idx], projNodes[idx + 1]),
|
||||
loc = iD.geo.interp(way.nodes[idx].loc, way.nodes[idx + 1].loc, ratio);
|
||||
loc = iD.geo.interp(nodes[idx].loc, nodes[idx + 1].loc, ratio);
|
||||
|
||||
return {
|
||||
index: idx + 1,
|
||||
|
||||
+14
-13
@@ -13,7 +13,7 @@ iD.Graph = function(entities, mutable) {
|
||||
this.transients = {};
|
||||
this._parentWays = {};
|
||||
this._parentRels = {};
|
||||
this._fetches = {};
|
||||
this._childNodes = {};
|
||||
|
||||
if (!mutable) {
|
||||
this.freeze();
|
||||
@@ -88,6 +88,18 @@ iD.Graph.prototype = {
|
||||
return this._parentRels[entity.id] || [];
|
||||
},
|
||||
|
||||
childNodes: function(entity) {
|
||||
if (this._childNodes[entity.id])
|
||||
return this._childNodes[entity.id];
|
||||
|
||||
var nodes = [];
|
||||
for (var i = 0, l = entity.nodes.length; i < l; i++) {
|
||||
nodes[i] = this.entity(entity.nodes[i]);
|
||||
}
|
||||
|
||||
return (this._childNodes[entity.id] = nodes);
|
||||
},
|
||||
|
||||
merge: function(graph) {
|
||||
for (var i in graph.entities) {
|
||||
this.original[i] = graph.entities[i];
|
||||
@@ -138,23 +150,12 @@ iD.Graph.prototype = {
|
||||
for (var i in this.entities) {
|
||||
var entity = this.entities[i];
|
||||
if (entity && entity.intersects(extent, this)) {
|
||||
items.push(this.fetch(entity.id));
|
||||
items.push(entity);
|
||||
}
|
||||
}
|
||||
return items;
|
||||
},
|
||||
|
||||
// Resolve the id references in a way, replacing them with actual objects.
|
||||
fetch: function(id) {
|
||||
if (this._fetches[id]) return this._fetches[id];
|
||||
var entity = this.entities[id], nodes = [];
|
||||
if (!entity || !entity.nodes || !entity.nodes.length) return entity;
|
||||
for (var i = 0, l = entity.nodes.length; i < l; i++) {
|
||||
nodes[i] = this.fetch(entity.nodes[i]);
|
||||
}
|
||||
return (this._fetches[id] = iD.Entity(entity, {nodes: nodes}));
|
||||
},
|
||||
|
||||
difference: function (graph) {
|
||||
var result = [],
|
||||
keys = Object.keys(this.entities),
|
||||
|
||||
@@ -99,13 +99,13 @@ iD.History = function() {
|
||||
|
||||
return {
|
||||
modified: current.modified().map(function (id) {
|
||||
return current.fetch(id);
|
||||
return current.entity(id);
|
||||
}),
|
||||
created: current.created().map(function (id) {
|
||||
return current.fetch(id);
|
||||
return current.entity(id);
|
||||
}),
|
||||
deleted: current.deleted().map(function (id) {
|
||||
return initial.fetch(id);
|
||||
return initial.entity(id);
|
||||
})
|
||||
};
|
||||
},
|
||||
|
||||
@@ -82,7 +82,7 @@ _.extend(iD.Relation.prototype, {
|
||||
multipolygon: function(resolver) {
|
||||
var members = this.members
|
||||
.filter(function (m) { return m.type === 'way' && resolver.entity(m.id); })
|
||||
.map(function (m) { return { role: m.role || 'outer', id: m.id, nodes: resolver.fetch(m.id).nodes }; });
|
||||
.map(function (m) { return { role: m.role || 'outer', id: m.id, nodes: resolver.childNodes(resolver.entity(m.id)) }; });
|
||||
|
||||
function join(ways) {
|
||||
var joined = [], current, first, last, i, how, what;
|
||||
|
||||
+3
-7
@@ -14,13 +14,9 @@ _.extend(iD.Way.prototype, {
|
||||
|
||||
extent: function(resolver) {
|
||||
return resolver.transient(this, 'extent', function() {
|
||||
var extent = iD.geo.Extent();
|
||||
for (var i = 0, l = this.nodes.length; i < l; i++) {
|
||||
var node = this.nodes[i];
|
||||
if (node.loc === undefined) node = resolver.entity(node);
|
||||
extent = extent.extend(node.loc);
|
||||
}
|
||||
return extent;
|
||||
return this.nodes.reduce(function (extent, id) {
|
||||
return extent.extend(resolver.entity(id).extent(resolver));
|
||||
}, iD.geo.Extent());
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ iD.Map = function() {
|
||||
for (var i = 0; i < parents.length; i++) {
|
||||
var parent = parents[i];
|
||||
if (only[parent.id] === undefined) {
|
||||
only[parent.id] = graph.fetch(parent.id);
|
||||
only[parent.id] = graph.entity(parent.id);
|
||||
addParents(graph.parentRelations(parent));
|
||||
}
|
||||
}
|
||||
@@ -78,7 +78,7 @@ iD.Map = function() {
|
||||
|
||||
for (var j = 0; j < difference.length; j++) {
|
||||
var id = difference[j],
|
||||
entity = graph.fetch(id);
|
||||
entity = graph.entity(id);
|
||||
|
||||
// Even if the entity is false (deleted), it needs to be
|
||||
// removed from the surface
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ iD.svg = {
|
||||
};
|
||||
},
|
||||
|
||||
LineString: function (projection) {
|
||||
LineString: function (projection, graph) {
|
||||
var cache = {};
|
||||
return function (entity) {
|
||||
if (cache[entity.id] !== undefined) {
|
||||
@@ -23,7 +23,7 @@ iD.svg = {
|
||||
}
|
||||
|
||||
return (cache[entity.id] =
|
||||
'M' + entity.nodes.map(function (n) { return projection(n.loc); }).join('L'));
|
||||
'M' + graph.childNodes(entity).map(function (n) { return projection(n.loc); }).join('L'));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ iD.svg.Areas = function(projection) {
|
||||
|
||||
areas.sort(areastack);
|
||||
|
||||
var lineString = iD.svg.LineString(projection);
|
||||
var lineString = iD.svg.LineString(projection, graph);
|
||||
|
||||
function drawPaths(group, areas, filter, classes) {
|
||||
var paths = group.selectAll('path.area')
|
||||
|
||||
+2
-2
@@ -257,7 +257,7 @@ iD.svg.Labels = function(projection) {
|
||||
}
|
||||
|
||||
function getLineLabel(entity, width, height) {
|
||||
var nodes = _.pluck(entity.nodes, 'loc').map(projection),
|
||||
var nodes = _.pluck(graph.childNodes(entity), 'loc').map(projection),
|
||||
length = iD.geo.pathLength(nodes);
|
||||
if (length < width + 20) return;
|
||||
|
||||
@@ -285,7 +285,7 @@ iD.svg.Labels = function(projection) {
|
||||
}
|
||||
|
||||
function getAreaLabel(entity, width, height) {
|
||||
var nodes = _.pluck(entity.nodes, 'loc')
|
||||
var nodes = _.pluck(graph.childNodes(entity), 'loc')
|
||||
.map(iD.svg.RoundProjection(projection)),
|
||||
centroid = d3.geom.polygon(nodes).centroid(),
|
||||
extent = entity.extent(graph),
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ iD.svg.Lines = function(projection) {
|
||||
|
||||
lines.sort(waystack);
|
||||
|
||||
var lineString = iD.svg.LineString(projection);
|
||||
var lineString = iD.svg.LineString(projection, graph);
|
||||
|
||||
var shadow = surface.select('.layer-shadow'),
|
||||
casing = surface.select('.layer-casing'),
|
||||
|
||||
@@ -8,12 +8,13 @@ iD.svg.Midpoints = function(projection) {
|
||||
if (entity.type !== 'way')
|
||||
continue;
|
||||
|
||||
for (var j = 0; j < entity.nodes.length - 1; j++) {
|
||||
var a = projection(entity.nodes[j].loc);
|
||||
var b = projection(entity.nodes[j + 1].loc);
|
||||
var nodes = graph.childNodes(entity);
|
||||
for (var j = 0; j < nodes.length - 1; j++) {
|
||||
var a = projection(nodes[j].loc);
|
||||
var b = projection(nodes[j + 1].loc);
|
||||
if (iD.geo.dist(a, b) > 40) {
|
||||
midpoints.push({
|
||||
loc: iD.geo.interp(entity.nodes[j].loc, entity.nodes[j + 1].loc, 0.5),
|
||||
loc: iD.geo.interp(nodes[j].loc, nodes[j + 1].loc, 0.5),
|
||||
way: entity.id,
|
||||
index: j + 1,
|
||||
midpoint: true
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@
|
||||
filter = d3.functor(true),
|
||||
a = iD.Node({loc: [15, 15]}),
|
||||
b = iD.Node({loc: [185, 15]}),
|
||||
way = iD.Way({nodes: [a, b]}),
|
||||
way = iD.Way({nodes: [a.id, b.id]}),
|
||||
vertices = iD.svg.Vertices(projection),
|
||||
lines = iD.svg.Lines(projection),
|
||||
midpoints = iD.svg.Midpoints(projection);
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
describe('iD.format.GeoJSON', function() {
|
||||
|
||||
describe('#mapping', function() {
|
||||
it('should be able to map a node to geojson', function() {
|
||||
expect(iD.format.GeoJSON.mapping({ type: 'node', loc: [-77, 38] }).geometry.type).to.equal('Point');
|
||||
it('converts a node to GeoJSON', function() {
|
||||
var node = iD.Node({loc: [-77, 38]}),
|
||||
graph = iD.Graph([node]);
|
||||
expect(iD.format.GeoJSON.mapping(node, graph).geometry.type).to.equal('Point');
|
||||
});
|
||||
it('should be able to map a way to geojson', function() {
|
||||
var way = { type: 'way', nodes: [] };
|
||||
var gj = iD.format.GeoJSON.mapping(way);
|
||||
expect(gj.type).to.equal('Feature');
|
||||
expect(gj.geometry.type).to.equal('LineString');
|
||||
|
||||
it('converts a way to GeoJSON', function() {
|
||||
var way = iD.Way(),
|
||||
graph = iD.Graph([way]),
|
||||
json = iD.format.GeoJSON.mapping(way, graph);
|
||||
expect(json.type).to.equal('Feature');
|
||||
expect(json.geometry.type).to.equal('LineString');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -129,12 +129,12 @@ describe('iD.Graph', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("#fetch", function () {
|
||||
it("replaces node ids with references", function () {
|
||||
describe("#childNodes", function () {
|
||||
it("returns an array of child nodes", function () {
|
||||
var node = iD.Node({id: "n1"}),
|
||||
way = iD.Way({id: "w1", nodes: ["n1"]}),
|
||||
graph = iD.Graph({n1: node, w1: way});
|
||||
expect(graph.fetch("w1").nodes).to.eql([node]);
|
||||
expect(graph.childNodes(way)).to.eql([node]);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+5
-3
@@ -2,16 +2,18 @@ describe("iD.svg.LineString", function () {
|
||||
it("returns an SVG path description for the entity's nodes", function () {
|
||||
var a = iD.Node({loc: [0, 0]}),
|
||||
b = iD.Node({loc: [2, 3]}),
|
||||
way = iD.Way({nodes: [a, b]}),
|
||||
way = iD.Way({nodes: [a.id, b.id]}),
|
||||
graph = iD.Graph([a, b, way]),
|
||||
projection = Object;
|
||||
|
||||
expect(iD.svg.LineString(projection)(way)).to.equal("M0,0L2,3");
|
||||
expect(iD.svg.LineString(projection, graph)(way)).to.equal("M0,0L2,3");
|
||||
});
|
||||
|
||||
it("returns null for an entity with no nodes", function () {
|
||||
var way = iD.Way(),
|
||||
graph = iD.Graph([way]),
|
||||
projection = Object;
|
||||
|
||||
expect(iD.svg.LineString(projection)(way)).to.be.null;
|
||||
expect(iD.svg.LineString(projection, graph)(way)).to.be.null;
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user