Ticket #9599: 9599.patch

File 9599.patch, 5.1 KB (added by GerdP, 4 years ago)
  • src/org/openstreetmap/josm/actions/JoinAreasAction.java

     
    674674
    675675        List<WayInPolygon> preparedWays = new ArrayList<>();
    676676
     677        // maps oldest way referring to start of each part
     678        Map<Node, Way> oldestWayMap = new HashMap<>();
     679
    677680        for (Way way : outerStartingWays) {
    678681            List<Way> splitWays = splitWayOnNodes(way, nodes);
     682
     683            // see #9599
     684            if (!way.isNew() && splitWays.size() > 1) {
     685                for (Way part : splitWays) {
     686                    Node n = part.firstNode();
     687                    Way old = oldestWayMap.get(n);
     688                    if (old == null || old.getUniqueId() > way.getUniqueId()) {
     689                        oldestWayMap.put(n, way);
     690                    }
     691                }
     692            }
     693
    679694            preparedWays.addAll(markWayInsideSide(splitWays, false));
    680695        }
    681696
     
    721736
    722737        commitCommands(marktr("Delete relations"));
    723738
     739        // see #9599: result should contain original way(s) where possible
     740        if (discardedWays.stream().anyMatch(w -> !w.isNew())) {
     741            for (int i = 0; i < polygons.size(); i++) {
     742                Multipolygon mp = polygons.get(i);
     743                for (int k = 0; k < mp.getInnerWays().size(); k++) {
     744                    Way inner = mp.getInnerWays().get(k);
     745                    Way older = keepOlder(inner, oldestWayMap, discardedWays);
     746                    if (inner != older) {
     747                        mp.getInnerWays().set(k, older);
     748                    }
     749                }
     750                Way older = keepOlder(mp.outerWay, oldestWayMap, discardedWays);
     751                if (older != mp.outerWay) {
     752                    Multipolygon mpNew = new Multipolygon(older);
     753                    mpNew.innerWays.addAll(mp.getInnerWays());
     754                    polygons.set(i, mpNew);
     755                }
     756            }
     757            commitCommands(marktr("Keep older versions"));
     758        }
     759
    724760        // Delete the discarded inner ways
    725761        if (!discardedWays.isEmpty()) {
    726762            Command deleteCmd = DeleteCommand.delete(discardedWays, true);
     
    742778    }
    743779
    744780    /**
     781     * Create copy of given way using an older id so that we don't create a new way instead of a modified old one.
     782     * @param way the way to check
     783     * @param oldestWayMap  nodes from old ways
     784     * @param discardedWays collection of ways which will be deleted (modified)
     785     * @return a copy of the way with an older id or the way itself
     786     */
     787    private Way keepOlder(Way way, Map<Node, Way> oldestWayMap , List<Way> discardedWays) {
     788        Way oldest = null;
     789        for (Node n : way.getNodes()) {
     790            Way orig = oldestWayMap .get(way.firstNode());
     791            if (orig != null && (oldest == null || oldest.getUniqueId() > orig.getUniqueId())
     792                    && discardedWays.contains(orig)) {
     793                oldest = orig;
     794            }
     795        }
     796        if (oldest != null) {
     797            discardedWays.remove(oldest);
     798            discardedWays.add(way);
     799            Way copy = new Way(oldest);
     800            copy.setNodes(way.getNodes());
     801            cmds.add(new ChangeCommand(oldest, copy));
     802            return copy;
     803        }
     804        return way;
     805    }
     806
     807    /**
    745808     * Checks if tags of two given ways differ, and presents the user a dialog to solve conflicts
    746809     * @param polygons ways to check
    747810     * @return {@code true} if all conflicts are resolved, {@code false} if conflicts remain.
     
    10551118     * Uses {@link SplitWayCommand#splitWay} for the heavy lifting.
    10561119     * @param way way to split
    10571120     * @param nodes split points
    1058      * @return list of split ways (or original ways if no splitting is done).
     1121     * @return list of split ways (or original way if no splitting is done).
    10591122     */
    10601123    private List<Way> splitWayOnNodes(Way way, Set<Node> nodes) {
    10611124
     
    13721435
    13731436        //TODO: ReverseWay and Combine way are really slow and we use them a lot here. This slows down large joins.
    13741437        List<Way> actionWays = new ArrayList<>(ways.size());
    1375 
     1438        int oldestPos = 0;
     1439        Way oldest = ways.get(0).way;
    13761440        for (WayInPolygon way : ways) {
    13771441            actionWays.add(way.way);
     1442            if (oldest.isNew() || !way.way.isNew() && oldest.getUniqueId() > way.way.getUniqueId()) {
     1443                oldest = way.way;
     1444                oldestPos = actionWays.size() - 1;
     1445            }
    13781446
    13791447            if (!way.insideToTheRight) {
    13801448                ReverseWayResult res = ReverseWayAction.reverseWay(way.way);
     
    13831451            }
    13841452        }
    13851453
     1454        // see #9599: Help CombineWayAction to use the oldest way
     1455        Collections.rotate(actionWays, actionWays.size() - oldestPos);
     1456
    13861457        Pair<Way, Command> result = CombineWayAction.combineWaysWorker(actionWays);
    13871458        if (result == null) {
    13881459            throw new JosmRuntimeException("Join areas internal error.");