diff --git a/js/id/actions/modes.js b/js/id/actions/modes.js index 73913476b..ace2a7e03 100644 --- a/js/id/actions/modes.js +++ b/js/id/actions/modes.js @@ -8,18 +8,6 @@ iD.modes._node = function(ll) { }); }; -iD.modes.chooseIndex = function(way, point, map) { - var dist = iD.util.geo.dist; - var projNodes = way.nodes.map(function(n) { - return map.projection([n.lon, n.lat]); - }); - for (var i = 0, changes = []; i < projNodes.length - 1; i++) { - changes[i] = - (dist(projNodes[i], point) + dist(point, projNodes[i + 1])) / - dist(projNodes[i], projNodes[i + 1]); - } - return _.indexOf(changes, _.min(changes)) + 1; -}; iD.modes.AddPlace = { id: 'add-place', @@ -114,7 +102,7 @@ iD.modes.AddRoad = { node = t.data()[0]; // snap into an existing way } else if (t.data() && t.data()[0] && t.data()[0].type === 'way') { - var index = iD.modes.chooseIndex(t.data()[0], d3.mouse(surface.node()), this.map); + var index = iD.util.geo.chooseIndex(t.data()[0], d3.mouse(surface.node()), this.map); node = iD.modes._node(this.map.projection.invert( d3.mouse(surface.node()))); var connectedWay = this.history.graph().entity(t.data()[0].id); diff --git a/js/id/util.js b/js/id/util.js index 4d297d2a7..08cf6a635 100644 --- a/js/id/util.js +++ b/js/id/util.js @@ -88,3 +88,16 @@ iD.util.geo.nodeIntersect = function(entity, extent) { entity.lat < extent[0][1] && entity.lat > extent[1][1]; }; + +iD.util.geo.chooseIndex = function(way, point, map) { + var dist = iD.util.geo.dist; + var projNodes = way.nodes.map(function(n) { + return map.projection([n.lon, n.lat]); + }); + for (var i = 0, changes = []; i < projNodes.length - 1; i++) { + changes[i] = + (dist(projNodes[i], point) + dist(point, projNodes[i + 1])) / + dist(projNodes[i], projNodes[i + 1]); + } + return _.indexOf(changes, _.min(changes)) + 1; +}; diff --git a/test/spec/util.js b/test/spec/util.js index 3ed2127d9..07968e7c7 100644 --- a/test/spec/util.js +++ b/test/spec/util.js @@ -22,16 +22,35 @@ describe('Util', function() { expect(iD.util.friendlyName({ tags: { name: 'hi', highway: 'Route 5' }})).to.equal('hi'); }); - describe('#interp', function() { - it('interpolates halfway', function() { - var a = { lat: 0, lon: 0 }, - b = { lat: 10, lon: 10 }; - expect(iD.util.geo.interp(a, b, 0.5)).to.eql({ lat: 5, lon: 5}); + describe('geo', function() { + describe('#interp', function() { + it('interpolates halfway', function() { + var a = { lat: 0, lon: 0 }, + b = { lat: 10, lon: 10 }; + expect(iD.util.geo.interp(a, b, 0.5)).to.eql({ lat: 5, lon: 5}); + }); + it('interpolates to one side', function() { + var a = { lat: 0, lon: 0 }, + b = { lat: 10, lon: 10 }; + expect(iD.util.geo.interp(a, b, 0)).to.eql({ lat: 0, lon: 0}); + }); }); - it('interpolates to one side', function() { - var a = { lat: 0, lon: 0 }, - b = { lat: 10, lon: 10 }; - expect(iD.util.geo.interp(a, b, 0)).to.eql({ lat: 0, lon: 0}); + describe('#dist', function() { + it('distance between two same points is zero', function() { + var a = [0, 0], + b = [0, 0]; + expect(iD.util.geo.dist(a, b)).to.eql(0); + }); + it('a straight 10 unit line is 10', function() { + var a = [0, 0], + b = [10, 0]; + expect(iD.util.geo.dist(a, b)).to.eql(10); + }); + it('a pythagorean triangle is right', function() { + var a = [0, 0], + b = [4, 3]; + expect(iD.util.geo.dist(a, b)).to.eql(5); + }); }); }); });