예제 #1
0
  /**
   * Tests if the areas have some intersections to join.
   *
   * @param areas Areas to test
   * @return @{code true} if areas are joinable
   */
  private boolean testJoin(List<Multipolygon> areas) {
    List<Way> allStartingWays = new ArrayList<Way>();

    for (Multipolygon area : areas) {
      allStartingWays.add(area.outerWay);
      allStartingWays.addAll(area.innerWays);
    }

    // find intersection points
    Set<Node> nodes = Geometry.addIntersections(allStartingWays, true, cmds);
    return !nodes.isEmpty();
  }
예제 #2
0
  /**
   * Will join two or more overlapping areas
   *
   * @param areas list of areas to join
   * @return new area formed.
   */
  private JoinAreasResult joinAreas(List<Multipolygon> areas) throws UserCancelException {

    JoinAreasResult result = new JoinAreasResult();
    result.hasChanges = false;

    List<Way> allStartingWays = new ArrayList<Way>();
    List<Way> innerStartingWays = new ArrayList<Way>();
    List<Way> outerStartingWays = new ArrayList<Way>();

    for (Multipolygon area : areas) {
      outerStartingWays.add(area.outerWay);
      innerStartingWays.addAll(area.innerWays);
    }

    allStartingWays.addAll(innerStartingWays);
    allStartingWays.addAll(outerStartingWays);

    // first remove nodes in the same coordinate
    boolean removedDuplicates = false;
    removedDuplicates |= removeDuplicateNodes(allStartingWays);

    if (removedDuplicates) {
      result.hasChanges = true;
      commitCommands(marktr("Removed duplicate nodes"));
    }

    // find intersection points
    Set<Node> nodes = Geometry.addIntersections(allStartingWays, false, cmds);

    // no intersections, return.
    if (nodes.isEmpty()) return result;
    commitCommands(marktr("Added node on all intersections"));

    List<RelationRole> relations = new ArrayList<RelationRole>();

    // Remove ways from all relations so ways can be combined/split quietly
    for (Way way : allStartingWays) {
      relations.addAll(removeFromAllRelations(way));
    }

    // Don't warn now, because it will really look corrupted
    boolean warnAboutRelations = !relations.isEmpty() && allStartingWays.size() > 1;

    List<WayInPolygon> preparedWays = new ArrayList<WayInPolygon>();

    for (Way way : outerStartingWays) {
      List<Way> splitWays = splitWayOnNodes(way, nodes);
      preparedWays.addAll(markWayInsideSide(splitWays, false));
    }

    for (Way way : innerStartingWays) {
      List<Way> splitWays = splitWayOnNodes(way, nodes);
      preparedWays.addAll(markWayInsideSide(splitWays, true));
    }

    // Find boundary ways
    List<Way> discardedWays = new ArrayList<Way>();
    List<AssembledPolygon> bounadries = findBoundaryPolygons(preparedWays, discardedWays);

    // find polygons
    List<AssembledMultipolygon> preparedPolygons = findPolygons(bounadries);

    // assemble final polygons
    List<Multipolygon> polygons = new ArrayList<Multipolygon>();
    Set<Relation> relationsToDelete = new LinkedHashSet<Relation>();

    for (AssembledMultipolygon pol : preparedPolygons) {

      // create the new ways
      Multipolygon resultPol = joinPolygon(pol);

      // create multipolygon relation, if necessary.
      RelationRole ownMultipolygonRelation =
          addOwnMultigonRelation(resultPol.innerWays, resultPol.outerWay);

      // add back the original relations, merged with our new multipolygon relation
      fixRelations(relations, resultPol.outerWay, ownMultipolygonRelation, relationsToDelete);

      // strip tags from inner ways
      // TODO: preserve tags on existing inner ways
      stripTags(resultPol.innerWays);

      polygons.add(resultPol);
    }

    commitCommands(marktr("Assemble new polygons"));

    for (Relation rel : relationsToDelete) {
      cmds.add(new DeleteCommand(rel));
    }

    commitCommands(marktr("Delete relations"));

    // Delete the discarded inner ways
    if (!discardedWays.isEmpty()) {
      Command deleteCmd = DeleteCommand.delete(Main.main.getEditLayer(), discardedWays, true);
      if (deleteCmd != null) {
        cmds.add(deleteCmd);
        commitCommands(marktr("Delete Ways that are not part of an inner multipolygon"));
      }
    }

    makeCommitsOneAction(marktr("Joined overlapping areas"));

    if (warnAboutRelations) {
      new Notification(
              tr(
                  "Some of the ways were part of relations that have been modified.<br>Please verify no errors have been introduced."))
          .setIcon(JOptionPane.INFORMATION_MESSAGE)
          .setDuration(Notification.TIME_LONG)
          .show();
    }

    result.hasChanges = true;
    result.polygons = polygons;
    return result;
  }