From e34ba10ade7522833dee5031e02c14c713c78370 Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Wed, 28 Nov 2012 18:23:44 -0500 Subject: [PATCH] Allow the beginning node of a way be an intersection with another way. This needs to be ported to drawway and addarea. Fixes #137 --- js/id/actions/modes.js | 26 ++++++++++++++++++++++++++ js/id/renderer/map.js | 11 +++++------ js/id/renderer/tiles.js | 4 +++- js/id/ui/inspector.js | 2 +- js/id/ui/loading.js | 2 +- 5 files changed, 36 insertions(+), 9 deletions(-) diff --git a/js/id/actions/modes.js b/js/id/actions/modes.js index da9dadb38..99ac888ad 100644 --- a/js/id/actions/modes.js +++ b/js/id/actions/modes.js @@ -75,6 +75,24 @@ iD.modes.AddRoad = { }); }); + // http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java#L431 + // https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/Way.as#L215 + var map = this.map; + function dist(a, b) { + return Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2)); + } + function chooseIndex(way, point) { + 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)); + } + function addRoad() { var t = d3.select(d3.event.target), node, @@ -83,6 +101,14 @@ iD.modes.AddRoad = { // connect a way to an existing way if (t.data() && t.data()[0] && t.data()[0].type === 'node') { node = t.data()[0]; + // snap into an existing way + } else if (t.data() && t.data()[0] && t.data()[0].type === 'way') { + var index = chooseIndex(t.data()[0], d3.mouse(surface.node())); + node = iD.modes._node(this.map.projection.invert( + d3.mouse(surface.node()))); + var connectedWay = this.map.history.graph().entity(t.data()[0].id); + connectedWay.nodes.splice(1, 0, node.id); + this.map.perform(iD.actions.addWayNode(connectedWay, node)); } else { node = iD.modes._node(this.map.projection.invert( d3.mouse(surface.node()))); diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js index b45d63e2e..c6ace627f 100644 --- a/js/id/renderer/map.js +++ b/js/id/renderer/map.js @@ -75,7 +75,6 @@ iD.Map = function(elem, connection) { class_stroke = iD.Style.styleClasses('stroke'), class_fill = iD.Style.styleClasses('stroke'), class_area = iD.Style.styleClasses('area'), - class_marker = iD.Style.styleClasses('marker'), class_casing = iD.Style.styleClasses('casing'), // For one-way roads, find the length of a triangle alength = (function() { @@ -237,9 +236,9 @@ iD.Map = function(elem, connection) { // Determine the lengths of oneway paths var lengths = {}; var oneways = strokes - .filter(function(d, i) { + .filter(function(d) { return d.tags.oneway && d.tags.oneway === 'yes'; - }).each(function(d, i) { + }).each(function(d) { lengths[d.id] = Math.floor(this.getTotalLength() / alength); }).data(); @@ -248,7 +247,7 @@ iD.Map = function(elem, connection) { uses.exit().remove(); uses.enter().append('path'); uses - .attr('id', function(d, i) { return 'shadow-' + d.id; }) + .attr('id', function(d) { return 'shadow-' + d.id; }) .attr('d', function(d) { return d._line; }); var labels = text_g.selectAll('text') @@ -264,7 +263,7 @@ iD.Map = function(elem, connection) { text_g.selectAll('.textpath') .attr('letter-spacing', alength * 2) .attr('xlink:href', function(d, i) { return '#shadow-' + d.id; }) - .text(function(d, i) { + .text(function(d) { return (new Array(Math.floor(lengths[d.id] / 2))).join('►'); }); } @@ -386,7 +385,7 @@ iD.Map = function(elem, connection) { }).on('remove', function(d) { map.perform(iD.actions.remove(d)); hideInspector(); - }).on('close', function(d) { + }).on('close', function() { deselectClick(); hideInspector(); }); diff --git a/js/id/renderer/tiles.js b/js/id/renderer/tiles.js index 527e9092d..765d1b499 100644 --- a/js/id/renderer/tiles.js +++ b/js/id/renderer/tiles.js @@ -25,7 +25,9 @@ iD.Tiles = function(selection, projection) { .translate(projection.translate())(); var image = selection - .attr("transform", function(d) { return "scale(" + tiles.scale + ")translate(" + tiles.translate + ")"; }) + .attr("transform", function() { + return "scale(" + tiles.scale + ")translate(" + tiles.translate + ")"; + }) .selectAll("image") .data(tiles, function(d) { return d; }); diff --git a/js/id/ui/inspector.js b/js/id/ui/inspector.js index 1718827b8..91643b92a 100644 --- a/js/id/ui/inspector.js +++ b/js/id/ui/inspector.js @@ -46,7 +46,7 @@ iD.Inspector = function() { event.close(entity); }); - var head = selection.append('div') + selection.append('div') .attr('class', 'head').call(drawhead); var table = selection diff --git a/js/id/ui/loading.js b/js/id/ui/loading.js index b858e80b6..99d2959a2 100644 --- a/js/id/ui/loading.js +++ b/js/id/ui/loading.js @@ -2,7 +2,7 @@ iD.loading = function(message) { var loading = d3.select('div.loading'); if (loading.empty()) loading = d3.select(document.body) .append('div').attr('class', 'loading shaded'); - var modal = loading.append('div') + loading.append('div') .attr('class', 'modal loading-pane') .text(message || '');