Ignore:
Timestamp:
2016-11-14T01:25:09+01:00 (8 years ago)
Author:
frederik
Message:

Make "reconstruct relation" option available for polygons with inner rings. Any outer ring that has an inner ring will be placed in a relation of its own and not reconstructed. This allows the reconstruction of large multipolygon relations with multiple outer rings, only some of which have an inner ring - at least those without can be turned into a way.

Also, copy tags from the first way only if that way has area tags, fixing a bug where highway or waterway tags would be copied from the first way onto the relation.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/ReconstructPolygonAction.java

    r32398 r33060  
    2323import org.openstreetmap.josm.command.DeleteCommand;
    2424import org.openstreetmap.josm.command.SequenceCommand;
     25import org.openstreetmap.josm.data.coor.EastNorth;
    2526import org.openstreetmap.josm.data.osm.MultipolygonBuilder;
    2627import org.openstreetmap.josm.data.osm.MultipolygonBuilder.JoinedPolygon;
     
    5758    public void actionPerformed(ActionEvent e) {
    5859        Relation r = rel.get();
     60        boolean relationReused = false;
    5961        List<Way> ways = new ArrayList<>();
    6062        boolean wont = false;
     
    7981        }
    8082
    81         if (!mpc.innerWays.isEmpty()) {
    82             JOptionPane.showMessageDialog(Main.parent,
    83                     tr("Reconstruction of polygons can be done only from outer ways"), tr("Reconstruct polygon"), JOptionPane.ERROR_MESSAGE);
     83        rel.clear();
     84        List<OsmPrimitive> newSelection = new ArrayList<>();
     85        List<Command> commands = new ArrayList<>();
     86        Command relationDeleteCommand = DeleteCommand.delete(Main.getLayerManager().getEditLayer(), Collections.singleton(r), true, true);
     87        if (relationDeleteCommand == null)
    8488            return;
    85         }
    86 
    87         rel.clear();
    88         List<Way> newSelection = new ArrayList<>();
    89         List<Command> commands = new ArrayList<>();
    90         Command c = DeleteCommand.delete(Main.getLayerManager().getEditLayer(), Collections.singleton(r), true, true);
    91         if (c == null)
    92             return;
    93         commands.add(c);
    9489
    9590        for (JoinedPolygon p : mpc.outerWays) {
     91
     92            ArrayList<JoinedPolygon> myInnerWays = new ArrayList<JoinedPolygon>();
     93            for (JoinedPolygon i : mpc.innerWays) {
     94                // if the first point of any inner ring is contained in this
     95                // outer ring, then this inner ring belongs to us. This
     96                // assumption only works if multipolygons have valid geometries
     97                EastNorth en = i.ways.get(0).firstNode().getEastNorth();
     98                if (p.area.contains(en.east(), en.north())) {
     99                    myInnerWays.add(i);
     100                }
     101            }
     102
     103            if (!myInnerWays.isEmpty()) {
     104                // this ring has inner rings, so we leave a multipolygon in
     105                // place and don't reconstruct the rings.
     106                Relation n = null;
     107                if (relationReused) {
     108                    n = new Relation();
     109                    n.setKeys(r.getKeys());
     110                } else {
     111                    n = new Relation(r);
     112                    n.setMembers(null);
     113                }
     114                for (Way w : p.ways) {
     115                    n.addMember(new RelationMember("outer", w));
     116                }
     117                for (JoinedPolygon i : myInnerWays) {
     118                    for (Way w : i.ways) {
     119                        n.addMember(new RelationMember("inner", w));
     120                    }
     121                }
     122                if (relationReused) {
     123                    commands.add(new AddCommand(n));
     124                } else {
     125                    relationReused = true;
     126                    commands.add(new ChangeCommand(r, n));
     127                }
     128                newSelection.add(n);
     129                continue;
     130            }
     131
    96132            // move all tags from relation and common tags from ways
     133            // start with all tags from first way but only if area tags are
     134            // present
    97135            Map<String, String> tags = p.ways.get(0).getKeys();
     136            if (!p.ways.get(0).hasAreaTags()) {
     137                tags.clear();
     138            }
    98139            List<OsmPrimitive> relations = p.ways.get(0).getReferrers();
    99140            Set<String> noTags = new HashSet<>(r.keySet());
     
    150191        }
    151192
     193        // only delete the relation if it hasn't been re-used
     194        if (!relationReused) {
     195            commands.add(relationDeleteCommand);
     196        }
     197
    152198        Main.main.undoRedo.add(new SequenceCommand(tr("Reconstruct polygons from relation {0}",
    153199                r.getDisplayName(DefaultNameFormatter.getInstance())), commands));
     
    164210            return false;
    165211        else {
    166             for (RelationMember m : newRelation.getMembers()) {
    167                 if ("inner".equals(m.getRole()))
    168                     return false;
    169             }
    170212            return true;
    171213        }
Note: See TracChangeset for help on using the changeset viewer.