diff --git a/modules/osm/node.js b/modules/osm/node.js index faad144a3..f72dbcae2 100644 --- a/modules/osm/node.js +++ b/modules/osm/node.js @@ -45,6 +45,16 @@ _.extend(osmNode.prototype, { }, + isEndpoint: function(resolver) { + return resolver.transient(this, 'isEndpoint', function() { + var id = this.id; + return resolver.parentWays(this).filter(function(parent) { + return !parent.isClosed() && !!parent.affix(id); + }).length > 0; + }); + }, + + isIntersection: function(resolver) { return resolver.transient(this, 'isIntersection', function() { return resolver.parentWays(this).filter(function(parent) { diff --git a/test/spec/osm/node.js b/test/spec/osm/node.js index 378624216..5465f4268 100644 --- a/test/spec/osm/node.js +++ b/test/spec/osm/node.js @@ -43,6 +43,30 @@ describe('iD.osmNode', function () { }); }); + describe('#isEndpoint', function () { + it('returns true for a node at an endpoint along a linear way', function () { + var a = iD.Node({id: 'a'}), + b = iD.Node({id: 'b'}), + c = iD.Node({id: 'c'}), + w = iD.Way({nodes: ['a', 'b', 'c']}), + graph = iD.Graph([a, b, c, w]); + expect(a.isEndpoint(graph)).to.equal(true, 'linear way, beginning node'); + expect(b.isEndpoint(graph)).to.equal(false, 'linear way, middle node'); + expect(c.isEndpoint(graph)).to.equal(true, 'linear way, ending node'); + }); + + it('returns false for nodes along a circular way', function () { + var a = iD.Node({id: 'a'}), + b = iD.Node({id: 'b'}), + c = iD.Node({id: 'c'}), + w = iD.Way({nodes: ['a', 'b', 'c', 'a']}), + graph = iD.Graph([a, b, c, w]); + expect(a.isEndpoint(graph)).to.equal(false, 'circular way, connector node'); + expect(b.isEndpoint(graph)).to.equal(false, 'circular way, middle node'); + expect(c.isEndpoint(graph)).to.equal(false, 'circular way, ending node'); + }); + }); + describe('#isIntersection', function () { it('returns true for a node shared by more than one highway', function () { var node = iD.Node(),