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

Last change on this file since 26882 was 26882, checked in by zverik, 13 years ago

ReconstructPolygonAction is done

File size: 4.9 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 commands.add(new DeleteCommand(r));
67
68 for( JoinedPolygon p : mpc.outerWays ) {
69 // move all tags from relation and common tags from ways
70 Map<String, String> tags = p.ways.get(0).getKeys();
71 List<OsmPrimitive> relations = p.ways.get(0).getReferrers();
72 Set<String> noTags = new HashSet<String>(r.keySet());
73 for( int i = 1; i < p.ways.size(); i++ ) {
74 Way w = p.ways.get(i);
75 for( String key : w.keySet() ) {
76 String value = w.get(key);
77 if( !noTags.contains(key) && tags.containsKey(key) && !tags.get(key).equals(value) ) {
78 tags.remove(key);
79 noTags.add(key);
80 }
81 }
82 List<OsmPrimitive> referrers = w.getReferrers();
83 for( Iterator<OsmPrimitive> ref1 = relations.iterator(); ref1.hasNext(); )
84 if( !referrers.contains(ref1.next()) )
85 ref1.remove();
86 }
87 tags.putAll(r.getKeys());
88 tags.remove("type");
89
90 // then delete ways that are not relevant (do not take part in other relations of have strange tags)
91 Way candidateWay = null;
92 for( Way w : p.ways ) {
93 if( w.getReferrers().equals(relations) ) {
94 // check tags that remain
95 Set<String> keys = new HashSet<String>(w.keySet());
96 keys.removeAll(tags.keySet());
97 keys.removeAll(IRRELEVANT_KEYS);
98 if( keys.isEmpty() ) {
99 if( candidateWay == null )
100 candidateWay = w;
101 else {
102 if( candidateWay.isNew() && !w.isNew() ) {
103 // prefer ways that are already in the database
104 Way tmp = w;
105 w = candidateWay;
106 candidateWay = w;
107 }
108 commands.add(new DeleteCommand(w));
109 }
110 }
111 }
112 }
113
114 // take the first way, put all nodes into it, making it a closed polygon
115 Way result = candidateWay == null ? new Way() : new Way(candidateWay);
116 result.setNodes(p.nodes);
117 result.addNode(result.firstNode());
118 result.setKeys(tags);
119 newSelection.add(candidateWay == null ? result : candidateWay);
120 commands.add(candidateWay == null ? new AddCommand(result) : new ChangeCommand(candidateWay, result));
121 }
122
123 Main.main.undoRedo.add(new SequenceCommand(tr("Reconstruct polygons from relation {0}",
124 r.getDisplayName(DefaultNameFormatter.getInstance())), commands));
125 Main.main.getCurrentDataSet().setSelected(newSelection);
126 }
127
128 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
129 setEnabled(isSuitableRelation(newRelation));
130 }
131
132 private boolean isSuitableRelation( Relation newRelation ) {
133 if( newRelation == null || !"multipolygon".equals(newRelation.get("type")) || newRelation.getMembersCount() == 0 )
134 return false;
135 else {
136 for( RelationMember m : newRelation.getMembers() )
137 if( "inner".equals(m.getRole()) )
138 return false;
139 return true;
140 }
141 }
142}
Note: See TracBrowser for help on using the repository browser.