return nodes[index];
}
+ public function getFirstNode():Node {
+ return nodes[0];
+ }
+
public function getLastNode():Node {
return nodes[nodes.length-1];
}
if (str=='area' && isArea()) return true;
return false;
}
+
+ /** Whether the way has a loop that joins back midway along its length */
+ public function isPShape():Boolean {
+ return getFirstNode() != getLastNode() && (!hasOnceOnly(getFirstNode()) || !hasOnceOnly(getLastNode()) );
+ }
+
+ /** Given a P-shaped way, return the index of midway node that one end connects back to. */
+ public function getPJunctionNodeIndex():uint {
+ if (isPShape()) {
+ if (hasOnceOnly(getFirstNode())) {
+ // nodes[0] is the free end
+ return nodes.indexOf(getLastNode());
+ } else {
+ // nodes[0] is in the loop
+ return nodes.lastIndexOf(getFirstNode());
+ }
+ }
+ return null;
+ }
}
-
}
package net.systemeD.halcyon.connection.actions {
import net.systemeD.halcyon.connection.*;
- import net.systemeD.halcyon.Globals;
public class SplitWayAction extends CompositeUndoableAction {
private var selectedWay:Way;
- private var selectedNode:Node;
+ private var nodeIndex:uint; // Index rather than node required as nodes can occur multiple times
private var newWay:Way;
- public function SplitWayAction(selectedWay:Way, selectedNode:Node) {
+ public function SplitWayAction(selectedWay:Way, nodeIndex:uint) {
super("Split way "+selectedWay.id);
this.selectedWay = selectedWay;
- this.selectedNode = selectedNode;
+ this.nodeIndex = nodeIndex;
}
public override function doAction():uint {
if (newWay==null) {
newWay = Connection.getConnection().createWay(
selectedWay.getTagsCopy(),
- selectedWay.sliceNodes(selectedWay.indexOfNode(selectedNode),selectedWay.length),
+ selectedWay.sliceNodes(nodeIndex,selectedWay.length),
push);
// we reverse the list, which is already sorted by position. This way positions aren't affected
}
// now that we're done with the selectedWay, remove the nodes
- selectedWay.deleteNodesFrom(selectedWay.indexOfNode(selectedNode)+1, push);
+ selectedWay.deleteNodesFrom(nodeIndex+1, push);
// and remove from any turn restrictions that aren't relevant
for each (var r:Relation in selectedWay.findParentRelationsOfType('restriction')) {
return new DrawWay(selectedWay, isLast, true);
}
+ /** Splits a way into two separate ways, at the currently selected node. Handles simple loops and P-shapes. Untested for anything funkier. */
public function splitWay():ControllerState {
+ var n:Node=firstSelected as Node;
+ var ni:uint = parentWay.indexOfNode(n);
// abort if start or end
- if (parentWay.getNode(0) == firstSelected) { return this; }
- if (parentWay.getLastNode() == firstSelected) { return this; }
+ if (parentWay.isPShape() && !parentWay.hasOnceOnly(n)) {
+ // If P-shaped, we want to split at the midway point on the stem, not at the end of the loop
+ ni = parentWay.getPJunctionNodeIndex();
+
+ } else {
+ if (parentWay.getNode(0) == n) { return this; }
+ if (parentWay.getLastNode() == n) { return this; }
+ }
controller.map.setHighlightOnNodes(parentWay, { selectedway: false } );
controller.map.setPurgable([parentWay],true);
- MainUndoStack.getGlobalStack().addAction(new SplitWayAction(parentWay, firstSelected as Node));
+ MainUndoStack.getGlobalStack().addAction(new SplitWayAction(parentWay, ni));
return new SelectedWay(parentWay);
}