Legend:
- Unmodified
- Added
- Removed
-
trunk/data_nodist/relation_sort.osm
r5630 r6461 1 1 <?xml version='1.0' encoding='UTF-8'?> 2 2 <osm version='0.6' upload='true' generator='JOSM'> 3 <node id='-66' action='modify' visible='true' lat='0.013038062491396258' lon='-0.022228708815553687'> 3 <node id='-136' action='modify' visible='true' lat='0.012919043857859922' lon='-0.02396592658039119'> 4 <tag k='leisure' v='playground' /> 5 <tag k='name' v='playground' /> 6 </node> 7 <node id='-119' action='modify' visible='true' lat='0.013321070318548687' lon='-0.02263899788567645'> 8 <tag k='name' v='tree' /> 9 <tag k='natural' v='tree' /> 10 </node> 11 <node id='-62' action='modify' visible='true' lat='0.011392242679627185' lon='-0.02151079901779618' /> 12 <node id='-60' action='modify' visible='true' lat='0.010990181404602947' lon='-0.02221645759558677' /> 13 <node id='-58' action='modify' visible='true' lat='0.0121881598958588' lon='-0.02275800952737954' /> 14 <node id='-56' action='modify' visible='true' lat='0.011571901667096615' lon='-0.023094362404978128' /> 15 <node id='-54' action='modify' visible='true' lat='0.01196661592868377' lon='-0.023053401490175603' /> 16 <node id='-52' action='modify' visible='true' lat='0.011096850722520079' lon='-0.023143660145474393' /> 17 <node id='-50' action='modify' visible='true' lat='0.011113261386811617' lon='-0.023652390748067607' /> 18 <node id='-48' action='modify' visible='true' lat='0.011539938658067678' lon='-0.02462061995945469' /> 19 <node id='-46' action='modify' visible='true' lat='0.01539626034645824' lon='-0.023880241371069214' /> 20 <node id='-44' action='modify' visible='true' lat='0.015428020586761428' lon='-0.023340317266381447' /> 21 <node id='-42' action='modify' visible='true' lat='0.0154002303764964' lon='-0.02298301455004395' /> 22 <node id='-40' action='modify' visible='true' lat='0.015181878724288504' lon='-0.022316049479547295' /> 23 <node id='-38' action='modify' visible='true' lat='0.014911916681254264' lon='-0.022177098423193826' /> 24 <node id='-36' action='modify' visible='true' lat='0.014657834758095989' lon='-0.022161218302467714' /> 25 <node id='-34' action='modify' visible='true' lat='0.01427274184276135' lon='-0.02253440113953132' /> 26 <node id='-32' action='modify' visible='true' lat='0.013986899678383742' lon='-0.022423240294448546' /> 27 <node id='-30' action='modify' visible='true' lat='0.01389955901697638' lon='-0.022077847668655632' /> 28 <node id='-28' action='modify' visible='true' lat='0.014014689888824738' lon='-0.021819795706856333' /> 29 <node id='-26' action='modify' visible='true' lat='0.014252891692468746' lon='-0.021776125374859526' /> 30 <node id='-24' action='modify' visible='true' lat='0.014379932654311749' lon='-0.021569683805420084'> 31 <tag k='name' v='t1n1' /> 32 </node> 33 <node id='-22' action='modify' visible='true' lat='0.014268771812702965' lon='-0.021518073413060227' /> 34 <node id='-20' action='modify' visible='true' lat='0.014332292293628876' lon='-0.02137515232652523'> 35 <tag k='name' v='t1n2' /> 36 </node> 37 <node id='-18' action='modify' visible='true' lat='0.01342315540873657' lon='-0.024273274359040455' /> 38 <node id='-16' action='modify' visible='true' lat='0.01305394261171071' lon='-0.023320467115473805' /> 39 <node id='-14' action='modify' visible='true' lat='0.013204803754647857' lon='-0.021911106401031468' /> 40 <node id='-12' action='modify' visible='true' lat='0.01301027228084355' lon='-0.02147837311124495' /> 41 <node id='-10' action='modify' visible='true' lat='0.013173043514037084' lon='-0.023991402216151987'> 42 <tag k='addr:housenumber' v='1' /> 43 <tag k='name' v='t2n1' /> 44 </node> 45 <node id='-8' action='modify' visible='true' lat='0.013073792762102373' lon='-0.023697619982718937'> 46 <tag k='addr:housenumber' v='2' /> 47 <tag k='name' v='t2n2' /> 48 </node> 49 <node id='-6' action='modify' visible='true' lat='0.012930871679247545' lon='-0.023173575998757284'> 50 <tag k='addr:housenumber' v='3' /> 51 <tag k='name' v='t2n3' /> 52 </node> 53 <node id='-4' action='modify' visible='true' lat='0.013038062491396258' lon='-0.022228708815553687'> 4 54 <tag k='addr:housenumber' v='4' /> 5 55 <tag k='name' v='t2n4' /> 6 56 </node> 7 <node id='-64' action='modify' visible='true' lat='0.012930871679247545' lon='-0.023173575998757284'>8 <tag k='addr:housenumber' v='3' />9 <tag k='name' v='t2n3' />10 </node>11 <node id='-62' action='modify' visible='true' lat='0.013073792762102373' lon='-0.023697619982718937'>12 <tag k='addr:housenumber' v='2' />13 <tag k='name' v='t2n2' />14 </node>15 <node id='-60' action='modify' visible='true' lat='0.013173043514037084' lon='-0.023991402216151987'>16 <tag k='addr:housenumber' v='1' />17 <tag k='name' v='t2n1' />18 </node>19 <node id='-58' action='modify' visible='true' lat='0.01301027228084355' lon='-0.02147837311124495' />20 <node id='-56' action='modify' visible='true' lat='0.013204803754647857' lon='-0.021911106401031468' />21 <node id='-54' action='modify' visible='true' lat='0.01305394261171071' lon='-0.023320467115473805' />22 <node id='-52' action='modify' visible='true' lat='0.01342315540873657' lon='-0.024273274359040455' />23 <node id='-50' action='modify' visible='true' lat='0.014332292293628876' lon='-0.02137515232652523'>24 <tag k='name' v='t1n2' />25 </node>26 <node id='-48' action='modify' visible='true' lat='0.014268771812702965' lon='-0.021518073413060227' />27 <node id='-46' action='modify' visible='true' lat='0.014379932654311749' lon='-0.021569683805420084'>28 <tag k='name' v='t1n1' />29 </node>30 <node id='-44' action='modify' visible='true' lat='0.014252891692468746' lon='-0.021776125374859526' />31 <node id='-42' action='modify' visible='true' lat='0.014014689888824738' lon='-0.021819795706856333' />32 <node id='-40' action='modify' visible='true' lat='0.01389955901697638' lon='-0.022077847668655632' />33 <node id='-38' action='modify' visible='true' lat='0.013986899678383742' lon='-0.022423240294448546' />34 <node id='-36' action='modify' visible='true' lat='0.01427274184276135' lon='-0.02253440113953132' />35 <node id='-34' action='modify' visible='true' lat='0.014657834758095989' lon='-0.022161218302467714' />36 <node id='-32' action='modify' visible='true' lat='0.014911916681254264' lon='-0.022177098423193826' />37 <node id='-30' action='modify' visible='true' lat='0.015181878724288504' lon='-0.022316049479547295' />38 <node id='-28' action='modify' visible='true' lat='0.0154002303764964' lon='-0.02298301455004395' />39 <node id='-26' action='modify' visible='true' lat='0.015428020586761428' lon='-0.023340317266381447' />40 <node id='-24' action='modify' visible='true' lat='0.01539626034645824' lon='-0.023880241371069214' />41 <node id='-22' action='modify' visible='true' lat='0.011539938658067678' lon='-0.02462061995945469' />42 <node id='-20' action='modify' visible='true' lat='0.011113261386811617' lon='-0.023652390748067607' />43 <node id='-18' action='modify' visible='true' lat='0.011096850722520079' lon='-0.023143660145474393' />44 <node id='-16' action='modify' visible='true' lat='0.01196661592868377' lon='-0.023053401490175603' />45 <node id='-14' action='modify' visible='true' lat='0.011571901667096615' lon='-0.023094362404978128' />46 <node id='-12' action='modify' visible='true' lat='0.0121881598958588' lon='-0.02275800952737954' />47 <node id='-10' action='modify' visible='true' lat='0.010990181404602947' lon='-0.02221645759558677' />48 <node id='-8' action='modify' visible='true' lat='0.011392242679627185' lon='-0.02151079901779618' />49 <way id='-112' action='modify' visible='true'>50 <nd ref='-12' />51 <nd ref='-18' />52 <tag k='name' v='t3w5' />53 </way>54 <way id='-96' action='modify' visible='true'>55 <nd ref='-54' />56 <nd ref='-56' />57 <nd ref='-58' />58 <tag k='name' v='t2w2' />59 </way>60 57 <way id='-94' action='modify' visible='true'> 61 58 <nd ref='-52' /> 62 <nd ref='-5 4' />63 <tag k='name' v='t 2w1' />59 <nd ref='-56' /> 60 <tag k='name' v='t3w2' /> 64 61 </way> 65 62 <way id='-92' action='modify' visible='true'> 66 <nd ref='-42' /> 67 <nd ref='-44' /> 68 <nd ref='-48' /> 69 <tag k='name' v='t1w7' /> 63 <nd ref='-60' /> 64 <nd ref='-62' /> 65 <tag k='name' v='t3w7' /> 70 66 </way> 71 67 <way id='-90' action='modify' visible='true'> 68 <nd ref='-54' /> 69 <nd ref='-58' /> 70 <tag k='name' v='t3w4' /> 71 </way> 72 <way id='-88' action='modify' visible='true'> 73 <nd ref='-56' /> 74 <nd ref='-54' /> 75 <tag k='name' v='t3w3' /> 76 </way> 77 <way id='-86' action='modify' visible='true'> 78 <nd ref='-52' /> 79 <nd ref='-60' /> 80 <tag k='name' v='t3w6' /> 81 </way> 82 <way id='-84' action='modify' visible='true'> 83 <nd ref='-48' /> 84 <nd ref='-50' /> 85 <nd ref='-52' /> 86 <tag k='name' v='t3w1' /> 87 </way> 88 <way id='-82' action='modify' visible='true'> 89 <nd ref='-46' /> 90 <nd ref='-44' /> 91 <tag k='name' v='t1w1' /> 92 </way> 93 <way id='-80' action='modify' visible='true'> 94 <nd ref='-36' /> 95 <nd ref='-34' /> 96 <tag k='name' v='t1w5' /> 97 </way> 98 <way id='-78' action='modify' visible='true'> 99 <nd ref='-32' /> 72 100 <nd ref='-30' /> 73 <nd ref='-32' /> 101 <nd ref='-28' /> 102 <tag k='name' v='t1w6' /> 103 </way> 104 <way id='-76' action='modify' visible='true'> 105 <nd ref='-44' /> 106 <nd ref='-42' /> 107 <tag k='name' v='t1w2' /> 108 </way> 109 <way id='-74' action='modify' visible='true'> 110 <nd ref='-42' /> 111 <nd ref='-40' /> 112 <tag k='name' v='t1w3' /> 113 </way> 114 <way id='-72' action='modify' visible='true'> 115 <nd ref='-40' /> 116 <nd ref='-38' /> 74 117 <tag k='name' v='t1w4' /> 75 118 </way> 76 <way id='- 88' action='modify' visible='true'>119 <way id='-70' action='modify' visible='true'> 77 120 <nd ref='-28' /> 78 <nd ref='-30' />79 <tag k='name' v='t1w3' />80 </way>81 <way id='-86' action='modify' visible='true'>82 121 <nd ref='-26' /> 83 <nd ref='-28' />84 <tag k='name' v='t1w2' />85 </way>86 <way id='-84' action='modify' visible='true'>87 <nd ref='-38' />88 <nd ref='-40' />89 <nd ref='-42' />90 <tag k='name' v='t1w6' />91 </way>92 <way id='-82' action='modify' visible='true'>93 <nd ref='-34' />94 <nd ref='-36' />95 <tag k='name' v='t1w5' />96 </way>97 <way id='-80' action='modify' visible='true'>98 <nd ref='-24' />99 <nd ref='-26' />100 <tag k='name' v='t1w1' />101 </way>102 <way id='-78' action='modify' visible='true'>103 122 <nd ref='-22' /> 104 <nd ref='-20' /> 105 <nd ref='-18' /> 106 <tag k='name' v='t3w1' /> 107 </way> 108 <way id='-76' action='modify' visible='true'> 109 <nd ref='-18' /> 110 <nd ref='-10' /> 111 <tag k='name' v='t3w6' /> 112 </way> 113 <way id='-74' action='modify' visible='true'> 114 <nd ref='-14' /> 115 <nd ref='-16' /> 116 <tag k='name' v='t3w3' /> 117 </way> 118 <way id='-72' action='modify' visible='true'> 119 <nd ref='-16' /> 120 <nd ref='-12' /> 121 <tag k='name' v='t3w4' /> 122 </way> 123 <way id='-70' action='modify' visible='true'> 124 <nd ref='-10' /> 125 <nd ref='-8' /> 126 <tag k='name' v='t3w7' /> 123 <tag k='name' v='t1w7' /> 127 124 </way> 128 125 <way id='-68' action='modify' visible='true'> 129 126 <nd ref='-18' /> 127 <nd ref='-16' /> 128 <tag k='name' v='t2w1' /> 129 </way> 130 <way id='-66' action='modify' visible='true'> 131 <nd ref='-16' /> 130 132 <nd ref='-14' /> 131 <tag k='name' v='t3w2' /> 133 <nd ref='-12' /> 134 <tag k='name' v='t2w2' /> 132 135 </way> 133 <relation id='-102' action='modify' visible='true'> 134 <member type='way' ref='-94' role='street' /> 135 <member type='way' ref='-96' role='street' /> 136 <member type='node' ref='-64' role='house' /> 137 <member type='node' ref='-62' role='house' /> 138 <member type='node' ref='-60' role='house' /> 139 <member type='node' ref='-66' role='house' /> 136 <way id='-64' action='modify' visible='true'> 137 <nd ref='-58' /> 138 <nd ref='-52' /> 139 <tag k='name' v='t3w5' /> 140 </way> 141 <relation id='-123' action='modify' visible='true'> 142 <member type='node' ref='-136' role='' /> 143 <member type='way' ref='-68' role='street' /> 144 <member type='node' ref='-10' role='house' /> 145 <member type='node' ref='-8' role='house' /> 146 <member type='node' ref='-6' role='house' /> 147 <member type='way' ref='-66' role='street' /> 148 <member type='node' ref='-119' role='tree' /> 149 <member type='node' ref='-4' role='house' /> 150 <tag k='test' v='street' /> 151 <tag k='type' v='street' /> 152 </relation> 153 <relation id='-100' action='modify' visible='true'> 154 <member type='way' ref='-64' role='forward' /> 155 <member type='way' ref='-94' role='forward' /> 156 <member type='way' ref='-92' role='' /> 157 <member type='way' ref='-90' role='forward' /> 158 <member type='way' ref='-86' role='' /> 159 <member type='way' ref='-88' role='forward' /> 160 <member type='way' ref='-84' role='' /> 161 <tag k='test' v='loop' /> 162 </relation> 163 <relation id='-98' action='modify' visible='true'> 164 <member type='way' ref='-74' role='' /> 165 <member type='way' ref='-70' role='' /> 166 <member type='way' ref='-82' role='' /> 167 <member type='way' ref='-76' role='' /> 168 <member type='way' ref='-72' role='' /> 169 <member type='way' ref='-80' role='' /> 170 <member type='way' ref='-78' role='' /> 171 <member type='node' ref='-24' role='' /> 172 <member type='node' ref='-20' role='' /> 173 <tag k='test' v='generic' /> 174 </relation> 175 <relation id='-96' action='modify' visible='true'> 176 <member type='way' ref='-68' role='street' /> 177 <member type='node' ref='-10' role='house' /> 178 <member type='node' ref='-8' role='house' /> 179 <member type='node' ref='-6' role='house' /> 180 <member type='way' ref='-66' role='street' /> 181 <member type='node' ref='-4' role='house' /> 140 182 <tag k='test' v='associatedStreet' /> 141 183 <tag k='type' v='associatedStreet' /> 142 184 </relation> 143 <relation id='-100' action='modify' visible='true'>144 <member type='way' ref='-88' role='' />145 <member type='way' ref='-92' role='' />146 <member type='way' ref='-80' role='' />147 <member type='way' ref='-86' role='' />148 <member type='way' ref='-90' role='' />149 <member type='way' ref='-82' role='' />150 <member type='way' ref='-84' role='' />151 <member type='node' ref='-46' role='' />152 <member type='node' ref='-50' role='' />153 <tag k='test' v='generic' />154 </relation>155 <relation id='-98' action='modify' visible='true'>156 <member type='way' ref='-112' role='forward' />157 <member type='way' ref='-68' role='forward' />158 <member type='way' ref='-70' role='' />159 <member type='way' ref='-72' role='forward' />160 <member type='way' ref='-76' role='' />161 <member type='way' ref='-74' role='forward' />162 <member type='way' ref='-78' role='' />163 <tag k='test' v='loop' />164 </relation>165 185 </osm> -
trunk/src/org/openstreetmap/josm/gui/dialogs/relation/sort/RelationSorter.java
r6316 r6461 6 6 import java.util.Collections; 7 7 import java.util.Comparator; 8 import java.util. HashMap;8 import java.util.LinkedHashMap; 9 9 import java.util.LinkedList; 10 10 import java.util.List; … … 13 13 14 14 import org.openstreetmap.josm.data.osm.RelationMember; 15 import org.openstreetmap.josm.gui.DefaultNameFormatter; 16 import org.openstreetmap.josm.tools.AlphanumComparator; 15 17 16 18 public class RelationSorter { … … 24 26 25 27 static { 26 additionalSorters.add(new AssociatedStreetSorter()); 28 // first adequate sorter is used, so order matters 29 additionalSorters.add(new AssociatedStreetRoleStreetSorter()); 30 additionalSorters.add(new AssociatedStreetRoleAddressHouseSorter()); 27 31 } 28 32 29 33 /** 30 * Class that sorts type=associatedStreet relation's houses. 34 * Class that sorts the {@code street} members of 35 * {@code type=associatedStreet} and {@code type=street} relations. 31 36 */ 32 private static class AssociatedStreet Sorter implements AdditionalSorter {37 private static class AssociatedStreetRoleStreetSorter implements AdditionalSorter { 33 38 34 39 @Override 35 40 public boolean acceptsMember(RelationMember m) { 36 return m != null 37 && m.getRole() != null && m.getRole().equals("house") 38 && m.getMember() != null && m.getMember().get("addr:housenumber") != null; 41 return "street".equals(m.getRole()); 42 } 43 44 @Override 45 public List<RelationMember> sortMembers(List<RelationMember> list) { 46 return sortMembersByConnectivity(list); 47 } 48 } 49 50 /** 51 * Class that sorts the {@code address} and {@code house} members of 52 * {@code type=associatedStreet} and {@code type=street} relations. 53 */ 54 private static class AssociatedStreetRoleAddressHouseSorter implements AdditionalSorter { 55 56 public static final AlphanumComparator ALPHANUM_COMPARATOR = new AlphanumComparator(); 57 58 @Override 59 public boolean acceptsMember(RelationMember m) { 60 return "address".equals(m.getRole()) || "house".equals(m.getRole()); 39 61 } 40 62 … … 44 66 @Override 45 67 public int compare(RelationMember a, RelationMember b) { 46 if (a == b || a.getMember() == b.getMember()) return 0; 47 String addrA = a.getMember().get("addr:housenumber").trim(); 48 String addrB = b.getMember().get("addr:housenumber").trim(); 49 if (addrA.equals(addrB)) return 0; 50 // Strip non-digits (from "1B" addresses for example) 51 String addrAnum = addrA.replaceAll("\\D+", ""); 52 String addrBnum = addrB.replaceAll("\\D+", ""); 53 // Compare only numbers 54 try { 55 Integer res = Integer.parseInt(addrAnum) - Integer.parseInt(addrBnum); 56 if (res != 0) return res; 57 } catch (NumberFormatException e) { 58 // Ignore NumberFormatException. If the number is not composed of digits, strings are compared next 68 final int houseNumber = ALPHANUM_COMPARATOR.compare( 69 a.getMember().get("addr:housenumber"), 70 b.getMember().get("addr:housenumber")); 71 if (houseNumber != 0) { 72 return houseNumber; 59 73 } 60 // Same number ? Compare full strings 61 return addrA.compareTo(addrB); 74 final String aDisplayName = a.getMember().getDisplayName(DefaultNameFormatter.getInstance()); 75 final String bDisplayName = b.getMember().getDisplayName(DefaultNameFormatter.getInstance()); 76 return ALPHANUM_COMPARATOR.compare(aDisplayName, bDisplayName); 62 77 } 63 78 }); … … 77 92 // Sort members with custom mechanisms (relation-dependent) 78 93 List<RelationMember> defaultMembers = new ArrayList<RelationMember>(relationMembers.size()); 79 Map<AdditionalSorter, List<RelationMember>> customMap = new HashMap<AdditionalSorter, List<RelationMember>>(); 94 // Maps sorter to assigned members for sorting. Use LinkedHashMap to retain order. 95 Map<AdditionalSorter, List<RelationMember>> customMap = new LinkedHashMap<AdditionalSorter, List<RelationMember>>(); 80 96 81 // Dispatch members to correct sorters97 // Dispatch members to the first adequate sorter 82 98 for (RelationMember m : relationMembers) { 99 boolean wasAdded = false; 83 100 for (AdditionalSorter sorter : additionalSorters) { 84 List<RelationMember> list = defaultMembers;85 101 if (sorter.acceptsMember(m)) { 102 List<RelationMember> list; 86 103 list = customMap.get(sorter); 87 104 if (list == null) { 88 105 customMap.put(sorter, list = new LinkedList<RelationMember>()); 89 106 } 107 list.add(m); 108 wasAdded = true; 109 break; 90 110 } 91 list.add(m); 111 } 112 if (!wasAdded) { 113 defaultMembers.add(m); 92 114 } 93 115 } … … 97 119 newMembers.addAll(entry.getKey().sortMembers(entry.getValue())); 98 120 } 121 newMembers.addAll(sortMembersByConnectivity(defaultMembers)); 122 return newMembers; 123 } 124 125 public static List<RelationMember> sortMembersByConnectivity(List<RelationMember> defaultMembers) { 126 127 List<RelationMember> newMembers = new ArrayList<RelationMember>(); 99 128 100 129 RelationNodeMap map = new RelationNodeMap(defaultMembers); -
trunk/test/unit/org/openstreetmap/josm/gui/dialogs/relation/sort/RelationSorterTest.java
r5630 r6461 50 50 public void testGeneric() { 51 51 String[] actual = getNames(sorter.sortMembers(getRelation("generic").getMembers())); 52 Assert.assertArrayEquals(new String[] {"t1w4", "t1w3", "t1w2", "t1w1", "t1w7", "t1w6", "t1w5", "t1n1", "t1n2"}, actual); 52 final String[] expected = {"t1w4", "t1w3", "t1w2", "t1w1", "t1w7", "t1w6", "t1w5", "t1n1", "t1n2"}; 53 // expect nodes to be sorted correctly 54 Assert.assertEquals(expected[7], actual[7]); 55 Assert.assertEquals(expected[8], actual[8]); 53 56 } 54 57 … … 56 59 public void testAssociatedStreet() { 57 60 String[] actual = getNames(sorter.sortMembers(getRelation("associatedStreet").getMembers())); 58 Assert.assertArrayEquals(new String[] {"t2n1", "t2n2", "t2n3", "t2n4", "t2w1", "t2w2"}, actual); 61 Assert.assertArrayEquals(new String[] {"t2w1", "t2w2", "t2n1", "t2n2", "t2n3", "t2n4"}, actual); 62 } 63 64 @Test 65 public void testStreet() { 66 String[] actual = getNames(sorter.sortMembers(getRelation("street").getMembers())); 67 Assert.assertArrayEquals(new String[]{"t2w1", "t2w2", "t2n1", "t2n2", "t2n3", "t2n4", "playground", "tree"}, actual); 59 68 } 60 69
Note:
See TracChangeset
for help on using the changeset viewer.