Changeset 32395 in osm for applications/editors/josm/plugins/reltoolbox
- Timestamp:
- 2016-06-24T09:10:57+02:00 (9 years ago)
- Location:
- applications/editors/josm/plugins/reltoolbox
- Files:
-
- 2 added
- 35 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/reltoolbox/.project
r32286 r32395 16 16 </arguments> 17 17 </buildCommand> 18 <buildCommand> 19 <name>net.sf.eclipsecs.core.CheckstyleBuilder</name> 20 <arguments> 21 </arguments> 22 </buildCommand> 18 23 </buildSpec> 19 24 <natures> 20 25 <nature>org.eclipse.jdt.core.javanature</nature> 26 <nature>net.sf.eclipsecs.core.CheckstyleNature</nature> 21 27 </natures> 22 28 </projectDescription> -
applications/editors/josm/plugins/reltoolbox/build.xml
r31923 r32395 4 4 <property name="commit.message" value="RelToolbox: make natural sort for relation and find relation lists"/> 5 5 <!-- enter the *lowest* JOSM version this plugin is currently compatible with --> 6 <property name="plugin.main.version" value=" 7392"/>6 <property name="plugin.main.version" value="10279"/> 7 7 8 8 <property name="plugin.author" value="Ilya Zverev"/> -
applications/editors/josm/plugins/reltoolbox/src/relcontext/ChosenRelation.java
r30841 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext; 2 3 3 import java.awt.*; 4 import java.awt.AlphaComposite; 5 import java.awt.BasicStroke; 6 import java.awt.Color; 7 import java.awt.Composite; 8 import java.awt.Graphics2D; 9 import java.awt.Point; 10 import java.awt.Stroke; 4 11 import java.awt.geom.GeneralPath; 5 import java.util.*; 12 import java.util.HashSet; 13 import java.util.Set; 14 6 15 import org.openstreetmap.josm.Main; 7 16 import org.openstreetmap.josm.data.Bounds; 8 import org.openstreetmap.josm.data.osm.*; 9 import org.openstreetmap.josm.data.osm.event.*; 17 import org.openstreetmap.josm.data.osm.Node; 18 import org.openstreetmap.josm.data.osm.OsmPrimitive; 19 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 20 import org.openstreetmap.josm.data.osm.Relation; 21 import org.openstreetmap.josm.data.osm.Way; 22 import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent; 23 import org.openstreetmap.josm.data.osm.event.DataChangedEvent; 24 import org.openstreetmap.josm.data.osm.event.DataSetListener; 25 import org.openstreetmap.josm.data.osm.event.NodeMovedEvent; 26 import org.openstreetmap.josm.data.osm.event.PrimitivesAddedEvent; 27 import org.openstreetmap.josm.data.osm.event.PrimitivesRemovedEvent; 28 import org.openstreetmap.josm.data.osm.event.RelationMembersChangedEvent; 29 import org.openstreetmap.josm.data.osm.event.TagsChangedEvent; 30 import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent; 10 31 import org.openstreetmap.josm.gui.MapView; 11 import org.openstreetmap.josm.gui.MapView.EditLayerChangeListener; 32 import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent; 33 import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener; 12 34 import org.openstreetmap.josm.gui.layer.MapViewPaintable; 13 35 import org.openstreetmap.josm.gui.layer.OsmDataLayer; … … 18 40 * @author Zverik 19 41 */ 20 public class ChosenRelation implements EditLayerChangeListener, MapViewPaintable, DataSetListener {42 public class ChosenRelation implements ActiveLayerChangeListener, MapViewPaintable, DataSetListener { 21 43 protected Relation chosenRelation = null; 22 44 private Set<ChosenRelationListener> chosenRelationListeners = new HashSet<>(); 23 45 24 public void set( Relation rel) {25 if ( rel == chosenRelation || (rel != null && chosenRelation != null && rel.equals(chosenRelation)) ) {46 public void set(Relation rel) { 47 if (rel == chosenRelation || (rel != null && chosenRelation != null && rel.equals(chosenRelation))) 26 48 return; // new is the same as old 27 }28 49 Relation oldRel = chosenRelation; 29 50 chosenRelation = rel; … … 33 54 } 34 55 35 protected void fireRelationChanged( Relation oldRel) {36 for ( ChosenRelationListener listener : chosenRelationListeners )56 protected void fireRelationChanged(Relation oldRel) { 57 for (ChosenRelationListener listener : chosenRelationListeners) { 37 58 listener.chosenRelationChanged(oldRel, chosenRelation); 59 } 38 60 } 39 61 … … 46 68 } 47 69 48 public boolean isSame( Object r) {49 if (r == null )70 public boolean isSame(Object r) { 71 if (r == null ) 50 72 return chosenRelation == null; 51 else if (!(r instanceof Relation) )73 else if (!(r instanceof Relation) ) 52 74 return false; 53 75 else 54 76 return chosenRelation != null && r.equals(chosenRelation); 55 77 } 56 57 private final staticString[] MULTIPOLYGON_TYPES = new String[] {58 "multipolygon", "boundary"78 79 private static final String[] MULTIPOLYGON_TYPES = new String[] { 80 "multipolygon", "boundary" 59 81 }; 60 82 … … 66 88 } 67 89 68 public static boolean isMultipolygon( Relation r) {69 if (r == null )90 public static boolean isMultipolygon(Relation r) { 91 if (r == null ) 70 92 return false; 71 93 String type = r.get("type"); 72 if (type == null )94 if (type == null ) 73 95 return false; 74 for (String t : MULTIPOLYGON_TYPES )75 if (t.equals(type) )96 for (String t : MULTIPOLYGON_TYPES ) 97 if (t.equals(type) ) 76 98 return true; 77 99 return false; … … 90 112 } 91 113 92 public void addChosenRelationListener( ChosenRelationListener listener) {114 public void addChosenRelationListener(ChosenRelationListener listener) { 93 115 chosenRelationListeners.add(listener); 94 116 } 95 117 96 public void removeChosenRelationListener( ChosenRelationListener listener) {118 public void removeChosenRelationListener(ChosenRelationListener listener) { 97 119 chosenRelationListeners.remove(listener); 98 120 } 99 121 100 public void editLayerChanged( OsmDataLayer oldLayer, OsmDataLayer newLayer ) { 122 @Override 123 public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) { 101 124 // todo: dim chosen relation when changing layer 102 125 // todo: check this WTF! 126 OsmDataLayer newLayer = Main.getLayerManager().getEditLayer(); 103 127 clear(); 104 if ( newLayer != null && oldLayer == null) {128 if (newLayer != null && e.getPreviousEditLayer() == null) { 105 129 Main.map.mapView.addTemporaryLayer(this); 106 } else if ( newLayer == null) {130 } else if (newLayer == null) { 107 131 Main.map.mapView.removeTemporaryLayer(this); 108 132 } 109 133 } 110 134 111 public void paint( Graphics2D g, MapView mv, Bounds bbox ) { 112 if( chosenRelation == null ) { 135 @Override 136 public void paint(Graphics2D g, MapView mv, Bounds bbox) { 137 if (chosenRelation == null) 113 138 return; 114 }115 139 116 140 OsmDataLayer dataLayer = mv.getEditLayer(); 117 141 float opacity = dataLayer == null ? 0.0f : !dataLayer.isVisible() ? 0.0f : (float)dataLayer.getOpacity(); 118 if (opacity < 0.01 )142 if (opacity < 0.01 ) 119 143 return; 120 144 121 145 Composite oldComposite = g.getComposite(); 122 146 Stroke oldStroke = g.getStroke(); … … 124 148 g.setColor(Color.yellow); 125 149 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f * opacity)); 126 150 127 151 drawRelations(g, mv, bbox, chosenRelation); 128 152 129 153 g.setComposite(oldComposite); 130 154 g.setStroke(oldStroke); 131 132 } 155 156 } 157 133 158 private void drawRelations(Graphics2D g, MapView mv, Bounds bbox, Relation rel) { 134 for ( OsmPrimitive element : rel.getMemberPrimitives()) {135 if ( element.getType() == OsmPrimitiveType.NODE) {159 for (OsmPrimitive element : rel.getMemberPrimitives()) { 160 if (element.getType() == OsmPrimitiveType.NODE) { 136 161 Node node = (Node)element; 137 162 Point center = mv.getPoint(node); 138 163 g.drawOval(center.x - 4, center.y - 4, 9, 9); 139 } else if ( element.getType() == OsmPrimitiveType.WAY) {164 } else if (element.getType() == OsmPrimitiveType.WAY) { 140 165 Way way = (Way)element; 141 if ( way.getNodesCount() >= 2) {166 if (way.getNodesCount() >= 2) { 142 167 GeneralPath b = new GeneralPath(); 143 168 Point p = mv.getPoint(way.getNode(0)); 144 169 b.moveTo(p.x, p.y); 145 for ( int i = 1; i < way.getNodesCount(); i++) {170 for (int i = 1; i < way.getNodesCount(); i++) { 146 171 p = mv.getPoint(way.getNode(i)); 147 172 b.lineTo(p.x, p.y); … … 149 174 g.draw(b); 150 175 } 151 } else if ( element.getType() == OsmPrimitiveType.RELATION) {176 } else if (element.getType() == OsmPrimitiveType.RELATION) { 152 177 Color oldColor = g.getColor(); 153 178 g.setColor(Color.magenta); … … 159 184 } 160 185 161 public void relationMembersChanged( RelationMembersChangedEvent event ) { 162 if( chosenRelation != null && event.getRelation().equals(chosenRelation) ) 186 @Override 187 public void relationMembersChanged(RelationMembersChangedEvent event) { 188 if (chosenRelation != null && event.getRelation().equals(chosenRelation) ) { 163 189 fireRelationChanged(chosenRelation); 164 } 165 166 public void tagsChanged( TagsChangedEvent event ) { 167 if( chosenRelation != null && event.getPrimitive().equals(chosenRelation) ) 190 } 191 } 192 193 @Override 194 public void tagsChanged(TagsChangedEvent event) { 195 if (chosenRelation != null && event.getPrimitive().equals(chosenRelation) ) { 168 196 fireRelationChanged(chosenRelation); 169 } 170 171 public void dataChanged( DataChangedEvent event ) { 172 if( chosenRelation != null ) 197 } 198 } 199 200 @Override 201 public void dataChanged(DataChangedEvent event) { 202 if (chosenRelation != null ) { 173 203 fireRelationChanged(chosenRelation); 174 } 175 176 public void primitivesRemoved( PrimitivesRemovedEvent event ) { 177 if( chosenRelation != null && event.getPrimitives().contains(chosenRelation) ) 204 } 205 } 206 207 @Override 208 public void primitivesRemoved(PrimitivesRemovedEvent event) { 209 if (chosenRelation != null && event.getPrimitives().contains(chosenRelation) ) { 178 210 clear(); 179 } 180 181 public void wayNodesChanged( WayNodesChangedEvent event ) { 182 if( chosenRelation != null ) 211 } 212 } 213 214 @Override 215 public void wayNodesChanged(WayNodesChangedEvent event) { 216 if (chosenRelation != null ) 217 { 183 218 fireRelationChanged(chosenRelation); // download incomplete primitives doesn't cause dataChanged event 184 } 185 186 public void primitivesAdded( PrimitivesAddedEvent event ) {} 187 public void nodeMoved( NodeMovedEvent event ) {} 188 public void otherDatasetChange( AbstractDatasetChangedEvent event ) {} 219 } 220 } 221 222 @Override 223 public void primitivesAdded(PrimitivesAddedEvent event) {} 224 @Override 225 public void nodeMoved(NodeMovedEvent event) {} 226 @Override 227 public void otherDatasetChange(AbstractDatasetChangedEvent event) {} 189 228 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/ChosenRelationComponent.java
r30841 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext; 2 3 … … 18 19 public ChosenRelationComponent(ChosenRelation rel) { 19 20 super(""); 20 /* setBackground(Color.white);21 /* setBackground(Color.white); 21 22 setOpaque(true); 22 23 setBorder(new LineBorder(Color.black, 1, true));*/ … … 25 26 } 26 27 27 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) { 28 @Override 29 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) { 28 30 setText(prepareText(newRelation)); 29 31 repaint(); 30 32 } 31 33 32 34 private final static String[] TYPE_KEYS = new String[] { 33 "natural", "landuse", "place", "waterway", "leisure", "amenity", "restriction", "public_transport", "route", "enforcement"35 "natural", "landuse", "place", "waterway", "leisure", "amenity", "restriction", "public_transport", "route", "enforcement" 34 36 }; 35 37 36 38 private final static String[] NAMING_TAGS = new String[] { 37 "name", "place_name", "ref", "destination", "note"39 "name", "place_name", "ref", "destination", "note" 38 40 }; 39 41 40 protected String prepareText( Relation rel) {41 if (rel == null )42 protected String prepareText(Relation rel) { 43 if (rel == null ) 42 44 return ""; 43 45 44 46 String type = rel.get("type"); 45 if ( type == null || type.length() == 0 )47 if (type == null || type.length() == 0 ) { 46 48 type = "-"; 49 } 47 50 48 51 String tag = null; 49 for (int i = 0; i < TYPE_KEYS.length && tag == null; i++ )50 if ( rel.hasKey(TYPE_KEYS[i]))52 for (int i = 0; i < TYPE_KEYS.length && tag == null; i++ ) 53 if (rel.hasKey(TYPE_KEYS[i])) { 51 54 tag = TYPE_KEYS[i]; 52 if( tag != null ) 55 } 56 if (tag != null ) { 53 57 tag = tag.substring(0, 2) + "=" + rel.get(tag); 58 } 54 59 55 60 String name = null; 56 for (int i = 0; i < NAMING_TAGS.length && name == null; i++ )57 if ( rel.hasKey(NAMING_TAGS[i]) )61 for (int i = 0; i < NAMING_TAGS.length && name == null; i++ ) 62 if (rel.hasKey(NAMING_TAGS[i]) ) { 58 63 name = rel.get(NAMING_TAGS[i]); 64 } 59 65 60 66 StringBuilder sb = new StringBuilder(); 61 67 sb.append(type.substring(0, 1)); 62 if ( type.equals("boundary") && rel.hasKey("admin_level") )68 if (type.equals("boundary") && rel.hasKey("admin_level") ) { 63 69 sb.append(rel.get("admin_level")); 64 if( name != null ) 70 } 71 if (name != null ) { 65 72 sb.append(" \"").append(name).append('"'); 66 if( tag != null ) 73 } 74 if (tag != null ) { 67 75 sb.append("; ").append(tag); 76 } 68 77 sb.append(" (").append(rel.getMembersCount()).append(')'); 69 78 -
applications/editors/josm/plugins/reltoolbox/src/relcontext/ChosenRelationListener.java
r30841 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext; 2 3 … … 9 10 */ 10 11 public interface ChosenRelationListener { 11 void chosenRelationChanged( Relation oldRelation, Relation newRelation);12 void chosenRelationChanged(Relation oldRelation, Relation newRelation); 12 13 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/ExtraNameFormatHook.java
r30841 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext; 2 3 … … 8 9 /** 9 10 * Formatter hook for some tags that Dirk does not want to support. 10 * 11 * 11 12 * @author Zverik 12 13 */ 13 14 public class ExtraNameFormatHook implements NameFormatterHook { 14 15 15 public String checkRelationTypeName( IRelation relation, String defaultName ) { 16 return null; 16 @Override 17 public String checkRelationTypeName(IRelation relation, String defaultName) { 18 return null; 17 19 } 18 20 19 public String checkFormat( INode node, String defaultName ) { 20 return null; 21 @Override 22 public String checkFormat(INode node, String defaultName) { 23 return null; 21 24 } 22 25 23 public String checkFormat( IWay way, String defaultName ) { 24 if( way.get("place") != null && way.get("name") == null && way.get("place_name") != null ) 25 return way.get("place_name") + " " + defaultName; 26 return null; 26 @Override 27 public String checkFormat(IWay way, String defaultName) { 28 if (way.get("place") != null && way.get("name") == null && way.get("place_name") != null ) 29 return way.get("place_name") + " " + defaultName; 30 return null; 27 31 } 28 32 29 public String checkFormat( IRelation relation, String defaultName ) { 30 String type = relation.get("type"); 31 if( type != null ) { 32 String name = relation.get("destination"); 33 if( type.equals("destination_sign") && name != null ) { 34 if( relation.get("distance") != null ) 35 name += " " + relation.get("distance"); 36 if( defaultName.indexOf('"') < 0 ) 37 return '"' + name + "\" " + defaultName; 38 else 39 return defaultName.replaceFirst("\".?+\"", '"'+name+'"'); 33 @Override 34 public String checkFormat(IRelation relation, String defaultName) { 35 String type = relation.get("type"); 36 if (type != null) { 37 String name = relation.get("destination"); 38 if (type.equals("destination_sign") && name != null) { 39 if (relation.get("distance") != null ) { 40 name += " " + relation.get("distance"); 41 } 42 if (defaultName.indexOf('"') < 0 ) 43 return '"' + name + "\" " + defaultName; 44 else 45 return defaultName.replaceFirst("\".?+\"", '"'+name+'"'); 46 } 40 47 } 41 } 42 return null; 48 return null; 43 49 } 44 50 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/RelContextDialog.java
r30841 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext; 2 3 … … 103 104 public class RelContextDialog extends ToggleDialog implements EditLayerChangeListener, ChosenRelationListener, SelectionChangedListener { 104 105 105 public final staticString PREF_PREFIX = "reltoolbox";106 public static final String PREF_PREFIX = "reltoolbox"; 106 107 107 108 private final DefaultTableModel relationsData; … … 124 125 chosenRelation = new ChosenRelation(); 125 126 chosenRelation.addChosenRelationListener(this); 126 Ma pView.addEditLayerChangeListener(chosenRelation);127 Main.getLayerManager().addActiveLayerChangeListener(chosenRelation); 127 128 128 129 popupMenu = new ChosenRelationPopupMenu(chosenRelation); … … 144 145 roleBox.addItemListener(new ItemListener() { 145 146 @Override 146 public void itemStateChanged( ItemEvent e) {147 if (e.getStateChange() == ItemEvent.DESELECTED ) return;147 public void itemStateChanged(ItemEvent e) { 148 if (e.getStateChange() == ItemEvent.DESELECTED ) return; 148 149 String memberRole = roleBoxModel.getSelectedMembersRole(); 149 150 String selectedRole = roleBoxModel.isAnotherRoleSelected() ? askForRoleName() : roleBoxModel.getSelectedRole(); 150 if ( memberRole != null && selectedRole != null && !memberRole.equals(selectedRole)) {151 if (memberRole != null && selectedRole != null && !memberRole.equals(selectedRole)) { 151 152 applyRoleToSelection(selectedRole.trim()); 152 153 } … … 177 178 roleBox.addPropertyChangeListener("enabled", new PropertyChangeListener() { 178 179 @Override 179 public void propertyChange( PropertyChangeEvent evt) {180 public void propertyChange(PropertyChangeEvent evt) { 180 181 boolean showRoleBox = roleBox.isEnabled(); 181 182 roleBox.setVisible(showRoleBox); … … 186 187 sortAndFixAction.addPropertyChangeListener(new PropertyChangeListener() { 187 188 @Override 188 public void propertyChange( PropertyChangeEvent evt) {189 public void propertyChange(PropertyChangeEvent evt) { 189 190 sortAndFixButton.setVisible(sortAndFixAction.isEnabled()); 190 191 } … … 194 195 downloadChosenRelationAction.addPropertyChangeListener(new PropertyChangeListener() { 195 196 @Override 196 public void propertyChange( PropertyChangeEvent evt) {197 public void propertyChange(PropertyChangeEvent evt) { 197 198 downloadButton.setVisible(downloadChosenRelationAction.isEnabled()); 198 199 } 199 200 }); 200 201 downloadButton.setVisible(false); 201 if ( Main.pref.getBoolean(PREF_PREFIX + ".hidetopline", false) )202 if (Main.pref.getBoolean(PREF_PREFIX + ".hidetopline", false) ) { 202 203 chosenRelationPanel.setVisible(false); 204 } 203 205 204 206 // [+][Multi] [X]Adm [X]Tags [X]1 … … 209 211 final JButton multipolygonButton = new JButton(createMultipolygonAction); 210 212 bottomLine.add(multipolygonButton, GBC.std()); 211 // bottomLine.add(sizeButton(new JButton(new MultipolygonSettingsAction()), 16, 0), GBC.std().fill(GBC.VERTICAL));213 // bottomLine.add(sizeButton(new JButton(new MultipolygonSettingsAction()), 16, 0), GBC.std().fill(GBC.VERTICAL)); 212 214 bottomLine.add(Box.createHorizontalGlue(), GBC.std().fill()); 213 215 findRelationAction = new FindRelationAction(chosenRelation); … … 217 219 multipolygonButton.addMouseListener(new MouseAdapter() { 218 220 @Override 219 public void mousePressed( MouseEvent e) {221 public void mousePressed(MouseEvent e) { 220 222 checkPopup(e); 221 223 } 222 224 223 225 @Override 224 public void mouseReleased( MouseEvent e) {226 public void mouseReleased(MouseEvent e) { 225 227 checkPopup(e); 226 228 } 227 229 228 private void checkPopup( MouseEvent e) {229 if ( e.isPopupTrigger() )230 private void checkPopup(MouseEvent e) { 231 if (e.isPopupTrigger() ) { 230 232 multiPopupMenu.show(e.getComponent(), e.getX(), e.getY()); 233 } 231 234 } 232 235 }); … … 237 240 private static final Color CHOSEN_RELATION_COLOR = new Color(255, 255, 128); 238 241 239 private void configureRelationsTable( final JTable relationsTable) {242 private void configureRelationsTable(final JTable relationsTable) { 240 243 relationsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 241 244 relationsTable.setTableHeader(null); 242 245 relationsTable.addMouseListener(new MouseAdapter() { 243 246 @Override 244 public void mouseClicked( MouseEvent e) {247 public void mouseClicked(MouseEvent e) { 245 248 Point p = e.getPoint(); 246 249 int row = relationsTable.rowAtPoint(p); 247 if ( SwingUtilities.isLeftMouseButton(e) && row >= 0) {250 if (SwingUtilities.isLeftMouseButton(e) && row >= 0) { 248 251 Relation relation = (Relation)relationsData.getValueAt(row, 0); 249 if ( e.getClickCount() > 1) {252 if (e.getClickCount() > 1) { 250 253 Main.main.getEditLayer().data.setSelected(relation); 251 254 } … … 254 257 255 258 @Override 256 public void mousePressed( MouseEvent e) {259 public void mousePressed(MouseEvent e) { 257 260 checkPopup(e); 258 261 } 259 262 260 263 @Override 261 public void mouseReleased( MouseEvent e) {264 public void mouseReleased(MouseEvent e) { 262 265 checkPopup(e); 263 266 } 264 267 265 public void checkPopup( MouseEvent e) {266 if ( e.isPopupTrigger()) {268 public void checkPopup(MouseEvent e) { 269 if (e.isPopupTrigger()) { 267 270 Point p = e.getPoint(); 268 271 int row = relationsTable.rowAtPoint(p); … … 280 283 columns.getColumn(0).setCellRenderer(new OsmPrimitivRenderer() { 281 284 @Override 282 protected String getComponentToolTipText( OsmPrimitive value) {285 protected String getComponentToolTipText(OsmPrimitive value) { 283 286 return null; 284 287 } 285 288 286 289 @Override 287 public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {290 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 288 291 Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 289 if ( !isSelected && value instanceof Relation && chosenRelation.isSame(value) )292 if (!isSelected && value instanceof Relation && chosenRelation.isSame(value) ) { 290 293 c.setBackground(CHOSEN_RELATION_COLOR); 291 else294 } else { 292 295 c.setBackground(table.getBackground()); 296 } 293 297 return c; 294 298 } … … 297 301 columns.getColumn(1).setCellRenderer(new DefaultTableCellRenderer() { 298 302 @Override 299 public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {303 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 300 304 Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 301 if ( !isSelected && chosenRelation.isSame(table.getValueAt(row, 0)) )305 if (!isSelected && chosenRelation.isSame(table.getValueAt(row, 0)) ) { 302 306 c.setBackground(CHOSEN_RELATION_COLOR); 303 else307 } else { 304 308 c.setBackground(table.getBackground()); 309 } 305 310 return c; 306 311 } … … 310 315 relationsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { 311 316 @Override 312 public void valueChanged( ListSelectionEvent e) {317 public void valueChanged(ListSelectionEvent e) { 313 318 int selectedRow = relationsTable.getSelectedRow(); 314 if ( selectedRow >= 0) {319 if (selectedRow >= 0) { 315 320 chosenRelation.set((Relation)relationsData.getValueAt(selectedRow, 0)); 316 321 relationsTable.clearSelection(); … … 320 325 } 321 326 322 private JComponent sizeButton( JComponent b, int width, int height) {327 private JComponent sizeButton(JComponent b, int width, int height) { 323 328 Dimension pref = b.getPreferredSize(); 324 329 b.setPreferredSize(new Dimension(width <= 0 ? pref.width : width, height <= 0 ? pref.height : height)); … … 346 351 347 352 @Override 348 public void chosenRelationChanged( Relation oldRelation, Relation newRelation) {349 if ( chosenRelationPanel != null && Main.pref.getBoolean(PREF_PREFIX + ".hidetopline", false) )353 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) { 354 if (chosenRelationPanel != null && Main.pref.getBoolean(PREF_PREFIX + ".hidetopline", false) ) { 350 355 chosenRelationPanel.setVisible(newRelation != null); 351 if( Main.main.getCurrentDataSet() != null ) 356 } 357 if (Main.main.getCurrentDataSet() != null ) { 352 358 selectionChanged(Main.main.getCurrentDataSet().getSelected()); 359 } 353 360 roleBoxModel.update(); 354 361 // ? … … 356 363 357 364 @Override 358 public void selectionChanged( Collection<? extends OsmPrimitive> newSelection) {359 if (!isVisible() || relationsData == null )365 public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) { 366 if (!isVisible() || relationsData == null ) 360 367 return; 361 368 roleBoxModel.update(); … … 363 370 relationsData.setRowCount(0); 364 371 sortAndFixAction.chosenRelationChanged(chosenRelation.get(), chosenRelation.get()); 365 if (newSelection == null )372 if (newSelection == null ) 366 373 return; 367 374 368 375 Set<Relation> relations = new TreeSet<>( 369 376 DefaultNameFormatter.getInstance().getRelationComparator()); 370 for ( OsmPrimitive element : newSelection) {371 for ( OsmPrimitive ref : element.getReferrers()) {372 if ( ref instanceof Relation && !ref.isIncomplete() && !ref.isDeleted()) {377 for (OsmPrimitive element : newSelection) { 378 for (OsmPrimitive ref : element.getReferrers()) { 379 if (ref instanceof Relation && !ref.isIncomplete() && !ref.isDeleted()) { 373 380 relations.add((Relation) ref); 374 381 } … … 376 383 } 377 384 378 for ( Relation rel : relations) {385 for (Relation rel : relations) { 379 386 String role = null; 380 for ( RelationMember m : rel.getMembers()) {381 for ( OsmPrimitive element : newSelection) {382 if ( m.getMember().equals(element)) {383 if ( role == null )387 for (RelationMember m : rel.getMembers()) { 388 for (OsmPrimitive element : newSelection) { 389 if (m.getMember().equals(element)) { 390 if (role == null ) { 384 391 role = m.getRole(); 385 else if( !role.equals(m.getRole())) {392 } else if (!role.equals(m.getRole())) { 386 393 role = tr("<different>"); 387 394 break; … … 392 399 relationsData.addRow(new Object[] {rel, role == null ? "" : role}); 393 400 } 394 for (OsmPrimitive element : newSelection )395 if ( element instanceof Relation && !chosenRelation.isSame(element) )401 for (OsmPrimitive element : newSelection ) 402 if (element instanceof Relation && !chosenRelation.isSame(element) ) { 396 403 relationsData.addRow(new Object[] {element, ""}); 404 } 397 405 } 398 406 … … 406 414 407 415 @Override 408 public void editLayerChanged( OsmDataLayer oldLayer, OsmDataLayer newLayer) {416 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) { 409 417 updateSelection(); 410 418 } … … 428 436 ClassLoader classLoader = RelContextDialog.class.getClassLoader(); 429 437 try ( 430 InputStream possibleRolesStream = classLoader.getResourceAsStream(POSSIBLE_ROLES_FILE);431 BufferedReader r = new BufferedReader(new InputStreamReader(possibleRolesStream));432 ) {433 while( r.ready()) {438 InputStream possibleRolesStream = classLoader.getResourceAsStream(POSSIBLE_ROLES_FILE); 439 BufferedReader r = new BufferedReader(new InputStreamReader(possibleRolesStream)); 440 ) { 441 while(r.ready()) { 434 442 String line = r.readLine(); 435 443 StringTokenizer t = new StringTokenizer(line, " ,;:\""); 436 if ( t.hasMoreTokens()) {444 if (t.hasMoreTokens()) { 437 445 String type = t.nextToken(); 438 446 List<String> roles = new ArrayList<>(); 439 while( t.hasMoreTokens() )447 while(t.hasMoreTokens() ) { 440 448 roles.add(t.nextToken()); 449 } 441 450 result.put(type, roles); 442 451 } 443 452 } 444 } catch( Exception e) {453 } catch(Exception e) { 445 454 Main.error("[RelToolbox] Error reading possible roles file."); 446 455 Main.error(e); … … 453 462 454 463 List<String> items = new ArrayList<>(); 455 for ( String role : roleBoxModel.getRoles()) {456 if ( role.length() > 1 )464 for (String role : roleBoxModel.getRoles()) { 465 if (role.length() > 1 ) { 457 466 items.add(role); 467 } 458 468 } 459 469 final AutoCompletingComboBox role = new AutoCompletingComboBox(); … … 477 487 role.getEditor().addActionListener(new ActionListener() { 478 488 @Override 479 public void actionPerformed( ActionEvent e) {489 public void actionPerformed(ActionEvent e) { 480 490 dlg.setVisible(false); 481 491 optionPane.setValue(JOptionPane.OK_OPTION); … … 486 496 487 497 Object answer = optionPane.getValue(); 488 if (answer == null || answer == JOptionPane.UNINITIALIZED_VALUE489 || (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION) ) {498 if (answer == null || answer == JOptionPane.UNINITIALIZED_VALUE 499 || (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION)) 490 500 return null; 491 }492 501 493 502 return role.getEditor().getItem().toString().trim(); … … 496 505 private class ChosenRelationMouseAdapter extends MouseAdapter { 497 506 @Override 498 public void mouseClicked( MouseEvent e) {499 if (e.isControlDown() || !(e.getComponent() instanceof JComboBox ) ) // do not use left click handler on combo box500 if( SwingUtilities.isLeftMouseButton(e) && chosenRelation.get() != null && Main.main.getEditLayer() != null) {501 Main.main.getEditLayer().data.setSelected(chosenRelation.get());502 }503 } 504 505 @Override 506 public void mousePressed( MouseEvent e) {507 public void mouseClicked(MouseEvent e) { 508 if (e.isControlDown() || !(e.getComponent() instanceof JComboBox ) ) // do not use left click handler on combo box 509 if (SwingUtilities.isLeftMouseButton(e) && chosenRelation.get() != null && Main.main.getEditLayer() != null) { 510 Main.main.getEditLayer().data.setSelected(chosenRelation.get()); 511 } 512 } 513 514 @Override 515 public void mousePressed(MouseEvent e) { 507 516 checkPopup(e); 508 517 } 509 518 510 519 @Override 511 public void mouseReleased( MouseEvent e) {520 public void mouseReleased(MouseEvent e) { 512 521 checkPopup(e); 513 522 } 514 523 515 private void checkPopup( MouseEvent e) {516 if ( e.isPopupTrigger() && chosenRelation.get() != null) {524 private void checkPopup(MouseEvent e) { 525 if (e.isPopupTrigger() && chosenRelation.get() != null) { 517 526 popupMenu.show(e.getComponent(), e.getX(), e.getY() - 5); 518 527 } … … 521 530 522 531 private class ChosenRelationPopupMenu extends JPopupMenu { 523 public ChosenRelationPopupMenu( ChosenRelation chosenRelation) {532 public ChosenRelationPopupMenu(ChosenRelation chosenRelation) { 524 533 add(new SelectMembersAction(chosenRelation)); 525 534 add(new SelectRelationAction(chosenRelation)); … … 535 544 } 536 545 537 protected void applyRoleToSelection( String role) {538 if ( chosenRelation != null && chosenRelation.get() != null && Main.main.getCurrentDataSet() != null && !Main.main.getCurrentDataSet().selectionEmpty()) {546 protected void applyRoleToSelection(String role) { 547 if (chosenRelation != null && chosenRelation.get() != null && Main.main.getCurrentDataSet() != null && !Main.main.getCurrentDataSet().selectionEmpty()) { 539 548 Collection<OsmPrimitive> selected = Main.main.getCurrentDataSet().getSelected(); 540 549 Relation r = chosenRelation.get(); 541 550 List<Command> commands = new ArrayList<>(); 542 for ( int i = 0; i < r.getMembersCount(); i++) {551 for (int i = 0; i < r.getMembersCount(); i++) { 543 552 RelationMember m = r.getMember(i); 544 if ( selected.contains(m.getMember())) {545 if ( !role.equals(m.getRole())) {546 // r.setMember(i, new RelationMember(role, m.getMember()));553 if (selected.contains(m.getMember())) { 554 if (!role.equals(m.getRole())) { 555 // r.setMember(i, new RelationMember(role, m.getMember())); 547 556 commands.add(new ChangeRelationMemberRoleCommand(r, i, role)); 548 557 } 549 558 } 550 559 } 551 if ( !commands.isEmpty()) {552 // Main.main.undoRedo.add(new ChangeCommand(chosenRelation.get(), r));560 if (!commands.isEmpty()) { 561 // Main.main.undoRedo.add(new ChangeCommand(chosenRelation.get(), r)); 553 562 Main.main.undoRedo.add(new SequenceCommand(tr("Change relation member roles to {0}", role), commands)); 554 563 } … … 567 576 } 568 577 } 569 /*578 /* 570 579 private class MultipolygonSettingsAction extends AbstractAction { 571 580 public MultipolygonSettingsAction() { … … 575 584 } 576 585 577 public void actionPerformed( ActionEvent e) {586 public void actionPerformed(ActionEvent e) { 578 587 Component c = e.getSource() instanceof Component ? (Component)e.getSource() : Main.parent; 579 588 multiPopupMenu.show(c, 0, 0); … … 591 600 } 592 601 593 protected final JCheckBoxMenuItem addMenuItem( String property, String title) {602 protected final JCheckBoxMenuItem addMenuItem(String property, String title) { 594 603 String fullProperty = PREF_PREFIX + ".multipolygon." + property; 595 604 JCheckBoxMenuItem item = new JCheckBoxMenuItem(tr(title)); … … 602 611 603 612 @Override 604 public void actionPerformed( ActionEvent e) {613 public void actionPerformed(ActionEvent e) { 605 614 String property = e.getActionCommand(); 606 if ( property != null && property.length() > 0 && e.getSource() instanceof JCheckBoxMenuItem) {615 if (property != null && property.length() > 0 && e.getSource() instanceof JCheckBoxMenuItem) { 607 616 boolean value = ((JCheckBoxMenuItem)e.getSource()).isSelected(); 608 617 Main.pref.put(property, value); … … 617 626 super(tr("Change role"), (String)null, tr("Enter role for selected members"), 618 627 Shortcut.registerShortcut("reltoolbox:changerole", tr("Relation Toolbox: {0}", tr("Enter role for selected members")), 619 KeyEvent.VK_R, Shortcut.ALT_CTRL), false, "relcontext/enterrole", true);628 KeyEvent.VK_R, Shortcut.ALT_CTRL), false, "relcontext/enterrole", true); 620 629 chosenRelation.addChosenRelationListener(this); 621 630 updateEnabledState(); … … 623 632 624 633 @Override 625 public void actionPerformed( ActionEvent e) {626 if ( roleBoxModel.membersRole != null) {634 public void actionPerformed(ActionEvent e) { 635 if (roleBoxModel.membersRole != null) { 627 636 String role = askForRoleName(); 628 if ( role != null )637 if (role != null ) { 629 638 applyRoleToSelection(role); 630 } 631 } 632 633 @Override 634 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) { 639 } 640 } 641 } 642 643 @Override 644 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) { 635 645 setEnabled(newRelation != null); 636 646 } … … 645 655 private final String ANOTHER_ROLE = tr("another..."); 646 656 647 public RoleComboBoxModel( JComboBox<String> combobox) {657 public RoleComboBoxModel(JComboBox<String> combobox) { 648 658 super(); 649 659 this.combobox = combobox; … … 653 663 public void update() { 654 664 membersRole = getSelectedMembersRoleIntl(); 655 if ( membersRole == null) {656 if ( combobox.isEnabled() )665 if (membersRole == null) { 666 if (combobox.isEnabled() ) { 657 667 combobox.setEnabled(false); 668 } 658 669 return; 659 670 } 660 if ( !combobox.isEnabled() )671 if (!combobox.isEnabled() ) { 661 672 combobox.setEnabled(true); 673 } 662 674 663 675 List<String> items = new ArrayList<>(); 664 if ( chosenRelation != null && chosenRelation.get() != null) {665 if ( chosenRelation.isMultipolygon()) {676 if (chosenRelation != null && chosenRelation.get() != null) { 677 if (chosenRelation.isMultipolygon()) { 666 678 items.add("outer"); 667 679 items.add("inner"); 668 680 } 669 if ( chosenRelation.get().get("type") != null) {681 if (chosenRelation.get().get("type") != null) { 670 682 List<String> values = possibleRoles.get(chosenRelation.get().get("type")); 671 if ( values != null )683 if (values != null ) { 672 684 items.addAll(values); 673 } 674 for( RelationMember m : chosenRelation.get().getMembers() ) 675 if( m.getRole().length() > 0 && !items.contains(m.getRole()) ) 685 } 686 } 687 for (RelationMember m : chosenRelation.get().getMembers() ) 688 if (m.getRole().length() > 0 && !items.contains(m.getRole()) ) { 676 689 items.add(m.getRole()); 690 } 677 691 } 678 692 items.add(EMPTY_ROLE); 679 if ( !items.contains(membersRole) )693 if (!items.contains(membersRole) ) { 680 694 items.add(0, membersRole); 695 } 681 696 items.add(ANOTHER_ROLE); 682 697 roles = Collections.unmodifiableList(items); 683 698 684 if ( membersRole != null )699 if (membersRole != null ) { 685 700 setSelectedItem(membersRole); 686 else701 } else { 687 702 fireContentsChanged(this, -1, -1); 703 } 688 704 combobox.repaint(); 689 705 } … … 699 715 private String getSelectedMembersRoleIntl() { 700 716 String role = null; 701 if ( chosenRelation != null && chosenRelation.get() != null && Main.main.getCurrentDataSet() != null && !Main.main.getCurrentDataSet().selectionEmpty()) {717 if (chosenRelation != null && chosenRelation.get() != null && Main.main.getCurrentDataSet() != null && !Main.main.getCurrentDataSet().selectionEmpty()) { 702 718 Collection<OsmPrimitive> selected = Main.main.getCurrentDataSet().getSelected(); 703 for ( RelationMember m : chosenRelation.get().getMembers()) {704 if ( selected.contains(m.getMember())) {705 if ( role == null )719 for (RelationMember m : chosenRelation.get().getMembers()) { 720 if (selected.contains(m.getMember())) { 721 if (role == null ) { 706 722 role = m.getRole(); 707 else if( m.getRole() != null && !role.equals(m.getRole())) {723 } else if (m.getRole() != null && !role.equals(m.getRole())) { 708 724 role = tr("<different>"); 709 725 break; … … 725 741 726 742 @Override 727 public String getElementAt( int index) {743 public String getElementAt(int index) { 728 744 return getRole(index); 729 745 } 730 746 731 public String getRole( int index) {747 public String getRole(int index) { 732 748 return roles.get(index); 733 749 } 734 750 735 751 @Override 736 public void setSelectedItem( Object anItem) {752 public void setSelectedItem(Object anItem) { 737 753 int newIndex = anItem == null ? -1 : roles.indexOf(anItem); 738 if ( newIndex != selectedIndex) {754 if (newIndex != selectedIndex) { 739 755 selectedIndex = newIndex; 740 756 fireContentsChanged(this, -1, -1); -
applications/editors/josm/plugins/reltoolbox/src/relcontext/RelContextPlugin.java
r30841 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext; 2 3 … … 9 10 private RelContextDialog dialog; 10 11 11 public RelContextPlugin( PluginInformation info) {12 public RelContextPlugin(PluginInformation info) { 12 13 super(info); 13 DefaultNameFormatter.registerFormatHook(new ExtraNameFormatHook());14 DefaultNameFormatter.registerFormatHook(new ExtraNameFormatHook()); 14 15 } 15 16 16 17 @Override 17 public void mapFrameInitialized( MapFrame oldFrame, MapFrame newFrame) {18 if ( oldFrame == null && newFrame != null) {19 // if (dialog!=null) dialog.destroy();18 public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { 19 if (oldFrame == null && newFrame != null) { 20 // if (dialog!=null) dialog.destroy(); 20 21 dialog = new RelContextDialog(); 21 22 newFrame.addToggleDialog(dialog); -
applications/editors/josm/plugins/reltoolbox/src/relcontext/StaticChosenRelation.java
r30841 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext; 2 3 … … 10 11 public class StaticChosenRelation extends ChosenRelation { 11 12 12 public StaticChosenRelation( Relation rel) {13 public StaticChosenRelation(Relation rel) { 13 14 chosenRelation = rel; 14 15 analyse(); … … 16 17 17 18 @Override 18 public void set( Relation rel) {19 // throw new UnsupportedOperationException("Changing static relation is not supported.");19 public void set(Relation rel) { 20 // throw new UnsupportedOperationException("Changing static relation is not supported."); 20 21 } 21 22 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/AddRemoveMemberAction.java
r31662 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 2 3 … … 36 37 private SortAndFixAction sortAndFix; 37 38 38 public AddRemoveMemberAction( ChosenRelation rel, SortAndFixAction sortAndFix) {39 public AddRemoveMemberAction(ChosenRelation rel, SortAndFixAction sortAndFix) { 39 40 super(null, "relcontext/addremove", tr("Add/remove members from the chosen relation"), 40 41 Shortcut.registerShortcut("reltoolbox:addremove", tr("Relation Toolbox: {0}", tr("Add/remove members from the chosen relation")), 41 KeyEvent.VK_EQUALS, Shortcut.DIRECT), false);42 KeyEvent.VK_EQUALS, Shortcut.DIRECT), false); 42 43 this.rel = rel; 43 44 this.sortAndFix = sortAndFix; … … 46 47 } 47 48 48 public void actionPerformed( ActionEvent e ) { 49 if( rel.get() == null ) 49 @Override 50 public void actionPerformed(ActionEvent e) { 51 if (rel.get() == null ) 50 52 return; 51 53 … … 63 65 64 66 // 2. add all new members 65 for ( OsmPrimitive p : toAdd) {67 for (OsmPrimitive p : toAdd) { 66 68 int pos = -1; //p instanceof Way ? findAdjacentMember(p, r) : -1; 67 if ( pos < 0 )69 if (pos < 0 ) { 68 70 r.addMember(new RelationMember("", p)); 69 else71 } else { 70 72 r.addMember(pos, new RelationMember("", p)); 73 } 71 74 } 72 75 73 76 // 3. check for roles again (temporary) 74 77 Command roleFix = !isBroken && sortAndFix.needsFixing(r) ? sortAndFix.fixRelation(r) : null; 75 if ( roleFix != null )78 if (roleFix != null ) { 76 79 roleFix.executeCommand(); 80 } 77 81 78 if ( !r.getMemberPrimitives().equals(rel.get().getMemberPrimitives()) )82 if (!r.getMemberPrimitives().equals(rel.get().getMemberPrimitives()) ) { 79 83 Main.main.undoRedo.add(new ChangeCommand(rel.get(), r)); 84 } 80 85 } 81 86 … … 84 89 * @see org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel#determineDirection 85 90 */ 86 protected int findAdjacentMember( Way w, Relation r) {91 protected int findAdjacentMember(Way w, Relation r) { 87 92 Node firstNode = w.firstNode(); 88 93 Node lastNode = w.lastNode(); 89 94 90 if ( firstNode != null && !firstNode.equals(lastNode)) {91 for ( int i = 0; i < r.getMembersCount(); i++) {92 if ( r.getMember(i).getType().equals(OsmPrimitiveType.WAY)) {95 if (firstNode != null && !firstNode.equals(lastNode)) { 96 for (int i = 0; i < r.getMembersCount(); i++) { 97 if (r.getMember(i).getType().equals(OsmPrimitiveType.WAY)) { 93 98 Way rw = (Way)r.getMember(i).getMember(); 94 99 Node firstNodeR = rw.firstNode(); 95 100 Node lastNodeR = rw.lastNode(); 96 if (firstNode.equals(firstNodeR) || firstNode.equals(lastNodeR) || lastNode.equals(firstNodeR) || lastNode.equals(lastNodeR) )101 if (firstNode.equals(firstNodeR) || firstNode.equals(lastNodeR) || lastNode.equals(firstNodeR) || lastNode.equals(lastNodeR) ) 97 102 return i + 1; 98 103 } … … 102 107 } 103 108 104 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) { 109 @Override 110 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) { 105 111 updateEnabledState(); 106 112 } … … 112 118 113 119 @Override 114 protected void updateEnabledState( Collection<? extends OsmPrimitive> selection) {120 protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) { 115 121 updateIcon(); 116 if ( rel == null || rel.get() == null || selection == null || selection.isEmpty()) {122 if (rel == null || rel.get() == null || selection == null || selection.isEmpty()) { 117 123 setEnabled(false); 118 124 return; 119 125 } 120 if ( selection.size() == 1 && selection.contains(rel.get())) {126 if (selection.size() == 1 && selection.contains(rel.get())) { 121 127 setEnabled(false); 122 128 return; … … 128 134 // todo: change icon based on selection 129 135 final int state; // 0=unknown, 1=add, 2=remove, 3=both 130 if (getCurrentDataSet() == null || getCurrentDataSet().getSelected() == null131 || getCurrentDataSet().getSelected().isEmpty() || rel == null || rel.get() == null ) 136 if (getCurrentDataSet() == null || getCurrentDataSet().getSelected() == null 137 || getCurrentDataSet().getSelected().isEmpty() || rel == null || rel.get() == null ) { 132 138 state = 0; 133 else {139 } else { 134 140 Collection<OsmPrimitive> toAdd = new ArrayList<>(getCurrentDataSet().getSelected()); 135 141 toAdd.remove(rel.get()); 136 142 int selectedSize = toAdd.size(); 137 if ( selectedSize == 0 )143 if (selectedSize == 0 ) { 138 144 state = 0; 139 else {145 } else { 140 146 toAdd.removeAll(rel.get().getMemberPrimitives()); 141 if ( toAdd.isEmpty() )147 if (toAdd.isEmpty() ) { 142 148 state = 2; 143 else if( toAdd.size() < selectedSize )149 } else if (toAdd.size() < selectedSize ) { 144 150 state = 3; 145 else151 } else { 146 152 state = 1; 153 } 147 154 } 148 155 } … … 150 157 @Override 151 158 public void run() { 152 // String name = state == 0 ? "?" : state == 1 ? "+" : state == 2 ? "-" : "±";153 // putValue(Action.NAME, name);159 // String name = state == 0 ? "?" : state == 1 ? "+" : state == 2 ? "-" : "±"; 160 // putValue(Action.NAME, name); 154 161 if (state == 0) { 155 // putValue(NAME, "?");162 // putValue(NAME, "?"); 156 163 putValue(LARGE_ICON_KEY, ImageProvider.get("relcontext", "addremove")); 157 164 } else { -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/ClearChosenRelationAction.java
r25695 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 2 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 3 6 import java.awt.event.ActionEvent; 7 4 8 import javax.swing.AbstractAction; 5 9 import javax.swing.Action; 6 import static org.openstreetmap.josm.tools.I18n.tr; 10 7 11 import org.openstreetmap.josm.data.osm.Relation; 8 12 import org.openstreetmap.josm.tools.ImageProvider; 13 9 14 import relcontext.ChosenRelation; 10 15 import relcontext.ChosenRelationListener; … … 13 18 private ChosenRelation rel; 14 19 15 public ClearChosenRelationAction( ChosenRelation rel) {20 public ClearChosenRelationAction(ChosenRelation rel) { 16 21 super(); 17 // putValue(Action.NAME, "X");22 // putValue(Action.NAME, "X"); 18 23 putValue(Action.SMALL_ICON, ImageProvider.get("relcontext", "clear")); 19 24 putValue(Action.SHORT_DESCRIPTION, tr("Clear the chosen relation")); … … 23 28 } 24 29 25 public void actionPerformed( ActionEvent e ) { 30 @Override 31 public void actionPerformed(ActionEvent e) { 26 32 rel.clear(); 27 33 } 28 34 29 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) { 35 @Override 36 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) { 30 37 setEnabled(newRelation != null); 31 38 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/CreateMultipolygonAction.java
r30738 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 2 5 3 6 import java.awt.Dialog.ModalityType; 4 7 import java.awt.GridBagLayout; 5 import static org.openstreetmap.josm.tools.I18n.tr;6 8 import java.awt.event.ActionEvent; 7 9 import java.awt.event.ActionListener; 8 10 import java.awt.event.KeyEvent; 9 import java.util.*; 10 import javax.swing.*; 11 import java.util.ArrayList; 12 import java.util.Arrays; 13 import java.util.Collection; 14 import java.util.HashMap; 15 import java.util.HashSet; 16 import java.util.List; 17 import java.util.Map; 18 import java.util.Set; 19 import java.util.TreeSet; 20 21 import javax.swing.Box; 22 import javax.swing.JDialog; 23 import javax.swing.JLabel; 24 import javax.swing.JOptionPane; 25 import javax.swing.JPanel; 26 import javax.swing.JTextField; 27 11 28 import org.openstreetmap.josm.Main; 12 29 import org.openstreetmap.josm.actions.JosmAction; 13 import org.openstreetmap.josm.command.*; 14 import org.openstreetmap.josm.data.osm.*; 30 import org.openstreetmap.josm.command.AddCommand; 31 import org.openstreetmap.josm.command.ChangeCommand; 32 import org.openstreetmap.josm.command.ChangePropertyCommand; 33 import org.openstreetmap.josm.command.Command; 34 import org.openstreetmap.josm.command.SequenceCommand; 35 import org.openstreetmap.josm.data.osm.MultipolygonBuilder; 36 import org.openstreetmap.josm.data.osm.Node; 37 import org.openstreetmap.josm.data.osm.OsmPrimitive; 38 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 39 import org.openstreetmap.josm.data.osm.Relation; 40 import org.openstreetmap.josm.data.osm.RelationMember; 41 import org.openstreetmap.josm.data.osm.Way; 15 42 import org.openstreetmap.josm.tools.GBC; 16 43 import org.openstreetmap.josm.tools.Shortcut; 44 17 45 import relcontext.ChosenRelation; 18 46 … … 27 55 protected ChosenRelation chRel; 28 56 29 public CreateMultipolygonAction( ChosenRelation chRel) {30 super("Multi", "data/multipolygon", tr("Create a multipolygon from selected objects"),31 Shortcut.registerShortcut("reltoolbox:multipolygon", tr("Relation Toolbox: {0}", tr("Create multipolygon")),32 KeyEvent.VK_A, Shortcut.ALT_CTRL), false);33 this.chRel = chRel;34 updateEnabledState();57 public CreateMultipolygonAction(ChosenRelation chRel) { 58 super("Multi", "data/multipolygon", tr("Create a multipolygon from selected objects"), 59 Shortcut.registerShortcut("reltoolbox:multipolygon", tr("Relation Toolbox: {0}", tr("Create multipolygon")), 60 KeyEvent.VK_A, Shortcut.ALT_CTRL), false); 61 this.chRel = chRel; 62 updateEnabledState(); 35 63 } 36 64 37 65 public CreateMultipolygonAction() { 38 this(null); 39 } 40 41 public static boolean getDefaultPropertyValue( String property ) { 42 if( property.equals("boundary") ) 43 return false; 44 else if( property.equals("boundaryways") ) 45 return true; 46 else if( property.equals("tags") ) 47 return true; 48 else if( property.equals("alltags") ) 49 return false; 50 else if( property.equals("single") ) 51 return true; 52 else if( property.equals("allowsplit") ) 53 return false; 54 throw new IllegalArgumentException(property); 55 } 56 57 private boolean getPref( String property ) { 58 return Main.pref.getBoolean(PREF_MULTIPOLY + property, getDefaultPropertyValue(property)); 59 } 60 61 public void actionPerformed( ActionEvent e ) { 62 boolean isBoundary = getPref("boundary"); 63 Collection<Way> selectedWays = getCurrentDataSet().getSelectedWays(); 64 if( !isBoundary && getPref("tags") ) { 65 List<Relation> rels = null; 66 if( getPref("allowsplit") || selectedWays.size() == 1 ) { 67 if( SplittingMultipolygons.canProcess(selectedWays) ) 68 rels = SplittingMultipolygons.process(getCurrentDataSet().getSelectedWays()); 66 this(null); 67 } 68 69 public static boolean getDefaultPropertyValue(String property) { 70 if (property.equals("boundary") ) 71 return false; 72 else if (property.equals("boundaryways") ) 73 return true; 74 else if (property.equals("tags") ) 75 return true; 76 else if (property.equals("alltags") ) 77 return false; 78 else if (property.equals("single") ) 79 return true; 80 else if (property.equals("allowsplit") ) 81 return false; 82 throw new IllegalArgumentException(property); 83 } 84 85 private boolean getPref(String property) { 86 return Main.pref.getBoolean(PREF_MULTIPOLY + property, getDefaultPropertyValue(property)); 87 } 88 89 @Override 90 public void actionPerformed(ActionEvent e) { 91 boolean isBoundary = getPref("boundary"); 92 Collection<Way> selectedWays = getCurrentDataSet().getSelectedWays(); 93 if (!isBoundary && getPref("tags")) { 94 List<Relation> rels = null; 95 if (getPref("allowsplit") || selectedWays.size() == 1) { 96 if (SplittingMultipolygons.canProcess(selectedWays) ) { 97 rels = SplittingMultipolygons.process(getCurrentDataSet().getSelectedWays()); 98 } 99 } else { 100 if (TheRing.areAllOfThoseRings(selectedWays)) { 101 List<Command> commands = new ArrayList<>(); 102 rels = TheRing.makeManySimpleMultipolygons(getCurrentDataSet().getSelectedWays(), commands); 103 if (!commands.isEmpty() ) { 104 Main.main.undoRedo.add(new SequenceCommand(tr("Create multipolygons from rings"), commands)); 105 } 106 } 107 } 108 if (rels != null && !rels.isEmpty()) { 109 if (chRel != null ) { 110 chRel.set(rels.size() == 1 ? rels.get(0) : null); 111 } 112 if (rels.size() == 1 ) { 113 getCurrentDataSet().setSelected(rels); 114 } else { 115 getCurrentDataSet().clearSelection(); 116 } 117 return; 118 } 119 } 120 121 // for now, just copying standard action 122 MultipolygonBuilder mpc = new MultipolygonBuilder(); 123 String error = mpc.makeFromWays(getCurrentDataSet().getSelectedWays()); 124 if (error != null) { 125 JOptionPane.showMessageDialog(Main.parent, error); 126 return; 127 } 128 Relation rel = new Relation(); 129 if (isBoundary) { 130 rel.put("type", "boundary"); 131 rel.put("boundary", "administrative"); 69 132 } else { 70 if( TheRing.areAllOfThoseRings(selectedWays) ) { 71 List<Command> commands = new ArrayList<>(); 72 rels = TheRing.makeManySimpleMultipolygons(getCurrentDataSet().getSelectedWays(), commands); 73 if( !commands.isEmpty() ) 74 Main.main.undoRedo.add(new SequenceCommand(tr("Create multipolygons from rings"), commands)); 75 } 76 } 77 if( rels != null && !rels.isEmpty() ) { 78 if( chRel != null ) 79 chRel.set(rels.size() == 1 ? rels.get(0) : null); 80 if( rels.size() == 1 ) 81 getCurrentDataSet().setSelected(rels); 82 else 83 getCurrentDataSet().clearSelection(); 84 return; 85 } 86 } 87 88 // for now, just copying standard action 89 MultipolygonBuilder mpc = new MultipolygonBuilder(); 90 String error = mpc.makeFromWays(getCurrentDataSet().getSelectedWays()); 91 if( error != null ) { 92 JOptionPane.showMessageDialog(Main.parent, error); 93 return; 94 } 95 Relation rel = new Relation(); 96 if( isBoundary ) { 97 rel.put("type", "boundary"); 98 rel.put("boundary", "administrative"); 99 } else 100 rel.put("type", "multipolygon"); 101 for( MultipolygonBuilder.JoinedPolygon poly : mpc.outerWays ) 102 for( Way w : poly.ways ) 103 rel.addMember(new RelationMember("outer", w)); 104 for( MultipolygonBuilder.JoinedPolygon poly : mpc.innerWays ) 105 for( Way w : poly.ways ) 106 rel.addMember(new RelationMember("inner", w)); 107 List<Command> list = removeTagsFromInnerWays(rel); 108 if( !list.isEmpty() && isBoundary ) { 109 Main.main.undoRedo.add(new SequenceCommand(tr("Move tags from ways to relation"), list)); 110 list = new ArrayList<>(); 111 } 112 if( isBoundary ) { 113 if( !askForAdminLevelAndName(rel) ) 114 return; 115 addBoundaryMembers(rel); 116 if( getPref("boundaryways") ) 117 list.addAll(fixWayTagsForBoundary(rel)); 118 } 119 list.add(new AddCommand(rel)); 120 Main.main.undoRedo.add(new SequenceCommand(tr("Create multipolygon"), list)); 121 122 if( chRel != null ) 123 chRel.set(rel); 124 125 getCurrentDataSet().setSelected(rel); 133 rel.put("type", "multipolygon"); 134 } 135 for (MultipolygonBuilder.JoinedPolygon poly : mpc.outerWays ) { 136 for (Way w : poly.ways ) { 137 rel.addMember(new RelationMember("outer", w)); 138 } 139 } 140 for (MultipolygonBuilder.JoinedPolygon poly : mpc.innerWays ) { 141 for (Way w : poly.ways ) { 142 rel.addMember(new RelationMember("inner", w)); 143 } 144 } 145 List<Command> list = removeTagsFromInnerWays(rel); 146 if (!list.isEmpty() && isBoundary) { 147 Main.main.undoRedo.add(new SequenceCommand(tr("Move tags from ways to relation"), list)); 148 list = new ArrayList<>(); 149 } 150 if (isBoundary) { 151 if (!askForAdminLevelAndName(rel) ) 152 return; 153 addBoundaryMembers(rel); 154 if (getPref("boundaryways") ) { 155 list.addAll(fixWayTagsForBoundary(rel)); 156 } 157 } 158 list.add(new AddCommand(rel)); 159 Main.main.undoRedo.add(new SequenceCommand(tr("Create multipolygon"), list)); 160 161 if (chRel != null ) { 162 chRel.set(rel); 163 } 164 165 getCurrentDataSet().setSelected(rel); 126 166 } 127 167 128 168 @Override 129 169 protected void updateEnabledState() { 130 if( getCurrentDataSet() == null) {131 setEnabled(false);132 } else {133 updateEnabledState(getCurrentDataSet().getSelected());134 }170 if (getCurrentDataSet() == null) { 171 setEnabled(false); 172 } else { 173 updateEnabledState(getCurrentDataSet().getSelected()); 174 } 135 175 } 136 176 137 177 @Override 138 protected void updateEnabledState( Collection<? extends OsmPrimitive> selection ) { 139 boolean isEnabled = true; 140 if( selection == null || selection.isEmpty() ) 141 isEnabled = false; 142 else { 143 if( !getPref("boundary") ) { 144 for( OsmPrimitive p : selection ) { 145 if( !(p instanceof Way) ) { 178 protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) { 179 boolean isEnabled = true; 180 if (selection == null || selection.isEmpty() ) { 146 181 isEnabled = false; 147 break; 148 } 149 } 150 } 151 } 152 setEnabled(isEnabled); 182 } else { 183 if (!getPref("boundary")) { 184 for (OsmPrimitive p : selection) { 185 if (!(p instanceof Way)) { 186 isEnabled = false; 187 break; 188 } 189 } 190 } 191 } 192 setEnabled(isEnabled); 153 193 } 154 194 … … 156 196 * Add selected nodes and relations with corresponding roles. 157 197 */ 158 private void addBoundaryMembers( Relation rel ) { 159 for( OsmPrimitive p : getCurrentDataSet().getSelected() ) { 160 String role = null; 161 if( p.getType().equals(OsmPrimitiveType.RELATION) ) { 162 role = "subarea"; 163 } else if( p.getType().equals(OsmPrimitiveType.NODE) ) { 164 Node n = (Node)p; 165 if( !n.isIncomplete() ) { 166 if( n.hasKey("place") ) 167 role = "admin_centre"; 168 else 169 role = "label"; 170 } 171 } 172 if( role != null ) 173 rel.addMember(new RelationMember(role, p)); 174 } 198 private void addBoundaryMembers(Relation rel) { 199 for (OsmPrimitive p : getCurrentDataSet().getSelected()) { 200 String role = null; 201 if (p.getType().equals(OsmPrimitiveType.RELATION)) { 202 role = "subarea"; 203 } else if (p.getType().equals(OsmPrimitiveType.NODE)) { 204 Node n = (Node)p; 205 if (!n.isIncomplete()) { 206 if (n.hasKey("place") ) { 207 role = "admin_centre"; 208 } else { 209 role = "label"; 210 } 211 } 212 } 213 if (role != null ) { 214 rel.addMember(new RelationMember(role, p)); 215 } 216 } 175 217 } 176 218 … … 178 220 * For all untagged ways in relation, add tags boundary and admin_level. 179 221 */ 180 private List<Command> fixWayTagsForBoundary( Relation rel ) { 181 List<Command> commands = new ArrayList<>(); 182 if( !rel.hasKey("boundary") || !rel.hasKey("admin_level") ) 222 private List<Command> fixWayTagsForBoundary(Relation rel) { 223 List<Command> commands = new ArrayList<>(); 224 if (!rel.hasKey("boundary") || !rel.hasKey("admin_level") ) 225 return commands; 226 String adminLevelStr = rel.get("admin_level"); 227 int adminLevel = 0; 228 try { 229 adminLevel = Integer.parseInt(adminLevelStr); 230 } catch(NumberFormatException e) { 231 return commands; 232 } 233 Set<OsmPrimitive> waysBoundary = new HashSet<>(); 234 Set<OsmPrimitive> waysAdminLevel = new HashSet<>(); 235 for (OsmPrimitive p : rel.getMemberPrimitives()) { 236 if (p instanceof Way) { 237 int count = 0; 238 if (p.hasKey("boundary") && p.get("boundary").equals("administrative") ) { 239 count++; 240 } 241 if (p.hasKey("admin_level") ) { 242 count++; 243 } 244 if (p.keySet().size() - count == 0) { 245 if (!p.hasKey("boundary") ) { 246 waysBoundary.add(p); 247 } 248 if (!p.hasKey("admin_level")) { 249 waysAdminLevel.add(p); 250 } else { 251 try { 252 int oldAdminLevel = Integer.parseInt(p.get("admin_level")); 253 if (oldAdminLevel > adminLevel ) { 254 waysAdminLevel.add(p); 255 } 256 } catch(NumberFormatException e) { 257 waysAdminLevel.add(p); // some garbage, replace it 258 } 259 } 260 } 261 } 262 } 263 if (!waysBoundary.isEmpty() ) { 264 commands.add(new ChangePropertyCommand(waysBoundary, "boundary", "administrative")); 265 } 266 if (!waysAdminLevel.isEmpty() ) { 267 commands.add(new ChangePropertyCommand(waysAdminLevel, "admin_level", adminLevelStr)); 268 } 183 269 return commands; 184 String adminLevelStr = rel.get("admin_level");185 int adminLevel = 0;186 try {187 adminLevel = Integer.parseInt(adminLevelStr);188 } catch( NumberFormatException e ) {189 return commands;190 }191 Set<OsmPrimitive> waysBoundary = new HashSet<>();192 Set<OsmPrimitive> waysAdminLevel = new HashSet<>();193 for( OsmPrimitive p : rel.getMemberPrimitives() ) {194 if( p instanceof Way ) {195 int count = 0;196 if( p.hasKey("boundary") && p.get("boundary").equals("administrative") )197 count++;198 if( p.hasKey("admin_level") )199 count++;200 if( p.keySet().size() - count == 0 ) {201 if( !p.hasKey("boundary") )202 waysBoundary.add(p);203 if( !p.hasKey("admin_level") ) {204 waysAdminLevel.add(p);205 } else {206 try {207 int oldAdminLevel = Integer.parseInt(p.get("admin_level"));208 if( oldAdminLevel > adminLevel )209 waysAdminLevel.add(p);210 } catch( NumberFormatException e ) {211 waysAdminLevel.add(p); // some garbage, replace it212 }213 }214 }215 }216 }217 if( !waysBoundary.isEmpty() )218 commands.add(new ChangePropertyCommand(waysBoundary, "boundary", "administrative"));219 if( !waysAdminLevel.isEmpty() )220 commands.add(new ChangePropertyCommand(waysAdminLevel, "admin_level", adminLevelStr));221 return commands;222 270 } 223 271 static public final List<String> DEFAULT_LINEAR_TAGS = Arrays.asList(new String[] {"barrier", "source"}); 224 272 private static final Set<String> REMOVE_FROM_BOUNDARY_TAGS = new TreeSet<>(Arrays.asList(new String[] { 225 "boundary", "boundary_type", "type", "admin_level"226 273 "boundary", "boundary_type", "type", "admin_level" 274 })); 227 275 228 276 /** … … 231 279 * Todo: rewrite it. 232 280 */ 233 private List<Command> removeTagsFromInnerWays( Relation relation ) { 234 Map<String, String> values = new HashMap<>(); 235 236 if( relation.hasKeys() ) { 237 for( String key : relation.keySet() ) { 238 values.put(key, relation.get(key)); 239 } 240 } 241 242 List<Way> innerWays = new ArrayList<>(); 243 List<Way> outerWays = new ArrayList<>(); 244 245 Set<String> conflictingKeys = new TreeSet<>(); 246 247 for( RelationMember m : relation.getMembers() ) { 248 249 if( m.hasRole() && "inner".equals(m.getRole()) && m.isWay() && m.getWay().hasKeys() ) { 250 innerWays.add(m.getWay()); 251 } 252 253 if( m.hasRole() && "outer".equals(m.getRole()) && m.isWay() && m.getWay().hasKeys() ) { 254 Way way = m.getWay(); 255 outerWays.add(way); 256 for( String key : way.keySet() ) { 257 if( !values.containsKey(key) ) { //relation values take precedence 258 values.put(key, way.get(key)); 259 } else if( !relation.hasKey(key) && !values.get(key).equals(way.get(key)) ) { 260 conflictingKeys.add(key); 261 } 262 } 263 } 264 } 265 266 // filter out empty key conflicts - we need second iteration 267 boolean isBoundary = getPref("boundary"); 268 if( isBoundary || !getPref("alltags") ) 269 for( RelationMember m : relation.getMembers() ) 270 if( m.hasRole() && m.getRole().equals("outer") && m.isWay() ) 271 for( String key : values.keySet() ) 272 if( !m.getWay().hasKey(key) && !relation.hasKey(key) ) 273 conflictingKeys.add(key); 274 275 for( String key : conflictingKeys ) 276 values.remove(key); 277 278 for( String linearTag : Main.pref.getCollection(PREF_MULTIPOLY + "lineartags", DEFAULT_LINEAR_TAGS) ) 279 values.remove(linearTag); 280 281 if( values.containsKey("natural") && values.get("natural").equals("coastline") ) 282 values.remove("natural"); 283 284 String name = values.get("name"); 285 if( isBoundary ) { 286 Set<String> keySet = new TreeSet<>(values.keySet()); 287 for( String key : keySet ) 288 if( !REMOVE_FROM_BOUNDARY_TAGS.contains(key) ) 281 private List<Command> removeTagsFromInnerWays(Relation relation) { 282 Map<String, String> values = new HashMap<>(); 283 284 if (relation.hasKeys()) { 285 for (String key : relation.keySet()) { 286 values.put(key, relation.get(key)); 287 } 288 } 289 290 List<Way> innerWays = new ArrayList<>(); 291 List<Way> outerWays = new ArrayList<>(); 292 293 Set<String> conflictingKeys = new TreeSet<>(); 294 295 for (RelationMember m : relation.getMembers()) { 296 297 if (m.hasRole() && "inner".equals(m.getRole()) && m.isWay() && m.getWay().hasKeys()) { 298 innerWays.add(m.getWay()); 299 } 300 301 if (m.hasRole() && "outer".equals(m.getRole()) && m.isWay() && m.getWay().hasKeys()) { 302 Way way = m.getWay(); 303 outerWays.add(way); 304 for (String key : way.keySet()) { 305 if (!values.containsKey(key)) { //relation values take precedence 306 values.put(key, way.get(key)); 307 } else if (!relation.hasKey(key) && !values.get(key).equals(way.get(key))) { 308 conflictingKeys.add(key); 309 } 310 } 311 } 312 } 313 314 // filter out empty key conflicts - we need second iteration 315 boolean isBoundary = getPref("boundary"); 316 if (isBoundary || !getPref("alltags") ) { 317 for (RelationMember m : relation.getMembers() ) 318 if (m.hasRole() && m.getRole().equals("outer") && m.isWay() ) { 319 for (String key : values.keySet() ) 320 if (!m.getWay().hasKey(key) && !relation.hasKey(key) ) { 321 conflictingKeys.add(key); 322 } 323 } 324 } 325 326 for (String key : conflictingKeys ) { 289 327 values.remove(key); 290 } 291 292 values.put("area", "yes"); 293 294 List<Command> commands = new ArrayList<>(); 295 boolean moveTags = getPref("tags"); 296 297 for( String key : values.keySet() ) { 298 List<OsmPrimitive> affectedWays = new ArrayList<>(); 299 String value = values.get(key); 300 301 for( Way way : innerWays ) { 302 if( way.hasKey(key) && (isBoundary || value.equals(way.get(key))) ) { 303 affectedWays.add(way); 304 } 305 } 306 307 if( moveTags ) { 308 // remove duplicated tags from outer ways 309 for( Way way : outerWays ) { 310 if( way.hasKey(key) ) { 311 affectedWays.add(way); 312 } 313 } 314 } 315 316 if( affectedWays.size() > 0 ) { 317 commands.add(new ChangePropertyCommand(affectedWays, key, null)); 318 } 319 } 320 321 if( moveTags ) { 322 // add those tag values to the relation 323 if( isBoundary ) 324 values.put("name", name); 325 boolean fixed = false; 326 Relation r2 = new Relation(relation); 327 for( String key : values.keySet() ) { 328 if( !r2.hasKey(key) && !key.equals("area") 329 && (!isBoundary || key.equals("admin_level") || key.equals("name")) ) { 330 if( relation.isNew() ) 331 relation.put(key, values.get(key)); 332 else 333 r2.put(key, values.get(key)); 334 fixed = true; 335 } 336 } 337 if( fixed && !relation.isNew() ) 338 commands.add(new ChangeCommand(relation, r2)); 339 } 340 341 return commands; 328 } 329 330 for (String linearTag : Main.pref.getCollection(PREF_MULTIPOLY + "lineartags", DEFAULT_LINEAR_TAGS) ) { 331 values.remove(linearTag); 332 } 333 334 if (values.containsKey("natural") && values.get("natural").equals("coastline") ) { 335 values.remove("natural"); 336 } 337 338 String name = values.get("name"); 339 if (isBoundary) { 340 Set<String> keySet = new TreeSet<>(values.keySet()); 341 for (String key : keySet ) 342 if (!REMOVE_FROM_BOUNDARY_TAGS.contains(key) ) { 343 values.remove(key); 344 } 345 } 346 347 values.put("area", "yes"); 348 349 List<Command> commands = new ArrayList<>(); 350 boolean moveTags = getPref("tags"); 351 352 for (String key : values.keySet()) { 353 List<OsmPrimitive> affectedWays = new ArrayList<>(); 354 String value = values.get(key); 355 356 for (Way way : innerWays) { 357 if (way.hasKey(key) && (isBoundary || value.equals(way.get(key)))) { 358 affectedWays.add(way); 359 } 360 } 361 362 if (moveTags) { 363 // remove duplicated tags from outer ways 364 for (Way way : outerWays) { 365 if (way.hasKey(key)) { 366 affectedWays.add(way); 367 } 368 } 369 } 370 371 if (affectedWays.size() > 0) { 372 commands.add(new ChangePropertyCommand(affectedWays, key, null)); 373 } 374 } 375 376 if (moveTags) { 377 // add those tag values to the relation 378 if (isBoundary ) { 379 values.put("name", name); 380 } 381 boolean fixed = false; 382 Relation r2 = new Relation(relation); 383 for (String key : values.keySet()) { 384 if (!r2.hasKey(key) && !key.equals("area") 385 && (!isBoundary || key.equals("admin_level") || key.equals("name"))) { 386 if (relation.isNew() ) { 387 relation.put(key, values.get(key)); 388 } else { 389 r2.put(key, values.get(key)); 390 } 391 fixed = true; 392 } 393 } 394 if (fixed && !relation.isNew() ) { 395 commands.add(new ChangeCommand(relation, r2)); 396 } 397 } 398 399 return commands; 342 400 } 343 401 … … 347 405 * @return false if user pressed "cancel". 348 406 */ 349 private boolean askForAdminLevelAndName( Relation rel ) { 350 String relAL = rel.get("admin_level"); 351 String relName = rel.get("name"); 352 if( relAL != null && relName != null ) 407 private boolean askForAdminLevelAndName(Relation rel) { 408 String relAL = rel.get("admin_level"); 409 String relName = rel.get("name"); 410 if (relAL != null && relName != null ) 411 return true; 412 413 JPanel panel = new JPanel(new GridBagLayout()); 414 panel.add(new JLabel(tr("Enter admin level and name for the border relation:")), GBC.eol().insets(0, 0, 0, 5)); 415 416 final JTextField admin = new JTextField(); 417 admin.setText(relAL != null ? relAL : Main.pref.get(PREF_MULTIPOLY + "lastadmin", "")); 418 panel.add(new JLabel(tr("Admin level")), GBC.std()); 419 panel.add(Box.createHorizontalStrut(10), GBC.std()); 420 panel.add(admin, GBC.eol().fill(GBC.HORIZONTAL).insets(0, 0, 0, 5)); 421 422 final JTextField name = new JTextField(); 423 if (relName != null ) { 424 name.setText(relName); 425 } 426 panel.add(new JLabel(tr("Name")), GBC.std()); 427 panel.add(Box.createHorizontalStrut(10), GBC.std()); 428 panel.add(name, GBC.eol().fill(GBC.HORIZONTAL)); 429 430 final JOptionPane optionPane = new JOptionPane(panel, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION) { 431 @Override 432 public void selectInitialValue() { 433 admin.requestFocusInWindow(); 434 admin.selectAll(); 435 } 436 }; 437 final JDialog dlg = optionPane.createDialog(Main.parent, tr("Create a new relation")); 438 dlg.setModalityType(ModalityType.DOCUMENT_MODAL); 439 440 name.addActionListener(new ActionListener() { 441 @Override 442 public void actionPerformed(ActionEvent e) { 443 dlg.setVisible(false); 444 optionPane.setValue(JOptionPane.OK_OPTION); 445 } 446 }); 447 448 dlg.setVisible(true); 449 450 Object answer = optionPane.getValue(); 451 if (answer == null || answer == JOptionPane.UNINITIALIZED_VALUE 452 || (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION)) 453 return false; 454 455 String admin_level = admin.getText().trim(); 456 String new_name = name.getText().trim(); 457 if (admin_level.equals("10") || (admin_level.length() == 1 && Character.isDigit(admin_level.charAt(0)))) { 458 rel.put("admin_level", admin_level); 459 Main.pref.put(PREF_MULTIPOLY + "lastadmin", admin_level); 460 } 461 if (new_name.length() > 0 ) { 462 rel.put("name", new_name); 463 } 353 464 return true; 354 355 JPanel panel = new JPanel(new GridBagLayout());356 panel.add(new JLabel(tr("Enter admin level and name for the border relation:")), GBC.eol().insets(0, 0, 0, 5));357 358 final JTextField admin = new JTextField();359 admin.setText(relAL != null ? relAL : Main.pref.get(PREF_MULTIPOLY + "lastadmin", ""));360 panel.add(new JLabel(tr("Admin level")), GBC.std());361 panel.add(Box.createHorizontalStrut(10), GBC.std());362 panel.add(admin, GBC.eol().fill(GBC.HORIZONTAL).insets(0, 0, 0, 5));363 364 final JTextField name = new JTextField();365 if( relName != null )366 name.setText(relName);367 panel.add(new JLabel(tr("Name")), GBC.std());368 panel.add(Box.createHorizontalStrut(10), GBC.std());369 panel.add(name, GBC.eol().fill(GBC.HORIZONTAL));370 371 final JOptionPane optionPane = new JOptionPane(panel, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION) {372 @Override373 public void selectInitialValue() {374 admin.requestFocusInWindow();375 admin.selectAll();376 }377 };378 final JDialog dlg = optionPane.createDialog(Main.parent, tr("Create a new relation"));379 dlg.setModalityType(ModalityType.DOCUMENT_MODAL);380 381 name.addActionListener(new ActionListener() {382 public void actionPerformed( ActionEvent e ) {383 dlg.setVisible(false);384 optionPane.setValue(JOptionPane.OK_OPTION);385 }386 });387 388 dlg.setVisible(true);389 390 Object answer = optionPane.getValue();391 if( answer == null || answer == JOptionPane.UNINITIALIZED_VALUE392 || (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION) ) {393 return false;394 }395 396 String admin_level = admin.getText().trim();397 String new_name = name.getText().trim();398 if( admin_level.equals("10") || (admin_level.length() == 1 && Character.isDigit(admin_level.charAt(0))) ) {399 rel.put("admin_level", admin_level);400 Main.pref.put(PREF_MULTIPOLY + "lastadmin", admin_level);401 }402 if( new_name.length() > 0 )403 rel.put("name", new_name);404 return true;405 465 } 406 466 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/CreateRelationAction.java
r27927 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 2 5 3 6 import java.awt.Dialog.ModalityType; 4 7 import java.awt.GridBagLayout; 5 import java.util.Collection;6 import org.openstreetmap.josm.data.osm.OsmPrimitive;7 import static org.openstreetmap.josm.tools.I18n.tr;8 8 import java.awt.event.ActionEvent; 9 9 import java.awt.event.ActionListener; 10 10 import java.awt.event.KeyEvent; 11 11 import java.util.Arrays; 12 import java.util.Collection; 12 13 import java.util.List; 14 13 15 import javax.swing.Box; 14 16 import javax.swing.JDialog; … … 16 18 import javax.swing.JOptionPane; 17 19 import javax.swing.JPanel; 20 18 21 import org.openstreetmap.josm.Main; 19 22 import org.openstreetmap.josm.actions.JosmAction; 20 23 import org.openstreetmap.josm.command.AddCommand; 24 import org.openstreetmap.josm.data.osm.OsmPrimitive; 21 25 import org.openstreetmap.josm.data.osm.Relation; 22 26 import org.openstreetmap.josm.data.osm.RelationMember; … … 24 28 import org.openstreetmap.josm.tools.GBC; 25 29 import org.openstreetmap.josm.tools.Shortcut; 30 26 31 import relcontext.ChosenRelation; 27 32 … … 36 41 protected ChosenRelation chRel; 37 42 38 public CreateRelationAction( ChosenRelation chRel) {43 public CreateRelationAction(ChosenRelation chRel) { 39 44 super(tr("New"), "data/relation", tr("Create a relation from selected objects"), 40 45 Shortcut.registerShortcut("reltoolbox:create", tr("Relation Toolbox: {0}", tr("Create a new relation")), 41 KeyEvent.VK_N, Shortcut.ALT_CTRL), false);46 KeyEvent.VK_N, Shortcut.ALT_CTRL), false); 42 47 this.chRel = chRel; 43 48 updateEnabledState(); … … 48 53 } 49 54 50 public void actionPerformed( ActionEvent e ) { 55 @Override 56 public void actionPerformed(ActionEvent e) { 51 57 String type = askForType(); 52 if (type == null )58 if (type == null ) 53 59 return; 54 60 55 61 Relation rel = new Relation(); 56 if ( type.length() > 0 )62 if (type.length() > 0 ) { 57 63 rel.put("type", type); 58 for( OsmPrimitive selected : getCurrentDataSet().getSelected() ) 64 } 65 for (OsmPrimitive selected : getCurrentDataSet().getSelected() ) { 59 66 rel.addMember(new RelationMember("", selected)); 67 } 60 68 61 69 Main.main.undoRedo.add(new AddCommand(rel)); 62 70 63 if ( chRel != null) {71 if (chRel != null) { 64 72 chRel.set(rel); 65 73 } … … 68 76 @Override 69 77 protected void updateEnabledState() { 70 if ( getCurrentDataSet() == null) {78 if (getCurrentDataSet() == null) { 71 79 setEnabled(false); 72 80 } else { … … 76 84 77 85 @Override 78 protected void updateEnabledState( Collection<? extends OsmPrimitive> selection) {86 protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) { 79 87 setEnabled(selection != null && !selection.isEmpty()); 80 88 } … … 82 90 // Thanks to TagInfo for the list 83 91 private static final List<String> RELATION_TYPES = Arrays.asList(new String[] { 84 "multipolygon", "boundary", "route", "site", "restriction", "associatedStreet", "public_transport",85 "street", "collection", "address", "enforcement", "destination_sign", "route_master", "junction",86 "waterway", "bridge", "tunnel", "surveillance"92 "multipolygon", "boundary", "route", "site", "restriction", "associatedStreet", "public_transport", 93 "street", "collection", "address", "enforcement", "destination_sign", "route_master", "junction", 94 "waterway", "bridge", "tunnel", "surveillance" 87 95 }); 88 96 … … 111 119 112 120 keys.getEditor().addActionListener(new ActionListener() { 113 public void actionPerformed( ActionEvent e ) { 121 @Override 122 public void actionPerformed(ActionEvent e) { 114 123 dlg.setVisible(false); 115 124 optionPane.setValue(JOptionPane.OK_OPTION); … … 120 129 121 130 Object answer = optionPane.getValue(); 122 if (answer == null || answer == JOptionPane.UNINITIALIZED_VALUE123 || (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION) ) {131 if (answer == null || answer == JOptionPane.UNINITIALIZED_VALUE 132 || (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION)) 124 133 return null; 125 }126 134 127 135 String result = keys.getEditor().getItem().toString().trim(); -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/DeleteChosenRelationAction.java
r28813 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 2 3 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 4 6 import java.awt.event.ActionEvent; 5 7 import java.util.Collections; 8 6 9 import javax.swing.AbstractAction; 10 7 11 import org.openstreetmap.josm.Main; 8 12 import org.openstreetmap.josm.command.Command; … … 10 14 import org.openstreetmap.josm.data.osm.Relation; 11 15 import org.openstreetmap.josm.tools.ImageProvider; 16 12 17 import relcontext.ChosenRelation; 13 18 import relcontext.ChosenRelationListener; … … 16 21 private ChosenRelation rel; 17 22 18 public DeleteChosenRelationAction( ChosenRelation rel) {23 public DeleteChosenRelationAction(ChosenRelation rel) { 19 24 super(tr("Delete relation")); 20 25 putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete")); … … 24 29 } 25 30 26 public void actionPerformed( ActionEvent e ) { 31 @Override 32 public void actionPerformed(ActionEvent e) { 27 33 Relation r = rel.get(); 28 34 rel.clear(); 29 35 Command c = DeleteCommand.delete(Main.main.getEditLayer(), Collections.singleton(r), true, true); 30 if ( c != null )36 if (c != null ) { 31 37 Main.main.undoRedo.add(c); 38 } 32 39 } 33 40 34 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) { 41 @Override 42 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) { 35 43 setEnabled(newRelation != null); 36 44 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/DownloadChosenRelationAction.java
r30737 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 2 3 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 4 6 import java.awt.event.ActionEvent; 5 7 import java.util.Collections; 6 8 import java.util.HashSet; 7 9 import java.util.Set; 10 8 11 import javax.swing.AbstractAction; 12 9 13 import org.openstreetmap.josm.Main; 10 14 import org.openstreetmap.josm.data.osm.OsmPrimitive; … … 14 18 import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationTask; 15 19 import org.openstreetmap.josm.tools.ImageProvider; 20 16 21 import relcontext.ChosenRelation; 17 22 import relcontext.ChosenRelationListener; … … 19 24 /** 20 25 * Downloads or updates chosen relation members, depending on completeness. 21 * 26 * 22 27 * @author Zverik 23 28 */ … … 25 30 private ChosenRelation rel; 26 31 27 public DownloadChosenRelationAction( ChosenRelation rel) {32 public DownloadChosenRelationAction(ChosenRelation rel) { 28 33 super(); 29 // putValue(NAME, "D");34 // putValue(NAME, "D"); 30 35 putValue(SMALL_ICON, ImageProvider.get("relcontext", "download")); 31 36 putValue(SHORT_DESCRIPTION, tr("Download incomplete members for the chosen relation")); … … 35 40 } 36 41 37 public void actionPerformed( ActionEvent e ) { 42 @Override 43 public void actionPerformed(ActionEvent e) { 38 44 Relation relation = rel.get(); 39 if (relation == null || relation.isNew() ) return;45 if (relation == null || relation.isNew() ) return; 40 46 int total = relation.getMembersCount(); 41 47 int incomplete = relation.getIncompleteMembers().size(); 42 // if(incomplete <= 5 || (incomplete <= 10 && incomplete * 3 < total) )43 if ( incomplete <= 10 && incomplete * 3 < total )48 // if (incomplete <= 5 || (incomplete <= 10 && incomplete * 3 < total) ) 49 if (incomplete <= 10 && incomplete * 3 < total ) { 44 50 downloadIncomplete(relation); 45 else51 } else { 46 52 downloadMembers(relation); 53 } 47 54 } 48 55 49 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) { 56 @Override 57 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) { 50 58 boolean incomplete = false; 51 if ( newRelation != null) {52 for (RelationMember m : newRelation.getMembers()) {53 if ( m.getMember().isIncomplete()) {59 if (newRelation != null) { 60 for (RelationMember m : newRelation.getMembers()) { 61 if (m.getMember().isIncomplete()) { 54 62 incomplete = true; 55 63 break; … … 60 68 } 61 69 62 protected void downloadMembers( Relation rel) {63 if ( !rel.isNew()) {70 protected void downloadMembers(Relation rel) { 71 if (!rel.isNew()) { 64 72 Main.worker.submit(new DownloadRelationTask(Collections.singletonList(rel), Main.main.getEditLayer())); 65 73 } 66 74 } 67 75 68 protected void downloadIncomplete( Relation rel) {69 if (rel.isNew() ) return;76 protected void downloadIncomplete(Relation rel) { 77 if (rel.isNew() ) return; 70 78 Set<OsmPrimitive> ret = new HashSet<>(); 71 79 ret.addAll(rel.getIncompleteMembers()); 72 if (ret.isEmpty() ) return;80 if (ret.isEmpty() ) return; 73 81 Main.worker.submit(new DownloadRelationMemberTask(Collections.singletonList(rel), ret, Main.main.getEditLayer())); 74 82 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/DownloadParentsAction.java
r30737 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 2 3 … … 25 26 /** 26 27 * Downloads parent relations for this relation and all parent objects for its members. 27 * 28 * 28 29 * @author Zverik 29 30 */ … … 31 32 private ChosenRelation rel; 32 33 33 public DownloadParentsAction( ChosenRelation rel) {34 public DownloadParentsAction(ChosenRelation rel) { 34 35 super(tr("Download referrers")); 35 36 putValue(SMALL_ICON, ImageProvider.get("download")); … … 40 41 } 41 42 42 public void actionPerformed( ActionEvent e ) { 43 @Override 44 public void actionPerformed(ActionEvent e) { 43 45 Relation relation = rel.get(); 44 if (relation == null ) return;46 if (relation == null ) return; 45 47 List<OsmPrimitive> objects = new ArrayList<>(); 46 48 objects.add(relation); … … 49 51 } 50 52 51 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) { 53 @Override 54 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) { 52 55 setEnabled(newRelation != null && Main.main.getEditLayer() != null); 53 56 } 54 57 55 protected void downloadMembers( Relation rel) {56 if ( !rel.isNew()) {58 protected void downloadMembers(Relation rel) { 59 if (!rel.isNew()) { 57 60 Main.worker.submit(new DownloadRelationTask(Collections.singletonList(rel), Main.main.getEditLayer())); 58 61 } 59 62 } 60 63 61 protected void downloadIncomplete( Relation rel) {62 if (rel.isNew() ) return;64 protected void downloadIncomplete(Relation rel) { 65 if (rel.isNew() ) return; 63 66 Set<OsmPrimitive> ret = new HashSet<>(); 64 67 ret.addAll(rel.getIncompleteMembers()); 65 if (ret.isEmpty() ) return;68 if (ret.isEmpty() ) return; 66 69 Main.worker.submit(new DownloadRelationMemberTask(Collections.singletonList(rel), ret, Main.main.getEditLayer())); 67 70 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/DuplicateChosenRelationAction.java
r26290 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 2 3 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 4 6 import java.awt.event.ActionEvent; 7 5 8 import javax.swing.AbstractAction; 9 6 10 import org.openstreetmap.josm.Main; 7 11 import org.openstreetmap.josm.command.AddCommand; 8 12 import org.openstreetmap.josm.data.osm.Relation; 9 13 import org.openstreetmap.josm.tools.ImageProvider; 14 10 15 import relcontext.ChosenRelation; 11 16 import relcontext.ChosenRelationListener; … … 14 19 private ChosenRelation rel; 15 20 16 public DuplicateChosenRelationAction( ChosenRelation rel) {21 public DuplicateChosenRelationAction(ChosenRelation rel) { 17 22 super(tr("Duplicate relation")); 18 23 putValue(SMALL_ICON, ImageProvider.get("duplicate")); … … 23 28 } 24 29 25 public void actionPerformed( ActionEvent e ) { 30 @Override 31 public void actionPerformed(ActionEvent e) { 26 32 Relation r = rel.get(); 27 33 Relation copy = new Relation(r, true); 28 34 Main.main.undoRedo.add(new AddCommand(copy)); 29 35 rel.set(copy); 30 if ( Main.main.getCurrentDataSet() != null )36 if (Main.main.getCurrentDataSet() != null ) { 31 37 Main.main.getCurrentDataSet().setSelected(copy); 38 } 32 39 } 33 40 34 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) { 41 @Override 42 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) { 35 43 setEnabled(newRelation != null); 36 44 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/EditChosenRelationAction.java
r30145 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 2 3 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 4 6 import java.awt.event.ActionEvent; 7 5 8 import javax.swing.AbstractAction; 9 6 10 import org.openstreetmap.josm.Main; 7 11 import org.openstreetmap.josm.data.osm.Relation; 8 12 import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor; 9 13 import org.openstreetmap.josm.tools.ImageProvider; 14 10 15 import relcontext.ChosenRelation; 11 16 import relcontext.ChosenRelationListener; … … 13 18 /** 14 19 * Opens an editor for chosen relation. 15 * 20 * 16 21 * @author Zverik 17 22 */ … … 19 24 private ChosenRelation rel; 20 25 21 public EditChosenRelationAction( ChosenRelation rel) {26 public EditChosenRelationAction(ChosenRelation rel) { 22 27 super(); 23 // putValue(NAME, "E");28 // putValue(NAME, "E"); 24 29 putValue(SMALL_ICON, ImageProvider.get("dialogs/mappaint", "pencil")); 25 30 putValue(SHORT_DESCRIPTION, tr("Open relation editor for the chosen relation")); … … 29 34 } 30 35 31 public void actionPerformed( ActionEvent e ) { 36 @Override 37 public void actionPerformed(ActionEvent e) { 32 38 Relation relation = rel.get(); 33 if (relation == null ) return;39 if (relation == null ) return; 34 40 RelationEditor.getEditor(Main.main.getEditLayer(), relation, null).setVisible(true); 35 41 } 36 42 37 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) { 43 @Override 44 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) { 38 45 setEnabled(newRelation != null); 39 46 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/FindRelationAction.java
r30737 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 2 5 3 6 import java.awt.BorderLayout; 4 7 import java.awt.Dialog.ModalityType; 5 8 import java.awt.Dimension; 6 import java.awt.event.*; 7 import static org.openstreetmap.josm.tools.I18n.tr; 8 import java.util.*; 9 import java.awt.event.ActionEvent; 10 import java.awt.event.ActionListener; 11 import java.awt.event.KeyAdapter; 12 import java.awt.event.KeyEvent; 13 import java.awt.event.MouseAdapter; 14 import java.awt.event.MouseEvent; 9 15 import java.util.ArrayList; 10 import javax.swing.*; 16 import java.util.Collection; 17 import java.util.Collections; 18 import java.util.List; 19 20 import javax.swing.AbstractListModel; 21 import javax.swing.DefaultListSelectionModel; 22 import javax.swing.JDialog; 23 import javax.swing.JList; 24 import javax.swing.JOptionPane; 25 import javax.swing.JPanel; 26 import javax.swing.JScrollPane; 27 import javax.swing.JTextField; 28 import javax.swing.ListSelectionModel; 29 import javax.swing.SwingUtilities; 30 11 31 import org.openstreetmap.josm.Main; 12 32 import org.openstreetmap.josm.actions.JosmAction; … … 15 35 import org.openstreetmap.josm.gui.OsmPrimitivRenderer; 16 36 import org.openstreetmap.josm.tools.Shortcut; 37 17 38 import relcontext.ChosenRelation; 18 39 … … 25 46 protected ChosenRelation chRel; 26 47 27 public FindRelationAction( ChosenRelation chRel) {48 public FindRelationAction(ChosenRelation chRel) { 28 49 super(tr("Find"), "relcontext/find", tr("Find a relation"), 29 50 Shortcut.registerShortcut("reltoolbox:find", tr("Relation Toolbox: {0}", tr("Find a relation")), 30 KeyEvent.VK_F, Shortcut.ALT_CTRL), false);51 KeyEvent.VK_F, Shortcut.ALT_CTRL), false); 31 52 this.chRel = chRel; 32 53 } 33 54 34 public void actionPerformed( ActionEvent e ) { 55 @Override 56 public void actionPerformed(ActionEvent e) { 35 57 JPanel panel = new JPanel(new BorderLayout()); 36 58 final JTextField searchField = new JTextField(); … … 55 77 relationsList.addMouseListener(new MouseAdapter() { 56 78 @Override 57 public void mouseClicked( MouseEvent e) {58 if ( e.getClickCount() >= 2 && !relationsList.isSelectionEmpty()) {79 public void mouseClicked(MouseEvent e) { 80 if (e.getClickCount() >= 2 && !relationsList.isSelectionEmpty()) { 59 81 dlg.setVisible(false); 60 82 optionPane.setValue(JOptionPane.OK_OPTION); … … 64 86 65 87 searchField.addActionListener(new ActionListener() { 66 public void actionPerformed( ActionEvent e ) { 67 if( !relationsList.isSelectionEmpty() ) { 88 @Override 89 public void actionPerformed(ActionEvent e) { 90 if (!relationsList.isSelectionEmpty()) { 68 91 dlg.setVisible(false); 69 92 optionPane.setValue(JOptionPane.OK_OPTION); … … 74 97 searchField.addKeyListener(new KeyAdapter() { 75 98 @Override 76 public void keyTyped( KeyEvent e) {99 public void keyTyped(KeyEvent e) { 77 100 SwingUtilities.invokeLater(new Runnable() { 101 @Override 78 102 public void run() { 79 103 updateRelationData(relationsData, searchField.getText()); … … 83 107 84 108 @Override 85 public void keyPressed( KeyEvent e) {86 if ( shouldForward(e) )109 public void keyPressed(KeyEvent e) { 110 if (shouldForward(e) ) { 87 111 relationsList.dispatchEvent(e); 88 } 89 90 @Override 91 public void keyReleased( KeyEvent e ) { 92 if( shouldForward(e) ) 112 } 113 } 114 115 @Override 116 public void keyReleased(KeyEvent e) { 117 if (shouldForward(e) ) { 93 118 relationsList.dispatchEvent(e); 94 } 95 96 private boolean shouldForward( KeyEvent e ) { 119 } 120 } 121 122 private boolean shouldForward(KeyEvent e) { 97 123 return e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_DOWN 98 124 || e.getKeyCode() == KeyEvent.VK_PAGE_DOWN || e.getKeyCode() == KeyEvent.VK_PAGE_UP … … 105 131 106 132 Object answer = optionPane.getValue(); 107 if (answer == null || answer == JOptionPane.UNINITIALIZED_VALUE108 || (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION) ) {133 if (answer == null || answer == JOptionPane.UNINITIALIZED_VALUE 134 || (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION)) 109 135 return; 110 } 111 112 Relation r = (Relation)relationsList.getSelectedValue(); 113 if( r != null ) 136 137 Relation r = relationsList.getSelectedValue(); 138 if (r != null ) { 114 139 chRel.set(r); 140 } 115 141 } 116 142 … … 120 146 } 121 147 122 protected void updateRelationData( FindRelationListModel data, String filter) {148 protected void updateRelationData(FindRelationListModel data, String filter) { 123 149 String[] keywords = filter == null ? new String[0] : filter.split("\\s+"); 124 if ( keywords.length > 0) {150 if (keywords.length > 0) { 125 151 List<String> filteredKeywords = new ArrayList<>(keywords.length); 126 for (String s : keywords )127 if ( s.length() > 0 )152 for (String s : keywords ) 153 if (s.length() > 0 ) { 128 154 filteredKeywords.add(s.trim().toLowerCase()); 155 } 129 156 keywords = filteredKeywords.toArray(new String[0]); 130 157 } 131 158 132 159 System.out.println("keywords.length = " + keywords.length); 133 for ( int i = 0; i < keywords.length; i++ )160 for (int i = 0; i < keywords.length; i++ ) { 134 161 System.out.println("keyword["+i+"] = " + keywords[i]); 162 } 135 163 136 164 List<Relation> relations = new ArrayList<>(); 137 if ( getEditLayer() != null) {138 for ( Relation r : getEditLayer().data.getRelations()) {139 if ( !r.isDeleted() && r.isVisible() && !r.isIncomplete()) {165 if (getEditLayer() != null) { 166 for (Relation r : getEditLayer().data.getRelations()) { 167 if (!r.isDeleted() && r.isVisible() && !r.isIncomplete()) { 140 168 boolean add = true; 141 for ( int i = 0; i < keywords.length && add; i++) {169 for (int i = 0; i < keywords.length && add; i++) { 142 170 boolean ok = false; 143 if ( String.valueOf(r.getPrimitiveId().getUniqueId()).contains(keywords[i]) )171 if (String.valueOf(r.getPrimitiveId().getUniqueId()).contains(keywords[i]) ) { 144 172 ok = true; 145 else {146 for ( String key : r.keySet()) {147 if (key.contains(keywords[i]) || r.get(key).toLowerCase().contains(keywords[i])148 || tr(r.get(key)).toLowerCase().contains(keywords[i]) 173 } else { 174 for (String key : r.keySet()) { 175 if (key.contains(keywords[i]) || r.get(key).toLowerCase().contains(keywords[i]) 176 || tr(r.get(key)).toLowerCase().contains(keywords[i])) { 149 177 ok = true; 150 178 break; … … 152 180 } 153 181 } 154 if( !ok ) add = false; 182 if (!ok ) { 183 add = false; 184 } 155 185 } 156 if ( add )186 if (add ) { 157 187 relations.add(r); 188 } 158 189 } 159 190 } … … 171 202 private DefaultListSelectionModel selectionModel; 172 203 173 public FindRelationListModel( DefaultListSelectionModel selectionModel) {204 public FindRelationListModel(DefaultListSelectionModel selectionModel) { 174 205 super(); 175 206 this.selectionModel = selectionModel; … … 190 221 191 222 @Override 192 public Relation getElementAt( int index) {223 public Relation getElementAt(int index) { 193 224 return relations.get(index); 194 225 } … … 197 228 int selectedIndex = selectionModel.getMinSelectionIndex(); 198 229 Relation sel = selectedIndex < 0 ? null : getElementAt(selectedIndex); 199 230 200 231 this.relations.clear(); 201 232 selectionModel.clearSelection(); 202 if ( relations != null )233 if (relations != null ) { 203 234 this.relations.addAll(relations); 235 } 204 236 fireIntervalAdded(this, 0, getSize()); 205 237 206 if ( sel != null) {238 if (sel != null) { 207 239 selectedIndex = this.relations.indexOf(sel); 208 if ( selectedIndex >= 0 )240 if (selectedIndex >= 0 ) { 209 241 selectionModel.addSelectionInterval(selectedIndex, selectedIndex); 210 } 211 if( selectionModel.isSelectionEmpty() && !this.relations.isEmpty() ) 242 } 243 } 244 if (selectionModel.isSelectionEmpty() && !this.relations.isEmpty() ) { 212 245 selectionModel.addSelectionInterval(0, 0); 246 } 213 247 } 214 248 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/PublicTransportHelper.java
r30841 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 2 3 3 import org.openstreetmap.josm.data.osm.Node;4 4 import org.openstreetmap.josm.data.osm.OsmPrimitive; 5 5 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 6 6 import org.openstreetmap.josm.data.osm.RelationMember; 7 import org.openstreetmap.josm.data.osm.Way;8 7 9 8 /** … … 26 25 public final static String BUS_STOP = "bus_stop"; 27 26 public final static String RAILWAY_HALT = "halt"; 28 public final static String RAILWAY_STATION = "station"; 29 27 public final static String RAILWAY_STATION = "station"; 28 30 29 private PublicTransportHelper() { 31 30 // Hide default constructor for utils classes 32 } 33 31 } 32 34 33 public static String getRoleByMember(RelationMember m) { 35 34 if (isMemberStop(m)) return STOP; … … 37 36 return null; 38 37 } 39 38 40 39 public static boolean isMemberStop(RelationMember m) { 41 40 return isNodeStop(m); // stop is only node 42 41 } 43 42 44 43 public static boolean isMemberPlatform(RelationMember m) { 45 44 return isNodePlatform(m) || isWayPlatform(m); 46 45 } 47 46 48 47 public static boolean isNodeStop(RelationMember m) { 49 48 return isNodeStop(m.getMember()); 50 49 } 51 50 52 51 public static boolean isNodeStop(OsmPrimitive p) { 53 52 if (p.getType() == OsmPrimitiveType.NODE && !p.isIncomplete()) { … … 63 62 return false; 64 63 } 65 64 66 65 public static boolean isNodePlatform(RelationMember m) { 67 66 return isNodePlatform(m.getMember()); 68 67 } 69 68 70 69 public static boolean isNodePlatform(OsmPrimitive p) { 71 70 if (p.getType() == OsmPrimitiveType.NODE && !p.isIncomplete()) { … … 87 86 return isWayPlatform(m.getMember()); 88 87 } 89 88 90 89 public static boolean isWayPlatform(OsmPrimitive p) { 91 90 if (p.getType() == OsmPrimitiveType.WAY && !p.isIncomplete()) { … … 103 102 return false; 104 103 } 105 104 106 105 public static boolean isMemberRouteway(RelationMember m) { 107 106 return isWayRouteway(m.getMember()); 108 107 } 109 108 110 109 public static boolean isWayRouteway(OsmPrimitive p) { 111 if (p.getType() == OsmPrimitiveType.WAY && !p.isIncomplete()) {110 if (p.getType() == OsmPrimitiveType.WAY && !p.isIncomplete()) 112 111 return p.hasKey(HIGHWAY) || p.hasKey(RAILWAY); 113 }114 112 return false; 115 113 } 116 114 117 115 public static String getNameViaStoparea(RelationMember m) { 118 116 return getNameViaStoparea(m.getMember()); 119 117 } 120 118 121 119 public static String getNameViaStoparea(OsmPrimitive prim) { 122 120 String result = prim.getName(); … … 125 123 for (OsmPrimitive refOp : prim.getReferrers()) 126 124 if (refOp.getType() == OsmPrimitiveType.RELATION 127 125 && refOp.hasTag(PUBLIC_TRANSPORT, STOP_AREA)) { 128 126 result = refOp.getName(); 129 127 if (result != null) return result; 130 128 } 131 129 return result; 132 } 130 } 133 131 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/ReconstructPolygonAction.java
r30738 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 2 3 … … 40 41 public class ReconstructPolygonAction extends AbstractAction implements ChosenRelationListener { 41 42 private ChosenRelation rel; 42 43 43 44 private static final List<String> IRRELEVANT_KEYS = Arrays.asList(new String[] { 44 "source", "created_by", "note"});45 "source", "created_by", "note"}); 45 46 46 public ReconstructPolygonAction( ChosenRelation rel) {47 public ReconstructPolygonAction(ChosenRelation rel) { 47 48 super(tr("Reconstruct polygon")); 48 49 putValue(SMALL_ICON, ImageProvider.get("dialogs", "filter")); 49 putValue(LONG_DESCRIPTION, "Reconstruct polygon from multipolygon relation");50 putValue(LONG_DESCRIPTION, "Reconstruct polygon from multipolygon relation"); 50 51 this.rel = rel; 51 52 rel.addChosenRelationListener(this); … … 53 54 } 54 55 55 public void actionPerformed( ActionEvent e ) { 56 @Override 57 public void actionPerformed(ActionEvent e) { 56 58 Relation r = rel.get(); 57 List<Way> ways = new ArrayList<>(); 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<>(); 84 List<Command> commands = new ArrayList<>(); 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<>(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); 59 List<Way> ways = new ArrayList<>(); 60 boolean wont = false; 61 for (RelationMember m : r.getMembers()) { 62 if (m.isWay() ) { 63 ways.add(m.getWay()); 64 } else { 65 wont = true; 102 66 } 103 67 } 104 List<OsmPrimitive> referrers = w.getReferrers(); 105 for( Iterator<OsmPrimitive> ref1 = relations.iterator(); ref1.hasNext(); ) 106 if( !referrers.contains(ref1.next()) ) 107 ref1.remove(); 68 if (wont) { 69 JOptionPane.showMessageDialog(Main.parent, tr("Multipolygon must consist only of ways"), tr("Reconstruct polygon"), JOptionPane.ERROR_MESSAGE); 70 return; 108 71 } 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<>(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; 72 73 MultipolygonBuilder mpc = new MultipolygonBuilder(); 74 String error = mpc.makeFromWays(ways); 75 if (error != null) { 76 JOptionPane.showMessageDialog(Main.parent, error); 77 return; 78 } 79 80 if (!mpc.innerWays.isEmpty()) { 81 JOptionPane.showMessageDialog(Main.parent, tr("Reconstruction of polygons can be done only from outer ways"), tr("Reconstruct polygon"), JOptionPane.ERROR_MESSAGE); 82 return; 83 } 84 85 rel.clear(); 86 List<Way> newSelection = new ArrayList<>(); 87 List<Command> commands = new ArrayList<>(); 88 Command c = DeleteCommand.delete(Main.main.getEditLayer(), Collections.singleton(r), true, true); 89 if (c == null ) 90 return; 91 commands.add(c); 92 93 for (JoinedPolygon p : mpc.outerWays) { 94 // move all tags from relation and common tags from ways 95 Map<String, String> tags = p.ways.get(0).getKeys(); 96 List<OsmPrimitive> relations = p.ways.get(0).getReferrers(); 97 Set<String> noTags = new HashSet<>(r.keySet()); 98 for (int i = 1; i < p.ways.size(); i++) { 99 Way w = p.ways.get(i); 100 for (String key : w.keySet()) { 101 String value = w.get(key); 102 if (!noTags.contains(key) && tags.containsKey(key) && !tags.get(key).equals(value)) { 103 tags.remove(key); 104 noTags.add(key); 105 } 129 106 } 130 commands.add(new DeleteCommand(w)); 107 List<OsmPrimitive> referrers = w.getReferrers(); 108 for (Iterator<OsmPrimitive> ref1 = relations.iterator(); ref1.hasNext(); ) 109 if (!referrers.contains(ref1.next()) ) { 110 ref1.remove(); 111 } 131 112 } 113 tags.putAll(r.getKeys()); 114 tags.remove("type"); 115 116 // then delete ways that are not relevant (do not take part in other relations of have strange tags) 117 Way candidateWay = null; 118 for (Way w : p.ways) { 119 if (w.getReferrers().equals(relations)) { 120 // check tags that remain 121 Set<String> keys = new HashSet<>(w.keySet()); 122 keys.removeAll(tags.keySet()); 123 keys.removeAll(IRRELEVANT_KEYS); 124 if (keys.isEmpty()) { 125 if (candidateWay == null ) { 126 candidateWay = w; 127 } else { 128 if (candidateWay.isNew() && !w.isNew()) { 129 // prefer ways that are already in the database 130 Way tmp = w; 131 w = candidateWay; 132 candidateWay = tmp; 133 } 134 commands.add(new DeleteCommand(w)); 135 } 136 } 137 } 132 138 } 139 140 // take the first way, put all nodes into it, making it a closed polygon 141 Way result = candidateWay == null ? new Way() : new Way(candidateWay); 142 result.setNodes(p.nodes); 143 result.addNode(result.firstNode()); 144 result.setKeys(tags); 145 newSelection.add(candidateWay == null ? result : candidateWay); 146 commands.add(candidateWay == null ? new AddCommand(result) : new ChangeCommand(candidateWay, result)); 133 147 } 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 148 145 149 Main.main.undoRedo.add(new SequenceCommand(tr("Reconstruct polygons from relation {0}", 146 r.getDisplayName(DefaultNameFormatter.getInstance())), commands));147 Main.main.getCurrentDataSet().setSelected(newSelection);150 r.getDisplayName(DefaultNameFormatter.getInstance())), commands)); 151 Main.main.getCurrentDataSet().setSelected(newSelection); 148 152 } 149 153 150 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) { 151 setEnabled(isSuitableRelation(newRelation)); 154 @Override 155 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) { 156 setEnabled(isSuitableRelation(newRelation)); 152 157 } 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()) ) 158 159 private boolean isSuitableRelation(Relation newRelation) { 160 if (newRelation == null || !"multipolygon".equals(newRelation.get("type")) || newRelation.getMembersCount() == 0 ) 160 161 return false; 161 return true; 162 } 162 else { 163 for (RelationMember m : newRelation.getMembers() ) 164 if ("inner".equals(m.getRole()) ) 165 return false; 166 return true; 167 } 163 168 } 164 169 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/ReconstructRouteAction.java
r30841 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 2 5 3 6 import java.awt.event.ActionEvent; … … 6 9 import java.util.List; 7 10 import java.util.Map; 11 8 12 import javax.swing.AbstractAction; 9 import static javax.swing.Action.LONG_DESCRIPTION; 10 import static javax.swing.Action.SMALL_ICON; 13 11 14 import org.openstreetmap.josm.Main; 12 15 import org.openstreetmap.josm.command.ChangeCommand; … … 21 24 import org.openstreetmap.josm.gui.dialogs.relation.sort.RelationSorter; 22 25 import org.openstreetmap.josm.tools.Geometry; 23 import static org.openstreetmap.josm.tools.I18n.tr;24 26 import org.openstreetmap.josm.tools.ImageProvider; 27 25 28 import relcontext.ChosenRelation; 26 29 import relcontext.ChosenRelationListener; … … 32 35 public class ReconstructRouteAction extends AbstractAction implements ChosenRelationListener { 33 36 private final ChosenRelation rel; 34 37 35 38 public ReconstructRouteAction (ChosenRelation rel) { 36 39 super(tr("Reconstruct route")); … … 41 44 setEnabled(isSuitableRelation(rel.get())); 42 45 } 43 44 public void actionPerformed( ActionEvent e ) { 46 47 @Override 48 public void actionPerformed(ActionEvent e) { 45 49 Relation r = rel.get(); 46 Relation recRel = new Relation(r); 50 Relation recRel = new Relation(r); 47 51 recRel.removeMembersFor(recRel.getMemberPrimitives()); 48 52 49 53 Map<OsmPrimitive, RelationMember> stopMembers = new LinkedHashMap<>(); 50 54 Map<String, List<RelationMember>> platformMembers = new LinkedHashMap<>(); … … 52 56 List<RelationMember> routeMembers = new ArrayList<>(); 53 57 List<RelationMember> wtfMembers = new ArrayList<>(); 54 58 55 59 int mCount = r.getMembersCount(); 56 60 for (int i = 0; i < mCount; i++) { … … 58 62 if (PublicTransportHelper.isMemberStop(m)) { 59 63 RelationMember rm = new RelationMember( 60 m.hasRole() ? m.getRole() : PublicTransportHelper.STOP, 61 m.getMember());64 m.hasRole() ? m.getRole() : PublicTransportHelper.STOP, 65 m.getMember()); 62 66 stopMembers.put(rm.getMember(), rm); 63 67 } 64 68 else if (PublicTransportHelper.isMemberPlatform(m)) { 65 69 RelationMember rm = new RelationMember( 66 m.hasRole() ? m.getRole() : PublicTransportHelper.PLATFORM, 67 m.getMember());70 m.hasRole() ? m.getRole() : PublicTransportHelper.PLATFORM, 71 m.getMember()); 68 72 String platformName = PublicTransportHelper.getNameViaStoparea(rm); 69 if (platformName == null) platformName = ""; 70 if (platformMembers.containsKey(platformName)) platformMembers.get(platformName).add(rm); 71 else { 73 if (platformName == null) { 74 platformName = ""; 75 } 76 if (platformMembers.containsKey(platformName)) { 77 platformMembers.get(platformName).add(rm); 78 } else { 72 79 List<RelationMember> nList = new ArrayList<>(); 73 80 nList.add(rm); 74 81 platformMembers.put(platformName, nList); 75 } 76 } 77 else if (PublicTransportHelper.isMemberRouteway(m)) routeMembers.add(new RelationMember(m)); 78 else wtfMembers.add(new RelationMember(m)); 79 } 80 82 } 83 } 84 else if (PublicTransportHelper.isMemberRouteway(m)) { 85 routeMembers.add(new RelationMember(m)); 86 } else { 87 wtfMembers.add(new RelationMember(m)); 88 } 89 } 90 81 91 routeMembers = RelationSorter.sortMembersByConnectivity(routeMembers); 82 92 83 93 Node lastNode = null; 84 94 for (int rIndex = 0; rIndex < routeMembers.size(); rIndex++) { … … 91 101 dirForward = true; 92 102 lastNode = w.lastNode(); 93 } else lastNode = w.firstNode(); 103 } else { 104 lastNode = w.firstNode(); 105 } 94 106 } // else one segment - direction unknown 95 107 } else { 96 if (lastNode.equals(w.firstNode())) { dirForward = true; lastNode = w.lastNode(); } 97 else lastNode = w.firstNode(); 108 if (lastNode.equals(w.firstNode())) { dirForward = true; lastNode = w.lastNode(); } else { 109 lastNode = w.firstNode(); 110 } 98 111 } 99 112 final int wayNodeBeginIndex = (dirForward ? 0 : w.getNodesCount() - 1); 100 113 final int wayNodeEndIndex = (dirForward ? w.getNodesCount() - 1 : 0); 101 114 final int increment = (dirForward ? 1 : -1); 102 for (int nIndex = wayNodeBeginIndex;115 for (int nIndex = wayNodeBeginIndex; 103 116 nIndex != wayNodeEndIndex; 104 117 nIndex += increment) { … … 109 122 stopMembers.remove(refNode); 110 123 String stopName = PublicTransportHelper.getNameViaStoparea(refNode); 111 if (stopName == null) stopName = ""; 124 if (stopName == null) { 125 stopName = ""; 126 } 112 127 boolean existsPlatform = platformMembers.containsKey(stopName); 113 128 if (!existsPlatform) { stopName = ""; } // find of the nameless … … 118 133 lMember.remove(0); 119 134 } else { 120 // choose closest 135 // choose closest 121 136 RelationMember candidat = getClosestPlatform(lMember, refNode); 122 137 if (candidat != null) { … … 125 140 } 126 141 } 127 if (lMember.isEmpty()) platformMembers.remove(stopName); 142 if (lMember.isEmpty()) { 143 platformMembers.remove(stopName); 144 } 128 145 } 129 146 } … … 131 148 } 132 149 } 133 150 134 151 for (RelationMember stop : stopMembers.values()) { 135 152 recRel.addMember(stop); … … 137 154 boolean existsPlatform = platformMembers.containsKey(stopName); 138 155 if (!existsPlatform) { stopName = ""; } // find of the nameless 139 if (existsPlatform || platformMembers.containsKey(stopName)) { 156 if (existsPlatform || platformMembers.containsKey(stopName)) { 140 157 List<RelationMember> lMember = platformMembers.get(stopName); 141 158 if (lMember.size() == 1) { … … 143 160 lMember.remove(0); 144 161 } else { 145 // choose closest 162 // choose closest 146 163 RelationMember candidat = getClosestPlatform(lMember, stop.getNode()); 147 164 if (candidat != null) { … … 150 167 } 151 168 } 152 if (lMember.isEmpty()) platformMembers.remove(stopName); 153 } 154 } 155 156 for (List<RelationMember> lPlatforms : platformMembers.values()) 157 for (RelationMember platform : lPlatforms) 169 if (lMember.isEmpty()) { 170 platformMembers.remove(stopName); 171 } 172 } 173 } 174 175 for (List<RelationMember> lPlatforms : platformMembers.values()) { 176 for (RelationMember platform : lPlatforms) { 158 177 recRel.addMember(platform); 159 160 for (RelationMember route : routeMembers) 178 } 179 } 180 181 for (RelationMember route : routeMembers) { 161 182 recRel.addMember(route); 162 for (RelationMember wtf : wtfMembers) 163 recRel.addMember(wtf); 183 } 184 for (RelationMember wtf : wtfMembers) { 185 recRel.addMember(wtf); 186 } 164 187 Command command = new ChangeCommand(r, recRel); 165 188 Main.main.undoRedo.add(command); 166 189 } 167 168 private static final double maxSqrDistBetweenStopAndPlatform = 2000; // ~ 26m 190 191 private static final double maxSqrDistBetweenStopAndPlatform = 2000; // ~ 26m 169 192 private RelationMember getClosestPlatform(List<RelationMember> members, Node stop) { 170 193 if (stop == null || members.isEmpty()) return null; … … 182 205 Way way = member.getWay(); 183 206 EastNorth closest = Geometry.closestPointToSegment( 184 way.firstNode().getEastNorth(),185 way.lastNode().getEastNorth(),186 187 );207 way.firstNode().getEastNorth(), 208 way.lastNode().getEastNorth(), 209 stop.getEastNorth() 210 ); 188 211 double sqrDist = stop.getEastNorth().distanceSq(closest); 189 212 if (sqrDist < maxDist) { … … 195 218 return result; 196 219 } 197 198 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) { 199 setEnabled(isSuitableRelation(newRelation)); 200 } 201 220 221 @Override 222 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) { 223 setEnabled(isSuitableRelation(newRelation)); 224 } 225 202 226 private boolean isSuitableRelation (Relation newRelation) { 203 227 return !(newRelation == null || !"route".equals(newRelation.get("type")) || newRelation.getMembersCount() == 0); -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/RelationHelpAction.java
r30737 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 2 3 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 4 6 import java.awt.event.ActionEvent; 5 7 import java.net.HttpURLConnection; … … 8 10 import java.util.ArrayList; 9 11 import java.util.List; 12 10 13 import javax.swing.AbstractAction; 14 11 15 import org.openstreetmap.josm.Main; 12 16 import org.openstreetmap.josm.data.osm.Relation; … … 14 18 import org.openstreetmap.josm.tools.LanguageInfo; 15 19 import org.openstreetmap.josm.tools.OpenBrowser; 20 16 21 import relcontext.ChosenRelation; 17 22 import relcontext.ChosenRelationListener; … … 20 25 private ChosenRelation rel; 21 26 22 public RelationHelpAction( ChosenRelation rel) {27 public RelationHelpAction(ChosenRelation rel) { 23 28 super(); 24 29 putValue(NAME, tr("Open relation wiki page")); … … 30 35 } 31 36 32 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) { 37 @Override 38 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) { 33 39 setEnabled(newRelation != null); 34 40 } … … 37 43 * Copypasted from {@link org.openstreetmap.josm.gui.dialogs.properties.PropertiesDialog.HelpAction}. 38 44 */ 39 public void actionPerformed( ActionEvent e ) { 40 if( rel.get() == null ) 45 @Override 46 public void actionPerformed(ActionEvent e) { 47 if (rel.get() == null ) 41 48 return; 42 49 try { … … 55 62 56 63 Main.worker.execute(new Runnable(){ 64 @Override 57 65 public void run() { 58 66 try { … … 73 81 .replace("=", "%3D") /* do not URLencode whole string! */ 74 82 .replaceFirst("/wiki/", "/w/index.php?redirect=no&title=") 75 ).toURL().openConnection();83 ).toURL().openConnection(); 76 84 conn.setConnectTimeout(5000); 77 85 -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/SelectInRelationPanelAction.java
r25711 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 2 3 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 4 6 import java.awt.event.ActionEvent; 7 5 8 import javax.swing.AbstractAction; 9 6 10 import org.openstreetmap.josm.Main; 7 11 import org.openstreetmap.josm.data.osm.Relation; 8 12 import org.openstreetmap.josm.tools.ImageProvider; 13 9 14 import relcontext.ChosenRelation; 10 15 import relcontext.ChosenRelationListener; … … 13 18 private ChosenRelation rel; 14 19 15 public SelectInRelationPanelAction( ChosenRelation rel) {20 public SelectInRelationPanelAction(ChosenRelation rel) { 16 21 super(); 17 22 putValue(NAME, tr("Select in relation list")); … … 23 28 } 24 29 25 public void actionPerformed( ActionEvent e ) { 26 if( rel.get() != null ) { 30 @Override 31 public void actionPerformed(ActionEvent e) { 32 if (rel.get() != null) { 27 33 Main.map.relationListDialog.selectRelation(rel.get()); 28 34 Main.map.relationListDialog.unfurlDialog(); … … 30 36 } 31 37 32 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) { 38 @Override 39 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) { 33 40 setEnabled(newRelation != null); 34 41 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/SelectMembersAction.java
r30145 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 2 3 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 4 6 import java.awt.event.ActionEvent; 7 5 8 import javax.swing.AbstractAction; 9 6 10 import org.openstreetmap.josm.Main; 7 11 import org.openstreetmap.josm.data.osm.Relation; 8 12 import org.openstreetmap.josm.tools.ImageProvider; 13 9 14 import relcontext.ChosenRelation; 10 15 import relcontext.ChosenRelationListener; … … 13 18 private ChosenRelation rel; 14 19 15 public SelectMembersAction( ChosenRelation rel) {20 public SelectMembersAction(ChosenRelation rel) { 16 21 super(tr("Select members")); 17 22 putValue(SMALL_ICON, ImageProvider.get("selectall")); … … 21 26 } 22 27 23 public void actionPerformed( ActionEvent e ) { 28 @Override 29 public void actionPerformed(ActionEvent e) { 24 30 Main.main.getEditLayer().data.setSelected(rel.get() == null ? null : rel.get().getMemberPrimitives()); 25 31 } 26 32 27 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) { 33 @Override 34 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) { 28 35 setEnabled(newRelation != null); 29 36 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/SelectRelationAction.java
r30145 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 2 3 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 4 6 import java.awt.event.ActionEvent; 7 5 8 import javax.swing.AbstractAction; 9 6 10 import org.openstreetmap.josm.Main; 7 11 import org.openstreetmap.josm.data.osm.Relation; 8 12 import org.openstreetmap.josm.tools.ImageProvider; 13 9 14 import relcontext.ChosenRelation; 10 15 import relcontext.ChosenRelationListener; … … 13 18 private ChosenRelation rel; 14 19 15 public SelectRelationAction( ChosenRelation rel) {20 public SelectRelationAction(ChosenRelation rel) { 16 21 super(tr("Select relation")); 17 22 putValue(SHORT_DESCRIPTION, tr("Select relation in main selection.")); … … 22 27 } 23 28 24 public void actionPerformed( ActionEvent e ) { 29 @Override 30 public void actionPerformed(ActionEvent e) { 25 31 Main.main.getEditLayer().data.setSelected(rel.get() == null ? null : rel.get()); 26 32 } 27 33 28 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) { 34 @Override 35 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) { 29 36 setEnabled(newRelation != null); 30 37 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/SortAndFixAction.java
r30841 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 2 3 … … 30 31 private List<RelationFixer> fixers; 31 32 32 public SortAndFixAction( ChosenRelation rel) {33 public SortAndFixAction(ChosenRelation rel) { 33 34 super(); 34 // putValue(Action.NAME, "AZ");35 // putValue(Action.NAME, "AZ"); 35 36 putValue(Action.SMALL_ICON, ImageProvider.get("data", "warning")); 36 37 putValue(Action.SHORT_DESCRIPTION, tr("Fix roles of the chosen relation members")); … … 47 48 fixers.add(new PublicTransportFixer()); //public_transport 48 49 49 for (RelationFixer fix : fixers) {50 for (RelationFixer fix : fixers) { 50 51 fix.setFixAction(this); 51 52 } … … 53 54 54 55 @Override 55 public void actionPerformed( ActionEvent e) {56 public void actionPerformed(ActionEvent e) { 56 57 Command c = fixRelation(rel.get()); 57 if ( c != null )58 if (c != null ) { 58 59 Main.main.undoRedo.add(c); 60 } 59 61 } 60 62 61 63 @Override 62 public void chosenRelationChanged( Relation oldRelation, Relation newRelation) {63 setEnabled(newRelation != null && needsFixing( 64 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) { 65 setEnabled(newRelation != null && needsFixing(newRelation)); 64 66 } 65 67 66 public boolean needsFixing( Relation rel) {68 public boolean needsFixing(Relation rel) { 67 69 return !isIncomplete(rel) && !getFixer(rel).isRelationGood(rel); 68 70 } 69 71 70 private RelationFixer getFixer( Relation rel) {71 for (RelationFixer fixer : fixers)72 private RelationFixer getFixer(Relation rel) { 73 for (RelationFixer fixer : fixers) 72 74 if (fixer.isFixerApplicable(rel)) 73 75 return fixer; … … 75 77 } 76 78 77 public Command fixRelation( Relation rel) {79 public Command fixRelation(Relation rel) { 78 80 return getFixer(rel).fixRelation(rel); 79 81 } 80 82 81 protected static boolean isIncomplete( Relation r) {82 if (r == null || r.isIncomplete() || r.isDeleted() )83 protected static boolean isIncomplete(Relation r) { 84 if (r == null || r.isIncomplete() || r.isDeleted() ) 83 85 return true; 84 for (RelationMember m : r.getMembers())85 if (m.getMember().isIncomplete() )86 for (RelationMember m : r.getMembers()) 87 if (m.getMember().isIncomplete() ) 86 88 return true; 87 89 return false; -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/SplittingMultipolygons.java
r30738 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 2 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 3 6 import java.awt.geom.Area; 4 5 import static org.openstreetmap.josm.tools.I18n.tr; 6 7 import java.util.*; 7 import java.util.ArrayList; 8 import java.util.Collection; 9 import java.util.Collections; 10 import java.util.HashMap; 11 import java.util.Iterator; 12 import java.util.List; 13 import java.util.Map; 8 14 9 15 import org.openstreetmap.josm.Main; 10 import org.openstreetmap.josm.command.*; 16 import org.openstreetmap.josm.command.AddCommand; 17 import org.openstreetmap.josm.command.ChangeCommand; 18 import org.openstreetmap.josm.command.Command; 19 import org.openstreetmap.josm.command.SequenceCommand; 11 20 import org.openstreetmap.josm.data.coor.EastNorth; 12 21 import org.openstreetmap.josm.data.coor.LatLon; 13 import org.openstreetmap.josm.data.osm.*; 22 import org.openstreetmap.josm.data.osm.Node; 23 import org.openstreetmap.josm.data.osm.OsmPrimitive; 24 import org.openstreetmap.josm.data.osm.Relation; 25 import org.openstreetmap.josm.data.osm.RelationMember; 26 import org.openstreetmap.josm.data.osm.Way; 14 27 import org.openstreetmap.josm.gui.DefaultNameFormatter; 15 28 import org.openstreetmap.josm.tools.Geometry; … … 23 36 private static final String PREF_MULTIPOLY = "reltoolbox.multipolygon."; 24 37 25 public static boolean canProcess( Collection<Way> ways ) { 26 List<Way> rings = new ArrayList<>(); 27 List<Way> arcs = new ArrayList<>(); 28 Area a = Main.main.getCurrentDataSet().getDataSourceArea(); 29 for( Way way : ways ) { 30 if( way.isDeleted() ) 31 return false; 32 for( Node n : way.getNodes() ) { 33 LatLon ll = n.getCoor(); 34 if( n.isIncomplete() || (a != null && !a.contains(ll.getX(), ll.getY())) ) 38 public static boolean canProcess(Collection<Way> ways) { 39 List<Way> rings = new ArrayList<>(); 40 List<Way> arcs = new ArrayList<>(); 41 Area a = Main.main.getCurrentDataSet().getDataSourceArea(); 42 for (Way way : ways) { 43 if (way.isDeleted() ) 35 44 return false; 36 } 37 if( way.isClosed() ) 38 rings.add(way); 39 else 40 arcs.add(way); 41 } 42 43 // If there are more that one segment, check that they touch rings 44 if( arcs.size() > 1 ) { 45 for( Way segment : arcs ) { 46 boolean found = false; 47 for( Way ring : rings ) 48 if( ring.containsNode(segment.firstNode()) && ring.containsNode(segment.lastNode()) ) 49 found = true; 50 if( !found ) 45 for (Node n : way.getNodes()) { 46 LatLon ll = n.getCoor(); 47 if (n.isIncomplete() || (a != null && !a.contains(ll.getX(), ll.getY())) ) 48 return false; 49 } 50 if (way.isClosed() ) { 51 rings.add(way); 52 } else { 53 arcs.add(way); 54 } 55 } 56 57 // If there are more that one segment, check that they touch rings 58 if (arcs.size() > 1) { 59 for (Way segment : arcs) { 60 boolean found = false; 61 for (Way ring : rings ) 62 if (ring.containsNode(segment.firstNode()) && ring.containsNode(segment.lastNode()) ) { 63 found = true; 64 } 65 if (!found ) 66 return false; 67 } 68 } 69 70 if (rings.isEmpty() && arcs.isEmpty() ) 51 71 return false; 52 } 53 } 54 55 if( rings.isEmpty() && arcs.isEmpty() ) 56 return false; 57 58 // check for non-containment of rings 59 for( int i = 0; i < rings.size() - 1; i++ ) { 60 for( int j = i + 1; j < rings.size(); j++ ) { 61 PolygonIntersection intersection = Geometry.polygonIntersection(rings.get(i).getNodes(), rings.get(j).getNodes()); 62 if( intersection == PolygonIntersection.FIRST_INSIDE_SECOND || intersection == PolygonIntersection.SECOND_INSIDE_FIRST ) 63 return false; 64 } 65 } 66 67 return true; 68 } 69 70 public static List<Relation> process( Collection<Way> selectedWays ) { 71 // System.out.println("---------------------------------------"); 72 List<Relation> result = new ArrayList<>(); 73 List<Way> rings = new ArrayList<>(); 74 List<Way> arcs = new ArrayList<>(); 75 for( Way way : selectedWays ) { 76 if( way.isClosed() ) 77 rings.add(way); 78 else 79 arcs.add(way); 80 } 81 82 for( Way ring : rings ) { 83 List<Command> commands = new ArrayList<>(); 84 Relation newRelation = SplittingMultipolygons.attachRingToNeighbours(ring, commands); 85 if( newRelation != null && !commands.isEmpty() ) { 86 Main.main.undoRedo.add(commands.get(0)); 87 result.add(newRelation); 88 } 89 } 90 91 for( Way arc : arcs) { 92 List<Command> commands = new ArrayList<>(); 93 Relation newRelation = SplittingMultipolygons.tryToCloseOneWay(arc, commands); 94 if( newRelation != null && !commands.isEmpty() ) { 95 Main.main.undoRedo.add(commands.get(0)); 96 result.add(newRelation); 97 } 98 } 99 return result; 72 73 // check for non-containment of rings 74 for (int i = 0; i < rings.size() - 1; i++) { 75 for (int j = i + 1; j < rings.size(); j++) { 76 PolygonIntersection intersection = Geometry.polygonIntersection(rings.get(i).getNodes(), rings.get(j).getNodes()); 77 if (intersection == PolygonIntersection.FIRST_INSIDE_SECOND || intersection == PolygonIntersection.SECOND_INSIDE_FIRST ) 78 return false; 79 } 80 } 81 82 return true; 83 } 84 85 public static List<Relation> process(Collection<Way> selectedWays) { 86 // System.out.println("---------------------------------------"); 87 List<Relation> result = new ArrayList<>(); 88 List<Way> rings = new ArrayList<>(); 89 List<Way> arcs = new ArrayList<>(); 90 for (Way way : selectedWays) { 91 if (way.isClosed() ) { 92 rings.add(way); 93 } else { 94 arcs.add(way); 95 } 96 } 97 98 for (Way ring : rings) { 99 List<Command> commands = new ArrayList<>(); 100 Relation newRelation = SplittingMultipolygons.attachRingToNeighbours(ring, commands); 101 if (newRelation != null && !commands.isEmpty()) { 102 Main.main.undoRedo.add(commands.get(0)); 103 result.add(newRelation); 104 } 105 } 106 107 for (Way arc : arcs) { 108 List<Command> commands = new ArrayList<>(); 109 Relation newRelation = SplittingMultipolygons.tryToCloseOneWay(arc, commands); 110 if (newRelation != null && !commands.isEmpty()) { 111 Main.main.undoRedo.add(commands.get(0)); 112 result.add(newRelation); 113 } 114 } 115 return result; 100 116 } 101 117 … … 103 119 * Appends "append" to "base" so the closed polygon forms. 104 120 */ 105 private static void closePolygon( List<Node> base, List<Node> append) {106 if( append.get(0).equals(base.get(0)) && append.get(append.size() - 1).equals(base.get(base.size() - 1))) {107 List<Node> ap2 = new ArrayList<>(append);108 Collections.reverse(ap2);109 append = ap2;110 }111 base.remove(base.size() - 1);112 base.addAll(append);121 private static void closePolygon(List<Node> base, List<Node> append) { 122 if (append.get(0).equals(base.get(0)) && append.get(append.size() - 1).equals(base.get(base.size() - 1))) { 123 List<Node> ap2 = new ArrayList<>(append); 124 Collections.reverse(ap2); 125 append = ap2; 126 } 127 base.remove(base.size() - 1); 128 base.addAll(append); 113 129 } 114 130 … … 116 132 * Checks if a middle point between two nodes is inside a polygon. Useful to check if the way is inside. 117 133 */ 118 private static boolean segmentInsidePolygon( Node n1, Node n2, List<Node> polygon) {119 EastNorth en1 = n1.getEastNorth();120 EastNorth en2 = n2.getEastNorth();121 Node testNode = new Node(new EastNorth((en1.east() + en2.east()) / 2.0, (en1.north() + en2.north()) / 2.0));122 return Geometry.nodeInsidePolygon(testNode, polygon);134 private static boolean segmentInsidePolygon(Node n1, Node n2, List<Node> polygon) { 135 EastNorth en1 = n1.getEastNorth(); 136 EastNorth en2 = n2.getEastNorth(); 137 Node testNode = new Node(new EastNorth((en1.east() + en2.east()) / 2.0, (en1.north() + en2.north()) / 2.0)); 138 return Geometry.nodeInsidePolygon(testNode, polygon); 123 139 } 124 140 … … 130 146 * @return Newly created ways. <b>Warning:</b> if commands is no not, newWays contains {@code w}. 131 147 */ 132 public static List<Way> splitWay( Way w, Node n1, Node n2, List<Command> commands ) { 133 List<Node> nodes = new ArrayList<>(w.getNodes()); 134 if( w.isClosed() ) 135 nodes.remove(nodes.size() - 1); 136 int index1 = nodes.indexOf(n1); 137 int index2 = n2 == null ? -1 : nodes.indexOf(n2); 138 if( index1 > index2 ) { 139 int tmp = index1; 140 index1 = index2; 141 index2 = tmp; 142 } 143 // right now index2 >= index1 144 if( index2 < 1 || index1 >= w.getNodesCount() - 1 || index2 >= w.getNodesCount() ) 145 return Collections.emptyList(); 146 if( w.isClosed() && (index1 < 0 || index1 == index2 || index1 + w.getNodesCount() == index2) ) 147 return Collections.emptyList(); 148 149 // todo: download parent relations! 150 151 // make a list of segments 152 List<List<Node>> chunks = new ArrayList<>(2); 153 List<Node> chunk = new ArrayList<>(); 154 for( int i = 0; i < nodes.size(); i++ ) { 155 chunk.add(nodes.get(i)); 156 if( (w.isClosed() || chunk.size() > 1) && (i == index1 || i == index2) ) { 148 public static List<Way> splitWay(Way w, Node n1, Node n2, List<Command> commands) { 149 List<Node> nodes = new ArrayList<>(w.getNodes()); 150 if (w.isClosed() ) { 151 nodes.remove(nodes.size() - 1); 152 } 153 int index1 = nodes.indexOf(n1); 154 int index2 = n2 == null ? -1 : nodes.indexOf(n2); 155 if (index1 > index2) { 156 int tmp = index1; 157 index1 = index2; 158 index2 = tmp; 159 } 160 // right now index2 >= index1 161 if (index2 < 1 || index1 >= w.getNodesCount() - 1 || index2 >= w.getNodesCount() ) 162 return Collections.emptyList(); 163 if (w.isClosed() && (index1 < 0 || index1 == index2 || index1 + w.getNodesCount() == index2) ) 164 return Collections.emptyList(); 165 166 // todo: download parent relations! 167 168 // make a list of segments 169 List<List<Node>> chunks = new ArrayList<>(2); 170 List<Node> chunk = new ArrayList<>(); 171 for (int i = 0; i < nodes.size(); i++) { 172 chunk.add(nodes.get(i)); 173 if ((w.isClosed() || chunk.size() > 1) && (i == index1 || i == index2)) { 174 chunks.add(chunk); 175 chunk = new ArrayList<>(); 176 chunk.add(nodes.get(i)); 177 } 178 } 157 179 chunks.add(chunk); 158 chunk = new ArrayList<>(); 159 chunk.add(nodes.get(i)); 160 } 161 } 162 chunks.add(chunk); 163 164 // for closed way ignore the way boundary 165 if( w.isClosed() ) { 166 chunks.get(chunks.size() - 1).addAll(chunks.get(0)); 167 chunks.remove(0); 168 } else if( chunks.get(chunks.size() - 1).size() < 2 ) 169 chunks.remove(chunks.size() - 1); 170 171 // todo remove debug: show chunks array contents 172 /*for( List<Node> c1 : chunks ) { 173 for( Node cn1 : c1 ) 180 181 // for closed way ignore the way boundary 182 if (w.isClosed()) { 183 chunks.get(chunks.size() - 1).addAll(chunks.get(0)); 184 chunks.remove(0); 185 } else if (chunks.get(chunks.size() - 1).size() < 2 ) { 186 chunks.remove(chunks.size() - 1); 187 } 188 189 // todo remove debug: show chunks array contents 190 /*for (List<Node> c1 : chunks) { 191 for (Node cn1 : c1 ) 174 192 System.out.print(cn1.getId() + ","); 175 193 System.out.println(); 176 194 }*/ 177 195 178 // build a map of referencing relations 179 Map<Relation, Integer> references = new HashMap<>(); 180 List<Command> relationCommands = new ArrayList<>(); 181 for( OsmPrimitive p : w.getReferrers() ) { 182 if( p instanceof Relation ) { 183 Relation rel = commands == null ? (Relation)p : new Relation((Relation)p); 184 if( commands != null ) 185 relationCommands.add(new ChangeCommand((Relation)p, rel)); 186 for( int i = 0; i < rel.getMembersCount(); i++ ) 187 if( rel.getMember(i).getMember().equals(w) ) 188 references.put(rel, Integer.valueOf(i)); 189 } 190 } 191 192 // build ways 193 List<Way> result = new ArrayList<>(); 194 Way updatedWay = commands == null ? w : new Way(w); 195 updatedWay.setNodes(chunks.get(0)); 196 if( commands != null ) { 197 commands.add(new ChangeCommand(w, updatedWay)); 198 result.add(updatedWay); 199 } 200 201 for( int i = 1; i < chunks.size(); i++ ) { 202 List<Node> achunk = chunks.get(i); 203 Way newWay = new Way(); 204 newWay.setKeys(w.getKeys()); 205 result.add(newWay); 206 for( Relation rel : references.keySet() ) { 207 int relIndex = references.get(rel); 208 rel.addMember(relIndex + 1, new RelationMember(rel.getMember(relIndex).getRole(), newWay)); 209 } 210 newWay.setNodes(achunk); 211 if( commands != null ) 212 commands.add(new AddCommand(newWay)); 213 } 214 if( commands != null ) 215 commands.addAll(relationCommands); 216 return result; 217 } 218 219 public static List<Way> splitWay( Way w, Node n1, Node n2 ) { 220 return splitWay(w, n1, n2, null); 196 // build a map of referencing relations 197 Map<Relation, Integer> references = new HashMap<>(); 198 List<Command> relationCommands = new ArrayList<>(); 199 for (OsmPrimitive p : w.getReferrers()) { 200 if (p instanceof Relation) { 201 Relation rel = commands == null ? (Relation)p : new Relation((Relation)p); 202 if (commands != null ) { 203 relationCommands.add(new ChangeCommand(p, rel)); 204 } 205 for (int i = 0; i < rel.getMembersCount(); i++ ) 206 if (rel.getMember(i).getMember().equals(w) ) { 207 references.put(rel, Integer.valueOf(i)); 208 } 209 } 210 } 211 212 // build ways 213 List<Way> result = new ArrayList<>(); 214 Way updatedWay = commands == null ? w : new Way(w); 215 updatedWay.setNodes(chunks.get(0)); 216 if (commands != null) { 217 commands.add(new ChangeCommand(w, updatedWay)); 218 result.add(updatedWay); 219 } 220 221 for (int i = 1; i < chunks.size(); i++) { 222 List<Node> achunk = chunks.get(i); 223 Way newWay = new Way(); 224 newWay.setKeys(w.getKeys()); 225 result.add(newWay); 226 for (Relation rel : references.keySet()) { 227 int relIndex = references.get(rel); 228 rel.addMember(relIndex + 1, new RelationMember(rel.getMember(relIndex).getRole(), newWay)); 229 } 230 newWay.setNodes(achunk); 231 if (commands != null ) { 232 commands.add(new AddCommand(newWay)); 233 } 234 } 235 if (commands != null ) { 236 commands.addAll(relationCommands); 237 } 238 return result; 239 } 240 241 public static List<Way> splitWay(Way w, Node n1, Node n2) { 242 return splitWay(w, n1, n2, null); 221 243 } 222 244 … … 224 246 * Find a way the tips of a segment, ensure it's in a multipolygon and try to close the relation. 225 247 */ 226 public static Relation tryToCloseOneWay( Way segment, List<Command> resultingCommands ) { 227 if( segment.isClosed() || segment.isIncomplete() ) 228 return null; 229 230 List<Way> ways = intersection( 231 OsmPrimitive.getFilteredList(segment.firstNode().getReferrers(), Way.class), 232 OsmPrimitive.getFilteredList(segment.lastNode().getReferrers(), Way.class)); 233 ways.remove(segment); 234 for( Iterator<Way> iter = ways.iterator(); iter.hasNext(); ) { 235 boolean save = false; 236 for( OsmPrimitive ref : iter.next().getReferrers() ) 237 if( ref instanceof Relation && ((Relation)ref).isMultipolygon() && !ref.isDeleted() ) 238 save = true; 239 if( !save ) 240 iter.remove(); 241 } 242 if( ways.isEmpty() ) 243 return null; // well... 244 Way target = ways.get(0); 245 246 // time to create a new multipolygon relation and a command stack 247 List<Command> commands = new ArrayList<>(); 248 Relation newRelation = new Relation(); 249 newRelation.put("type", "multipolygon"); 250 newRelation.addMember(new RelationMember("outer", segment)); 251 Collection<String> linearTags = Main.pref.getCollection(PREF_MULTIPOLY + "lineartags", CreateMultipolygonAction.DEFAULT_LINEAR_TAGS); 252 Way segmentCopy = new Way(segment); 253 boolean changed = false; 254 for( String key : segmentCopy.keySet() ) { 255 if( !linearTags.contains(key) ) { 256 newRelation.put(key, segmentCopy.get(key)); 257 segmentCopy.remove(key); 258 changed = true; 259 } 260 } 261 if( changed ) 262 commands.add(new ChangeCommand(segment, segmentCopy)); 263 264 // now split the way, at last 265 List<Way> newWays = new ArrayList<>(splitWay(target, segment.firstNode(), segment.lastNode(), commands)); 266 267 Way addingWay = null; 268 if( target.isClosed() ) { 269 Way utarget = newWays.get(1); 270 Way alternate = newWays.get(0); 271 List<Node> testRing = new ArrayList<>(segment.getNodes()); 272 closePolygon(testRing, utarget.getNodes()); 273 addingWay = segmentInsidePolygon(alternate.getNode(0), alternate.getNode(1), testRing) ? alternate : utarget; 274 } else { 275 for( Way w : newWays ) { 276 if( (w.firstNode().equals(segment.firstNode()) && w.lastNode().equals(segment.lastNode())) 277 || (w.firstNode().equals(segment.lastNode()) && w.lastNode().equals(segment.firstNode())) ) { 278 addingWay = w; 279 break; 280 } 281 } 282 } 283 newRelation.addMember(new RelationMember("outer", addingWay.getUniqueId() == target.getUniqueId() ? target : addingWay)); 284 commands.add(new AddCommand(newRelation)); 285 resultingCommands.add(new SequenceCommand(tr("Complete multipolygon for way {0}", 286 DefaultNameFormatter.getInstance().format(segment)), commands)); 287 return newRelation; 248 public static Relation tryToCloseOneWay(Way segment, List<Command> resultingCommands) { 249 if (segment.isClosed() || segment.isIncomplete() ) 250 return null; 251 252 List<Way> ways = intersection( 253 OsmPrimitive.getFilteredList(segment.firstNode().getReferrers(), Way.class), 254 OsmPrimitive.getFilteredList(segment.lastNode().getReferrers(), Way.class)); 255 ways.remove(segment); 256 for (Iterator<Way> iter = ways.iterator(); iter.hasNext();) { 257 boolean save = false; 258 for (OsmPrimitive ref : iter.next().getReferrers() ) 259 if (ref instanceof Relation && ((Relation)ref).isMultipolygon() && !ref.isDeleted() ) { 260 save = true; 261 } 262 if (!save ) { 263 iter.remove(); 264 } 265 } 266 if (ways.isEmpty() ) 267 return null; // well... 268 Way target = ways.get(0); 269 270 // time to create a new multipolygon relation and a command stack 271 List<Command> commands = new ArrayList<>(); 272 Relation newRelation = new Relation(); 273 newRelation.put("type", "multipolygon"); 274 newRelation.addMember(new RelationMember("outer", segment)); 275 Collection<String> linearTags = Main.pref.getCollection(PREF_MULTIPOLY + "lineartags", CreateMultipolygonAction.DEFAULT_LINEAR_TAGS); 276 Way segmentCopy = new Way(segment); 277 boolean changed = false; 278 for (String key : segmentCopy.keySet()) { 279 if (!linearTags.contains(key)) { 280 newRelation.put(key, segmentCopy.get(key)); 281 segmentCopy.remove(key); 282 changed = true; 283 } 284 } 285 if (changed ) { 286 commands.add(new ChangeCommand(segment, segmentCopy)); 287 } 288 289 // now split the way, at last 290 List<Way> newWays = new ArrayList<>(splitWay(target, segment.firstNode(), segment.lastNode(), commands)); 291 292 Way addingWay = null; 293 if (target.isClosed()) { 294 Way utarget = newWays.get(1); 295 Way alternate = newWays.get(0); 296 List<Node> testRing = new ArrayList<>(segment.getNodes()); 297 closePolygon(testRing, utarget.getNodes()); 298 addingWay = segmentInsidePolygon(alternate.getNode(0), alternate.getNode(1), testRing) ? alternate : utarget; 299 } else { 300 for (Way w : newWays) { 301 if ((w.firstNode().equals(segment.firstNode()) && w.lastNode().equals(segment.lastNode())) 302 || (w.firstNode().equals(segment.lastNode()) && w.lastNode().equals(segment.firstNode()))) { 303 addingWay = w; 304 break; 305 } 306 } 307 } 308 newRelation.addMember(new RelationMember("outer", addingWay.getUniqueId() == target.getUniqueId() ? target : addingWay)); 309 commands.add(new AddCommand(newRelation)); 310 resultingCommands.add(new SequenceCommand(tr("Complete multipolygon for way {0}", 311 DefaultNameFormatter.getInstance().format(segment)), commands)); 312 return newRelation; 288 313 } 289 314 … … 291 316 * Returns all elements from {@code list1} that are in {@code list2}. 292 317 */ 293 private static <T> List<T> intersection( Collection<T> list1, Collection<T> list2 ) { 294 List<T> result = new ArrayList<>(); 295 for( T item : list1 ) 296 if( list2.contains(item) ) 297 result.add(item); 298 return result; 299 } 300 318 private static <T> List<T> intersection(Collection<T> list1, Collection<T> list2) { 319 List<T> result = new ArrayList<>(); 320 for (T item : list1 ) 321 if (list2.contains(item) ) { 322 result.add(item); 323 } 324 return result; 325 } 326 301 327 /** 302 328 * Make a multipolygon out of the ring, but split it to attach to neighboring multipolygons. 303 329 */ 304 public static Relation attachRingToNeighbours( Way ring, List<Command> resultingCommands ) { 305 if( !ring.isClosed() || ring.isIncomplete() ) 306 return null; 307 Map<Way, Boolean> touchingWays = new HashMap<>(); 308 for( Node n : ring.getNodes() ) { 309 for( OsmPrimitive p : n.getReferrers() ) { 310 if( p instanceof Way && !p.equals(ring) ) { 311 for( OsmPrimitive r : p.getReferrers() ) { 312 if( r instanceof Relation && ((Relation)r).hasKey("type") && ((Relation)r).get("type").equals("multipolygon") ) { 313 if( touchingWays.containsKey((Way)p) ) 314 touchingWays.put((Way)p, Boolean.TRUE); 315 else 316 touchingWays.put((Way)p, Boolean.FALSE); 317 break; 318 } 319 } 320 } 321 } 322 } 323 324 List<TheRing> otherWays = new ArrayList<>(); 325 for( Way w : touchingWays.keySet() ) 326 if( touchingWays.get(w) ) { 327 otherWays.add(new TheRing(w)); 328 // System.out.println("Touching ring: " + otherWays.get(otherWays.size()-1)); 329 } 330 331 // for( Iterator<Way> keys = touchingWays.keySet().iterator(); keys.hasNext(); ) { 332 // if( !touchingWays.get(keys.next()) ) 333 // keys.remove(); 334 // } 335 336 // now touchingWays has only ways that touch the ring twice 337 List<Command> commands = new ArrayList<>(); 338 TheRing theRing = new TheRing(ring); // this is actually useful 339 340 for( TheRing otherRing : otherWays ) 341 theRing.collide(otherRing); 342 343 theRing.putSourceWayFirst(); 344 for( TheRing otherRing : otherWays ) 345 otherRing.putSourceWayFirst(); 346 347 Map<Relation, Relation> relationCache = new HashMap<>(); 348 for( TheRing otherRing : otherWays ) 349 commands.addAll(otherRing.getCommands(false, relationCache)); 350 commands.addAll(theRing.getCommands(relationCache)); 351 TheRing.updateCommandsWithRelations(commands, relationCache); 352 resultingCommands.add(new SequenceCommand(tr("Complete multipolygon for way {0}", 353 DefaultNameFormatter.getInstance().format(ring)), commands)); 354 return theRing.getRelation(); 330 public static Relation attachRingToNeighbours(Way ring, List<Command> resultingCommands) { 331 if (!ring.isClosed() || ring.isIncomplete() ) 332 return null; 333 Map<Way, Boolean> touchingWays = new HashMap<>(); 334 for (Node n : ring.getNodes()) { 335 for (OsmPrimitive p : n.getReferrers()) { 336 if (p instanceof Way && !p.equals(ring)) { 337 for (OsmPrimitive r : p.getReferrers()) { 338 if (r instanceof Relation && ((Relation)r).hasKey("type") && ((Relation)r).get("type").equals("multipolygon")) { 339 if (touchingWays.containsKey(p) ) { 340 touchingWays.put((Way)p, Boolean.TRUE); 341 } else { 342 touchingWays.put((Way)p, Boolean.FALSE); 343 } 344 break; 345 } 346 } 347 } 348 } 349 } 350 351 List<TheRing> otherWays = new ArrayList<>(); 352 for (Way w : touchingWays.keySet() ) 353 if (touchingWays.get(w)) { 354 otherWays.add(new TheRing(w)); 355 // System.out.println("Touching ring: " + otherWays.get(otherWays.size()-1)); 356 } 357 358 // for (Iterator<Way> keys = touchingWays.keySet().iterator(); keys.hasNext();) { 359 // if (!touchingWays.get(keys.next()) ) 360 // keys.remove(); 361 // } 362 363 // now touchingWays has only ways that touch the ring twice 364 List<Command> commands = new ArrayList<>(); 365 TheRing theRing = new TheRing(ring); // this is actually useful 366 367 for (TheRing otherRing : otherWays ) { 368 theRing.collide(otherRing); 369 } 370 371 theRing.putSourceWayFirst(); 372 for (TheRing otherRing : otherWays ) { 373 otherRing.putSourceWayFirst(); 374 } 375 376 Map<Relation, Relation> relationCache = new HashMap<>(); 377 for (TheRing otherRing : otherWays ) { 378 commands.addAll(otherRing.getCommands(false, relationCache)); 379 } 380 commands.addAll(theRing.getCommands(relationCache)); 381 TheRing.updateCommandsWithRelations(commands, relationCache); 382 resultingCommands.add(new SequenceCommand(tr("Complete multipolygon for way {0}", 383 DefaultNameFormatter.getInstance().format(ring)), commands)); 384 return theRing.getRelation(); 355 385 } 356 386 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/TheRing.java
r30738 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.actions; 2 3 … … 25 26 * One ring that contains segments forming an outer way of multipolygon. 26 27 * This class is used in {@link CreateMultipolygonAction#makeManySimpleMultipolygons(java.util.Collection)}. 27 * 28 * 28 29 * @author Zverik 29 30 */ … … 35 36 private Relation relation = null; 36 37 37 public TheRing( Way source ) { 38 this.source = source; 39 segments = new ArrayList<>(1); 40 segments.add(new RingSegment(source)); 41 } 42 43 public static boolean areAllOfThoseRings( Collection<Way> ways ) { 44 List<Way> rings = new ArrayList<>(); 45 for( Way way : ways ) { 46 if( way.isClosed() ) 47 rings.add(way); 48 else 49 return false; 50 } 51 if( rings.isEmpty() || ways.size() == 1 ) 52 return false; 53 54 // check for non-containment of rings 55 for( int i = 0; i < rings.size() - 1; i++ ) { 56 for( int j = i + 1; j < rings.size(); j++ ) { 57 PolygonIntersection intersection = Geometry.polygonIntersection(rings.get(i).getNodes(), rings.get(j).getNodes()); 58 if( intersection == PolygonIntersection.FIRST_INSIDE_SECOND || intersection == PolygonIntersection.SECOND_INSIDE_FIRST ) 38 public TheRing(Way source) { 39 this.source = source; 40 segments = new ArrayList<>(1); 41 segments.add(new RingSegment(source)); 42 } 43 44 public static boolean areAllOfThoseRings(Collection<Way> ways) { 45 List<Way> rings = new ArrayList<>(); 46 for (Way way : ways) { 47 if (way.isClosed() ) { 48 rings.add(way); 49 } else 50 return false; 51 } 52 if (rings.isEmpty() || ways.size() == 1 ) 59 53 return false; 60 } 61 } 62 63 return true; 54 55 // check for non-containment of rings 56 for (int i = 0; i < rings.size() - 1; i++) { 57 for (int j = i + 1; j < rings.size(); j++) { 58 PolygonIntersection intersection = Geometry.polygonIntersection(rings.get(i).getNodes(), rings.get(j).getNodes()); 59 if (intersection == PolygonIntersection.FIRST_INSIDE_SECOND || intersection == PolygonIntersection.SECOND_INSIDE_FIRST ) 60 return false; 61 } 62 } 63 64 return true; 64 65 } 65 66 … … 68 69 * @return list of new relations. 69 70 */ 70 public static List<Relation> makeManySimpleMultipolygons( Collection<Way> selection, List<Command> commands ) { 71 log("---------------------------------------"); 72 List<TheRing> rings = new ArrayList<>(selection.size()); 73 for( Way w : selection ) 74 rings.add(new TheRing(w)); 75 for( int i = 0; i < rings.size() - 1; i++ ) 76 for( int j = i + 1; j < rings.size(); j++ ) 77 rings.get(i).collide(rings.get(j)); 78 redistributeSegments(rings); 79 List<Relation> relations = new ArrayList<>(); 80 Map<Relation, Relation> relationCache = new HashMap<>(); 81 for( TheRing r : rings ) { 82 commands.addAll(r.getCommands(relationCache)); 83 relations.add(r.getRelation()); 84 } 85 updateCommandsWithRelations(commands, relationCache); 86 return relations; 87 } 88 89 public void collide( TheRing other ) { 90 boolean collideNoted = false; 91 for( int i = 0; i < segments.size(); i++ ) { 92 RingSegment segment1 = segments.get(i); 93 if( !segment1.isReference() ) { 94 for( int j = 0; j < other.segments.size(); j++ ) { 95 RingSegment segment2 = other.segments.get(j); 96 if( !segment2.isReference() ) { 97 log("Comparing " + segment1 + " and " + segment2); 98 Node[] split = getSplitNodes(segment1.getNodes(), segment2.getNodes(), segment1.isRing(), segment2.isRing()); 99 if( split != null ) { 100 if( !collideNoted ) { 101 log("Rings for ways " + source.getUniqueId() + " and " + other.source.getUniqueId() + " collide."); 102 collideNoted = true; 103 } 104 RingSegment segment = splitRingAt(i, split[0], split[1]); 105 RingSegment otherSegment = other.splitRingAt(j, split[2], split[3]); 106 if( !areSegmentsEqual(segment, otherSegment) ) 107 throw new IllegalArgumentException("Error: algorithm gave incorrect segments: " + segment + " and " + otherSegment); 108 segment.makeReference(otherSegment); 109 } 110 } 111 if( segment1.isReference() ) 112 break; 113 } 114 } 115 } 116 } 117 71 public static List<Relation> makeManySimpleMultipolygons(Collection<Way> selection, List<Command> commands) { 72 log("---------------------------------------"); 73 List<TheRing> rings = new ArrayList<>(selection.size()); 74 for (Way w : selection ) { 75 rings.add(new TheRing(w)); 76 } 77 for (int i = 0; i < rings.size() - 1; i++ ) { 78 for (int j = i + 1; j < rings.size(); j++ ) { 79 rings.get(i).collide(rings.get(j)); 80 } 81 } 82 redistributeSegments(rings); 83 List<Relation> relations = new ArrayList<>(); 84 Map<Relation, Relation> relationCache = new HashMap<>(); 85 for (TheRing r : rings) { 86 commands.addAll(r.getCommands(relationCache)); 87 relations.add(r.getRelation()); 88 } 89 updateCommandsWithRelations(commands, relationCache); 90 return relations; 91 } 92 93 public void collide(TheRing other) { 94 boolean collideNoted = false; 95 for (int i = 0; i < segments.size(); i++) { 96 RingSegment segment1 = segments.get(i); 97 if (!segment1.isReference()) { 98 for (int j = 0; j < other.segments.size(); j++) { 99 RingSegment segment2 = other.segments.get(j); 100 if (!segment2.isReference()) { 101 log("Comparing " + segment1 + " and " + segment2); 102 Node[] split = getSplitNodes(segment1.getNodes(), segment2.getNodes(), segment1.isRing(), segment2.isRing()); 103 if (split != null) { 104 if (!collideNoted) { 105 log("Rings for ways " + source.getUniqueId() + " and " + other.source.getUniqueId() + " collide."); 106 collideNoted = true; 107 } 108 RingSegment segment = splitRingAt(i, split[0], split[1]); 109 RingSegment otherSegment = other.splitRingAt(j, split[2], split[3]); 110 if (!areSegmentsEqual(segment, otherSegment) ) 111 throw new IllegalArgumentException("Error: algorithm gave incorrect segments: " + segment + " and " + otherSegment); 112 segment.makeReference(otherSegment); 113 } 114 } 115 if (segment1.isReference() ) { 116 break; 117 } 118 } 119 } 120 } 121 } 122 118 123 /** 119 124 * Returns array of {start1, last1, start2, last2} or null if there is no common nodes. 120 125 */ 121 public static Node[] getSplitNodes( List<Node> nodes1, List<Node> nodes2, boolean isRing1, boolean isRing2 ) { 122 int pos = 0; 123 while( pos < nodes1.size() && !nodes2.contains(nodes1.get(pos)) ) 124 pos++; 125 boolean collideFound = pos == nodes1.size(); 126 if( pos == 0 && isRing1 ) { 127 // rewind a bit 128 pos = nodes1.size() - 1; 129 while( pos > 0 && nodes2.contains(nodes1.get(pos)) ) 130 pos--; 131 if( pos == 0 && nodes1.size() == nodes2.size() ) { 132 JOptionPane.showMessageDialog(Main.parent, "Two rings are equal, and this must not be.", "Multipolygon from rings", JOptionPane.ERROR_MESSAGE); 126 public static Node[] getSplitNodes(List<Node> nodes1, List<Node> nodes2, boolean isRing1, boolean isRing2) { 127 int pos = 0; 128 while(pos < nodes1.size() && !nodes2.contains(nodes1.get(pos)) ) { 129 pos++; 130 } 131 boolean collideFound = pos == nodes1.size(); 132 if (pos == 0 && isRing1) { 133 // rewind a bit 134 pos = nodes1.size() - 1; 135 while(pos > 0 && nodes2.contains(nodes1.get(pos)) ) { 136 pos--; 137 } 138 if (pos == 0 && nodes1.size() == nodes2.size()) { 139 JOptionPane.showMessageDialog(Main.parent, "Two rings are equal, and this must not be.", "Multipolygon from rings", JOptionPane.ERROR_MESSAGE); 140 return null; 141 } 142 pos = pos == nodes1.size() - 1 ? 0 : pos + 1; 143 } 144 int firstPos = isRing1 ? pos : nodes1.size(); 145 while(!collideFound) { 146 log("pos=" + pos); 147 int start1 = pos; 148 int start2 = nodes2.indexOf(nodes1.get(start1)); 149 int last1 = incrementBy(start1, 1, nodes1.size(), isRing1); 150 int last2 = start2; 151 int increment2 = 0; 152 if (last1 >= 0) { 153 last2 = incrementBy(start2, -1, nodes2.size(), isRing2); 154 if (last2 >= 0 && nodes1.get(last1).equals(nodes2.get(last2)) ) { 155 increment2 = -1; 156 } else { 157 last2 = incrementBy(start2, 1, nodes2.size(), isRing2); 158 if (last2 >= 0 && nodes1.get(last1).equals(nodes2.get(last2)) ) { 159 increment2 = 1; 160 } 161 } 162 } 163 log("last1=" + last1 + " last2=" + last2 + " increment2=" + increment2); 164 if (increment2 != 0) { 165 // find the first nodes 166 boolean reachedEnd = false; 167 while(!reachedEnd) { 168 int newLast1 = incrementBy(last1, 1, nodes1.size(), isRing1); 169 int newLast2 = incrementBy(last2, increment2, nodes2.size(), isRing2); 170 if (newLast1 < 0 || newLast2 < 0 || !nodes1.get(newLast1).equals(nodes2.get(newLast2)) ) { 171 reachedEnd = true; 172 } else { 173 last1 = newLast1; 174 last2 = newLast2; 175 } 176 } 177 log("last1=" + last1 + " last2=" + last2); 178 if (increment2 < 0) { 179 int tmp = start2; 180 start2 = last2; 181 last2 = tmp; 182 } 183 return new Node[] {nodes1.get(start1), nodes1.get(last1), nodes2.get(start2), nodes2.get(last2)}; 184 } else { 185 pos = last1; 186 while(pos != firstPos && pos >= 0 && !nodes2.contains(nodes1.get(pos)) ) { 187 pos = incrementBy(pos, 1, nodes1.size(), isRing1); 188 } 189 if (pos < 0 || pos == firstPos || !nodes2.contains(nodes1.get(pos)) ) { 190 collideFound = true; 191 } 192 } 193 } 133 194 return null; 134 } 135 pos = pos == nodes1.size() - 1 ? 0 : pos + 1; 136 } 137 int firstPos = isRing1 ? pos : nodes1.size(); 138 while( !collideFound ) { 139 log("pos=" + pos); 140 int start1 = pos; 141 int start2 = nodes2.indexOf(nodes1.get(start1)); 142 int last1 = incrementBy(start1, 1, nodes1.size(), isRing1); 143 int last2 = start2; 144 int increment2 = 0; 145 if( last1 >= 0 ) { 146 last2 = incrementBy(start2, -1, nodes2.size(), isRing2); 147 if( last2 >= 0 && nodes1.get(last1).equals(nodes2.get(last2)) ) 148 increment2 = -1; 149 else { 150 last2 = incrementBy(start2, 1, nodes2.size(), isRing2); 151 if( last2 >= 0 && nodes1.get(last1).equals(nodes2.get(last2)) ) 152 increment2 = 1; 153 } 154 } 155 log("last1=" + last1 + " last2=" + last2 + " increment2=" + increment2); 156 if( increment2 != 0 ) { 157 // find the first nodes 158 boolean reachedEnd = false; 159 while( !reachedEnd ) { 160 int newLast1 = incrementBy(last1, 1, nodes1.size(), isRing1); 161 int newLast2 = incrementBy(last2, increment2, nodes2.size(), isRing2); 162 if( newLast1 < 0 || newLast2 < 0 || !nodes1.get(newLast1).equals(nodes2.get(newLast2)) ) 163 reachedEnd = true; 164 else { 165 last1 = newLast1; 166 last2 = newLast2; 167 } 168 } 169 log("last1=" + last1 + " last2=" + last2); 170 if( increment2 < 0 ) { 171 int tmp = start2; 172 start2 = last2; 173 last2 = tmp; 174 } 175 return new Node[] {nodes1.get(start1), nodes1.get(last1), nodes2.get(start2), nodes2.get(last2)}; 176 } else { 177 pos = last1; 178 while( pos != firstPos && pos >= 0 && !nodes2.contains(nodes1.get(pos)) ) 179 pos = incrementBy(pos, 1, nodes1.size(), isRing1); 180 if( pos < 0 || pos == firstPos || !nodes2.contains(nodes1.get(pos)) ) 181 collideFound = true; 182 } 183 } 184 return null; 185 } 186 187 private static int incrementBy( int value, int increment, int limit1, boolean isRing ) { 188 int result = value + increment; 189 if( result < 0 ) 190 return isRing ? result + limit1 : -1; 191 else if( result >= limit1 ) 192 return isRing ? result - limit1 : -1; 193 else 194 return result; 195 } 196 197 private boolean areSegmentsEqual( RingSegment seg1, RingSegment seg2 ) { 198 List<Node> nodes1 = seg1.getNodes(); 199 List<Node> nodes2 = seg2.getNodes(); 200 int size = nodes1.size(); 201 if( size != nodes2.size() ) 202 return false; 203 boolean reverse = size > 1 && !nodes1.get(0).equals(nodes2.get(0)); 204 for( int i = 0; i < size; i++ ) 205 if( !nodes1.get(i).equals(nodes2.get(reverse ? size-1-i : i)) ) 206 return false; 207 return true; 195 } 196 197 private static int incrementBy(int value, int increment, int limit1, boolean isRing) { 198 int result = value + increment; 199 if (result < 0 ) 200 return isRing ? result + limit1 : -1; 201 else if (result >= limit1 ) 202 return isRing ? result - limit1 : -1; 203 else 204 return result; 205 } 206 207 private boolean areSegmentsEqual(RingSegment seg1, RingSegment seg2) { 208 List<Node> nodes1 = seg1.getNodes(); 209 List<Node> nodes2 = seg2.getNodes(); 210 int size = nodes1.size(); 211 if (size != nodes2.size() ) 212 return false; 213 boolean reverse = size > 1 && !nodes1.get(0).equals(nodes2.get(0)); 214 for (int i = 0; i < size; i++ ) 215 if (!nodes1.get(i).equals(nodes2.get(reverse ? size-1-i : i)) ) 216 return false; 217 return true; 208 218 } 209 219 … … 212 222 * @return The segment between nodes. 213 223 */ 214 private RingSegment splitRingAt( int segmentIndex, Node n1, Node n2 ) { 215 if( n1.equals(n2) ) 216 throw new IllegalArgumentException("Both nodes are equal, id=" + n1.getUniqueId()); 217 RingSegment segment = segments.get(segmentIndex); 218 boolean isRing = segment.isRing(); 219 log("Split segment " + segment + " at nodes " + n1.getUniqueId() + " and " + n2.getUniqueId()); 220 boolean reversed = segment.getNodes().indexOf(n2) < segment.getNodes().indexOf(n1); 221 if( reversed && !isRing ) { 222 // order nodes 223 Node tmp = n1; 224 n1 = n2; 225 n2 = tmp; 226 } 227 RingSegment secondPart = isRing ? segment.split(n1, n2) : segment.split(n1); 228 // if secondPart == null, then n1 == firstNode 229 RingSegment thirdPart = isRing ? null : secondPart == null ? segment.split(n2) : secondPart.split(n2); 230 // if secondPart == null, then thirdPart is between n1 and n2 231 // otherwise, thirdPart is between n2 and lastNode 232 // if thirdPart == null, then n2 == lastNode 233 int pos = segmentIndex + 1; 234 if( secondPart != null ) 235 segments.add(pos++, secondPart); 236 if( thirdPart != null ) 237 segments.add(pos++, thirdPart); 238 return isRing || secondPart == null ? segment : secondPart; 224 private RingSegment splitRingAt(int segmentIndex, Node n1, Node n2) { 225 if (n1.equals(n2) ) 226 throw new IllegalArgumentException("Both nodes are equal, id=" + n1.getUniqueId()); 227 RingSegment segment = segments.get(segmentIndex); 228 boolean isRing = segment.isRing(); 229 log("Split segment " + segment + " at nodes " + n1.getUniqueId() + " and " + n2.getUniqueId()); 230 boolean reversed = segment.getNodes().indexOf(n2) < segment.getNodes().indexOf(n1); 231 if (reversed && !isRing) { 232 // order nodes 233 Node tmp = n1; 234 n1 = n2; 235 n2 = tmp; 236 } 237 RingSegment secondPart = isRing ? segment.split(n1, n2) : segment.split(n1); 238 // if secondPart == null, then n1 == firstNode 239 RingSegment thirdPart = isRing ? null : secondPart == null ? segment.split(n2) : secondPart.split(n2); 240 // if secondPart == null, then thirdPart is between n1 and n2 241 // otherwise, thirdPart is between n2 and lastNode 242 // if thirdPart == null, then n2 == lastNode 243 int pos = segmentIndex + 1; 244 if (secondPart != null ) { 245 segments.add(pos++, secondPart); 246 } 247 if (thirdPart != null ) { 248 segments.add(pos++, thirdPart); 249 } 250 return isRing || secondPart == null ? segment : secondPart; 239 251 } 240 252 … … 242 254 * Tries to arrange segments in order for each ring to have at least one. 243 255 * Also, sets source way for all rings. 244 * 256 * 245 257 * If this method is not called, do not forget to call {@link #putSourceWayFirst()} for all rings. 246 258 */ 247 public static void redistributeSegments( List<TheRing> rings ) { 248 // build segments map 249 Map<RingSegment, TheRing> segmentMap = new HashMap<>(); 250 for( TheRing ring : rings ) 251 for( RingSegment seg : ring.segments ) 252 if( !seg.isReference() ) 253 segmentMap.put(seg, ring); 254 255 // rearrange references 256 for( int i = 0; i < rings.size(); i++ ) { 257 TheRing ring = rings.get(i); 258 if( ring.countNonReferenceSegments() == 0 ) { 259 // need to find one non-reference segment 260 for( RingSegment seg : ring.segments ) { 261 TheRing otherRing = segmentMap.get(seg.references); 262 if( otherRing.countNonReferenceSegments() > 1 ) { 263 // we could check for >0, but it is prone to deadlocking 264 seg.swapReference(); 265 } 266 } 267 } 268 } 269 270 // initializing source way for each ring 271 for( TheRing ring : rings ) 272 ring.putSourceWayFirst(); 259 public static void redistributeSegments(List<TheRing> rings) { 260 // build segments map 261 Map<RingSegment, TheRing> segmentMap = new HashMap<>(); 262 for (TheRing ring : rings ) { 263 for (RingSegment seg : ring.segments ) 264 if (!seg.isReference() ) { 265 segmentMap.put(seg, ring); 266 } 267 } 268 269 // rearrange references 270 for (int i = 0; i < rings.size(); i++) { 271 TheRing ring = rings.get(i); 272 if (ring.countNonReferenceSegments() == 0) { 273 // need to find one non-reference segment 274 for (RingSegment seg : ring.segments) { 275 TheRing otherRing = segmentMap.get(seg.references); 276 if (otherRing.countNonReferenceSegments() > 1) { 277 // we could check for >0, but it is prone to deadlocking 278 seg.swapReference(); 279 } 280 } 281 } 282 } 283 284 // initializing source way for each ring 285 for (TheRing ring : rings ) { 286 ring.putSourceWayFirst(); 287 } 273 288 } 274 289 275 290 private int countNonReferenceSegments() { 276 int count = 0; 277 for( RingSegment seg : segments ) 278 if( !seg.isReference() ) 279 count++; 280 return count; 291 int count = 0; 292 for (RingSegment seg : segments ) 293 if (!seg.isReference() ) { 294 count++; 295 } 296 return count; 281 297 } 282 298 283 299 public void putSourceWayFirst() { 284 for( RingSegment seg : segments) {285 if( !seg.isReference()) {286 seg.overrideWay(source);287 return;288 }289 }290 } 291 300 for (RingSegment seg : segments) { 301 if (!seg.isReference()) { 302 seg.overrideWay(source); 303 return; 304 } 305 } 306 } 307 292 308 public List<Command> getCommands() { 293 return getCommands(true, null);294 } 295 296 public List<Command> getCommands( Map<Relation, Relation> relationChangeMap) {297 return getCommands(true, relationChangeMap);298 } 299 309 return getCommands(true, null); 310 } 311 312 public List<Command> getCommands(Map<Relation, Relation> relationChangeMap) { 313 return getCommands(true, relationChangeMap); 314 } 315 300 316 /** 301 317 * Returns a list of commands to make a new relation and all newly created ways. 302 318 * The first way is copied from the source one, ChangeCommand is issued in this case. 303 319 */ 304 public List<Command> getCommands( boolean createMultipolygon, Map<Relation, Relation> relationChangeMap ) { 305 Way sourceCopy = new Way(source); 306 if( createMultipolygon ) { 307 Collection<String> linearTags = Main.pref.getCollection(PREF_MULTIPOLY + "lineartags", CreateMultipolygonAction.DEFAULT_LINEAR_TAGS); 308 relation = new Relation(); 309 relation.put("type", "multipolygon"); 310 for( String key : sourceCopy.keySet() ) { 311 if( linearTags.contains(key) ) continue; 312 if( key.equals("natural") && sourceCopy.get("natural").equals("coastline") ) continue; 320 public List<Command> getCommands(boolean createMultipolygon, Map<Relation, Relation> relationChangeMap) { 321 Way sourceCopy = new Way(source); 322 if (createMultipolygon) { 323 Collection<String> linearTags = Main.pref.getCollection(PREF_MULTIPOLY + "lineartags", CreateMultipolygonAction.DEFAULT_LINEAR_TAGS); 324 relation = new Relation(); 325 relation.put("type", "multipolygon"); 326 for (String key : sourceCopy.keySet()) { 327 if (linearTags.contains(key) ) { 328 continue; 329 } 330 if (key.equals("natural") && sourceCopy.get("natural").equals("coastline") ) { 331 continue; 332 } 313 333 relation.put(key, sourceCopy.get(key)); 314 334 sourceCopy.remove(key); 315 } 316 } 317 318 // build a map of referencing relations 319 Map<Relation, Integer> referencingRelations = new HashMap<>(); 320 List<Command> relationCommands = new ArrayList<>(); 321 for( OsmPrimitive p : source.getReferrers() ) { 322 if( p instanceof Relation ) { 323 Relation rel = null; 324 if( relationChangeMap != null ) { 325 if( relationChangeMap.containsKey((Relation)p) ) 326 rel = relationChangeMap.get((Relation)p); 327 else { 328 rel = new Relation((Relation)p); 329 relationChangeMap.put((Relation)p, rel); 330 } 331 } else { 332 rel = new Relation((Relation)p); 333 relationCommands.add(new ChangeCommand((Relation)p, rel)); 334 } 335 for( int i = 0; i < rel.getMembersCount(); i++ ) 336 if( rel.getMember(i).getMember().equals(source) ) 337 referencingRelations.put(rel, Integer.valueOf(i)); 338 } 339 } 340 // todo: когда два кольца менÑ�ÑŽÑ‚ одно и то же отношение, в Ñ�пиÑ�ок команд добавлÑ�етÑ�Ñ� 341 // изменение базового отношениÑ� на новое, а не предыдущего 342 // поÑ�тому Ñ�охранÑ�етÑ�Ñ� только первое изменение 343 344 List<Command> commands = new ArrayList<>(); 345 boolean foundOwnWay = false; 346 for( RingSegment seg : segments ) { 347 boolean needAdding = !seg.isWayConstructed(); 348 Way w = seg.constructWay(seg.isReference() ? null : sourceCopy); 349 if( needAdding ) 350 commands.add(new AddCommand(w)); 351 if( w.equals(source) ) { 352 if( createMultipolygon || !seg.getWayNodes().equals(source.getNodes()) ) { 353 sourceCopy.setNodes(seg.getWayNodes()); 354 commands.add(new ChangeCommand(source, sourceCopy)); 355 } 356 foundOwnWay = true; 357 } else { 358 for( Relation rel : referencingRelations.keySet() ) { 359 int relIndex = referencingRelations.get(rel); 360 rel.addMember(new RelationMember(rel.getMember(relIndex).getRole(), w)); 361 } 362 } 363 if( createMultipolygon ) 364 relation.addMember(new RelationMember("outer", w)); 365 } 366 if( !foundOwnWay ) 367 commands.add(new DeleteCommand(source)); 368 commands.addAll(relationCommands); 369 if( createMultipolygon ) 370 commands.add(new AddCommand(relation)); 371 return commands; 372 } 373 374 public static void updateCommandsWithRelations( List<Command> commands, Map<Relation, Relation> relationCache ) { 375 for( Relation src : relationCache.keySet() ) 376 commands.add(new ChangeCommand(src, relationCache.get(src))); 335 } 336 } 337 338 // build a map of referencing relations 339 Map<Relation, Integer> referencingRelations = new HashMap<>(); 340 List<Command> relationCommands = new ArrayList<>(); 341 for (OsmPrimitive p : source.getReferrers()) { 342 if (p instanceof Relation) { 343 Relation rel = null; 344 if (relationChangeMap != null) { 345 if (relationChangeMap.containsKey(p) ) { 346 rel = relationChangeMap.get(p); 347 } else { 348 rel = new Relation((Relation)p); 349 relationChangeMap.put((Relation)p, rel); 350 } 351 } else { 352 rel = new Relation((Relation)p); 353 relationCommands.add(new ChangeCommand(p, rel)); 354 } 355 for (int i = 0; i < rel.getMembersCount(); i++ ) 356 if (rel.getMember(i).getMember().equals(source) ) { 357 referencingRelations.put(rel, Integer.valueOf(i)); 358 } 359 } 360 } 361 // todo: когда два кольца менÑ�ÑŽÑ‚ одно и то же отношение, в Ñ�пиÑ�ок команд добавлÑ�етÑ�Ñ� 362 // изменение базового отношениÑ� на новое, а не предыдущего 363 // поÑ�тому Ñ�охранÑ�етÑ�Ñ� только первое изменение 364 365 List<Command> commands = new ArrayList<>(); 366 boolean foundOwnWay = false; 367 for (RingSegment seg : segments) { 368 boolean needAdding = !seg.isWayConstructed(); 369 Way w = seg.constructWay(seg.isReference() ? null : sourceCopy); 370 if (needAdding ) { 371 commands.add(new AddCommand(w)); 372 } 373 if (w.equals(source)) { 374 if (createMultipolygon || !seg.getWayNodes().equals(source.getNodes())) { 375 sourceCopy.setNodes(seg.getWayNodes()); 376 commands.add(new ChangeCommand(source, sourceCopy)); 377 } 378 foundOwnWay = true; 379 } else { 380 for (Relation rel : referencingRelations.keySet()) { 381 int relIndex = referencingRelations.get(rel); 382 rel.addMember(new RelationMember(rel.getMember(relIndex).getRole(), w)); 383 } 384 } 385 if (createMultipolygon ) { 386 relation.addMember(new RelationMember("outer", w)); 387 } 388 } 389 if (!foundOwnWay ) { 390 commands.add(new DeleteCommand(source)); 391 } 392 commands.addAll(relationCommands); 393 if (createMultipolygon ) { 394 commands.add(new AddCommand(relation)); 395 } 396 return commands; 397 } 398 399 public static void updateCommandsWithRelations(List<Command> commands, Map<Relation, Relation> relationCache) { 400 for (Relation src : relationCache.keySet() ) { 401 commands.add(new ChangeCommand(src, relationCache.get(src))); 402 } 377 403 } 378 404 … … 381 407 */ 382 408 public Relation getRelation() { 383 return relation;409 return relation; 384 410 } 385 411 386 412 @Override 387 413 public String toString() { 388 StringBuilder sb = new StringBuilder("TheRing@"); 389 sb.append(this.hashCode()).append('[').append("wayId: ").append(source == null ? "null" : source.getUniqueId()).append("; segments: "); 390 if( segments.isEmpty() ) 391 sb.append("empty"); 392 else { 393 sb.append(segments.get(0)); 394 for( int i = 1; i < segments.size(); i++ ) 395 sb.append(", ").append(segments.get(i)); 396 } 397 return sb.append(']').toString(); 414 StringBuilder sb = new StringBuilder("TheRing@"); 415 sb.append(this.hashCode()).append('[').append("wayId: ").append(source == null ? "null" : source.getUniqueId()).append("; segments: "); 416 if (segments.isEmpty() ) { 417 sb.append("empty"); 418 } else { 419 sb.append(segments.get(0)); 420 for (int i = 1; i < segments.size(); i++ ) { 421 sb.append(", ").append(segments.get(i)); 422 } 423 } 424 return sb.append(']').toString(); 398 425 } 399 426 … … 401 428 * Appends "append" to "base" so the closed polygon forms. 402 429 */ 403 /*private static void closePolygon( List<Node> base, List<Node> append) {404 if ( append.get(0).equals(base.get(0)) && append.get(append.size() - 1).equals(base.get(base.size() - 1))) {430 /*private static void closePolygon(List<Node> base, List<Node> append) { 431 if (append.get(0).equals(base.get(0)) && append.get(append.size() - 1).equals(base.get(base.size() - 1))) { 405 432 List<Node> ap2 = new ArrayList<Node>(append); 406 433 Collections.reverse(ap2); … … 414 441 * Checks if a middle point between two nodes is inside a polygon. Useful to check if the way is inside. 415 442 */ 416 /*private static boolean segmentInsidePolygon( Node n1, Node n2, List<Node> polygon) {443 /*private static boolean segmentInsidePolygon(Node n1, Node n2, List<Node> polygon) { 417 444 EastNorth en1 = n1.getEastNorth(); 418 445 EastNorth en2 = n2.getEastNorth(); … … 420 447 return Geometry.nodeInsidePolygon(testNode, polygon); 421 448 }*/ 422 423 private static void log( String s) {424 // System.out.println(s);425 } 426 449 450 private static void log(String s) { 451 // System.out.println(s); 452 } 453 427 454 private static class RingSegment { 428 private List<Node> nodes;429 private RingSegment references;430 private Way resultingWay = null;431 private boolean wasTemplateApplied = false;432 private boolean isRing;433 434 /*private RingSegment() {455 private List<Node> nodes; 456 private RingSegment references; 457 private Way resultingWay = null; 458 private boolean wasTemplateApplied = false; 459 private boolean isRing; 460 461 /*private RingSegment() { 435 462 }*/ 436 463 437 public RingSegment( Way w ) { 438 this(w.getNodes()); 439 } 440 441 public RingSegment( List<Node> nodes ) { 442 this.nodes = nodes; 443 isRing = nodes.size() > 1 && nodes.get(0).equals(nodes.get(nodes.size() - 1)); 444 if( isRing ) 445 nodes.remove(nodes.size() - 1); 446 references = null; 447 } 448 449 /*public RingSegment( RingSegment ref ) { 464 public RingSegment(Way w) { 465 this(w.getNodes()); 466 } 467 468 public RingSegment(List<Node> nodes) { 469 this.nodes = nodes; 470 isRing = nodes.size() > 1 && nodes.get(0).equals(nodes.get(nodes.size() - 1)); 471 if (isRing ) { 472 nodes.remove(nodes.size() - 1); 473 } 474 references = null; 475 } 476 477 /*public RingSegment(RingSegment ref) { 450 478 this.nodes = null; 451 479 this.references = ref; 452 480 }*/ 453 481 454 /** 455 * Splits this segment at node n. Retains nodes 0..n and moves 456 * nodes n..N to a separate segment that is returned. 457 * @param n node at which to split. 458 * @return new segment, {@code null} if splitting is unnecessary. 459 */ 460 public RingSegment split( Node n ) { 461 if( nodes == null ) 462 throw new IllegalArgumentException("Cannot split segment: it is a reference"); 463 int pos = nodes.indexOf(n); 464 if( pos <= 0 || pos >= nodes.size() - 1 ) 465 return null; 466 List<Node> newNodes = new ArrayList<>(nodes.subList(pos, nodes.size())); 467 nodes.subList(pos + 1, nodes.size()).clear(); 468 return new RingSegment(newNodes); 469 } 470 471 /** 472 * Split this segment as a way at two nodes. If one of them is null or at the end, 473 * split as an arc. Note: order of nodes is important. 474 * @return A new segment from n2 to n1. 475 */ 476 public RingSegment split( Node n1, Node n2 ) { 477 if( nodes == null ) 478 throw new IllegalArgumentException("Cannot split segment: it is a reference"); 479 if( !isRing ) { 480 if( n1 == null || nodes.get(0).equals(n1) || nodes.get(nodes.size() - 1).equals(n1) ) 481 return split(n2); 482 if( n2 == null || nodes.get(0).equals(n2) || nodes.get(nodes.size() - 1).equals(n2) ) 483 return split(n1); 484 throw new IllegalArgumentException("Split for two nodes is called for not-ring: " + this); 485 } 486 int pos1 = nodes.indexOf(n1); 487 int pos2 = nodes.indexOf(n2); 488 if( pos1 == pos2 ) 489 return null; 490 491 List<Node> newNodes = new ArrayList<>(); 492 if( pos2 > pos1 ) { 493 newNodes.addAll(nodes.subList(pos2, nodes.size())); 494 newNodes.addAll(nodes.subList(0, pos1 + 1)); 495 if( pos2 + 1 < nodes.size() ) 496 nodes.subList(pos2 + 1, nodes.size()).clear(); 497 if( pos1 > 0 ) 498 nodes.subList(0, pos1).clear(); 499 } else { 500 newNodes.addAll(nodes.subList(pos2, pos1 + 1)); 501 nodes.addAll(new ArrayList<>(nodes.subList(0, pos2 + 1))); 502 nodes.subList(0, pos1).clear(); 503 } 504 isRing = false; 505 return new RingSegment(newNodes); 506 } 507 508 public List<Node> getNodes() { 509 return nodes == null ? references.nodes : nodes; 510 } 511 512 public List<Node> getWayNodes() { 513 if( nodes == null ) 514 throw new IllegalArgumentException("Won't give you wayNodes: it is a reference"); 515 List<Node> wayNodes = new ArrayList<>(nodes); 516 if( isRing ) 517 wayNodes.add(wayNodes.get(0)); 518 return wayNodes; 519 } 520 521 public boolean isReference() { 522 return nodes == null; 523 } 524 525 public boolean isRing() { 526 return isRing; 527 } 528 529 public void makeReference( RingSegment segment ) { 530 log(this + " was made a reference to " + segment); 531 this.nodes = null; 532 this.references = segment; 533 } 534 535 public void swapReference() { 536 this.nodes = references.nodes; 537 references.nodes = null; 538 references.references = this; 539 this.references = null; 540 } 541 542 public boolean isWayConstructed() { 543 return isReference() ? references.isWayConstructed() : resultingWay != null; 544 } 545 546 public Way constructWay( Way template ) { 547 if( isReference() ) 548 return references.constructWay(template); 549 if( resultingWay == null ) { 550 resultingWay = new Way(); 551 resultingWay.setNodes(getWayNodes()); 552 } 553 if( template != null && !wasTemplateApplied ) { 554 resultingWay.setKeys(template.getKeys()); 555 wasTemplateApplied = true; 556 } 557 return resultingWay; 558 } 559 560 public void overrideWay( Way source ) { 561 if( isReference() ) 562 references.overrideWay(source); 563 else { 564 resultingWay = source; 565 wasTemplateApplied = true; 566 } 567 } 568 569 /** 570 * Compares two segments with respect to referencing. 571 * @return true if ways are equals, or one references another. 572 */ 573 /*public boolean isReferencingEqual( RingSegment other ) { 482 /** 483 * Splits this segment at node n. Retains nodes 0..n and moves 484 * nodes n..N to a separate segment that is returned. 485 * @param n node at which to split. 486 * @return new segment, {@code null} if splitting is unnecessary. 487 */ 488 public RingSegment split(Node n) { 489 if (nodes == null ) 490 throw new IllegalArgumentException("Cannot split segment: it is a reference"); 491 int pos = nodes.indexOf(n); 492 if (pos <= 0 || pos >= nodes.size() - 1 ) 493 return null; 494 List<Node> newNodes = new ArrayList<>(nodes.subList(pos, nodes.size())); 495 nodes.subList(pos + 1, nodes.size()).clear(); 496 return new RingSegment(newNodes); 497 } 498 499 /** 500 * Split this segment as a way at two nodes. If one of them is null or at the end, 501 * split as an arc. Note: order of nodes is important. 502 * @return A new segment from n2 to n1. 503 */ 504 public RingSegment split(Node n1, Node n2) { 505 if (nodes == null ) 506 throw new IllegalArgumentException("Cannot split segment: it is a reference"); 507 if (!isRing) { 508 if (n1 == null || nodes.get(0).equals(n1) || nodes.get(nodes.size() - 1).equals(n1) ) 509 return split(n2); 510 if (n2 == null || nodes.get(0).equals(n2) || nodes.get(nodes.size() - 1).equals(n2) ) 511 return split(n1); 512 throw new IllegalArgumentException("Split for two nodes is called for not-ring: " + this); 513 } 514 int pos1 = nodes.indexOf(n1); 515 int pos2 = nodes.indexOf(n2); 516 if (pos1 == pos2 ) 517 return null; 518 519 List<Node> newNodes = new ArrayList<>(); 520 if (pos2 > pos1) { 521 newNodes.addAll(nodes.subList(pos2, nodes.size())); 522 newNodes.addAll(nodes.subList(0, pos1 + 1)); 523 if (pos2 + 1 < nodes.size() ) { 524 nodes.subList(pos2 + 1, nodes.size()).clear(); 525 } 526 if (pos1 > 0 ) { 527 nodes.subList(0, pos1).clear(); 528 } 529 } else { 530 newNodes.addAll(nodes.subList(pos2, pos1 + 1)); 531 nodes.addAll(new ArrayList<>(nodes.subList(0, pos2 + 1))); 532 nodes.subList(0, pos1).clear(); 533 } 534 isRing = false; 535 return new RingSegment(newNodes); 536 } 537 538 public List<Node> getNodes() { 539 return nodes == null ? references.nodes : nodes; 540 } 541 542 public List<Node> getWayNodes() { 543 if (nodes == null ) 544 throw new IllegalArgumentException("Won't give you wayNodes: it is a reference"); 545 List<Node> wayNodes = new ArrayList<>(nodes); 546 if (isRing ) { 547 wayNodes.add(wayNodes.get(0)); 548 } 549 return wayNodes; 550 } 551 552 public boolean isReference() { 553 return nodes == null; 554 } 555 556 public boolean isRing() { 557 return isRing; 558 } 559 560 public void makeReference(RingSegment segment) { 561 log(this + " was made a reference to " + segment); 562 this.nodes = null; 563 this.references = segment; 564 } 565 566 public void swapReference() { 567 this.nodes = references.nodes; 568 references.nodes = null; 569 references.references = this; 570 this.references = null; 571 } 572 573 public boolean isWayConstructed() { 574 return isReference() ? references.isWayConstructed() : resultingWay != null; 575 } 576 577 public Way constructWay(Way template) { 578 if (isReference() ) 579 return references.constructWay(template); 580 if (resultingWay == null) { 581 resultingWay = new Way(); 582 resultingWay.setNodes(getWayNodes()); 583 } 584 if (template != null && !wasTemplateApplied) { 585 resultingWay.setKeys(template.getKeys()); 586 wasTemplateApplied = true; 587 } 588 return resultingWay; 589 } 590 591 public void overrideWay(Way source) { 592 if (isReference() ) { 593 references.overrideWay(source); 594 } else { 595 resultingWay = source; 596 wasTemplateApplied = true; 597 } 598 } 599 600 /** 601 * Compares two segments with respect to referencing. 602 * @return true if ways are equals, or one references another. 603 */ 604 /*public boolean isReferencingEqual(RingSegment other) { 574 605 return this.equals(other) || (other.isReference() && other.references == this) || (isReference() && references == other); 575 606 }*/ 576 607 577 @Override 578 public String toString() { 579 StringBuilder sb = new StringBuilder("RingSegment@"); 580 sb.append(this.hashCode()).append('['); 581 if( isReference() ) 582 sb.append("references ").append(references.hashCode()); 583 else if( nodes.isEmpty() ) 584 sb.append("empty"); 585 else { 586 if( isRing ) 587 sb.append("ring:"); 588 sb.append(nodes.get(0).getUniqueId()); 589 for( int i = 1; i < nodes.size(); i++ ) 590 sb.append(',').append(nodes.get(i).getUniqueId()); 591 } 592 return sb.append(']').toString(); 593 } 608 @Override 609 public String toString() { 610 StringBuilder sb = new StringBuilder("RingSegment@"); 611 sb.append(this.hashCode()).append('['); 612 if (isReference() ) { 613 sb.append("references ").append(references.hashCode()); 614 } else if (nodes.isEmpty() ) { 615 sb.append("empty"); 616 } else { 617 if (isRing ) { 618 sb.append("ring:"); 619 } 620 sb.append(nodes.get(0).getUniqueId()); 621 for (int i = 1; i < nodes.size(); i++ ) { 622 sb.append(',').append(nodes.get(i).getUniqueId()); 623 } 624 } 625 return sb.append(']').toString(); 626 } 594 627 } 595 628 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/relationfix/AssociatedStreetFixer.java
r30738 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.relationfix; 2 3 … … 46 47 // check that all street members have same name as relation (???) 47 48 String streetName = rel.get("name"); 48 if (streetName == null) streetName = ""; 49 if (streetName == null) { 50 streetName = ""; 51 } 49 52 for (RelationMember m : rel.getMembers()) { 50 53 if ("street".equals(m.getRole()) && !streetName.equals(m.getWay().get("name"))) { … … 101 104 // fill relation name 102 105 Map<String, Integer> streetNames = new HashMap<>(); 103 for (RelationMember m : rel.getMembers()) 106 for (RelationMember m : rel.getMembers()) { 104 107 if ("street".equals(m.getRole()) && m.isWay()) { 105 108 String name = m.getWay().get("name"); 106 if (name == null || name.isEmpty()) continue; 109 if (name == null || name.isEmpty()) { 110 continue; 111 } 107 112 108 113 Integer count = streetNames.get(name); 109 114 110 streetNames.put(name, count != null ? count + 1 : 1);115 streetNames.put(name, count != null ? count + 1 : 1); 111 116 } 117 } 112 118 String commonName = ""; 113 119 Integer commonCount = 0; … … 146 152 commandList.add(new ChangeCommand(oldWay, newWay)); 147 153 } 148 */154 */ 149 155 // return results 150 156 if (commandList.size() == 0) -
applications/editors/josm/plugins/reltoolbox/src/relcontext/relationfix/BoundaryFixer.java
r30738 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.relationfix; 2 3 … … 32 33 @Override 33 34 public boolean isRelationGood(Relation rel) { 34 for ( RelationMember m : rel.getMembers()) {35 for (RelationMember m : rel.getMembers()) { 35 36 if (m.getType().equals(OsmPrimitiveType.RELATION) && !"subarea".equals(m.getRole())) { 36 37 setWarningMessage(tr("Relation without ''subarea'' role found")); … … 67 68 } 68 69 69 private Relation fixBoundaryRoles( Relation source) {70 private Relation fixBoundaryRoles(Relation source) { 70 71 Relation r = new Relation(source); 71 72 boolean fixed = false; 72 for ( int i = 0; i < r.getMembersCount(); i++) {73 for (int i = 0; i < r.getMembersCount(); i++) { 73 74 RelationMember m = r.getMember(i); 74 75 String role = null; 75 if ( m.isRelation() )76 if (m.isRelation()) { 76 77 role = "subarea"; 77 else if( m.isNode()) {78 Node n = (Node) m.getMember();79 if ( !n.isIncomplete()) {80 if ( n.hasKey("place")) {78 } else if (m.isNode()) { 79 Node n = (Node) m.getMember(); 80 if (!n.isIncomplete()) { 81 if (n.hasKey("place")) { 81 82 String place = n.get("place"); 82 83 if (place.equals("state") || place.equals("country") || … … 86 87 role = "admin_centre"; 87 88 } 88 } else 89 } else { 89 90 role = "label"; 91 } 90 92 } 91 93 } 92 if ( role != null && !role.equals(m.getRole())) {94 if (role != null && !role.equals(m.getRole())) { 93 95 r.setMember(i, new RelationMember(role, m.getMember())); 94 96 fixed = true; -
applications/editors/josm/plugins/reltoolbox/src/relcontext/relationfix/MultipolygonFixer.java
r30738 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.relationfix; 2 3 … … 30 31 } 31 32 32 33 33 @Override 34 34 public boolean isRelationGood(Relation rel) { 35 for (RelationMember m : rel.getMembers()) 35 for (RelationMember m : rel.getMembers()) { 36 36 if (m.getType().equals(OsmPrimitiveType.WAY) && !("outer".equals(m.getRole()) || "inner".equals(m.getRole()))) { 37 37 setWarningMessage(tr("Way without ''inner'' or ''outer'' role found")); 38 38 return false; 39 39 } 40 } 40 41 clearWarningMessage(); 41 42 return true; … … 45 46 public Command fixRelation(Relation rel) { 46 47 Relation rr = fixMultipolygonRoles(rel); 47 return rr != null ? new ChangeCommand(rel, rr) : null;48 return rr != null ? new ChangeCommand(rel, rr) : null; 48 49 } 49 50 … … 51 52 * Basically, created multipolygon from scratch, and if successful, replace roles with new ones. 52 53 */ 53 protected Relation fixMultipolygonRoles( Relation source) {54 protected Relation fixMultipolygonRoles(Relation source) { 54 55 Collection<Way> ways = new ArrayList<>(); 55 for( OsmPrimitive p : source.getMemberPrimitives() ) 56 if( p instanceof Way ) 57 ways.add((Way)p); 56 for (OsmPrimitive p : source.getMemberPrimitives()) { 57 if (p instanceof Way) { 58 ways.add((Way) p); 59 } 60 } 58 61 MultipolygonBuilder mpc = new MultipolygonBuilder(); 59 62 String error = mpc.makeFromWays(ways); 60 if ( error != null)63 if (error != null) 61 64 return null; 62 65 … … 64 67 boolean fixed = false; 65 68 Set<Way> outerWays = new HashSet<>(); 66 for ( MultipolygonBuilder.JoinedPolygon poly : mpc.outerWays )67 for ( Way w : poly.ways )69 for (MultipolygonBuilder.JoinedPolygon poly : mpc.outerWays) { 70 for (Way w : poly.ways) { 68 71 outerWays.add(w); 72 } 73 } 69 74 Set<Way> innerWays = new HashSet<>(); 70 for ( MultipolygonBuilder.JoinedPolygon poly : mpc.innerWays )71 for ( Way w : poly.ways )75 for (MultipolygonBuilder.JoinedPolygon poly : mpc.innerWays) { 76 for (Way w : poly.ways) { 72 77 innerWays.add(w); 73 for( int i = 0; i < r.getMembersCount(); i++ ) { 78 } 79 } 80 for (int i = 0; i < r.getMembersCount(); i++) { 74 81 RelationMember m = r.getMember(i); 75 if ( m.isWay()) {82 if (m.isWay()) { 76 83 String role = null; 77 if ( outerWays.contains((Way)m.getMember()) )84 if (outerWays.contains(m.getMember())) { 78 85 role = "outer"; 79 else if( innerWays.contains((Way)m.getMember()) )86 } else if (innerWays.contains(m.getMember())) { 80 87 role = "inner"; 81 if( role != null && !role.equals(m.getRole()) ) { 88 } 89 if (role != null && !role.equals(m.getRole())) { 82 90 r.setMember(i, new RelationMember(role, m.getMember())); 83 91 fixed = true; -
applications/editors/josm/plugins/reltoolbox/src/relcontext/relationfix/NothingFixer.java
r30738 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.relationfix; 2 3 … … 12 13 super(""); 13 14 } 15 14 16 @Override 15 17 public boolean isFixerApplicable(Relation rel) { 16 18 return true; 17 19 } 20 18 21 @Override 19 22 public boolean isRelationGood(Relation rel) { … … 25 28 return null; 26 29 } 27 28 30 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/relationfix/PublicTransportFixer.java
r30841 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.relationfix; 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 2 5 3 6 import org.openstreetmap.josm.command.ChangeCommand; … … 6 9 import org.openstreetmap.josm.data.osm.Relation; 7 10 import org.openstreetmap.josm.data.osm.RelationMember; 8 import static org.openstreetmap.josm.tools.I18n.tr; 11 9 12 import relcontext.actions.PublicTransportHelper; 10 13 … … 18 21 */ 19 22 public class PublicTransportFixer extends RelationFixer { 20 23 21 24 public PublicTransportFixer() { 22 25 super("route", "public_transport"); … … 30 33 public boolean isRelationGood(Relation rel) { 31 34 for (RelationMember m : rel.getMembers()) { 32 if (m.getType().equals(OsmPrimitiveType.NODE) 35 if (m.getType().equals(OsmPrimitiveType.NODE) 33 36 && !(m.getRole().startsWith(PublicTransportHelper.STOP) || m.getRole().startsWith(PublicTransportHelper.PLATFORM))) { 34 37 setWarningMessage(tr("Node without ''stop'' or ''platform'' role found")); … … 62 65 return fixed ? new ChangeCommand(rel, r) : null; 63 66 } 64 67 65 68 private Relation fixStopPlatformRole(Relation source) { 66 69 Relation r = new Relation(source); 67 70 boolean fixed = false; 68 for ( int i = 0; i < r.getMembersCount(); i++) {71 for (int i = 0; i < r.getMembersCount(); i++) { 69 72 RelationMember m = r.getMember(i); 70 73 String role = PublicTransportHelper.getRoleByMember(m); … … 75 78 } 76 79 } 77 return fixed ? r : null; 80 return fixed ? r : null; 78 81 } 79 82 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/relationfix/RelationFixer.java
r30738 r32395 1 // License: GPL. For details, see LICENSE file. 1 2 package relcontext.relationfix; 2 3 … … 20 21 /** 21 22 * Construct new RelationFixer by a list of applicable types 22 * @param types 23 * @param types types 23 24 */ 24 25 public RelationFixer(String... types) { 25 26 applicableTypes = new ArrayList<>(); 26 for (String type: types) {27 for (String type: types) { 27 28 applicableTypes.add(type); 28 29 } … … 33 34 * and then check desired relation properties. 34 35 * Note that this only verifies if current RelationFixer can be used to check and fix given relation 35 * Deeper relation checking is at {@link isRelationGood}36 * Deeper relation checking is at {@link #isRelationGood} 36 37 * 37 38 * @param rel Relation to check … … 45 46 46 47 String type = rel.get("type"); 47 for (String oktype: applicableTypes)48 for (String oktype: applicableTypes) { 48 49 if (oktype.equals(type)) 49 50 return true; 51 } 50 52 51 53 return false; … … 73 75 this.sortAndFixAction = sortAndFixAction; 74 76 } 77 75 78 protected void setWarningMessage(String text) { 76 79 if (text == null) { … … 80 83 } 81 84 } 85 82 86 protected void clearWarningMessage() { 83 87 sortAndFixAction.putValue(Action.SHORT_DESCRIPTION, tr("Fix roles of the chosen relation members")); 84 88 } 85 86 89 }
Note:
See TracChangeset
for help on using the changeset viewer.