diff --git a/js/id/actions/straighten.js b/js/id/actions/straighten.js index 3f61fb825..ea0190cb0 100644 --- a/js/id/actions/straighten.js +++ b/js/id/actions/straighten.js @@ -45,7 +45,7 @@ iD.actions.Straighten = function(wayId, projection) { return graph; }; - + action.disabled = function(graph) { // check way isn't too bendy var way = graph.entity(wayId), @@ -56,6 +56,10 @@ iD.actions.Straighten = function(wayId, projection) { threshold = 0.2 * Math.sqrt(Math.pow(startPoint[0] - endPoint[0], 2) + Math.pow(startPoint[1] - endPoint[1], 2)), i; + if (threshold === 0) { + return 'too_bendy'; + } + for (i = 1; i < points.length-1; i++) { var point = points[i], u = positionAlongWay(point, startPoint, endPoint), @@ -64,7 +68,7 @@ iD.actions.Straighten = function(wayId, projection) { dist = Math.sqrt(Math.pow(p0 - point[0], 2) + Math.pow(p1 - point[1], 2)); // to bendy if point is off by 20% of total start/end distance in projected space - if (dist > threshold) { + if (isNaN(dist) || dist > threshold) { return 'too_bendy'; } } diff --git a/test/spec/actions/straighten.js b/test/spec/actions/straighten.js index 8f43683c6..b373a5e89 100644 --- a/test/spec/actions/straighten.js +++ b/test/spec/actions/straighten.js @@ -1,6 +1,44 @@ describe("iD.actions.Straighten", function () { var projection = d3.geo.mercator(); + describe("#disabled", function () { + it("returns falsy for ways with internal nodes near centerline", function () { + var graph = iD.Graph([ + iD.Node({id: 'a', loc: [0, 0]}), + iD.Node({id: 'b', loc: [1, 0.1]}), + iD.Node({id: 'c', loc: [2, 0]}), + iD.Node({id: 'd', loc: [3, 0]}), + iD.Way({id: '-', nodes: ['a', 'b', 'c', 'd']}) + ]); + + expect(iD.actions.Straighten('-', projection).disabled(graph)).not.to.be.ok; + }); + + it("returns 'too_bendy' for ways with internal nodes far off centerline", function () { + var graph = iD.Graph([ + iD.Node({id: 'a', loc: [0, 0]}), + iD.Node({id: 'b', loc: [1, 1]}), + iD.Node({id: 'c', loc: [2, 0]}), + iD.Node({id: 'd', loc: [3, 0]}), + iD.Way({id: '-', nodes: ['a', 'b', 'c', 'd']}) + ]); + + expect(iD.actions.Straighten('-', projection).disabled(graph)).to.equal('too_bendy'); + }); + + it("returns 'too_bendy' for ways with coincident start/end nodes", function () { + var graph = iD.Graph([ + iD.Node({id: 'a', loc: [0, 0]}), + iD.Node({id: 'b', loc: [1, 0]}), + iD.Node({id: 'c', loc: [2, 0]}), + iD.Node({id: 'd', loc: [0, 0]}), + iD.Way({id: '-', nodes: ['a', 'b', 'c', 'd']}) + ]); + + expect(iD.actions.Straighten('-', projection).disabled(graph)).to.equal('too_bendy'); + }); + }); + it("deletes empty nodes", function() { var graph = iD.Graph([ iD.Node({id: 'a', loc: [0, 0]}), @@ -10,7 +48,7 @@ describe("iD.actions.Straighten", function () { ]); graph = iD.actions.Straighten('-', projection)(graph); - + expect(graph.hasEntity('b')).to.eq(undefined); }); @@ -23,10 +61,10 @@ describe("iD.actions.Straighten", function () { ]); graph = iD.actions.Straighten('-', projection)(graph); - + expect(graph.entity('-').nodes).to.eql(['a', 'b', 'c']); }); - + it("does not delete nodes connected to other ways", function() { var graph = iD.Graph([ iD.Node({id: 'a', loc: [0, 0]}), @@ -38,7 +76,7 @@ describe("iD.actions.Straighten", function () { ]); graph = iD.actions.Straighten('-', projection)(graph); - + expect(graph.entity('-').nodes).to.have.length(3); }); });