diff --git a/js/id/actions/actions.js b/js/id/actions/actions.js index e40ab5bc5..593e33d3f 100644 --- a/js/id/actions/actions.js +++ b/js/id/actions/actions.js @@ -61,12 +61,9 @@ iD.actions.changeTags = function(node, tags) { // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as -iD.actions.move = function(entity, to) { +iD.actions.move = function(entity, loc) { return function(graph) { - return graph.replace(entity.update({ - lon: to.lon || to[0], - lat: to.lat || to[1] - }), 'moved an element'); + return graph.replace(entity.update({loc: loc}), 'moved an element'); }; }; diff --git a/js/id/actions/modes.js b/js/id/actions/modes.js index e184aceb6..1ba422607 100644 --- a/js/id/actions/modes.js +++ b/js/id/actions/modes.js @@ -1,11 +1,7 @@ iD.modes = {}; iD.modes._node = function(ll) { - return iD.Node({ - lat: ll[1], - lon: ll[0], - tags: {} - }); + return iD.Node({loc: ll}); }; @@ -129,9 +125,7 @@ iD.modes.DrawRoad = function(way_id, direction) { function mousemove() { var ll = this.map.projection.invert(d3.mouse(surface.node())); - var node = iD.Entity(this.history.graph().entity(nextnode_id), { - lon: ll[0], lat: ll[1] - }); + var node = iD.Entity(this.history.graph().entity(nextnode_id), {loc: ll}); this.history.replace(iD.actions.addWayNode(way, node, index)); } @@ -265,10 +259,7 @@ iD.modes.DrawArea = function(way_id) { function mousemove() { var ll = this.map.projection.invert(d3.mouse(surface.node())); - var node = iD.Entity(this.history.graph().entity(nextnode_id), { - lon: ll[0], - lat: ll[1] - }); + var node = iD.Entity(this.history.graph().entity(nextnode_id), {loc: ll}); this.history.replace(iD.actions.addWayNode(way, node)); } diff --git a/js/id/connection.js b/js/id/connection.js index 07af7f442..432c052ab 100644 --- a/js/id/connection.js +++ b/js/id/connection.js @@ -62,8 +62,11 @@ iD.Connection = function() { var v = obj.attributes[i].nodeValue; o[n] = v; } - if (o.lat) o.lat = parseFloat(o.lat); - if (o.lon) o.lon = parseFloat(o.lon); + if (o.lon && o.lat) { + o.loc = [parseFloat(o.lon), parseFloat(o.lat)]; + delete o.lon; + delete o.lat; + } o._id = o.id; o.id = o.type[0] + o.id; return iD.Entity(o); diff --git a/js/id/format/geojson.js b/js/id/format/geojson.js index 5821fb550..cf859d9b1 100644 --- a/js/id/format/geojson.js +++ b/js/id/format/geojson.js @@ -11,7 +11,7 @@ iD.format.GeoJSON = { properties: entity.tags, geometry: { type: 'Point', - coordinates: [entity.lon, entity.lat] + coordinates: entity.loc } }; }, @@ -22,7 +22,7 @@ iD.format.GeoJSON = { geometry: { 'type': 'LineString', 'coordinates': entity.nodes.map(function(node) { - return [node.lon, node.lat]; + return node.loc; }) } }; diff --git a/js/id/format/xml.js b/js/id/format/xml.js index 16bc0942c..1c0fe8ad6 100644 --- a/js/id/format/xml.js +++ b/js/id/format/xml.js @@ -76,7 +76,8 @@ iD.format.XML = { var r = { node: { '@id': entity.id.replace('n', ''), - '@lat': entity.lat, '@lon': entity.lon, + '@lon': entity.loc[0], + '@lat': entity.loc[1], '@version': (entity.version || 0), tag: _.map(entity.tags, function(v, k) { return { keyAttributes: { k: k, v: v } }; diff --git a/js/id/graph/graph.js b/js/id/graph/graph.js index 5ef7daef1..c829f9a60 100644 --- a/js/id/graph/graph.js +++ b/js/id/graph/graph.js @@ -42,10 +42,10 @@ iD.Graph.prototype = { }, nodeIntersect: function(entity, extent) { - return entity.lon > extent[0][0] && - entity.lon < extent[1][0] && - entity.lat < extent[0][1] && - entity.lat > extent[1][1]; + return entity.loc[0] > extent[0][0] && + entity.loc[0] < extent[1][0] && + entity.loc[1] < extent[0][1] && + entity.loc[1] > extent[1][1]; }, wayIntersect: function(entity, extent) { @@ -61,10 +61,10 @@ iD.Graph.prototype = { var extent = [[-Infinity, Infinity], [Infinity, -Infinity]]; var w = way; for (var j = 0, l = w.nodes.length; j < l; j++) { - if (w.nodes[j].lon > extent[0][0]) extent[0][0] = w.nodes[j].lon; - if (w.nodes[j].lon < extent[1][0]) extent[1][0] = w.nodes[j].lon; - if (w.nodes[j].lat < extent[0][1]) extent[0][1] = w.nodes[j].lat; - if (w.nodes[j].lat > extent[1][1]) extent[1][1] = w.nodes[j].lat; + if (w.nodes[j].loc[0] > extent[0][0]) extent[0][0] = w.nodes[j].loc[0]; + if (w.nodes[j].loc[0] < extent[1][0]) extent[1][0] = w.nodes[j].loc[0]; + if (w.nodes[j].loc[1] < extent[0][1]) extent[0][1] = w.nodes[j].loc[1]; + if (w.nodes[j].loc[1] > extent[1][1]) extent[1][1] = w.nodes[j].loc[1]; } way._extent = extent; } diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js index a00327aa3..a247490ed 100644 --- a/js/id/renderer/map.js +++ b/js/id/renderer/map.js @@ -18,7 +18,7 @@ iD.Map = function() { dragbehavior = d3.behavior.drag() .origin(function(entity) { if (!dragEnabled) return { x: 0, y: 0 }; - var p = projection(ll2a(entity)); + var p = projection(entity.loc); return { x: p[0], y: p[1] }; }) .on('drag', function(entity) { @@ -47,7 +47,7 @@ iD.Map = function() { }), waydragbehavior = d3.behavior.drag() .origin(function(entity) { - var p = projection(ll2a(entity.nodes[0])); + var p = projection(entity.nodes[0].loc); return { x: p[0], y: p[1] }; }) .on('drag', function(entity) { @@ -62,10 +62,9 @@ iD.Map = function() { } entity.nodes.forEach(function(node) { - var start = projection(ll2a(node)); + var start = projection(node.loc); var end = projection.invert([start[0] + d3.event.dx, start[1] + d3.event.dy]); - node.lon = end[0]; - node.lat = end[1]; + node.loc = end; history.replace(iD.actions.move(node, end)); }); }) @@ -133,13 +132,12 @@ iD.Map = function() { map.surface = surface; } - function ll2a(o) { return [o.lon, o.lat]; } function pxCenter() { return [dimensions[0] / 2, dimensions[1] / 2]; } function classActive(d) { return d.id === selection; } function getline(d) { return d._line; } function key(d) { return d.id; } function nodeline(d) { - return 'M' + d.nodes.map(ll2a).map(projection).map(iD.util.geo.roundCoords).join('L'); + return 'M' + _.pluck(d.nodes, 'loc').map(projection).map(iD.util.geo.roundCoords).join('L'); } function hideInspector() { @@ -189,7 +187,8 @@ iD.Map = function() { function accuracyHandles(way) { var handles = []; for (var i = 0; i < way.nodes.length - 1; i++) { - handles[i] = iD.Node(iD.util.geo.interp(way.nodes[i], way.nodes[i + 1], 0.5)); + handles[i] = iD.Node(); + handles[i].loc = iD.util.geo.interp(way.nodes[i].loc, way.nodes[i + 1].loc, 0.5); handles[i].way = way.id; handles[i].index = i + 1; handles[i].accuracy = true; @@ -210,7 +209,7 @@ iD.Map = function() { .attr({ width: 6, height: 6, 'class': 'handle', 'xlink:href': 'css/handle.png' }) .call(dragbehavior); handles.attr('transform', function(entity) { - var p = projection(ll2a(entity)); + var p = projection(entity.loc); return 'translate(' + [~~p[0], ~~p[1]] + ') translate(-3, -3) rotate(45, 3, 3)'; }) .classed('active', classActive) @@ -225,7 +224,7 @@ iD.Map = function() { .attr({ r: 2, 'class': 'accuracy-handle' }) .call(dragbehavior); handles.attr('transform', function(entity) { - var p = projection(ll2a(entity)); + var p = projection(entity.loc); return 'translate(' + [~~p[0], ~~p[1]] + ')'; }).classed('active', classActive); } @@ -261,7 +260,7 @@ iD.Map = function() { marker.append('image') .attr({ width: 16, height: 16 }); markers.attr('transform', function(d) { - var pt = projection([d.lon, d.lat]); + var pt = projection(d.loc); return 'translate(' + [~~pt[0], ~~pt[1]] + ') translate(-8, -8)'; }) .classed('active', classActive); diff --git a/js/id/util.js b/js/id/util.js index 2c83d96b8..a39d2db75 100644 --- a/js/id/util.js +++ b/js/id/util.js @@ -79,10 +79,8 @@ iD.util.geo.roundCoords = function(c) { }; iD.util.geo.interp = function(p1, p2, t) { - return { - lon: p1.lon + (p2.lon - p1.lon) * t, - lat: p1.lat + (p2.lat - p1.lat) * t - }; + return [p1[0] + (p2[0] - p1[0]) * t, + p1[1] + (p2[1] - p1[1]) * t] }; iD.util.geo.dist = function(a, b) { @@ -91,16 +89,16 @@ iD.util.geo.dist = function(a, b) { }; iD.util.geo.nodeIntersect = function(entity, extent) { - return entity.lon > extent[0][0] && - entity.lon < extent[1][0] && - entity.lat < extent[0][1] && - entity.lat > extent[1][1]; + return entity.loc[0] > extent[0][0] && + entity.loc[0] < extent[1][0] && + entity.loc[1] < extent[0][1] && + entity.loc[1] > 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]); + return map.projection(n.loc); }); for (var i = 0, changes = []; i < projNodes.length - 1; i++) { changes[i] = diff --git a/test/spec/format/geojson.js b/test/spec/format/geojson.js index 6fb671756..f9b58f66f 100644 --- a/test/spec/format/geojson.js +++ b/test/spec/format/geojson.js @@ -2,7 +2,7 @@ describe('GeoJSON', function() { describe('#mapping', function() { it('should be able to map a node to geojson', function() { - expect(iD.format.GeoJSON.mapping({ type: 'node', lat: 38, lon: -77 }).geometry.type).to.equal('Point'); + expect(iD.format.GeoJSON.mapping({ type: 'node', loc: [-77, 38] }).geometry.type).to.equal('Point'); }); it('should be able to map a way to geojson', function() { var way = { type: 'way', nodes: [] }; diff --git a/test/spec/format/xml.js b/test/spec/format/xml.js index bd5181495..ac8143128 100644 --- a/test/spec/format/xml.js +++ b/test/spec/format/xml.js @@ -7,7 +7,7 @@ describe('XML', function() { describe('#rep', function() { it('converts a node to jxon', function() { - expect(iD.format.XML.rep({ id: 'n-1', type: 'node', lat: 38, lon: -77 })) + expect(iD.format.XML.rep({ id: 'n-1', type: 'node', loc: [-77, 38] })) .to.eql({ node : { '@id': '-1', '@lat': 38, '@lon': -77, '@version': 0, tag: [ ] } }); }); it('converts a way to jxon', function() { @@ -18,8 +18,8 @@ describe('XML', function() { describe('#mapping', function() { it('serializes a node to xml', function() { - expect(iD.format.XML.mapping({ id: 'n-1', type: 'node', lat: 38, lon: -77 })) - .to.equal('<node id="-1" lat="38" lon="-77" version="0"/>'); + expect(iD.format.XML.mapping({ id: 'n-1', type: 'node', loc: [-77, 38] })) + .to.equal('<node id="-1" lon="-77" lat="38" version="0"/>'); }); it('serializes a way to xml', function() { diff --git a/test/spec/graph/graph.js b/test/spec/graph/graph.js index 487bdd0f7..bd12753e0 100644 --- a/test/spec/graph/graph.js +++ b/test/spec/graph/graph.js @@ -4,8 +4,7 @@ describe('Graph', function() { it('entity', function() { var entities = { 'n-1': { type: 'node', - lat: 30, - lon: -80, + loc: [-80, 30], id: 'n-1' } }; @@ -23,8 +22,7 @@ describe('Graph', function() { it('#remove', function() { var entities = { 'n-1': { type: 'node', - lat: 30, - lon: -80, + loc: [-80, 30], id: 'n-1' } }; @@ -36,21 +34,19 @@ describe('Graph', function() { it('#replace', function() { var entities = { 'n-1': { type: 'node', - lat: 30, - lon: -80, + loc: [-80, 30], id: 'n-1' } }; var replacement = { type: 'node', - lat: 40, - lon: -80, + loc: [-80, 40], id: 'n-1' }; var graph = iD.Graph(entities, 'first graph'); var g2 = graph.replace(replacement, 'Removed node'); - expect(graph.entity('n-1').lat).to.equal(30); - expect(g2.entity('n-1').lat).to.equal(40); + expect(graph.entity('n-1').loc[1]).to.equal(30); + expect(g2.entity('n-1').loc[1]).to.equal(40); }); }); diff --git a/test/spec/util.js b/test/spec/util.js index 6c47a98aa..6cd2e62aa 100644 --- a/test/spec/util.js +++ b/test/spec/util.js @@ -25,26 +25,26 @@ describe('Util', function() { 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}); + var a = [0, 0], + b = [10, 10]; + expect(iD.util.geo.interp(a, b, 0.5)).to.eql([5, 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}); + var a = [0, 0], + b = [10, 10]; + expect(iD.util.geo.interp(a, b, 0)).to.eql([0, 0]); }); }); describe('#nodeIntersect', function() { it('correctly says that a node is in an extent', function() { expect(iD.util.geo.nodeIntersect({ - lat: 0, lon: 0 + loc: [0, 0] }, [[-180, 90], [180, -90]])).to.be.true; }); it('correctly says that a node is outside of an extent', function() { expect(iD.util.geo.nodeIntersect({ - lat: 0, lon: 0 + loc: [0, 0] }, [[100, 90], [180, -90]])).to.be.false; });