예제 #1
0
  /**
   * Determine which ways to split.
   *
   * @param selectedWays List of user selected ways.
   * @param selectedNodes List of user selected nodes.
   * @return List of ways to split
   */
  private List<Way> getApplicableWays(List<Way> selectedWays, List<Node> selectedNodes) {
    if (selectedNodes.isEmpty()) return null;

    // Special case - one of the selected ways touches (not cross) way that we
    // want to split
    if (selectedNodes.size() == 1) {
      Node n = selectedNodes.get(0);
      List<Way> referedWays = OsmPrimitive.getFilteredList(n.getReferrers(), Way.class);
      Way inTheMiddle = null;
      for (Way w : referedWays) {
        // Need to look at all nodes see #11184 for a case where node n is
        // firstNode, lastNode and also in the middle
        if (selectedWays.contains(w) && w.isInnerNode(n)) {
          if (inTheMiddle == null) {
            inTheMiddle = w;
          } else {
            inTheMiddle = null;
            break;
          }
        }
      }
      if (inTheMiddle != null) return Collections.singletonList(inTheMiddle);
    }

    // List of ways shared by all nodes
    List<Way> result =
        new ArrayList<>(
            OsmPrimitive.getFilteredList(selectedNodes.get(0).getReferrers(), Way.class));
    for (int i = 1; i < selectedNodes.size(); i++) {
      List<OsmPrimitive> ref = selectedNodes.get(i).getReferrers();
      for (Iterator<Way> it = result.iterator(); it.hasNext(); ) {
        if (!ref.contains(it.next())) {
          it.remove();
        }
      }
    }

    // Remove broken ways
    for (Iterator<Way> it = result.iterator(); it.hasNext(); ) {
      if (it.next().getNodesCount() <= 2) {
        it.remove();
      }
    }

    if (selectedWays.isEmpty()) return result;
    else {
      // Return only selected ways
      for (Iterator<Way> it = result.iterator(); it.hasNext(); ) {
        if (!selectedWays.contains(it.next())) {
          it.remove();
        }
      }
      return result;
    }
  }
예제 #2
0
  /**
   * Called when the action is executed.
   *
   * <p>This method performs an expensive check whether the selection clearly defines one of the
   * split actions outlined above, and if yes, calls the splitWay method.
   */
  @Override
  public void actionPerformed(ActionEvent e) {

    Collection<OsmPrimitive> selection = getCurrentDataSet().getSelected();

    List<Node> selectedNodes = OsmPrimitive.getFilteredList(selection, Node.class);
    List<Way> selectedWays = OsmPrimitive.getFilteredList(selection, Way.class);
    List<Relation> selectedRelations = OsmPrimitive.getFilteredList(selection, Relation.class);
    List<Way> applicableWays = getApplicableWays(selectedWays, selectedNodes);

    if (applicableWays == null) {
      new Notification(
              tr("The current selection cannot be used for splitting - no node is selected."))
          .setIcon(JOptionPane.WARNING_MESSAGE)
          .show();
      return;
    } else if (applicableWays.isEmpty()) {
      new Notification(tr("The selected nodes do not share the same way."))
          .setIcon(JOptionPane.WARNING_MESSAGE)
          .show();
      return;
    }

    // If several ways have been found, remove ways that doesn't have selected
    // node in the middle
    if (applicableWays.size() > 1) {
      for (Iterator<Way> it = applicableWays.iterator(); it.hasNext(); ) {
        Way w = it.next();
        for (Node n : selectedNodes) {
          if (!w.isInnerNode(n)) {
            it.remove();
            break;
          }
        }
      }
    }

    if (applicableWays.isEmpty()) {
      new Notification(
              trn(
                  "The selected node is not in the middle of any way.",
                  "The selected nodes are not in the middle of any way.",
                  selectedNodes.size()))
          .setIcon(JOptionPane.WARNING_MESSAGE)
          .show();
      return;
    } else if (applicableWays.size() > 1) {
      new Notification(
              trn(
                  "There is more than one way using the node you selected. Please select the way also.",
                  "There is more than one way using the nodes you selected. Please select the way also.",
                  selectedNodes.size()))
          .setIcon(JOptionPane.WARNING_MESSAGE)
          .show();
      return;
    }

    // Finally, applicableWays contains only one perfect way
    final Way selectedWay = applicableWays.get(0);
    final List<List<Node>> wayChunks = buildSplitChunks(selectedWay, selectedNodes);
    if (wayChunks != null) {
      final List<OsmPrimitive> sel =
          new ArrayList<>(selectedWays.size() + selectedRelations.size());
      sel.addAll(selectedWays);
      sel.addAll(selectedRelations);

      final List<Way> newWays = createNewWaysFromChunks(selectedWay, wayChunks);
      final Way wayToKeep = determineWayToKeep(newWays);

      if (ExpertToggleAction.isExpert() && !selectedWay.isNew()) {
        final ExtendedDialog dialog =
            new SegmentToKeepSelectionDialog(selectedWay, newWays, wayToKeep, sel);
        dialog.setModal(false);
        dialog.showDialog();
      } else {
        final SplitWayResult result =
            doSplitWay(getEditLayer(), selectedWay, wayToKeep, newWays, sel);
        Main.main.undoRedo.add(result.getCommand());
        getCurrentDataSet().setSelected(result.getNewSelection());
      }
    }
  }