Ignore:
Timestamp:
2009-03-30T16:32:25+02:00 (16 years ago)
Author:
stoecker
Message:

close #2343 - wrong joining - patch by xeen

File:
1 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/utilsplugin/src/UtilsPlugin/JoinAreasAction.java

    r13776 r14356  
    11package UtilsPlugin;
    22
     3import static org.openstreetmap.josm.tools.I18n.marktr;
    34import static org.openstreetmap.josm.tools.I18n.tr;
    45import static org.openstreetmap.josm.tools.I18n.trn;
     
    214215        ArrayList<OsmPrimitive> nodes = addIntersections(a, b);
    215216        if(nodes.size() == 0) return hadChanges;
    216         commitCommands("Added node on all intersections");
     217        commitCommands(marktr("Added node on all intersections"));
    217218
    218219        // Remove ways from all relations so ways can be combined/split quietly
     
    238239        if(innerWays != null && innerWays.size() > 0)
    239240            cmds.add(DeleteCommand.delete(innerWays, true));
    240         commitCommands("Delete Ways that are not part of an inner multipolygon");
     241        commitCommands(marktr("Delete Ways that are not part of an inner multipolygon"));
    241242
    242243        // We can attach our new multipolygon relation and pretend it has always been there
    243244        addOwnMultigonRelation(newInnerWays, outerWay, relations);
    244245        fixRelations(relations, outerWay);
    245         commitCommands("Fix relations");
     246        commitCommands(marktr("Fix relations"));
    246247
    247248        stripTags(newInnerWays);
    248249        makeCommitsOneAction(
    249             a.equals(b)
    250                 ? "Joined self-overlapping area " + a.getName()
    251                 : "Joined overlapping areas " + a.getName() + " and " + b.getName()
     250            same
     251                ? marktr("Joined self-overlapping area")
     252                : marktr("Joined overlapping areas")
    252253        );
    253254
     
    328329        cmds.add(new ChangeCommand(a, ax));
    329330        cmds.add(new ChangeCommand(b, bx));
    330         commitCommands("Fix tag conflicts");
     331        commitCommands(marktr("Fix tag conflicts"));
    331332        return false;
    332333    }
     
    477478        }
    478479
    479         commitCommands("Removed Element from Relations");
     480        commitCommands(marktr("Removed Element from Relations"));
    480481        return result;
    481482    }
     
    542543            for(Node n: multigonNodes) {
    543544                if(!((Way)w).nodes.contains(n) && poly.contains(latlonToXY(n.coor.lat()), latlonToXY(n.coor.lon()))) {
    544                     innerWays.addAll(getWaysByNode(multigonWays, n));
     545                    getWaysByNode(innerWays, multigonWays, n);
    545546                }
    546547            }
     
    557558    /**
    558559     * Finds all ways that contain the given node.
    559      * @param Collection<OsmPrimitive> A collection of OsmPrimitives, but only ways will be honored
     560     * @param Collection<Way> A list to which matching ways will be added
     561     * @param Collection<Way> A list of ways to check
    560562     * @param Node The node the ways should be checked against
    561      * @return Collection<Way> A list of ways that contain the given node
    562      */
    563     private Collection<Way> getWaysByNode(Collection<Way> w, Node n) {
    564         Collection<Way> deletedWays = new ArrayList<Way>();
     563     */
     564    private void getWaysByNode(Collection<Way> innerWays, Collection<Way> w, Node n) {
    565565        for(Way way : w) {
    566566            if(!((Way)way).nodes.contains(n)) continue;
    567             if(!deletedWays.contains(way)) deletedWays.add(way); // Will need this later for multigons
    568         }
    569         return deletedWays;
     567            if(!innerWays.contains(way)) innerWays.add(way); // Will need this later for multigons
     568        }
    570569    }
    571570
     
    588587        }
    589588
    590         commitCommands("Join Areas: Remove Short Ways");
    591         return joinWays(join);
     589        commitCommands(marktr("Join Areas: Remove Short Ways"));
     590        return closeWay(joinWays(join));
     591    }
     592
     593    /**
     594     * Ensures a way is closed. If it isn't, last and first node are connected.
     595     * @param Way the way to ensure it's closed
     596     * @return Way The joined way.
     597     */
     598    private Way closeWay(Way w) {
     599        if(w.isClosed())
     600            return w;
     601        Main.ds.setSelected(w);
     602        Way wnew = new Way(w);
     603        wnew.addNode(wnew.firstNode());
     604        cmds.add(new ChangeCommand(w, wnew));
     605        commitCommands(marktr("Closed Way"));
     606        return (Way)(Main.ds.getSelectedWays().toArray())[0];
    592607    }
    593608
     
    599614    private Way joinWays(ArrayList<Way> ways) {
    600615        if(ways.size() < 2) return ways.get(0);
    601         //Main.ds.setSelected(ways);
    602616
    603617        // This will turn ways so all of them point in the same direction and CombineAction won't bug
     
    618632        }
    619633        Main.ds.setSelected(ways);
     634        // TODO: It might be possible that a confirmation dialog is presented even after reversing (for
     635        // "strange" ways). If the user cancels this, makeCommitsOneAction will wrongly consume a previous
     636        // action. Make CombineWayAction either silent or expose its combining capabilities.
    620637        new CombineWayAction().actionPerformed(null);
    621638        cmdsCount++;
     
    641658        // inner multigon part will have at least two ways, so we can use this to find which ways do
    642659        // belong to the multigon.
    643         Collection<Way> possibleWays = new ArrayList<Way>();
     660        ArrayList<Way> possibleWays = new ArrayList<Way>();
    644661        wayIterator: for(Way w : uninterestingWays) {
    645662            boolean hasInnerNodes = false;
     
    648665                if(!hasInnerNodes && innerNodes.contains(n)) hasInnerNodes = true;
    649666            }
    650             if(!hasInnerNodes && w.nodes.size() >= 2) continue;
     667            if(!hasInnerNodes || w.nodes.size() < 2) continue;
    651668            possibleWays.add(w);
    652669        }
     670
     671        // This removes unnecessary ways that might have been added.
     672        removeAlmostAlikeWays(possibleWays);
     673        removePartlyUnconnectedWays(possibleWays);
    653674
    654675        // Join all ways that have one start/ending node in common
     
    685706        } while(joined != null);
    686707        return newInnerWays;
     708    }
     709
     710    /**
     711     * Removes almost alike ways (= ways that are on top of each other for all nodes)
     712     * @param ArrayList<Way> the ways to remove almost-duplicates from
     713     */
     714    private void removeAlmostAlikeWays(ArrayList<Way> ways) {
     715        Collection<Way> removables = new ArrayList<Way>();
     716        outer: for(int i=0; i < ways.size(); i++) {
     717            Way a = ways.get(i);
     718            for(int j=i+1; j < ways.size(); j++) {
     719                Way b = ways.get(j);
     720                List<Node> revNodes = new ArrayList<Node>(b.nodes);
     721                Collections.reverse(revNodes);
     722                if(a.nodes.equals(b.nodes) || a.nodes.equals(revNodes)) {
     723                    removables.add(a);
     724                    continue outer;
     725                }
     726            }
     727        }
     728        ways.removeAll(removables);
     729    }
     730
     731    /**
     732     * Removes ways from the given list whose starting or ending node doesn't
     733     * connect to other ways from the same list (it's like removing spikes).
     734     * @param ArrayList<Way> The list of ways to remove "spikes" from
     735     */
     736    private void removePartlyUnconnectedWays(ArrayList<Way> ways) {
     737        List<Way> removables = new ArrayList<Way>();
     738        for(Way a : ways) {
     739            if(a.isClosed()) continue;
     740            boolean connectedStart = false;
     741            boolean connectedEnd = false;
     742            for(Way b : ways) {
     743                if(a.equals(b))
     744                    continue;
     745                if(b.isFirstLastNode(a.firstNode()))
     746                    connectedStart = true;
     747                if(b.isFirstLastNode(a.lastNode()))
     748                    connectedEnd = true;
     749            }
     750            if(!connectedStart || !connectedEnd)
     751                removables.add(a);
     752        }
     753        ways.removeAll(removables);
    687754    }
    688755
     
    803870    private void stripTags(Collection<Way> ways) {
    804871        for(Way w: ways) stripTags(w);
    805         commitCommands("Remove tags from inner ways");
     872        commitCommands(marktr("Remove tags from inner ways"));
    806873    }
    807874
     
    825892        UndoRedoHandler ur = Main.main.undoRedo;
    826893        cmds.clear();
    827         for(int i = ur.commands.size() - cmdsCount; i < ur.commands.size(); i++)
     894        int i = Math.max(ur.commands.size() - cmdsCount, 0);
     895        for(; i < ur.commands.size(); i++)
    828896            cmds.add(ur.commands.get(i));
    829897
    830         for(int i = 0; i < cmdsCount; i++)
     898        for(i = 0; i < cmds.size(); i++)
    831899            ur.undo();
    832900
    833         commitCommands(message == null ? "Join Areas Function" : message);
     901        commitCommands(message == null ? marktr("Join Areas Function") : message);
    834902        cmdsCount = 0;
    835903    }
Note: See TracChangeset for help on using the changeset viewer.