Example #1
0
  @Override
  public boolean isFixable(TestError testError) {
    if (!(testError.getTester() instanceof DuplicateWay)) return false;

    // Do not automatically fix same ways with different tags
    if (testError.getCode() != DUPLICATE_WAY) return false;

    // We fix it only if there is no more than one way that is relation member.
    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 false;

    int waysWithRelations = 0;
    for (Way w : ways) {
      List<Relation> rel = OsmPrimitive.getFilteredList(w.getReferrers(), Relation.class);
      if (!rel.isEmpty()) {
        ++waysWithRelations;
      }
    }
    return (waysWithRelations <= 1);
  }
Example #2
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);
  }
Example #3
0
  static SplitWayResult doSplitWay(
      OsmDataLayer layer,
      Way way,
      Way wayToKeep,
      List<Way> newWays,
      List<OsmPrimitive> newSelection) {

    Collection<Command> commandList = new ArrayList<>(newWays.size());
    Collection<String> nowarnroles =
        Main.pref.getCollection(
            "way.split.roles.nowarn",
            Arrays.asList(
                "outer", "inner", "forward", "backward", "north", "south", "east", "west"));

    // Change the original way
    final Way changedWay = new Way(way);
    changedWay.setNodes(wayToKeep.getNodes());
    commandList.add(new ChangeCommand(way, changedWay));
    if (!newSelection.contains(way)) {
      newSelection.add(way);
    }
    newWays.remove(wayToKeep);

    for (Way wayToAdd : newWays) {
      commandList.add(new AddCommand(layer, wayToAdd));
      newSelection.add(wayToAdd);
    }

    boolean warnmerole = false;
    boolean warnme = false;
    // now copy all relations to new way also

    for (Relation r : OsmPrimitive.getFilteredList(way.getReferrers(), Relation.class)) {
      if (!r.isUsable()) {
        continue;
      }
      Relation c = null;
      String type = r.get("type");
      if (type == null) {
        type = "";
      }

      int i_c = 0, i_r = 0;
      List<RelationMember> relationMembers = r.getMembers();
      for (RelationMember rm : relationMembers) {
        if (rm.isWay() && rm.getMember() == way) {
          boolean insert = true;
          if ("restriction".equals(type)) {
            /* this code assumes the restriction is correct. No real error checking done */
            String role = rm.getRole();
            if ("from".equals(role) || "to".equals(role)) {
              OsmPrimitive via = null;
              for (RelationMember rmv : r.getMembers()) {
                if ("via".equals(rmv.getRole())) {
                  via = rmv.getMember();
                }
              }
              List<Node> nodes = new ArrayList<>();
              if (via != null) {
                if (via instanceof Node) {
                  nodes.add((Node) via);
                } else if (via instanceof Way) {
                  nodes.add(((Way) via).lastNode());
                  nodes.add(((Way) via).firstNode());
                }
              }
              Way res = null;
              for (Node n : nodes) {
                if (changedWay.isFirstLastNode(n)) {
                  res = way;
                }
              }
              if (res == null) {
                for (Way wayToAdd : newWays) {
                  for (Node n : nodes) {
                    if (wayToAdd.isFirstLastNode(n)) {
                      res = wayToAdd;
                    }
                  }
                }
                if (res != null) {
                  if (c == null) {
                    c = new Relation(r);
                  }
                  c.addMember(new RelationMember(role, res));
                  c.removeMembersFor(way);
                  insert = false;
                }
              } else {
                insert = false;
              }
            } else if (!"via".equals(role)) {
              warnme = true;
            }
          } else if (!("route".equals(type)) && !("multipolygon".equals(type))) {
            warnme = true;
          }
          if (c == null) {
            c = new Relation(r);
          }

          if (insert) {
            if (rm.hasRole() && !nowarnroles.contains(rm.getRole())) {
              warnmerole = true;
            }

            Boolean backwards = null;
            int k = 1;
            while (i_r - k >= 0 || i_r + k < relationMembers.size()) {
              if ((i_r - k >= 0) && relationMembers.get(i_r - k).isWay()) {
                Way w = relationMembers.get(i_r - k).getWay();
                if ((w.lastNode() == way.firstNode()) || w.firstNode() == way.firstNode()) {
                  backwards = Boolean.FALSE;
                } else if ((w.firstNode() == way.lastNode()) || w.lastNode() == way.lastNode()) {
                  backwards = Boolean.TRUE;
                }
                break;
              }
              if ((i_r + k < relationMembers.size()) && relationMembers.get(i_r + k).isWay()) {
                Way w = relationMembers.get(i_r + k).getWay();
                if ((w.lastNode() == way.firstNode()) || w.firstNode() == way.firstNode()) {
                  backwards = Boolean.TRUE;
                } else if ((w.firstNode() == way.lastNode()) || w.lastNode() == way.lastNode()) {
                  backwards = Boolean.FALSE;
                }
                break;
              }
              k++;
            }

            int j = i_c;
            for (Way wayToAdd : newWays) {
              RelationMember em = new RelationMember(rm.getRole(), wayToAdd);
              j++;
              if ((backwards != null) && backwards) {
                c.addMember(i_c, em);
              } else {
                c.addMember(j, em);
              }
            }
            i_c = j;
          }
        }
        i_c++;
        i_r++;
      }

      if (c != null) {
        commandList.add(new ChangeCommand(layer, r, c));
      }
    }
    if (warnmerole) {
      new Notification(
              tr(
                  "A role based relation membership was copied to all new ways.<br>You should verify this and correct it when necessary."))
          .setIcon(JOptionPane.WARNING_MESSAGE)
          .show();
    } else if (warnme) {
      new Notification(
              tr(
                  "A relation membership was copied to all new ways.<br>You should verify this and correct it when necessary."))
          .setIcon(JOptionPane.WARNING_MESSAGE)
          .show();
    }

    return new SplitWayResult(
        new SequenceCommand(
            /* for correct i18n of plural forms - see #9110 */
            trn(
                "Split way {0} into {1} part",
                "Split way {0} into {1} parts",
                newWays.size(),
                way.getDisplayName(DefaultNameFormatter.getInstance()),
                newWays.size()),
            commandList),
        newSelection,
        way,
        newWays);
  }