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

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

[josm_reltoolbox] Fix some warnings

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