Create junctions when drawing a way

This commit is contained in:
Richard Fairhurst
2012-07-11 18:23:13 +01:00
parent 553c605adb
commit b23ce19b1f
4 changed files with 123 additions and 9 deletions
+61 -6
View File
@@ -1,9 +1,9 @@
// iD/Entity.js
// Entity classes for iD
define(['dojo/_base/declare','dojo/_base/array',
'iD/actions/AddNodeToWayAction'
], function(declare,array){
define(['dojo/_base/declare','dojo/_base/array','dojo/_base/lang',
'iD/actions/AddNodeToWayAction','iD/actions/MoveNodeAction'
], function(declare,array,lang){
// ----------------------------------------------------------------------
// Entity base class
@@ -117,11 +117,29 @@ declare("iD.Node", [iD.Entity], {
this.modified=this.id<0;
},
project:function() {
this.latp=180/Math.PI * Math.log(Math.tan(Math.PI/4+this.lat*(Math.PI/180)/2));
},
project:function() { this.latp=180/Math.PI * Math.log(Math.tan(Math.PI/4+this.lat*(Math.PI/180)/2)); },
latp2lat:function(a) { return 180/Math.PI * (2 * Math.atan(Math.exp(a*Math.PI/180)) - Math.PI/2); },
within:function(left,right,top,bottom) { return (this.lon>=left) && (this.lon<=right) && (this.lat>=bottom) && (this.lat<=top) && !this.deleted; },
refresh:function() {
var ways=this.parentWays();
var conn=this.connection;
array.forEach(ways,function(way) { conn.refreshEntity(way); });
this.connection.refreshEntity(this);
},
doSetLonLatp:function(lon,latproj,performAction) {
performAction(new iD.actions.MoveNodeAction(this, this.latp2lat(latproj), lon, lang.hitch(this,this._setLatLonImmediate) ));
},
_setLatLonImmediate:function(lat,lon) {
this.lat = lat;
this.lon = lon;
this.project();
var ways = this.parentWays();
for (var i=0; i<ways.length; i++) { ways[i].expandBbox(this); }
},
});
@@ -205,7 +223,44 @@ declare("iD.Way", [iD.Entity], {
if (node!=this.getFirstNode()) performAction(new iD.actions.AddNodeToWayAction(this, node, this.nodes, 0, true));
return this.nodes.length + 1;
},
doInsertNode:function(index, node, performAction) {
if (index>0 && this.getNode(index-1)==node) return;
if (index<this.nodes.length-1 && this.getNode(index)==node) return;
performAction(new iD.actions.AddNodeToWayAction(this, node, this.nodes, index, false));
},
doInsertNodeAtClosestPosition:function(newNode, isSnap, performAction) {
var closestProportion = 1;
var newIndex = 0;
var snapped;
for (var i=0; i<this.nodes.length-1; i++) {
var node1 = this.getNode(i);
var node2 = this.getNode(i+1);
var directDist = this.pythagoras(node1, node2);
var viaNewDist = this.pythagoras(node1, newNode) + this.pythagoras(node2, newNode);
var proportion = Math.abs(viaNewDist/directDist - 1);
if (proportion < closestProportion) {
newIndex = i+1;
closestProportion = proportion;
snapped = this.calculateSnappedPoint(node1, node2, newNode);
}
}
// splice in new node
if (isSnap) { newNode.doSetLonLatp(snapped.x, snapped.y, performAction); }
this.doInsertNode(newIndex, newNode, performAction);
return newIndex;
},
pythagoras:function(node1, node2) { return (Math.sqrt(Math.pow(node1.lon-node2.lon,2)+Math.pow(node1.latp-node2.latp,2))); },
calculateSnappedPoint:function(node1, node2, newNode) {
var w = node2.lon - node1.lon;
var h = node2.latp - node1.latp;
var u = ((newNode.lon-node1.lon) * w + (newNode.latp-node1.latp) * h) / (w*w + h*h);
return { x: node1.lon + u*w, y: node1.latp + u*h };
},
});
// ----------------------------------------------------------------------
+58
View File
@@ -0,0 +1,58 @@
// iD/actions/MoveNodeAction.js
define(['dojo/_base/declare','iD/actions/UndoableAction'], function(declare){
// ----------------------------------------------------------------------
// MoveNodeAction class
declare("iD.actions.MoveNodeAction", [iD.actions.UndoableEntityAction], {
createTime: NaN,
oldLat: NaN,
oldLon: NaN,
newLat: NaN,
newLon: NaN,
setLatLon: null,
constructor:function(node, newLat, newLon, setLatLon) {
this.entity = node;
this.newLat = newLat;
this.newLon = newLon;
this.setLatLon = setLatLon;
this.createTime = new Date().getTime();
},
doAction:function() {
var node = this.entity;
this.oldLat = node.lat;
this.oldLon = node.lon;
if (this.oldLat==this.newLat && this.oldLon==this.newLon) { return NO_CHANGE; }
this.setLatLon(this.newLat, this.newLon);
this.markDirty();
node.refresh();
return this.SUCCESS;
},
undoAction:function() {
this.setLatLon(this.oldLat, this.oldLon);
this.markClean();
this.refresh();
return this.SUCCESS;
},
mergePrevious:function(prev) {
if (prev.declaredClass!=this.declaredClass) { return false; }
if (prev.entity == this.entity && prev.createTime+1000>this.createTime) {
this.oldLat = prev.oldLat;
this.oldLon = prev.oldLon;
return true;
}
return false;
},
});
// ----------------------------------------------------------------------
// End of module
});
+3 -2
View File
@@ -14,7 +14,8 @@
*/
define(['dojo/_base/declare','dojo/_base/lang','dojox/gfx/shape','iD/controller/ControllerState'], function(declare,lang,shape){
define(['dojo/_base/declare','dojo/_base/lang','dojo/_base/array','dojox/gfx/shape','iD/controller/ControllerState'],
function(declare,lang,array,shape){
// ----------------------------------------------------------------------
// DrawWay class
@@ -111,7 +112,7 @@ declare("iD.controller.shape.DrawWay", [iD.controller.ControllerState], {
var ways=[entity]; // ** needs to find all the ways under the mouse
var undo=new iD.actions.CompositeUndoableAction();
var node=this.appendNewNode(event, undo);
// array.forEach(ways, function(w) { w.insertNodeAtClosestPosition(node, true, undo.push); } );
array.forEach(ways, function(w) { w.doInsertNodeAtClosestPosition(node, true, lang.hitch(undo,undo.push)); } );
var action=this.undoAdder(); action(undo);
return this;
}
+1 -1
View File
@@ -132,7 +132,7 @@ way::highlight :hover { z-index: 2; width: eval('_width+10'); color: #ffff99; }
way::highlight :selected { z-index: 2; width: eval('_width+10'); color: yellow; opacity: 0.7;}
node :selectedway { z-index: 9; icon-image: square; icon-width: 8; color: red; layer: 5; }
node::junction :junction :selectedway { z-index: 8; icon-image: square; icon-width: 11; casing-color: black; casing-width: 1; layer: 5; }
node::junction :junction :selectedway, node::junction :junction :hoverway { z-index: 8; icon-image: square; icon-width: 11; casing-color: black; casing-width: 1; layer: 5; }
node !:drawn :poi { z-index: 2; icon-image: circle; icon-width: 4; color: green; casing-color: black; casing-width: 1; }