source: osm/applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/ReconstructPolygonAction.java@ 30587

Last change on this file since 30587 was 30587, checked in by donvip, 11 years ago

[josm_reltoolbox] update to JOSM 7392

File size: 5.7 KB
Line 
1package relcontext.actions;
2
3import static org.openstreetmap.josm.tools.I18n.tr;
4
5import java.awt.event.ActionEvent;
6import java.util.ArrayList;
7import java.util.Arrays;
8import java.util.Collections;
9import java.util.HashSet;
10import java.util.Iterator;
11import java.util.List;
12import java.util.Map;
13import java.util.Set;
14
15import javax.swing.AbstractAction;
16import javax.swing.JOptionPane;
17
18import org.openstreetmap.josm.Main;
19import org.openstreetmap.josm.command.AddCommand;
20import org.openstreetmap.josm.command.ChangeCommand;
21import org.openstreetmap.josm.command.Command;
22import org.openstreetmap.josm.command.DeleteCommand;
23import org.openstreetmap.josm.command.SequenceCommand;
24import org.openstreetmap.josm.data.osm.MultipolygonBuilder;
25import org.openstreetmap.josm.data.osm.MultipolygonBuilder.JoinedPolygon;
26import org.openstreetmap.josm.data.osm.OsmPrimitive;
27import org.openstreetmap.josm.data.osm.Relation;
28import org.openstreetmap.josm.data.osm.RelationMember;
29import org.openstreetmap.josm.data.osm.Way;
30import org.openstreetmap.josm.gui.DefaultNameFormatter;
31import org.openstreetmap.josm.tools.ImageProvider;
32
33import relcontext.ChosenRelation;
34import relcontext.ChosenRelationListener;
35
36/**
37 * Make a single polygon out of the multipolygon relation. The relation must have only outer members.
38 * @author Zverik
39 */
40public class ReconstructPolygonAction extends AbstractAction implements ChosenRelationListener {
41 private ChosenRelation rel;
42
43 private static final List<String> IRRELEVANT_KEYS = Arrays.asList(new String[] {
44 "source", "created_by", "note"});
45
46 public ReconstructPolygonAction( ChosenRelation rel ) {
47 super(tr("Reconstruct polygon"));
48 putValue(SMALL_ICON, ImageProvider.get("dialogs", "filter"));
49 putValue(LONG_DESCRIPTION, "Reconstruct polygon from multipolygon relation");
50 this.rel = rel;
51 rel.addChosenRelationListener(this);
52 setEnabled(isSuitableRelation(rel.get()));
53 }
54
55 public void actionPerformed( ActionEvent e ) {
56 Relation r = rel.get();
57 List<Way> ways = new ArrayList<Way>();
58 boolean wont = false;
59 for( RelationMember m : r.getMembers() ) {
60 if( m.isWay() )
61 ways.add(m.getWay());
62 else
63 wont = true;
64 }
65 if( wont ) {
66 JOptionPane.showMessageDialog(Main.parent, tr("Multipolygon must consist only of ways"), tr("Reconstruct polygon"), JOptionPane.ERROR_MESSAGE);
67 return;
68 }
69
70 MultipolygonBuilder mpc = new MultipolygonBuilder();
71 String error = mpc.makeFromWays(ways);
72 if( error != null ) {
73 JOptionPane.showMessageDialog(Main.parent, error);
74 return;
75 }
76
77 if( !mpc.innerWays.isEmpty() ) {
78 JOptionPane.showMessageDialog(Main.parent, tr("Reconstruction of polygons can be done only from outer ways"), tr("Reconstruct polygon"), JOptionPane.ERROR_MESSAGE);
79 return;
80 }
81
82 rel.clear();
83 List<Way> newSelection = new ArrayList<Way>();
84 List<Command> commands = new ArrayList<Command>();
85 Command c = DeleteCommand.delete(Main.main.getEditLayer(), Collections.singleton(r), true, true);
86 if( c == null )
87 return;
88 commands.add(c);
89
90 for( JoinedPolygon p : mpc.outerWays ) {
91 // move all tags from relation and common tags from ways
92 Map<String, String> tags = p.ways.get(0).getKeys();
93 List<OsmPrimitive> relations = p.ways.get(0).getReferrers();
94 Set<String> noTags = new HashSet<String>(r.keySet());
95 for( int i = 1; i < p.ways.size(); i++ ) {
96 Way w = p.ways.get(i);
97 for( String key : w.keySet() ) {
98 String value = w.get(key);
99 if( !noTags.contains(key) && tags.containsKey(key) && !tags.get(key).equals(value) ) {
100 tags.remove(key);
101 noTags.add(key);
102 }
103 }
104 List<OsmPrimitive> referrers = w.getReferrers();
105 for( Iterator<OsmPrimitive> ref1 = relations.iterator(); ref1.hasNext(); )
106 if( !referrers.contains(ref1.next()) )
107 ref1.remove();
108 }
109 tags.putAll(r.getKeys());
110 tags.remove("type");
111
112 // then delete ways that are not relevant (do not take part in other relations of have strange tags)
113 Way candidateWay = null;
114 for( Way w : p.ways ) {
115 if( w.getReferrers().equals(relations) ) {
116 // check tags that remain
117 Set<String> keys = new HashSet<String>(w.keySet());
118 keys.removeAll(tags.keySet());
119 keys.removeAll(IRRELEVANT_KEYS);
120 if( keys.isEmpty() ) {
121 if( candidateWay == null )
122 candidateWay = w;
123 else {
124 if( candidateWay.isNew() && !w.isNew() ) {
125 // prefer ways that are already in the database
126 Way tmp = w;
127 w = candidateWay;
128 candidateWay = tmp;
129 }
130 commands.add(new DeleteCommand(w));
131 }
132 }
133 }
134 }
135
136 // take the first way, put all nodes into it, making it a closed polygon
137 Way result = candidateWay == null ? new Way() : new Way(candidateWay);
138 result.setNodes(p.nodes);
139 result.addNode(result.firstNode());
140 result.setKeys(tags);
141 newSelection.add(candidateWay == null ? result : candidateWay);
142 commands.add(candidateWay == null ? new AddCommand(result) : new ChangeCommand(candidateWay, result));
143 }
144
145 Main.main.undoRedo.add(new SequenceCommand(tr("Reconstruct polygons from relation {0}",
146 r.getDisplayName(DefaultNameFormatter.getInstance())), commands));
147 Main.main.getCurrentDataSet().setSelected(newSelection);
148 }
149
150 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
151 setEnabled(isSuitableRelation(newRelation));
152 }
153
154 private boolean isSuitableRelation( Relation newRelation ) {
155 if( newRelation == null || !"multipolygon".equals(newRelation.get("type")) || newRelation.getMembersCount() == 0 )
156 return false;
157 else {
158 for( RelationMember m : newRelation.getMembers() )
159 if( "inner".equals(m.getRole()) )
160 return false;
161 return true;
162 }
163 }
164}
Note: See TracBrowser for help on using the repository browser.