* Uses {@link #newN1en}, {@link #newN2en} calculated by {@link #calculateBestMovementAndNewNodes}
*/
private void performExtrusion() {
// create extrusion
Collection<Command> cmds = new LinkedList<>();
Way wnew = new Way(selectedSegment.way);
boolean wayWasModified = false;
boolean wayWasSingleSegment = wnew.getNodesCount() == 2;
int insertionPoint = selectedSegment.lowerIndex + 1;
//find if the new points overlap existing segments (in case of 90 degree angles)
Node prevNode = getPreviousNode(selectedSegment.lowerIndex);
boolean nodeOverlapsSegment = prevNode != null && Geometry.segmentsParallel(initialN1en, prevNode.getEastNorth(), initialN1en, newN1en);
// segmentAngleZero marks subset of nodeOverlapsSegment. nodeOverlapsSegment is true if angle between segments is 0 or PI, segmentAngleZero only if angle is 0
boolean segmentAngleZero = prevNode != null && Math.abs(Geometry.getCornerAngle(prevNode.getEastNorth(), initialN1en, newN1en)) < 1e-5;
boolean hasOtherWays = hasNodeOtherWays(selectedSegment.getFirstNode(), selectedSegment.way);
ArrayList<Node> changedNodes = new ArrayList<>();
if (nodeOverlapsSegment && !alwaysCreateNodes && !hasOtherWays) {
//move existing node
Node n1Old = selectedSegment.getFirstNode();
cmds.add(new MoveCommand(n1Old, Main.getProjection().eastNorth2latlon(newN1en)));
changedNodes.add(n1Old);
} else if (ignoreSharedNodes && segmentAngleZero && !alwaysCreateNodes && hasOtherWays) {
// replace shared node with new one
Node n1Old = selectedSegment.getFirstNode();
Node n1New = new Node(Main.getProjection().eastNorth2latlon(newN1en));
wnew.addNode(insertionPoint, n1New);
wnew.removeNode(n1Old);
wayWasModified = true;
cmds.add(new AddCommand(n1New));
changedNodes.add(n1New);
} else {
//introduce new node
Node n1New = new Node(Main.getProjection().eastNorth2latlon(newN1en));
wnew.addNode(insertionPoint, n1New);
wayWasModified = true;
insertionPoint ++;
cmds.add(new AddCommand(n1New));
changedNodes.add(n1New);
}
//find if the new points overlap existing segments (in case of 90 degree angles)
Node nextNode = getNextNode(selectedSegment.lowerIndex + 1);
nodeOverlapsSegment = nextNode != null && Geometry.segmentsParallel(initialN2en, nextNode.getEastNorth(), initialN2en, newN2en);
segmentAngleZero = nextNode != null && Math.abs(Geometry.getCornerAngle(nextNode.getEastNorth(), initialN2en, newN2en)) < 1e-5;
hasOtherWays = hasNodeOtherWays(selectedSegment.getSecondNode(), selectedSegment.way);
if (nodeOverlapsSegment && !alwaysCreateNodes && !hasOtherWays) {
//move existing node
Node n2Old = selectedSegment.getSecondNode();
cmds.add(new MoveCommand(n2Old, Main.getProjection().eastNorth2latlon(newN2en)));
changedNodes.add(n2Old);
} else if (ignoreSharedNodes && segmentAngleZero && !alwaysCreateNodes && hasOtherWays) {
// replace shared node with new one
Node n2Old = selectedSegment.getSecondNode();
Node n2New = new Node(Main.getProjection().eastNorth2latlon(newN2en));
wnew.addNode(insertionPoint, n2New);
wnew.removeNode(n2Old);
wayWasModified = true;
cmds.add(new AddCommand(n2New));
changedNodes.add(n2New);
} else {
//introduce new node
Node n2New = new Node(Main.getProjection().eastNorth2latlon(newN2en));
wnew.addNode(insertionPoint, n2New);
wayWasModified = true;
insertionPoint ++;
cmds.add(new AddCommand(n2New));
changedNodes.add(n2New);
}
//the way was a single segment, close the way
if (wayWasSingleSegment) {
wnew.addNode(selectedSegment.getFirstNode());
wayWasModified = true;
}
if (wayWasModified) {
// we only need to change the way if its node list was really modified
cmds.add(new ChangeCommand(selectedSegment.way, wnew));