Ejemplo n.º 1
0
  /** Fix the error by removing all but one instance of duplicate ways */
  @Override
  public Command fixError(TestError testError) {
    Collection<? extends OsmPrimitive> sel = testError.getPrimitives();
    HashSet<Way> ways = new HashSet<Way>();

    for (OsmPrimitive osm : sel) {
      if (osm instanceof Way) {
        ways.add((Way) osm);
      }
    }

    if (ways.size() < 2) return null;

    long idToKeep = 0;
    Way wayToKeep = ways.iterator().next();
    // Only one way will be kept - the one with lowest positive ID, if such exist
    // or one "at random" if no such exists. Rest of the ways will be deleted
    for (Way w : ways) {
      if (!w.isNew()) {
        if (idToKeep == 0 || w.getId() < idToKeep) {
          idToKeep = w.getId();
          wayToKeep = w;
        }
      }
    }

    // Find the way that is member of one or more relations. (If any)
    Way wayWithRelations = null;
    List<Relation> relations = null;
    for (Way w : ways) {
      List<Relation> rel = OsmPrimitive.getFilteredList(w.getReferrers(), Relation.class);
      if (!rel.isEmpty()) {
        if (wayWithRelations != null)
          throw new AssertionError(
              "Cannot fix duplicate Ways: More than one way is relation member.");
        wayWithRelations = w;
        relations = rel;
      }
    }

    Collection<Command> commands = new LinkedList<Command>();

    // Fix relations.
    if (wayWithRelations != null && wayToKeep != wayWithRelations) {
      for (Relation rel : relations) {
        Relation newRel = new Relation(rel);
        for (int i = 0; i < newRel.getMembers().size(); ++i) {
          RelationMember m = newRel.getMember(i);
          if (wayWithRelations.equals(m.getMember())) {
            newRel.setMember(i, new RelationMember(m.getRole(), wayToKeep));
          }
        }
        commands.add(new ChangeCommand(rel, newRel));
      }
    }

    // Delete all ways in the list
    // Note: nodes are not deleted, these can be detected and deleted at next pass
    ways.remove(wayToKeep);
    commands.add(new DeleteCommand(ways));
    return new SequenceCommand(tr("Delete duplicate ways"), commands);
  }
Ejemplo n.º 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());
      }
    }
  }