Changeset 428 in josm for trunk


Ignore:
Timestamp:
2007-10-26T10:21:22+02:00 (17 years ago)
Author:
gebner
Message:

Apply changes from CombineWayAction to MergeNodesAction.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/MergeNodesAction.java

    r424 r428  
    3939import org.openstreetmap.josm.data.osm.Node;
    4040import org.openstreetmap.josm.data.osm.NodePair;
     41import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor;
    4142import org.openstreetmap.josm.tools.GBC;
    4243
     
    9697        }
    9798
     99        private static class RelationRolePair {
     100                public Relation rel;
     101                public String role;
     102
     103                public RelationRolePair(Relation rel, String role) {
     104                        this.rel = rel;
     105                        this.role = role;
     106                }
     107
     108                @Override public boolean equals(Object o) {
     109                        return o instanceof RelationRolePair
     110                                && rel == ((RelationRolePair) o).rel
     111                                && role.equals(((RelationRolePair) o).role);
     112                }
     113
     114                @Override public int hashCode() {
     115                        return rel.hashCode() ^ role.hashCode();
     116                }
     117        }
     118
    98119        /**
    99120         * really do the merging - returns the node that is left
     
    102123                Node newNode = new Node(dest);
    103124
    104                 // Check whether all ways have identical relationship membership. More 
     125                // Check whether all ways have identical relationship membership. More
    105126                // specifically: If one of the selected ways is a member of relation X
    106127                // in role Y, then all selected ways must be members of X in role Y.
    107128
    108                 // FIXME: In a later revision, we should display some sort of conflict 
     129                // FIXME: In a later revision, we should display some sort of conflict
    109130                // dialog like we do for tags, to let the user choose which relations
    110131                // should be kept.
    111132
    112                 // Step 1, iterate over all relations and create counters indicating
    113                 // how many of the selected ways are part of relation X in role Y
    114                 // (hashMap backlinks contains keys formed like X@Y)
    115                 HashMap<String, Integer> backlinks = new HashMap<String, Integer>();
     133                // Step 1, iterate over all relations and figure out which of our
     134                // selected ways are members of a relation.
     135                HashMap<RelationRolePair, HashSet<Node>> backlinks =
     136                        new HashMap<RelationRolePair, HashSet<Node>>();
    116137                HashSet<Relation> relationsUsingNodes = new HashSet<Relation>();
    117138                for (Relation r : Main.ds.relations) {
     
    119140                        for (RelationMember rm : r.members) {
    120141                                if (rm.member instanceof Node) {
    121                                         for(Node n : allNodes) {
     142                                        for (Node n : allNodes) {
    122143                                                if (rm.member == n) {
    123                                                         String hash = Long.toString(r.id) + "@" + rm.role;
    124                                                         System.out.println(hash);
    125                                                         if (backlinks.containsKey(hash)) {
    126                                                                 backlinks.put(hash, new Integer(backlinks.get(hash)+1));
     144                                                        RelationRolePair pair = new RelationRolePair(r, rm.role);
     145                                                        HashSet<Node> nodelinks = new HashSet<Node>();
     146                                                        if (backlinks.containsKey(pair)) {
     147                                                                nodelinks = backlinks.get(pair);
    127148                                                        } else {
    128                                                                 backlinks.put(hash, 1);
     149                                                                nodelinks = new HashSet<Node>();
     150                                                                backlinks.put(pair, nodelinks);
    129151                                                        }
     152                                                        nodelinks.add(n);
     153
    130154                                                        // this is just a cache for later use
    131155                                                        relationsUsingNodes.add(r);
     
    136160                }
    137161
    138                 // Step 2, all values of the backlinks HashMap must now equal the size
    139                 // of the selection.
    140                 for (Integer i : backlinks.values()) {
    141                         if (i.intValue() != allNodes.size()) {
    142                                 JOptionPane.showMessageDialog(Main.parent, tr("The selected nodes cannot be merged as they have differing relation memberships."));
    143                                 return null;
     162                // Complain to the user if the ways don't have equal memberships.
     163                for (HashSet<Node> nodelinks : backlinks.values()) {
     164                        if (!nodelinks.containsAll(allNodes)) {
     165                                int option = JOptionPane.showConfirmDialog(Main.parent,
     166                                        tr("The selected nodes have differing relation memberships.  "
     167                                                + "Do you still want to merge them?"),
     168                                        tr("Merge nodes with different memberships?"),
     169                                        JOptionPane.YES_NO_OPTION);
     170                                if (option == JOptionPane.YES_OPTION) {
     171                                        break;
     172                                } else {
     173                                        return null;
     174                                }
    144175                        }
    145176                }
     
    181212                cmds.add(new ChangeCommand(dest, newNode));
    182213
    183                 // OK, now to merge the nodes - this should be fairly
    184                 // straightforward:
    185                 //   for each node in allNodes that is not newNode, do:
    186                 //     search all existing ways and replace references of
    187                 //     current node with newNode, then delete current node
    188 
    189214                Collection<OsmPrimitive> del = new HashSet<OsmPrimitive>();
    190215
     
    213238                        }
    214239                        if (nn.size() < 2) {
     240                                CollectBackReferencesVisitor backRefs =
     241                                        new CollectBackReferencesVisitor(Main.ds, false);
     242                                w.visit(backRefs);
     243                                if (!backRefs.data.isEmpty()) {
     244                                        JOptionPane.showMessageDialog(Main.parent,
     245                                                tr("Cannot merge nodes: " +
     246                                                        "Would have to delete a way that is still used."));
     247                                        return null;
     248                                }
    215249                                del.add(w);
    216250                        } else {
     
    223257
    224258                // delete any merged nodes
    225                 for (Node n : allNodes) {
    226                         if (n != dest) {
    227                                 del.add(n);
    228                         }
    229                 }
     259                del.addAll(allNodes);
     260                del.remove(dest);
    230261                if (!del.isEmpty()) cmds.add(new DeleteCommand(del));
    231262
     
    234265                        Relation newRel = new Relation(r);
    235266                        newRel.members.clear();
     267                        HashSet<String> rolesToReAdd = new HashSet<String>();
    236268                        for (RelationMember rm : r.members) {
    237                                 // only copy member if it is either the first of all the selected
    238                                 // nodes (indexOf==0) or not one of the selected nodes (indexOf==-1)
    239                                 if (allNodes.indexOf(rm.member) < 1) {
    240                                         newRel.members.add(new RelationMember(rm));
    241                                 }
     269                                // Don't copy the member if it points to one of our nodes,
     270                                // just keep a note to re-add it later on.
     271                                if (allNodes.contains(rm.member)) {
     272                                        rolesToReAdd.add(rm.role);
     273                                } else {
     274                                        newRel.members.add(rm);
     275                                }
     276                        }
     277                        for (String role : rolesToReAdd) {
     278                                newRel.members.add(new RelationMember(role, dest));
    242279                        }
    243280                        cmds.add(new ChangeCommand(r, newRel));
Note: See TracChangeset for help on using the changeset viewer.