From d245121b1970a77e0dc198b81428daa3a1281f24 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Wed, 23 Apr 2014 14:12:20 -0400 Subject: [PATCH] Fix isConvex() to correctly test the angle that closes the way. --- js/id/core/way.js | 13 ++++++++---- test/spec/core/way.js | 47 ++++++++++++++++++++++++++++--------------- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/js/id/core/way.js b/js/id/core/way.js index 181691ea7..ff7416dc4 100644 --- a/js/id/core/way.js +++ b/js/id/core/way.js @@ -58,12 +58,17 @@ _.extend(iD.Way.prototype, { isConvex: function(resolver) { if (!this.isClosed() || this.isDegenerate()) return null; - var coords = _.pluck(resolver.childNodes(this), 'loc'), + var nodes = _.uniq(resolver.childNodes(this)), + coords = _.pluck(nodes, 'loc'), curr = 0, prev = 0; - for (var i = 1; i < coords.length - 1; i++) { - curr = iD.geo.cross(coords[i-1], coords[i], coords[i+1]); - curr = (curr > 0) ? 1 : (curr < 0) ? -1 : 0; + for (var i = 0; i < coords.length; i++) { + var o = coords[(i+1) % coords.length], + a = coords[i], + b = coords[(i+2) % coords.length], + res = iD.geo.cross(o, a, b); + + curr = (res > 0) ? 1 : (res < 0) ? -1 : 0; if (curr === 0) { continue; } else if (prev && curr !== prev) { diff --git a/test/spec/core/way.js b/test/spec/core/way.js index d9f29fee5..b253638c7 100644 --- a/test/spec/core/way.js +++ b/test/spec/core/way.js @@ -89,36 +89,51 @@ describe('iD.Way', function() { describe('#isConvex', function() { it('returns true for convex ways', function() { + // d -- e + // | \ + // | a + // | / + // c -- b var graph = iD.Graph([ - iD.Node({id: 'a', loc: [-0.0002, 0.0002]}), - iD.Node({id: 'b', loc: [ 0.0002, 0.0002]}), - iD.Node({id: 'c', loc: [ 0.0003, 0.0000]}), - iD.Node({id: 'd', loc: [ 0.0002, -0.0002]}), - iD.Node({id: 'e', loc: [-0.0002, -0.0002]}), + iD.Node({id: 'a', loc: [ 0.0003, 0.0000]}), + iD.Node({id: 'b', loc: [ 0.0002, -0.0002]}), + iD.Node({id: 'c', loc: [-0.0002, -0.0002]}), + iD.Node({id: 'd', loc: [-0.0002, 0.0002]}), + iD.Node({id: 'e', loc: [ 0.0002, 0.0002]}), iD.Way({id: 'w', nodes: ['a','b','c','d','e','a']}) ]); expect(graph.entity('w').isConvex(graph)).to.be.true; }); it('returns false for concave ways', function() { + // d -- e + // | / + // | a + // | \ + // c -- b var graph = iD.Graph([ - iD.Node({id: 'a', loc: [-0.0002, 0.0002]}), - iD.Node({id: 'b', loc: [ 0.0002, 0.0002]}), - iD.Node({id: 'c', loc: [ 0.0000, 0.0000]}), - iD.Node({id: 'd', loc: [ 0.0002, -0.0002]}), - iD.Node({id: 'e', loc: [-0.0002, -0.0002]}), + iD.Node({id: 'a', loc: [ 0.0000, 0.0000]}), + iD.Node({id: 'b', loc: [ 0.0002, -0.0002]}), + iD.Node({id: 'c', loc: [-0.0002, -0.0002]}), + iD.Node({id: 'd', loc: [-0.0002, 0.0002]}), + iD.Node({id: 'e', loc: [ 0.0002, 0.0002]}), iD.Way({id: 'w', nodes: ['a','b','c','d','e','a']}) ]); expect(graph.entity('w').isConvex(graph)).to.be.false; }); it('returns null for non-closed ways', function() { + // d -- e + // | + // | a + // | \ + // c -- b var graph = iD.Graph([ - iD.Node({id: 'a', loc: [-0.0002, 0.0002]}), - iD.Node({id: 'b', loc: [ 0.0002, 0.0002]}), - iD.Node({id: 'c', loc: [ 0.0000, 0.0000]}), - iD.Node({id: 'd', loc: [ 0.0002, -0.0002]}), - iD.Node({id: 'e', loc: [-0.0002, -0.0002]}), + iD.Node({id: 'a', loc: [ 0.0000, 0.0000]}), + iD.Node({id: 'b', loc: [ 0.0002, -0.0002]}), + iD.Node({id: 'c', loc: [-0.0002, -0.0002]}), + iD.Node({id: 'd', loc: [-0.0002, 0.0002]}), + iD.Node({id: 'e', loc: [ 0.0002, 0.0002]}), iD.Way({id: 'w', nodes: ['a','b','c','d','e']}) ]); expect(graph.entity('w').isConvex(graph)).to.be.null; @@ -126,7 +141,7 @@ describe('iD.Way', function() { it('returns null for degenerate ways', function() { var graph = iD.Graph([ - iD.Node({id: 'a', loc: [-0.0002, 0.0002]}), + iD.Node({id: 'a', loc: [0.0000, 0.0000]}), iD.Way({id: 'w', nodes: ['a','a']}) ]); expect(graph.entity('w').isConvex(graph)).to.be.null;