Ticket #6149: multipolygon.patch
| File multipolygon.patch, 10.8 KB (added by , 15 years ago) |
|---|
-
src/org/openstreetmap/josm/data/osm/visitor/paint/relations/Multipolygon.java
7 7 import java.util.ArrayList; 8 8 import java.util.Collection; 9 9 import java.util.List; 10 import java.util.logging.Logger; 10 11 12 import org.openstreetmap.josm.Main; 13 import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent; 14 import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener; 11 15 import org.openstreetmap.josm.data.osm.Node; 12 16 import org.openstreetmap.josm.data.osm.Relation; 13 17 import org.openstreetmap.josm.data.osm.RelationMember; … … 16 20 import org.openstreetmap.josm.gui.NavigatableComponent; 17 21 18 22 public class Multipolygon { 23 static private final Logger logger = Logger.getLogger(Multipolygon.class.getName()); 19 24 25 /** preference key for a collection of roles which indicate that the respective member belongs to an 26 * <em>outer</em> polygon. Default is <tt>outer</tt>. 27 */ 28 static public final String PREF_KEY_OUTER_ROLES = "mappaint.multipolygon.outer.roles"; 29 /** preference key for collection of role prefixes which indicate that the respective 30 * member belongs to an <em>outer</em> polygon. Default is empty. 31 */ 32 static public final String PREF_KEY_OUTER_ROLE_PREFIXES = "mappaint.multipolygon.outer.role-prefixes"; 33 /** preference key for a collection of roles which indicate that the respective member belongs to an 34 * <em>inner</em> polygon. Default is <tt>inner</tt>. 35 */ 36 static public final String PREF_KEY_INNER_ROLES = "mappaint.multipolygon.inner.roles"; 37 /** preference key for collection of role prefixes which indicate that the respective 38 * member belongs to an <em>inner</em> polygon. Default is empty. 39 */ 40 static public final String PREF_KEY_INNER_ROLE_PREFIXES = "mappaint.multipolygon.inner.role-prefixes"; 41 42 /** 43 * <p>Kind of strategy object which is responsible for deciding whether a given 44 * member role indicates that the member belongs to an <em>outer</em> or an 45 * <em>inner</em> polygon.</p> 46 * 47 * <p>The decision is taken based on preference settings, see the four preference keys 48 * above.</p> 49 * 50 */ 51 private static class MultipolygonRoleMatcher implements PreferenceChangedListener{ 52 private final List<String> outerExactRoles = new ArrayList<String>(); 53 private final List<String> outerRolePrefixes = new ArrayList<String>(); 54 private final List<String> innerExactRoles = new ArrayList<String>(); 55 private final List<String> innerRolePrefixes = new ArrayList<String>(); 56 57 private void initDefaults() { 58 outerExactRoles.clear(); 59 outerRolePrefixes.clear(); 60 innerExactRoles.clear(); 61 innerRolePrefixes.clear(); 62 outerExactRoles.add("outer"); 63 innerExactRoles.add("inner"); 64 } 65 66 private void setNormalized(Collection<String> literals, List<String> target){ 67 target.clear(); 68 for(String l: literals) { 69 if (l == null) { 70 continue; 71 } 72 l = l.trim(); 73 if (!target.contains(l)) { 74 target.add(l); 75 } 76 } 77 } 78 79 private void initFromPreferences() { 80 initDefaults(); 81 if (Main.pref == null) return; 82 Collection<String> literals; 83 literals = Main.pref.getCollection(PREF_KEY_OUTER_ROLES); 84 if (literals != null && !literals.isEmpty()){ 85 setNormalized(literals, outerExactRoles); 86 } 87 literals = Main.pref.getCollection(PREF_KEY_OUTER_ROLE_PREFIXES); 88 if (literals != null && !literals.isEmpty()){ 89 setNormalized(literals, outerRolePrefixes); 90 } 91 literals = Main.pref.getCollection(PREF_KEY_INNER_ROLES); 92 if (literals != null && !literals.isEmpty()){ 93 setNormalized(literals, innerExactRoles); 94 } 95 literals = Main.pref.getCollection(PREF_KEY_INNER_ROLE_PREFIXES); 96 if (literals != null && !literals.isEmpty()){ 97 setNormalized(literals, innerRolePrefixes); 98 } 99 } 100 101 @Override 102 public void preferenceChanged(PreferenceChangeEvent evt) { 103 if (PREF_KEY_INNER_ROLE_PREFIXES.equals(evt.getKey()) || 104 PREF_KEY_INNER_ROLES.equals(evt.getKey()) || 105 PREF_KEY_OUTER_ROLE_PREFIXES.equals(evt.getKey()) || 106 PREF_KEY_OUTER_ROLES.equals(evt.getKey())){ 107 initFromPreferences(); 108 } 109 } 110 111 public boolean isOuterRole(String role){ 112 if (role == null) return false; 113 for (String candidate: outerExactRoles) { 114 if (role.equals(candidate)) return true; 115 } 116 for (String candidate: outerRolePrefixes) { 117 if (role.startsWith(candidate)) return true; 118 } 119 return false; 120 } 121 122 public boolean isInnerRole(String role){ 123 if (role == null) return false; 124 for (String candidate: innerExactRoles) { 125 if (role.equals(candidate)) return true; 126 } 127 for (String candidate: innerRolePrefixes) { 128 if (role.startsWith(candidate)) return true; 129 } 130 return false; 131 } 132 } 133 134 /* 135 * Init a private global matcher object which will listen to preference 136 * changes. 137 */ 138 private static MultipolygonRoleMatcher roleMatcher; 139 private static MultipolygonRoleMatcher getMultipoloygonRoleMatcher() { 140 if (roleMatcher == null) { 141 roleMatcher = new MultipolygonRoleMatcher(); 142 if (Main.pref != null){ 143 roleMatcher.initFromPreferences(); 144 Main.pref.addPreferenceChangeListener(roleMatcher); 145 } 146 } 147 return roleMatcher; 148 } 149 20 150 public static class JoinedWay { 21 151 private final List<Node> nodes; 22 152 private final boolean selected; … … 122 252 } 123 253 124 254 public void load(Relation r) { 255 MultipolygonRoleMatcher matcher = getMultipoloygonRoleMatcher(); 256 125 257 // Fill inner and outer list with valid ways 126 258 for (RelationMember m : r.getMembers()) { 127 259 if (m.getMember().isDrawable()) { … … 132 264 continue; 133 265 } 134 266 135 if( "inner".equals(m.getRole())) {136 getInnerWays().add(w);137 } else if( "outer".equals(m.getRole())) {138 getOuterWays().add(w);267 if(matcher.isInnerRole(m.getRole())) { 268 innerWays.add(w); 269 } else if(matcher.isOuterRole(m.getRole())) { 270 outerWays.add(w); 139 271 } else if (!m.hasRole()) { 140 getOuterWays().add(w);272 outerWays.add(w); 141 273 } // Remaining roles ignored 142 274 } // Non ways ignored 143 275 } -
test/unit/org/openstreetmap/josm/data/osm/visitor/paint/relations/MultipolygonTest.groovy
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.data.osm.visitor.paint.relations; 3 4 import static org.junit.Assert.*; 5 import org.junit.*; 6 import org.openstreetmap.josm.Main; 7 import org.openstreetmap.josm.fixtures.JOSMFixture 8 9 class MultipolygonTest { 10 11 @BeforeClass 12 public static void createJOSMFixture(){ 13 JOSMFixture.createUnitTestFixture().init() 14 } 15 16 @Before 17 public void setUp() { 18 Main.pref.put(Multipolygon.PREF_KEY_INNER_ROLE_PREFIXES, null) 19 Main.pref.put(Multipolygon.PREF_KEY_INNER_ROLES, null) 20 Main.pref.put(Multipolygon.PREF_KEY_OUTER_ROLE_PREFIXES, null) 21 Main.pref.put(Multipolygon.PREF_KEY_OUTER_ROLES, null) 22 } 23 24 @Test 25 public void matchRolesWithDefaultSettings() { 26 def matcher = Multipolygon.getMultipoloygonRoleMatcher() 27 28 /* 29 * Default behavioiur - Only the roles "outer" and "inner" are supported. 30 */ 31 assert matcher.isOuterRole("outer") 32 assert !matcher.isOuterRole("outer:mask") 33 assert matcher.isInnerRole("inner") 34 assert !matcher.isInnerRole("inner:mask") 35 } 36 37 @Test 38 public void matchAdditionalOuterRoles() { 39 Main.pref.putCollection(Multipolygon.PREF_KEY_OUTER_ROLES,["outer", "outer:mask", "outer:show"]) 40 41 def matcher = Multipolygon.getMultipoloygonRoleMatcher() 42 43 assert matcher.isOuterRole("outer") 44 assert matcher.isOuterRole("outer:mask") 45 assert matcher.isOuterRole("outer:show") 46 assert !matcher.isOuterRole("outer:something_else") 47 } 48 49 @Test 50 public void matchAdditionalOuterRolePrefixes() { 51 Main.pref.putCollection(Multipolygon.PREF_KEY_OUTER_ROLE_PREFIXES,["outer:"]) 52 53 def matcher = Multipolygon.getMultipoloygonRoleMatcher() 54 55 assert matcher.isOuterRole("outer") 56 assert matcher.isOuterRole("outer:mask") 57 assert matcher.isOuterRole("outer:show") 58 assert matcher.isOuterRole("outer:something_else") 59 } 60 61 @Test 62 public void matchAdditionanInnerRoles() { 63 Main.pref.putCollection(Multipolygon.PREF_KEY_INNER_ROLES,["inner", "inner:mask", "inner:show"]) 64 65 def matcher = Multipolygon.getMultipoloygonRoleMatcher() 66 67 assert matcher.isInnerRole("inner") 68 assert matcher.isInnerRole("inner:mask") 69 assert matcher.isInnerRole("inner:show") 70 assert !matcher.isInnerRole("inner:something_else") 71 } 72 73 @Test 74 public void matchAdditionanInnerRolesPrefixes() { 75 Main.pref.putCollection(Multipolygon.PREF_KEY_INNER_ROLE_PREFIXES,["inner:"]) 76 77 def matcher = Multipolygon.getMultipoloygonRoleMatcher() 78 79 assert matcher.isInnerRole("inner") 80 assert matcher.isInnerRole("inner:mask") 81 assert matcher.isInnerRole("inner:show") 82 assert matcher.isInnerRole("inner:something_else") 83 } 84 }
