예제 #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
 /**
  * Collect all nodes with more than one referrer.
  *
  * @param ways Ways from witch nodes are selected
  * @return List of nodes with more than one referrer
  */
 private static List<Node> collectNodesWithExternReferers(List<Way> ways) {
   List<Node> withReferrers = new ArrayList<>();
   for (Way w : ways) {
     for (Node n : w.getNodes()) {
       if (n.getReferrers().size() > 1) {
         withReferrers.add(n);
       }
     }
   }
   return withReferrers;
 }
예제 #3
0
 /**
  * Determines if ways can be joined into a polygon.
  *
  * @param ways The ways collection to check
  * @return true if all ways can be joined into a polygon
  */
 protected static boolean checkWaysArePolygon(Collection<Way> ways) {
   // For each way, nodes strictly between first and last should't be reference by an other way
   for (Way way : ways) {
     for (Node node : way.getNodes()) {
       if (way.isFirstLastNode(node)) continue;
       for (Way wayOther : ways) {
         if (way == wayOther) continue;
         if (node.getReferrers().contains(wayOther)) return false;
       }
     }
   }
   // Test if ways can be joined
   Way currentWay = null;
   Node startNode = null, endNode = null;
   int used = 0;
   while (true) {
     Way nextWay = null;
     for (Way w : ways) {
       if (w.isClosed()) return ways.size() == 1;
       if (w == currentWay) continue;
       if (currentWay == null) {
         nextWay = w;
         startNode = w.firstNode();
         endNode = w.lastNode();
         break;
       }
       if (w.firstNode() == endNode) {
         nextWay = w;
         endNode = w.lastNode();
         break;
       }
       if (w.lastNode() == endNode) {
         nextWay = w;
         endNode = w.firstNode();
         break;
       }
     }
     if (nextWay == null) return false;
     used += 1;
     currentWay = nextWay;
     if (endNode == startNode) return used == ways.size();
   }
 }
예제 #4
0
파일: Addresses.java 프로젝트: jawohl/josm
 @Override
 public void visit(Node n) {
   List<Relation> associatedStreets = getAndCheckAssociatedStreets(n);
   // Find house number without proper location (neither addr:street, associatedStreet, addr:place
   // or addr:interpolation)
   if (n.hasKey(ADDR_HOUSE_NUMBER) && !n.hasKey(ADDR_STREET) && !n.hasKey(ADDR_PLACE)) {
     for (Relation r : associatedStreets) {
       if (r.hasTag("type", ASSOCIATED_STREET)) {
         return;
       }
     }
     for (Way w : OsmPrimitive.getFilteredList(n.getReferrers(), Way.class)) {
       if (w.hasKey(ADDR_INTERPOLATION) && w.hasKey(ADDR_STREET)) {
         return;
       }
     }
     // No street found
     errors.add(
         new AddressError(HOUSE_NUMBER_WITHOUT_STREET, n, tr("House number without street")));
   }
 }
예제 #5
0
 /**
  * Replies the collection of nodes referred to by primitives in <code>primitivesToDelete</code>
  * which can be deleted too. A node can be deleted if
  *
  * <ul>
  *   <li>it is untagged (see {@link Node#isTagged()}
  *   <li>it is not referred to by other non-deleted primitives outside of <code>primitivesToDelete
  *       </code>
  * </ul>
  *
  * @param primitivesToDelete the primitives to delete
  * @return the collection of nodes referred to by primitives in <code>primitivesToDelete</code>
  *     which can be deleted too
  */
 protected static Collection<Node> computeNodesToDelete(
     Collection<OsmPrimitive> primitivesToDelete) {
   Collection<Node> nodesToDelete = new HashSet<>();
   for (Way way : OsmPrimitive.getFilteredList(primitivesToDelete, Way.class)) {
     for (Node n : way.getNodes()) {
       if (n.isTagged()) {
         continue;
       }
       Collection<OsmPrimitive> referringPrimitives = n.getReferrers();
       referringPrimitives.removeAll(primitivesToDelete);
       int count = 0;
       for (OsmPrimitive p : referringPrimitives) {
         if (!p.isDeleted()) {
           count++;
         }
       }
       if (count == 0) {
         nodesToDelete.add(n);
       }
     }
   }
   return nodesToDelete;
 }
예제 #6
0
  @Override
  public void actionPerformed(ActionEvent e) {
    if (!isEnabled()) return;

    Collection<OsmPrimitive> sel = getCurrentDataSet().getAllSelected();
    layer = Main.map.mapView.getEditLayer();

    toPurge = new HashSet<OsmPrimitive>(sel);
    toPurgeAdditionally = new ArrayList<OsmPrimitive>();
    toPurgeChecked = new HashSet<OsmPrimitive>();

    // Add referrer, unless the object to purge is not new
    // and the parent is a relation
    HashSet<OsmPrimitive> toPurgeRecursive = new HashSet<OsmPrimitive>();
    while (!toPurge.isEmpty()) {

      for (OsmPrimitive osm : toPurge) {
        for (OsmPrimitive parent : osm.getReferrers()) {
          if (toPurge.contains(parent)
              || toPurgeChecked.contains(parent)
              || toPurgeRecursive.contains(parent)) {
            continue;
          }
          if (parent instanceof Way || (parent instanceof Relation && osm.isNew())) {
            toPurgeAdditionally.add(parent);
            toPurgeRecursive.add(parent);
          }
        }
        toPurgeChecked.add(osm);
      }
      toPurge = toPurgeRecursive;
      toPurgeRecursive = new HashSet<OsmPrimitive>();
    }

    makeIncomplete = new HashSet<OsmPrimitive>();

    // Find the objects that will be incomplete after purging.
    // At this point, all parents of new to-be-purged primitives are
    // also to-be-purged and
    // all parents of not-new to-be-purged primitives are either
    // to-be-purged or of type relation.
    TOP:
    for (OsmPrimitive child : toPurgeChecked) {
      if (child.isNew()) {
        continue;
      }
      for (OsmPrimitive parent : child.getReferrers()) {
        if (parent instanceof Relation && !toPurgeChecked.contains(parent)) {
          makeIncomplete.add(child);
          continue TOP;
        }
      }
    }

    // Add untagged way nodes. Do not add nodes that have other
    // referrers not yet to-be-purged.
    if (Main.pref.getBoolean("purge.add_untagged_waynodes", true)) {
      Set<OsmPrimitive> wayNodes = new HashSet<OsmPrimitive>();
      for (OsmPrimitive osm : toPurgeChecked) {
        if (osm instanceof Way) {
          Way w = (Way) osm;
          NODE:
          for (Node n : w.getNodes()) {
            if (n.isTagged() || toPurgeChecked.contains(n)) {
              continue;
            }
            for (OsmPrimitive ref : n.getReferrers()) {
              if (ref != w && !toPurgeChecked.contains(ref)) {
                continue NODE;
              }
            }
            wayNodes.add(n);
          }
        }
      }
      toPurgeChecked.addAll(wayNodes);
      toPurgeAdditionally.addAll(wayNodes);
    }

    if (Main.pref.getBoolean("purge.add_relations_with_only_incomplete_members", true)) {
      Set<Relation> relSet = new HashSet<Relation>();
      for (OsmPrimitive osm : toPurgeChecked) {
        for (OsmPrimitive parent : osm.getReferrers()) {
          if (parent instanceof Relation
              && !(toPurgeChecked.contains(parent))
              && hasOnlyIncompleteMembers((Relation) parent, toPurgeChecked, relSet)) {
            relSet.add((Relation) parent);
          }
        }
      }

      /** Add higher level relations (list gets extended while looping over it) */
      List<Relation> relLst = new ArrayList<Relation>(relSet);
      for (int i = 0; i < relLst.size(); ++i) {
        for (OsmPrimitive parent : relLst.get(i).getReferrers()) {
          if (!(toPurgeChecked.contains(parent))
              && hasOnlyIncompleteMembers((Relation) parent, toPurgeChecked, relLst)) {
            relLst.add((Relation) parent);
          }
        }
      }
      relSet = new HashSet<Relation>(relLst);
      toPurgeChecked.addAll(relSet);
      toPurgeAdditionally.addAll(relSet);
    }

    boolean modified = false;
    for (OsmPrimitive osm : toPurgeChecked) {
      if (osm.isModified()) {
        modified = true;
        break;
      }
    }

    ExtendedDialog confirmDlg =
        new ExtendedDialog(
            Main.parent, tr("Confirm Purging"), new String[] {tr("Purge"), tr("Cancel")});
    confirmDlg.setContent(buildPanel(modified), false);
    confirmDlg.setButtonIcons(new String[] {"ok", "cancel"});

    int answer = confirmDlg.showDialog().getValue();
    if (answer != 1) return;

    Main.pref.put("purge.clear_undo_redo", cbClearUndoRedo.isSelected());

    Main.main.undoRedo.add(
        new PurgeCommand(Main.map.mapView.getEditLayer(), toPurgeChecked, makeIncomplete));

    if (cbClearUndoRedo.isSelected()) {
      Main.main.undoRedo.clean();
      getCurrentDataSet().clearSelectionHistory();
    }
  }
예제 #7
0
 /**
  * Collect all nodes with more than one referrer.
  *
  * @param ways Ways from witch nodes are selected
  * @return List of nodes with more than one referrer
  */
 private List<Node> collectNodesWithExternReferers(List<Way> ways) {
   ArrayList<Node> withReferrers = new ArrayList<>();
   for (Way w : ways)
     for (Node n : w.getNodes()) if (n.getReferrers().size() > 1) withReferrers.add(n);
   return withReferrers;
 }