From 459dc00ce51c8d8868f7f8e98d19b687dd9ab7e4 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 30 Jan 2013 12:42:34 -0500 Subject: [PATCH 1/2] Change the midpoint data a bit Store the ways which share the segment and the index of the segment. This will be used in both DragWay and Draw behaviors. --- js/id/behavior/drag_midpoint.js | 34 ++++++++++----------- js/id/svg/midpoints.js | 20 ++++++------- test/index.html | 1 + test/index_packaged.html | 1 + test/spec/svg/midpoints.js | 52 +++++++++++++++++++++++++++++++++ 5 files changed, 79 insertions(+), 29 deletions(-) create mode 100644 test/spec/svg/midpoints.js diff --git a/js/id/behavior/drag_midpoint.js b/js/id/behavior/drag_midpoint.js index 9f73a7115..e0b0c7a1a 100644 --- a/js/id/behavior/drag_midpoint.js +++ b/js/id/behavior/drag_midpoint.js @@ -1,29 +1,26 @@ iD.behavior.DragMidpoint = function(mode) { var history = mode.history, - projection = mode.map.projection, - behavior = iD.behavior.drag() + projection = mode.map.projection; + + var behavior = iD.behavior.drag() .delegate(".midpoint") .origin(function(d) { return projection(d.loc); }) .on('start', function(d) { - var w, nds; - d.node = iD.Node({loc: d.loc}); - var args = [iD.actions.AddNode(d.node)]; - for (var i = 0; i < d.ways.length; i++) { - w = d.ways[i], nds = w.nodes; - for (var j = 0; j < nds.length; j++) { - if ((nds[j] === d.nodes[0] && nds[j + 1] === d.nodes[1]) || - (nds[j] === d.nodes[1] && nds[j + 1] === d.nodes[0])) { - args.push(iD.actions.AddWayNode(w.id, d.node.id, j + 1)); - } - } - } - history.perform.apply(history, args); - var node = d3.selectAll('.node.vertex') - .filter(function(data) { return data.id === d.node.id; }); - behavior.target(node.node(), node.datum()); + var node = iD.Node({loc: d.loc}); + var args = [iD.actions.AddNode(node)]; + for (var i = 0; i < d.ways.length; i++) { + args.push(iD.actions.AddWayNode(d.ways[i].id, node.id, d.ways[i].index)); + } + + history.perform.apply(history, args); + + var vertex = d3.selectAll('.vertex') + .filter(function(data) { return data.id === node.id; }); + + behavior.target(vertex.node(), vertex.datum()); }) .on('move', function(d) { d3.event.sourceEvent.stopPropagation(); @@ -35,5 +32,6 @@ iD.behavior.DragMidpoint = function(mode) { iD.actions.Noop(), 'added a node to a way'); }); + return behavior; }; diff --git a/js/id/svg/midpoints.js b/js/id/svg/midpoints.js index 655e35013..da4af659c 100644 --- a/js/id/svg/midpoints.js +++ b/js/id/svg/midpoints.js @@ -15,19 +15,17 @@ iD.svg.Midpoints = function(projection) { b = nodes[j + 1], id = [a.id, b.id].sort().join('-'); - if (!midpoints[id] && - iD.geo.dist(projection(a.loc), projection(b.loc)) > 40) { - - var midpoint_loc = iD.geo.interp(a.loc, b.loc, 0.5), - parents = _.intersection(graph.parentWays(a), - graph.parentWays(b)); + if (midpoints[id]) { + midpoints[id].ways.push({id: entity.id, index: j + 1}); + } else if (iD.geo.dist(projection(a.loc), projection(b.loc)) > 40) { midpoints[id] = { - loc: midpoint_loc, - ways: parents, - nodes: [a.id, b.id], + midpoint: true, id: id, - midpoint: true + loc: iD.geo.interp(a.loc, b.loc, 0.5), + a: a.id, + b: b.id, + ways: [{id: entity.id, index: j + 1}] }; } } @@ -35,7 +33,7 @@ iD.svg.Midpoints = function(projection) { var groups = surface.select('.layer-hit').selectAll('g.midpoint') .filter(filter) - .data(_.values(midpoints), function (d) { return [d.parents, d.id].join(","); }); + .data(_.values(midpoints), function (d) { return d.id; }); var group = groups.enter() .insert('g', ':first-child') diff --git a/test/index.html b/test/index.html index 4bdd4b5ba..97cd63b9b 100644 --- a/test/index.html +++ b/test/index.html @@ -170,6 +170,7 @@ + diff --git a/test/index_packaged.html b/test/index_packaged.html index 7ae72a056..25093d5b3 100644 --- a/test/index_packaged.html +++ b/test/index_packaged.html @@ -65,6 +65,7 @@ + diff --git a/test/spec/svg/midpoints.js b/test/spec/svg/midpoints.js new file mode 100644 index 000000000..c34ac0350 --- /dev/null +++ b/test/spec/svg/midpoints.js @@ -0,0 +1,52 @@ +describe("iD.svg.Midpoints", function () { + var surface, + projection = Object, + filter = d3.functor(true); + + beforeEach(function () { + surface = d3.select(document.createElementNS('http://www.w3.org/2000/svg', 'svg')) + .call(iD.svg.Surface()); + }); + + it("finds the location of the midpoints", function () { + var a = iD.Node({loc: [0, 0]}), + b = iD.Node({loc: [50, 0]}), + line = iD.Way({nodes: [a.id, b.id]}), + graph = iD.Graph([a, b, line]); + + surface.call(iD.svg.Midpoints(projection), graph, [line], filter); + + expect(surface.select('.midpoint').datum().loc).to.eql([25, 0]); + }); + + it("doesn't create midpoints on segments with pixel length less than 40", function () { + var a = iD.Node({loc: [0, 0]}), + b = iD.Node({loc: [39, 0]}), + line = iD.Way({nodes: [a.id, b.id]}), + graph = iD.Graph([a, b, line]); + + surface.call(iD.svg.Midpoints(projection), graph, [line], filter); + + expect(surface.selectAll('.midpoint')[0]).to.have.length(0); + }); + + it("binds a datum whose 'ways' property lists ways which include the segement", function () { + var a = iD.Node({loc: [0, 0]}), + b = iD.Node({loc: [50, 0]}), + c = iD.Node({loc: [1, 1]}), + d = iD.Node({loc: [2, 2]}), + l1 = iD.Way({nodes: [a.id, b.id]}), + l2 = iD.Way({nodes: [b.id, a.id]}), + l3 = iD.Way({nodes: [c.id, a.id, b.id, d.id]}), + l4 = iD.Way({nodes: [a.id, d.id, b.id]}), + graph = iD.Graph([a, b, c, d, l1, l2, l3, l4]), + ab = function (d) { return d.id === [a.id, b.id].sort().join("-"); }; + + surface.call(iD.svg.Midpoints(projection), graph, [l1, l2, l3, l4], filter); + + expect(surface.selectAll('.midpoint').filter(ab).datum().ways).to.eql([ + {id: l1.id, index: 1}, + {id: l2.id, index: 1}, + {id: l3.id, index: 2}]); + }); +}); From e381b6ab261b9d83875c7c2ad6edf92bbaa5e860 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 30 Jan 2013 15:44:21 -0500 Subject: [PATCH 2/2] Extract AddMidpoint action --- index.html | 1 + js/id/actions/add_midpoint.js | 11 +++++++++++ js/id/behavior/drag_midpoint.js | 9 ++------- test/index.html | 2 ++ test/index_packaged.html | 1 + test/spec/actions/add_midpoint.js | 22 ++++++++++++++++++++++ 6 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 js/id/actions/add_midpoint.js create mode 100644 test/spec/actions/add_midpoint.js diff --git a/index.html b/index.html index fae1fc940..5f62b0f8f 100644 --- a/index.html +++ b/index.html @@ -73,6 +73,7 @@ + diff --git a/js/id/actions/add_midpoint.js b/js/id/actions/add_midpoint.js new file mode 100644 index 000000000..c0cb97f59 --- /dev/null +++ b/js/id/actions/add_midpoint.js @@ -0,0 +1,11 @@ +iD.actions.AddMidpoint = function(midpoint, node) { + return function(graph) { + graph = graph.replace(node.move(midpoint.loc)); + + midpoint.ways.forEach(function(way) { + graph = graph.replace(graph.entity(way.id).addNode(node.id, way.index)); + }); + + return graph; + }; +}; diff --git a/js/id/behavior/drag_midpoint.js b/js/id/behavior/drag_midpoint.js index e0b0c7a1a..72691a512 100644 --- a/js/id/behavior/drag_midpoint.js +++ b/js/id/behavior/drag_midpoint.js @@ -8,14 +8,9 @@ iD.behavior.DragMidpoint = function(mode) { return projection(d.loc); }) .on('start', function(d) { - var node = iD.Node({loc: d.loc}); + var node = iD.Node(); - var args = [iD.actions.AddNode(node)]; - for (var i = 0; i < d.ways.length; i++) { - args.push(iD.actions.AddWayNode(d.ways[i].id, node.id, d.ways[i].index)); - } - - history.perform.apply(history, args); + history.perform(iD.actions.AddMidpoint(d, node)); var vertex = d3.selectAll('.vertex') .filter(function(data) { return data.id === node.id; }); diff --git a/test/index.html b/test/index.html index 97cd63b9b..731800f62 100644 --- a/test/index.html +++ b/test/index.html @@ -68,6 +68,7 @@ + @@ -137,6 +138,7 @@ + diff --git a/test/index_packaged.html b/test/index_packaged.html index 25093d5b3..aba99ba04 100644 --- a/test/index_packaged.html +++ b/test/index_packaged.html @@ -32,6 +32,7 @@ + diff --git a/test/spec/actions/add_midpoint.js b/test/spec/actions/add_midpoint.js new file mode 100644 index 000000000..1f749217e --- /dev/null +++ b/test/spec/actions/add_midpoint.js @@ -0,0 +1,22 @@ +describe("iD.actions.AddMidpoint", function () { + it("adds the node at the midpoint location", function () { + var node = iD.Node(), + midpoint = {loc: [1, 2], ways: []}, + graph = iD.actions.AddMidpoint(midpoint, node)(iD.Graph()); + + expect(graph.entity(node.id).loc).to.eql([1, 2]); + }); + + it("adds the node to all ways at the respective indexes", function () { + var node = iD.Node(), + a = iD.Node(), + b = iD.Node(), + w1 = iD.Way(), + w2 = iD.Way({nodes: [a.id, b.id]}), + midpoint = {loc: [1, 2], ways: [{id: w1.id, index: 0}, {id: w2.id, index: 1}]}, + graph = iD.actions.AddMidpoint(midpoint, node)(iD.Graph([a, b, w1, w2])); + + expect(graph.entity(w1.id).nodes).to.eql([node.id]); + expect(graph.entity(w2.id).nodes).to.eql([a.id, node.id, b.id]); + }); +});