package net.systemeD.halcyon.connection {
import flash.geom.Point;
- import net.systemeD.halcyon.Globals;
- import net.systemeD.halcyon.connection.actions.*;
+
+ import net.systemeD.halcyon.connection.actions.*;
public class Way extends Entity {
private var nodes:Array;
public function getLastNode():Node {
return nodes[nodes.length-1];
}
+
+ /** Given one node, return the next in sequence, cycling around a loop if necessary. */
+ // TODO make behave correctly for P-shaped topologies?
+ public function getNextNode(node:Node):Node {
+ // If the last node in a loop is selected, this behaves correctly.
+ var i:uint = indexOfNode(node);
+ if(i < length-1)
+ return nodes[i+1];
+ return null;
+ // What should happen for very short lengths?
+ }
+
+ // TODO make behave correctly for P-shaped topologies?
+ /** Given one node, return the previous, cycling around a loop if necessary. */
+ public function getPrevNode(node:Node):Node {
+ var i:uint = indexOfNode(node);
+ if(i > 0)
+ return nodes[i-1];
+ if(i == 0 && isArea() )
+ return nodes[nodes.length - 2]
+ return null;
+ // What should happen for very short lengths?
+ }
public function insertNode(index:uint, node:Node, performAction:Function):void {
performAction(new AddNodeToWayAction(this, node, nodes, index));
case Keyboard.BACKSPACE:
case 189: /* minus */ return backspaceNode(MainUndoStack.getGlobalStack().addAction);
case 82: /* R */ repeatTags(firstSelected); return this;
+ case 70: /* F */ followWay(); return this;
}
var cs:ControllerState = sharedKeyboardEvents(event);
return cs ? cs : this;
return state;
}
+ /** Extends the current way by "following" an existing way, after the user has already selected two nodes in a row. */
+ protected function followWay() {
+ // TODO add a bit of feedback when following can't be carried out for some reason.
+ // Perhaps use the new FloatingAlert that I couldn't figure out how to use
+
+ /*
+ If drawing way has at least two nodes
+ and both belong to another way
+ and those ways are the same
+ then find the next node
+ then add that node
+ then update screen and scroll the new node into shot if necessary */
+ var curnode:Node;
+ var prevnode:Node;
+ if (Way(firstSelected).length < 2) {
+ return;
+ }
+ if (editEnd) {
+ curnode = Way(firstSelected).getLastNode();
+ prevnode = Way(firstSelected).getNode(Way(firstSelected).length-2);
+ } else {
+ curnode = Way(firstSelected).getNode(0);
+ prevnode = Way(firstSelected).getNode(1);
+
+ }
+ if (curnode.numParentWays <2 || prevnode.numParentWays <2)
+ return;
+ var followedWay:Way = null;
+ for (var i in curnode.parentWays) {
+ if (curnode.parentWays[i]!=firstSelected && prevnode.hasParent(curnode.parentWays[i])) {
+ // Could be slightly smarter when there are more than one candidate. Perhaps could see which
+ // of the 2+ ways is the most colinear with the currently drawn way.
+ followedWay = curnode.parentWays[i];
+ }
+ }
+ if (!followedWay)
+ return;
+ var nextNode:Node;
+ if (followedWay.getNextNode(prevnode) == curnode) {
+ nextNode = followedWay.getNextNode(curnode);
+ } else if (followedWay.getNextNode(curnode) == prevnode){
+ nextNode = followedWay.getPrevNode(curnode);
+ } else // The two nodes selected aren't actually consecutive. Make a half-hearted
+ // guess at which way to follow. Will be "incorrect" if the join in the loop
+ // is between the two points.
+ if (followedWay.indexOfNode(curnode) > followedWay.indexOfNode(prevnode)) {
+ nextNode = followedWay.getNextNode(curnode);
+ } else {
+ nextNode = followedWay.getPrevNode(curnode);
+ }
+ if (!nextNode) return;
+ if (nextNode.hasParent(firstSelected))
+ return;
+
+ appendNode(nextNode as Node, MainUndoStack.getGlobalStack().addAction);
+ resetElastic(nextNode as Node);
+ lastClick=nextNode;
+ controller.map.setHighlight(nextNode, { selectedway: true });
+
+ // recentre the map if the new lat/lon is offscreen
+ if (nextNode.lat > controller.map.edge_t ||
+ nextNode.lat < controller.map.edge_b ||
+ nextNode.lon < controller.map.edge_l ||
+ nextNode.lon > controller.map.edge_r) {
+
+ controller.map.moveMapFromLatLon(nextNode.lat, nextNode.lon);
+ }
+ }
+
override public function enterState():void {
super.enterState();