From 8b6bb964ad85dc710dd3fb6c725afba89f4add59 Mon Sep 17 00:00:00 2001 From: Dr Ian Date: Sat, 2 Feb 2013 23:52:16 +0100 Subject: [PATCH 01/10] Added orthogonalize function (square corners) --- index.html | 2 + js/id/actions/orthogonalize.js | 132 ++++++++++++++++++++++++++++++ js/id/operations/orthogonalize.js | 25 ++++++ locale/en.js | 9 ++ 4 files changed, 168 insertions(+) create mode 100644 js/id/actions/orthogonalize.js create mode 100644 js/id/operations/orthogonalize.js diff --git a/index.html b/index.html index d8be52dcd..adfe92752 100644 --- a/index.html +++ b/index.html @@ -85,6 +85,7 @@ + @@ -112,6 +113,7 @@ + diff --git a/js/id/actions/orthogonalize.js b/js/id/actions/orthogonalize.js new file mode 100644 index 000000000..c0a9d64ed --- /dev/null +++ b/js/id/actions/orthogonalize.js @@ -0,0 +1,132 @@ +iD.actions.Orthogonalize = function(wayId, map) { + + var action = function(graph) { + var way = graph.entity(wayId), + nodes = graph.childNodes(way), + tags = {},key,role; + + var points = nodes.map(function(n) { + return map.projection(n.loc); + }), + quad_nodes = []; + + var score = squareness(); + for (var i = 0; i < 1000; ++i) { + var motions = points.map(stepMap); + //return false; + for (var j = 0; j < motions.length; ++j) { + points[j] = addPoints(points[j],motions[j]); + } + var newScore = squareness(); + if (newScore > score) { + return false; + } + score = newScore; + if (score < 1.0e-8) { + break; + } + } + for (var i = 0; i < points.length; i++) { + quad_nodes.push(iD.Node({ loc: map.projection.invert(points[i]) })); + } + quad_nodes.push(quad_nodes[0]); + + for (var i = 0; i < nodes.length; i++) { + graph = graph.remove(nodes[i]); + } + + for (var i = 0; i < quad_nodes.length; i++) { + graph = graph.replace(quad_nodes[i]); + } + + return graph.replace(way.update({ + nodes: _.pluck(quad_nodes, 'id') + })); + + + function stepMap(b,i,array){ + var a,c,p,q = []; + a = array[(i-1+array.length) % array.length]; + c = array[(i+1) % array.length]; + p = subtractPoints(a,b); + q = subtractPoints(c,b); + + + var scale = p.length + q.length; + p = normalizePoint(p,1.0); + q = normalizePoint(q,1.0); + var dotp = p[0]*q[0] + p[1]*q[1]; + // nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270). + if (dotp < -0.707106781186547) { + dotp += 1.0; + } + var v = []; + v = addPoints(p,q); + v = normalizePoint(v,0.1 * dotp * scale); + return v; + } + + function squareness(){ + + var g = 0.0; + for (var i = 1; i < points.length - 1; i++) { + var score = scoreOfPoints(points[i-1], points[i], points[i+1]); + g += score; + } + var startScore = scoreOfPoints(points[points.length-1], points[0], points[1]); + var endScore = scoreOfPoints(points[points.length-2], points[points.length-1], points[0]); + g += startScore; + g += endScore; + return g; + } + + function scoreOfPoints(a, b, c) { + var p,q = []; + p = subtractPoints(a,b); + q = subtractPoints(c,b); + + p = normalizePoint(p,1.0); + q = normalizePoint(q,1.0); + + var dotp = p[0]*q[0] + p[1]*q[1]; + // score is constructed so that +1, -1 and 0 are all scored 0, any other angle + // is scored higher. + var score = 2.0 * Math.min(Math.abs(dotp-1.0), Math.min(Math.abs(dotp), Math.abs(dotp+1))); + return score; + } + + function subtractPoints(a,b){ + var vector = [0,0]; + vector[0] = a[0]-b[0]; + vector[1] = a[1]-b[1]; + return vector; + } + + function addPoints(a,b){ + var vector = [0,0]; + vector[0] = a[0]+b[0]; + vector[1] = a[1]+b[1]; + return vector; + } + + function normalizePoint(point,thickness){ + var vector = [0,0]; + var length = Math.sqrt( point[0] * point[0] + point[1] * point[1]); + if(length != 0){ + vector[0] = point[0]/length; + vector[1] = point[1]/length; + } + + vector[0] *= thickness; + vector[1] *= thickness; + + return vector; + } + }; + + action.enabled = function(graph) { + return graph.entity(wayId).isClosed(); + }; + + return action; +}; diff --git a/js/id/operations/orthogonalize.js b/js/id/operations/orthogonalize.js new file mode 100644 index 000000000..888d0015e --- /dev/null +++ b/js/id/operations/orthogonalize.js @@ -0,0 +1,25 @@ +iD.operations.Orthogonalize = function(selection, context) { + var entityId = selection[0], + action = iD.actions.Orthogonalize(entityId, context.map()); + + var operation = function() { + var annotation = t('operations.orthogonalize.annotation.' + context.geometry(entityId)); + context.perform(action, annotation); + }; + + operation.available = function() { + return selection.length === 1 && + context.entity(entityId).type === 'way'; + }; + + operation.enabled = function() { + return action.enabled(context.graph()); + }; + + operation.id = "orthogonalize"; + operation.key = t('operations.orthogonalize.key'); + operation.title = t('operations.orthogonalize.title'); + operation.description = t('operations.orthogonalize.description'); + + return operation; +}; diff --git a/locale/en.js b/locale/en.js index 866c7eca3..31d6a13de 100644 --- a/locale/en.js +++ b/locale/en.js @@ -65,6 +65,15 @@ locale.en = { area: "Made an area circular." } }, + orthogonalize: { + title: "Orthogonalize", + description: "Square these corners.", + key: "Q", + annotation: { + line: "Squared the corners of a line.", + area: "Squared the corners of an area." + } + }, delete: { title: "Delete", description: "Remove this from the map.", From 26b8b8789e1415c0e3adca277deb2131c929ca28 Mon Sep 17 00:00:00 2001 From: Dr Ian Date: Sun, 3 Feb 2013 00:05:11 +0100 Subject: [PATCH 02/10] Fix case where parentnodes present --- js/id/actions/orthogonalize.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/js/id/actions/orthogonalize.js b/js/id/actions/orthogonalize.js index c0a9d64ed..80c6a12c8 100644 --- a/js/id/actions/orthogonalize.js +++ b/js/id/actions/orthogonalize.js @@ -19,7 +19,7 @@ iD.actions.Orthogonalize = function(wayId, map) { } var newScore = squareness(); if (newScore > score) { - return false; + return graph; } score = newScore; if (score < 1.0e-8) { @@ -31,8 +31,22 @@ iD.actions.Orthogonalize = function(wayId, map) { } quad_nodes.push(quad_nodes[0]); - for (var i = 0; i < nodes.length; i++) { + for (i = 0; i < nodes.length; i++) { + if (graph.parentWays(nodes[i]).length > 1) { + var closest, closest_dist = Infinity, dist; + for (var j = 0; j < quad_nodes.length; j++) { + dist = iD.geo.dist(quad_nodes[j].loc, nodes[i].loc); + if (dist < closest_dist) { + closest_dist = dist; + closest = j; + } + } + quad_nodes.splice(closest, 1, nodes[i]); + if (closest === 0) quad_nodes.splice(quad_nodes.length - 1, 1, nodes[i]); + else if (closest === quad_nodes.length - 1) quad_nodes.splice(0, 1, nodes[i]); + } else { graph = graph.remove(nodes[i]); + } } for (var i = 0; i < quad_nodes.length; i++) { From b912097ee42fc540be636542c03be88b235a8f7d Mon Sep 17 00:00:00 2001 From: Dr Ian Date: Sun, 3 Feb 2013 08:17:03 +0100 Subject: [PATCH 03/10] Tidy up: fix indents, spaces etc. - Update orthogonalize to match new circularize. - Add orthoganalize to test index.html - Revert whitespace on index.html --- js/id/actions/orthogonalize.js | 109 ++++++++++++++---------------- js/id/operations/orthogonalize.js | 2 +- test/index.html | 2 + 3 files changed, 54 insertions(+), 59 deletions(-) diff --git a/js/id/actions/orthogonalize.js b/js/id/actions/orthogonalize.js index 80c6a12c8..830d1a1eb 100644 --- a/js/id/actions/orthogonalize.js +++ b/js/id/actions/orthogonalize.js @@ -1,20 +1,18 @@ -iD.actions.Orthogonalize = function(wayId, map) { +iD.actions.Orthogonalize = function(wayId, projection) { var action = function(graph) { var way = graph.entity(wayId), - nodes = graph.childNodes(way), - tags = {},key,role; + nodes = graph.childNodes(way); var points = nodes.map(function(n) { - return map.projection(n.loc); - }), - quad_nodes = []; + return projection(n.loc); + }), + quad_nodes = []; var score = squareness(); - for (var i = 0; i < 1000; ++i) { + for (var i = 0; i < 1000; i++) { var motions = points.map(stepMap); - //return false; - for (var j = 0; j < motions.length; ++j) { + for (var j = 0; j < motions.length; j++) { points[j] = addPoints(points[j],motions[j]); } var newScore = squareness(); @@ -26,10 +24,9 @@ iD.actions.Orthogonalize = function(wayId, map) { break; } } - for (var i = 0; i < points.length; i++) { - quad_nodes.push(iD.Node({ loc: map.projection.invert(points[i]) })); + for (i = 0; i < points.length - 1; i++) { + quad_nodes.push(iD.Node({ loc: projection.invert(points[i]) })); } - quad_nodes.push(quad_nodes[0]); for (i = 0; i < nodes.length; i++) { if (graph.parentWays(nodes[i]).length > 1) { @@ -42,93 +39,89 @@ iD.actions.Orthogonalize = function(wayId, map) { } } quad_nodes.splice(closest, 1, nodes[i]); - if (closest === 0) quad_nodes.splice(quad_nodes.length - 1, 1, nodes[i]); - else if (closest === quad_nodes.length - 1) quad_nodes.splice(0, 1, nodes[i]); - } else { - graph = graph.remove(nodes[i]); } } - for (var i = 0; i < quad_nodes.length; i++) { - graph = graph.replace(quad_nodes[i]); + for (i = 0; i < quad_nodes.length; i++) { + graph = graph.replace(quad_nodes[i]); } - return graph.replace(way.update({ - nodes: _.pluck(quad_nodes, 'id') - })); + var ids = _.pluck(quad_nodes, 'id'), + difference = _.difference(_.uniq(way.nodes), ids); + ids.push(ids[0]); - function stepMap(b,i,array){ - var a,c,p,q = []; - a = array[(i-1+array.length) % array.length]; - c = array[(i+1) % array.length]; - p = subtractPoints(a,b); - q = subtractPoints(c,b); + graph = graph.replace(way.update({nodes: ids})); + for (i = 0; i < difference.length; i++) { + graph = iD.actions.DeleteNode(difference[i])(graph); + } + + return graph; + + function stepMap(b, i, array) { + var a, c, p, q = []; + a = array[(i - 1 + array.length) % array.length]; + c = array[(i + 1) % array.length]; + p = subtractPoints(a, b); + q = subtractPoints(c, b); var scale = p.length + q.length; - p = normalizePoint(p,1.0); - q = normalizePoint(q,1.0); - var dotp = p[0]*q[0] + p[1]*q[1]; + p = normalizePoint(p, 1.0); + q = normalizePoint(q, 1.0); + var dotp = p[0] *q[0] + p[1] *q[1]; // nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270). if (dotp < -0.707106781186547) { dotp += 1.0; } var v = []; - v = addPoints(p,q); - v = normalizePoint(v,0.1 * dotp * scale); + v = addPoints(p, q); + v = normalizePoint(v, 0.1 * dotp * scale); return v; } - function squareness(){ + function squareness() { var g = 0.0; for (var i = 1; i < points.length - 1; i++) { - var score = scoreOfPoints(points[i-1], points[i], points[i+1]); + var score = scoreOfPoints(points[i - 1], points[i], points[i + 1]); g += score; } - var startScore = scoreOfPoints(points[points.length-1], points[0], points[1]); - var endScore = scoreOfPoints(points[points.length-2], points[points.length-1], points[0]); + var startScore = scoreOfPoints(points[points.length - 1], points[0], points[1]); + var endScore = scoreOfPoints(points[points.length - 2], points[points.length - 1], points[0]); g += startScore; g += endScore; return g; } function scoreOfPoints(a, b, c) { - var p,q = []; - p = subtractPoints(a,b); - q = subtractPoints(c,b); + var p, q = []; + p = subtractPoints(a, b); + q = subtractPoints(c, b); + p = normalizePoint(p, 1.0); + q = normalizePoint(q, 1.0); - p = normalizePoint(p,1.0); - q = normalizePoint(q,1.0); - - var dotp = p[0]*q[0] + p[1]*q[1]; + var dotp = p[0] * q[0] + p[1] * q[1]; // score is constructed so that +1, -1 and 0 are all scored 0, any other angle // is scored higher. - var score = 2.0 * Math.min(Math.abs(dotp-1.0), Math.min(Math.abs(dotp), Math.abs(dotp+1))); + var score = 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1))); return score; } - function subtractPoints(a,b){ - var vector = [0,0]; - vector[0] = a[0]-b[0]; - vector[1] = a[1]-b[1]; - return vector; + function subtractPoints(a, b) { + return [a[0] - b[0], a[1] - b[1]]; } - function addPoints(a,b){ - var vector = [0,0]; - vector[0] = a[0]+b[0]; - vector[1] = a[1]+b[1]; - return vector; + function addPoints(a, b) { + return [a[0]+b[0],a[1]+b[1]]; } - function normalizePoint(point,thickness){ + function normalizePoint(point, thickness) { var vector = [0,0]; - var length = Math.sqrt( point[0] * point[0] + point[1] * point[1]); + var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]); if(length != 0){ - vector[0] = point[0]/length; - vector[1] = point[1]/length; + vector[0] = point[0] / length; + vector[1] = point[1] / length; } vector[0] *= thickness; diff --git a/js/id/operations/orthogonalize.js b/js/id/operations/orthogonalize.js index 888d0015e..c59ed13e4 100644 --- a/js/id/operations/orthogonalize.js +++ b/js/id/operations/orthogonalize.js @@ -1,6 +1,6 @@ iD.operations.Orthogonalize = function(selection, context) { var entityId = selection[0], - action = iD.actions.Orthogonalize(entityId, context.map()); + action = iD.actions.Orthogonalize(entityId, context.projection); var operation = function() { var annotation = t('operations.orthogonalize.annotation.' + context.geometry(entityId)); diff --git a/test/index.html b/test/index.html index b6d925923..551a87621 100644 --- a/test/index.html +++ b/test/index.html @@ -73,6 +73,7 @@ + @@ -108,6 +109,7 @@ + From 285ef7584d0f42560ea8f8a3e5c887580756026a Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Mon, 4 Feb 2013 11:55:25 -0500 Subject: [PATCH 04/10] Contributing --- CONTRIBUTING.md | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 3 +- 2 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..5a4bdcca8 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,77 @@ +# Contributing to iD + +Thinking of contributing to iD? High five! Here are some basics for our habits +so that you can write code that fits in perfectly. + +## Javascript + +We use the [Airbnb style for Javascript](https://github.com/airbnb/javascript) with +only one difference: + +**4 space soft tabs always for Javascript, not 2.** + +No aligned `=`, no aligned arguments, spaces are either indents or the 1 +space between expressions. No hard tabs, ever. + +Javascript code should pass through [JSHint](http://www.jshint.com/) with no +warnings. + +## HTML + +There isn't much HTML in iD, but what there is is similar to JS: 4 spaces +always, indented by the level of the tree: + +```html +
+
+
+``` + +## CSS + +Just like HTML and Javascript, 4 space soft tabs always. + +```css +.radial-menu-tooltip { + background: rgba(255, 255, 255, 0.8); +} +``` + +We write vanilla CSS with no preprocessing step. Since iD targets modern browsers, +feel free to use newer features wisely. + +## Tests + +Test your code and make sure it passes. Our testing harness requires [node.js](http://nodejs.org/) +and a few modules: + +1. [Install node.js](http://nodejs.org/) - 'Install' will download a package for your OS +2. Go to the directory where you have checked out `iD` +3. Run `npm install` +4. Run `npm test` to see whether your tests pass or fail. + +## Licensing + +iD is under the [WTFPL](http://www.wtfpl.net/). Some of the libraries it uses +are under different licenses. If you're contributing to iD, you're contributing +WTFPL code. + +## Submitting Changes + +Let's say that you've thought of a great improvement to iD - a change that +turns everything red (please do not do this, we like colors other than red). + +In your local copy, make a branch for this change: + + git checkout -b make-red + +Make your changes to source files. By source files we mean the files in `js/`. +the `iD.js` and `iD.min.js` files in this project are autogenerated - don't edit +them. + +So let's say you've changed `js/ui/confirm.js`. + +1. Run `jshint src` to make sure your code is clean +2. Run tests with `npm test` +3. Commit your changes with an informative commit message +4. [Submit a pull request](https://help.github.com/articles/using-pull-requests) to the `systemed/iD` project. diff --git a/README.md b/README.md index 711cb5418..08c6764c0 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,7 @@ ## Participate! -* [Read NOTES.md, our ongoing dev journal](https://github.com/systemed/iD/blob/master/NOTES.md) -* Fork this project. We eagerly accept pull requests. +* [Read up on Contributing and the code style of iD](CONTRIBUTING.md) * See [open issues in the issue tracker if you're looking for something to do](https://github.com/systemed/iD/issues?state=open) To run the code locally, just fork this project and run it from a local webserver. From e5ad28feb75e79173892b1f54208851deea2f2cc Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Mon, 4 Feb 2013 12:10:23 -0500 Subject: [PATCH 05/10] JShint fixups --- js/id/actions/split.js | 2 +- js/id/behavior/draw_way.js | 2 +- js/id/graph/history.js | 2 +- js/id/graph/node.js | 2 +- js/id/operations.js | 2 +- js/id/services/taginfo.js | 2 +- js/id/svg.js | 18 ++++++++++-------- js/id/ui/splash.js | 13 +++++++++---- 8 files changed, 25 insertions(+), 18 deletions(-) diff --git a/js/id/actions/split.js b/js/id/actions/split.js index 19a71c619..24f2b4318 100644 --- a/js/id/actions/split.js +++ b/js/id/actions/split.js @@ -17,7 +17,7 @@ iD.actions.Split = function(nodeId, newWayId) { return parents.filter(function (parent) { return parent.first() !== nodeId && parent.last() !== nodeId; - }) + }); } var action = function(graph) { diff --git a/js/id/behavior/draw_way.js b/js/id/behavior/draw_way.js index 3089bd6ee..1cc52ab1f 100644 --- a/js/id/behavior/draw_way.js +++ b/js/id/behavior/draw_way.js @@ -82,7 +82,7 @@ iD.behavior.DrawWay = function(context, wayId, index, mode, baseGraph) { return graph .replace(way.removeNode(nodeId).addNode(newNode.id, index)) .remove(node); - } + }; } // Accept the current position of the temporary node and continue drawing. diff --git a/js/id/graph/history.js b/js/id/graph/history.js index 3cc1ace01..7d1098027 100644 --- a/js/id/graph/history.js +++ b/js/id/graph/history.js @@ -127,7 +127,7 @@ iD.History = function() { modified: difference.modified(), created: difference.created(), deleted: difference.deleted() - } + }; }, hasChanges: function() { diff --git a/js/id/graph/node.js b/js/id/graph/node.js index b9a171752..56fc14eab 100644 --- a/js/id/graph/node.js +++ b/js/id/graph/node.js @@ -47,6 +47,6 @@ _.extend(iD.Node.prototype, { type: 'Point', coordinates: this.loc } - } + }; } }); diff --git a/js/id/operations.js b/js/id/operations.js index 2786d046f..a72fe1d82 100644 --- a/js/id/operations.js +++ b/js/id/operations.js @@ -1 +1 @@ -iD.operations = {} +iD.operations = {}; diff --git a/js/id/services/taginfo.js b/js/id/services/taginfo.js index aa89a37fa..fc4e72542 100644 --- a/js/id/services/taginfo.js +++ b/js/id/services/taginfo.js @@ -40,7 +40,7 @@ iD.taginfo = function() { } function popularValues(parameters) { - return function(d) { return parseFloat(d['fraction']) > 0.01; }; + return function(d) { return parseFloat(d.fraction) > 0.01; }; } function valKey(d) { return { value: d.key }; } diff --git a/js/id/svg.js b/js/id/svg.js index 5b07b3a53..aadb6b830 100644 --- a/js/id/svg.js +++ b/js/id/svg.js @@ -1,19 +1,19 @@ iD.svg = { - RoundProjection: function (projection) { - return function (d) { + RoundProjection: function(projection) { + return function(d) { return iD.geo.roundCoords(projection(d)); }; }, - PointTransform: function (projection) { - return function (entity) { + PointTransform: function(projection) { + return function(entity) { return 'translate(' + projection(entity.loc) + ')'; }; }, - LineString: function (projection, graph) { + LineString: function(projection, graph) { var cache = {}; - return function (entity) { + return function(entity) { if (cache[entity.id] !== undefined) { return cache[entity.id]; } @@ -23,7 +23,9 @@ iD.svg = { } return (cache[entity.id] = - 'M' + graph.childNodes(entity).map(function (n) { return projection(n.loc); }).join('L')); - } + 'M' + graph.childNodes(entity).map(function(n) { + return projection(n.loc); + }).join('L')); + }; } }; diff --git a/js/id/ui/splash.js b/js/id/ui/splash.js index 43489fab1..a4d2a915e 100644 --- a/js/id/ui/splash.js +++ b/js/id/ui/splash.js @@ -2,15 +2,20 @@ iD.ui.splash = function() { var modal = iD.ui.modal(); modal.select('.modal') - .attr('class', 'modal-splash modal') + .attr('class', 'modal-splash modal'); var introModal = modal.select('.content') .append('div') .attr('class', 'modal-section fillL'); - introModal.append('div').attr('class','logo'); + introModal.append('div') + .attr('class','logo'); - introModal.append('div').html("

Welcome to the iD OpenStreetMap editor

This is development version 0.0.0-alpha1. For more information see ideditor.com and report bugs at github.com.systemed/iD.

"); + introModal.append('div') + .html("

Welcome to the iD OpenStreetMap editor

" + + "This is development version 0.0.0-alpha1. " + + "For more information see ideditor.com" + + " and report bugs at github.com.systemed/iD.

"); return modal; -}; \ No newline at end of file +}; From 8699b4a49e62108a9bf31b845534c68209cade9a Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 4 Feb 2013 09:17:00 -0800 Subject: [PATCH 06/10] Adjust for style, formatting, and jshint --- js/id/actions/orthogonalize.js | 51 +++++++++++++++------------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/js/id/actions/orthogonalize.js b/js/id/actions/orthogonalize.js index 830d1a1eb..068db55bd 100644 --- a/js/id/actions/orthogonalize.js +++ b/js/id/actions/orthogonalize.js @@ -1,18 +1,14 @@ iD.actions.Orthogonalize = function(wayId, projection) { - var action = function(graph) { var way = graph.entity(wayId), - nodes = graph.childNodes(way); - - var points = nodes.map(function(n) { - return projection(n.loc); - }), - quad_nodes = []; + nodes = graph.childNodes(way), + points = nodes.map(function(n) { return projection(n.loc); }), + quad_nodes = [], i, j; var score = squareness(); - for (var i = 0; i < 1000; i++) { + for (i = 0; i < 1000; i++) { var motions = points.map(stepMap); - for (var j = 0; j < motions.length; j++) { + for (j = 0; j < motions.length; j++) { points[j] = addPoints(points[j],motions[j]); } var newScore = squareness(); @@ -24,6 +20,7 @@ iD.actions.Orthogonalize = function(wayId, projection) { break; } } + for (i = 0; i < points.length - 1; i++) { quad_nodes.push(iD.Node({ loc: projection.invert(points[i]) })); } @@ -31,7 +28,7 @@ iD.actions.Orthogonalize = function(wayId, projection) { for (i = 0; i < nodes.length; i++) { if (graph.parentWays(nodes[i]).length > 1) { var closest, closest_dist = Infinity, dist; - for (var j = 0; j < quad_nodes.length; j++) { + for (j = 0; j < quad_nodes.length; j++) { dist = iD.geo.dist(quad_nodes[j].loc, nodes[i].loc); if (dist < closest_dist) { closest_dist = dist; @@ -47,7 +44,7 @@ iD.actions.Orthogonalize = function(wayId, projection) { } var ids = _.pluck(quad_nodes, 'id'), - difference = _.difference(_.uniq(way.nodes), ids); + difference = _.difference(_.uniq(way.nodes), ids); ids.push(ids[0]); @@ -60,28 +57,25 @@ iD.actions.Orthogonalize = function(wayId, projection) { return graph; function stepMap(b, i, array) { - var a, c, p, q = []; - a = array[(i - 1 + array.length) % array.length]; - c = array[(i + 1) % array.length]; - p = subtractPoints(a, b); - q = subtractPoints(c, b); + var a = array[(i - 1 + array.length) % array.length], + c = array[(i + 1) % array.length], + p = subtractPoints(a, b), + q = subtractPoints(c, b); var scale = p.length + q.length; p = normalizePoint(p, 1.0); q = normalizePoint(q, 1.0); + var dotp = p[0] *q[0] + p[1] *q[1]; // nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270). if (dotp < -0.707106781186547) { dotp += 1.0; } - var v = []; - v = addPoints(p, q); - v = normalizePoint(v, 0.1 * dotp * scale); - return v; + + return normalizePoint(addPoints(p, q), 0.1 * dotp * scale); } function squareness() { - var g = 0.0; for (var i = 1; i < points.length - 1; i++) { var score = scoreOfPoints(points[i - 1], points[i], points[i + 1]); @@ -95,17 +89,16 @@ iD.actions.Orthogonalize = function(wayId, projection) { } function scoreOfPoints(a, b, c) { - var p, q = []; - p = subtractPoints(a, b); - q = subtractPoints(c, b); + var p = subtractPoints(a, b), + q = subtractPoints(c, b); + p = normalizePoint(p, 1.0); q = normalizePoint(q, 1.0); var dotp = p[0] * q[0] + p[1] * q[1]; // score is constructed so that +1, -1 and 0 are all scored 0, any other angle // is scored higher. - var score = 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1))); - return score; + return 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1))); } function subtractPoints(a, b) { @@ -113,13 +106,13 @@ iD.actions.Orthogonalize = function(wayId, projection) { } function addPoints(a, b) { - return [a[0]+b[0],a[1]+b[1]]; + return [a[0] + b[0], a[1] + b[1]]; } function normalizePoint(point, thickness) { - var vector = [0,0]; + var vector = [0, 0]; var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]); - if(length != 0){ + if (length !== 0) { vector[0] = point[0] / length; vector[1] = point[1] / length; } From 7036758833aedff52e37af03753132d298a9cbda Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 4 Feb 2013 09:20:56 -0800 Subject: [PATCH 07/10] Fix directory --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5a4bdcca8..952266aa2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -71,7 +71,7 @@ them. So let's say you've changed `js/ui/confirm.js`. -1. Run `jshint src` to make sure your code is clean +1. Run `jshint js/id` to make sure your code is clean 2. Run tests with `npm test` 3. Commit your changes with an informative commit message 4. [Submit a pull request](https://help.github.com/articles/using-pull-requests) to the `systemed/iD` project. From 4ee620cb09835425945a1076b18abc10313b63ac Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Mon, 4 Feb 2013 12:23:46 -0500 Subject: [PATCH 08/10] Namespace selectors to iD-owned elements --- js/id/behavior/drag_midpoint.js | 2 +- js/id/renderer/map.js | 1 + js/id/svg/labels.js | 3 +-- js/id/ui/commit.js | 9 +++++---- js/id/ui/layerswitcher.js | 11 ++++++----- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/js/id/behavior/drag_midpoint.js b/js/id/behavior/drag_midpoint.js index 42099963c..4e39be2c6 100644 --- a/js/id/behavior/drag_midpoint.js +++ b/js/id/behavior/drag_midpoint.js @@ -9,7 +9,7 @@ iD.behavior.DragMidpoint = function(context) { context.perform(iD.actions.AddMidpoint(d, node)); - var vertex = d3.selectAll('.vertex') + var vertex = context.surface().selectAll('.vertex') .filter(function(data) { return data.id === node.id; }); behavior.target(vertex.node(), vertex.datum()); diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js index b2561f21f..19354d7f3 100644 --- a/js/id/renderer/map.js +++ b/js/id/renderer/map.js @@ -49,6 +49,7 @@ iD.Map = function(context) { map.size(selection.size()); map.surface = surface; + map.tilesurface = tilegroup; supersurface .call(tail); diff --git a/js/id/svg/labels.js b/js/id/svg/labels.js index eb4297bca..551c29e81 100644 --- a/js/id/svg/labels.js +++ b/js/id/svg/labels.js @@ -226,7 +226,7 @@ iD.svg.Labels = function(projection) { d3.select(surface.node().parentNode) .on('mousemove.hidelabels', hideOnMouseover); - var hidePoints = !d3.select('.node.point').node(); + var hidePoints = !surface.select('.node.point').node(); var labelable = [], i, k, entity; for (i = 0; i < label_stack.length; i++) labelable.push([]); @@ -254,7 +254,6 @@ iD.svg.Labels = function(projection) { } } - var positions = { point: [], line: [], diff --git a/js/id/ui/commit.js b/js/id/ui/commit.js index 09bb99404..8d724a732 100644 --- a/js/id/ui/commit.js +++ b/js/id/ui/commit.js @@ -35,11 +35,12 @@ iD.ui.commit = function(context) { // Comment Box var comment_section = body.append('div').attr('class','modal-section fillD'); - comment_section.append('textarea') + var commentField = comment_section.append('textarea') .attr('class', 'changeset-comment') .attr('placeholder', 'Brief Description of your contributions') - .property('value', context.storage('comment') || '') - .node().select(); + .property('value', context.storage('comment') || ''); + + commentField.node().select(); var commit_info = comment_section @@ -73,7 +74,7 @@ iD.ui.commit = function(context) { .append('button') .attr('class', 'save action col6 button') .on('click.save', function() { - var comment = d3.select('textarea.changeset-comment').node().value; + var comment = commentField.node().value; localStorage.comment = comment; event.save({ comment: comment diff --git a/js/id/ui/layerswitcher.js b/js/id/ui/layerswitcher.js index 5c4835757..9e5e4dd4f 100644 --- a/js/id/ui/layerswitcher.js +++ b/js/id/ui/layerswitcher.js @@ -61,9 +61,10 @@ iD.ui.layerswitcher = function(context) { opa.append('h4').text(t('layerswitcher.layers')); - opa.append('ul') - .attr('class', 'opacity-options') - .selectAll('div.opacity') + var opacityList = opa.append('ul') + .attr('class', 'opacity-options'); + + opacityList.selectAll('div.opacity') .data(opacities) .enter() .append('li') @@ -71,11 +72,11 @@ iD.ui.layerswitcher = function(context) { return t('layerswitcher.percent_brightness', { opacity: (d * 100) }); }) .on('click.set-opacity', function(d) { - d3.select('#tile-g') + context.map().tilesurface .transition() .style('opacity', d) .attr('data-opacity', d); - d3.selectAll('.opacity-options li') + opacityList.selectAll('li') .classed('selected', false); d3.select(this) .classed('selected', true); From 8d90fb777b29b6d6b49afe7aea48382639eb95d2 Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Mon, 4 Feb 2013 12:32:14 -0500 Subject: [PATCH 09/10] Purge a few more uses of d3.select, refs #595 --- js/id/ui.js | 8 +++++--- js/id/ui/geocoder.js | 7 +++---- js/id/ui/save.js | 2 ++ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/js/id/ui.js b/js/id/ui.js index 87cc3745a..69f20c2fd 100644 --- a/js/id/ui.js +++ b/js/id/ui.js @@ -140,8 +140,10 @@ iD.ui = function (context) { var about = container.append('div') .attr('class','col12 about-block fillD pad1'); - about.append('div') - .attr('class', 'user-container') + var userContainer = about.append('div') + .attr('class', 'user-container'); + + userContainer .append('div') .attr('class', 'hello'); @@ -243,7 +245,7 @@ iD.ui = function (context) { map.centerZoom([-77.02271, 38.90085], 20); } - d3.select('.user-container').call(iD.ui.userpanel(connection) + userContainer.call(iD.ui.userpanel(connection) .on('logout.editor', connection.logout) .on('login.editor', connection.authenticate)); diff --git a/js/id/ui/geocoder.js b/js/id/ui/geocoder.js index 4aac10bf2..063e8b517 100644 --- a/js/id/ui/geocoder.js +++ b/js/id/ui/geocoder.js @@ -38,9 +38,8 @@ iD.ui.geocoder = function() { function setVisible(show) { button.classed('active', show); gcForm.classed('hide', !show); - var input_node = d3.select('.map-overlay input').node(); - if (show) input_node.focus(); - else input_node.blur(); + if (show) inputNode.node().focus(); + else inputNode.node().blur(); } var button = selection.append('button') @@ -51,7 +50,7 @@ iD.ui.geocoder = function() { var gcForm = selection.append('form'); - gcForm.attr('class','content fillD map-overlay hide') + var inputNode = gcForm.attr('class','content fillD map-overlay hide') .append('input') .attr({ type: 'text', placeholder: t('geocoder.find_a_place') }) .on('keydown', keydown); diff --git a/js/id/ui/save.js b/js/id/ui/save.js index ba217adcf..773ae4d50 100644 --- a/js/id/ui/save.js +++ b/js/id/ui/save.js @@ -14,6 +14,7 @@ iD.ui.save = function(context) { .on('click', function() { function commit(e) { + d3.select('.shaded').remove(); var l = iD.ui.loading(t('uploading_changes'), true); connection.putChangeset(history.changes(), e.comment, history.imagery_used(), function(err, changeset_id) { @@ -40,6 +41,7 @@ iD.ui.save = function(context) { })); } }); + } if (history.hasChanges()) { From 59b6acdb08b0de54099c0837225e27ac4adc2c63 Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Mon, 4 Feb 2013 12:52:58 -0500 Subject: [PATCH 10/10] Add notes on reporting issues --- CONTRIBUTING.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 952266aa2..09dbab7ba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,6 +3,30 @@ Thinking of contributing to iD? High five! Here are some basics for our habits so that you can write code that fits in perfectly. +## Reporting Issues + +We'd love to hear what you think about iD, about any specific problems or +concerns you have. Here's a quick list of things to consider: + +Please [search for your issue before filing it: many bugs and improvements have already been reported](https://github.com/systemed/iD/issues/search?q=) + +To report a bug: + +* Write specifically what browser (type and version, like Firefox 22), OS, and browser extensions you have installed +* Write steps to replicate the error: when did it happen? What did you expect to happen? What happened instead? +* Please keep bug reports professional and straightforward: trust us, we share your dismay at software breaking. +* If you can, [enable web developer extensions](http://macwright.org/enable-web-developer-extensions/) and report the + Javascript error message. + +When in doubt, be over-descriptive of the bug and how you discovered it. + +To request a feature: + +* If the feature is available in some other software (like Potlatch), link to that software and the implementation. + We care about prior art. +* Understand that iD is meant to be a simple editor and doesn't aim to be + as complete or complicated as JOSM or similar. + ## Javascript We use the [Airbnb style for Javascript](https://github.com/airbnb/javascript) with