Changeset 20799 in osm for applications


Ignore:
Timestamp:
2010-04-06T18:29:45+02:00 (15 years ago)
Author:
bastik
Message:

'don't break relations, when fixing duplicate ways'

Location:
applications/editors/josm/plugins/validator
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/validator/build.xml

    r20546 r20799  
    2626          ** update before publishing
    2727        -->
    28         <property name="commit.message" value="validator: fixed memory leak" />
     28        <property name="commit.message" value="don't break relations, when fixing duplicate ways" />
    2929        <property name="plugin.main.version" value="3118" />
    3030
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicateWay.java

    r19335 r20799  
    44
    55import java.util.Collection;
     6import java.util.HashSet;
    67import java.util.LinkedList;
    78import java.util.List;
     
    1011
    1112import org.openstreetmap.josm.Main;
     13import org.openstreetmap.josm.command.ChangeCommand;
    1214import org.openstreetmap.josm.command.Command;
    1315import org.openstreetmap.josm.command.DeleteCommand;
     
    1618import org.openstreetmap.josm.data.osm.Node;
    1719import org.openstreetmap.josm.data.osm.OsmPrimitive;
     20import org.openstreetmap.josm.data.osm.Relation;
     21import org.openstreetmap.josm.data.osm.RelationMember;
    1822import org.openstreetmap.josm.data.osm.Way;
    1923import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     
    107111    {
    108112        Collection<? extends OsmPrimitive> sel = testError.getPrimitives();
    109         LinkedList<Way> ways = new LinkedList<Way>();
     113        HashSet<Way> ways = new HashSet<Way>();
    110114
    111115        for (OsmPrimitive osm : sel)
     
    117121
    118122        long idToKeep = 0;
     123        Way wayToKeep = ways.iterator().next();
    119124        // Only one way will be kept - the one with lowest positive ID, if such exist
    120125        // or one "at random" if no such exists. Rest of the ways will be deleted
    121126        for (Way w: ways) {
    122127            if (!w.isNew()) {
    123                 if (idToKeep == 0 || w.getId() < idToKeep) idToKeep = w.getId();
     128                if (idToKeep == 0 || w.getId() < idToKeep) {
     129                    idToKeep = w.getId();
     130                    wayToKeep = w;
     131                }
    124132            }
    125133        }
    126134
    127         if (idToKeep > 0) {
    128             //Remove chosen way from the list, rest of ways in the list will be deleted
    129             for (Way w: ways) {
    130                 if (w.getId() == idToKeep) {
    131                         ways.remove(w);
    132                     break;
     135        // Find the way that is member of one or more relations. (If any)
     136        Way wayWithRelations = null;
     137        List<Relation> relations = null;
     138        for (Way w : ways) {
     139            List<Relation> rel = OsmPrimitive.getFilteredList(w.getReferrers(), Relation.class);
     140            if (!rel.isEmpty()) {
     141                if (wayWithRelations != null)
     142                    throw new AssertionError("Cannot fix duplicate Ways: More than one way is relation member.");
     143                wayWithRelations = w;
     144                relations = rel;
     145            }
     146        }
     147
     148        Collection<Command> commands = new LinkedList<Command>();
     149
     150        // Fix relations.
     151        if (wayWithRelations != null && wayToKeep != wayWithRelations) {
     152            for (Relation rel : relations) {
     153                Relation newRel = new Relation(rel);
     154                for (int i = 0; i < newRel.getMembers().size(); ++i) {
     155                    RelationMember m = newRel.getMember(i);
     156                    if (wayWithRelations.equals(m.getMember())) {
     157                        newRel.setMember(i, new RelationMember(m.getRole(), wayToKeep));
     158                    }
    133159                }
     160                commands.add(new ChangeCommand(rel, newRel));
    134161            }
    135         } else {
    136             //Remove first way from the list, delete the rest
    137             ways.remove(0);
    138162        }
    139163
    140164        //Delete all ways in the list
    141165        //Note: nodes are not deleted, these can be detected and deleted at next pass
    142         Collection<Command> commands = new LinkedList<Command>();
     166        ways.remove(wayToKeep);
    143167        commands.add(new DeleteCommand(ways));
    144168        Main.main.undoRedo.add(new SequenceCommand(tr("Delete duplicate ways"), commands));
     
    149173    public boolean isFixable(TestError testError)
    150174    {
    151         return (testError.getTester() instanceof DuplicateWay);
     175        if (!(testError.getTester() instanceof DuplicateWay))
     176            return false;
     177
     178        // We fix it only if there is no more than one way that is relation member.
     179        Collection<? extends OsmPrimitive> sel = testError.getPrimitives();
     180        HashSet<Way> ways = new HashSet<Way>();
     181
     182        for (OsmPrimitive osm : sel)
     183            if (osm instanceof Way)
     184                ways.add((Way)osm);
     185
     186        if (ways.size() < 2)
     187            return false;
     188
     189        int waysWithRelations = 0;
     190        for (Way w : ways) {
     191            List<Relation> rel = OsmPrimitive.getFilteredList(w.getReferrers(), Relation.class);
     192            if (!rel.isEmpty()) {
     193                ++waysWithRelations;
     194            }
     195        }
     196        return (waysWithRelations <= 1);
    152197    }
    153198}
Note: See TracChangeset for help on using the changeset viewer.