Changeset 18379 in osm for applications/editors/josm/plugins/validator
- Timestamp:
- 2009-10-30T23:53:08+01:00 (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnconnectedWays.java
r18223 r18379 5 5 import java.awt.geom.Area; 6 6 import java.awt.geom.Line2D; 7 import java.awt.geom.Point2D; 8 import java.util.ArrayList; 7 9 import java.util.Arrays; 10 import java.util.Collection; 11 import java.util.Collections; 12 import java.util.List; 8 13 import java.util.HashMap; 9 14 import java.util.HashSet; … … 12 17 13 18 import org.openstreetmap.josm.Main; 19 import org.openstreetmap.josm.data.coor.LatLon; 20 import org.openstreetmap.josm.data.coor.EastNorth; 14 21 import org.openstreetmap.josm.data.osm.Node; 15 22 import org.openstreetmap.josm.data.osm.OsmUtils; 16 23 import org.openstreetmap.josm.data.osm.Way; 17 24 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 25 import org.openstreetmap.josm.data.osm.DataSet; 26 import org.openstreetmap.josm.data.osm.QuadBuckets; 18 27 import org.openstreetmap.josm.plugins.validator.PreferenceEditor; 19 28 import org.openstreetmap.josm.plugins.validator.Severity; … … 36 45 Set<Node> middlenodes; // nodes in middle of way 37 46 Set<Node> othernodes; // nodes appearing at least twice 47 //NodeSearchCache nodecache; 48 QuadBuckets<Node> nodecache; 49 Area ds_area; 50 DataSet ds; 38 51 39 52 double mindist; … … 59 72 mindist = Main.pref.getDouble(PREFIX + ".node_way_distance", 10.0)/6378135.0; 60 73 minmiddledist = Main.pref.getDouble(PREFIX + ".way_way_distance", 0.0)/6378135.0; 74 this.ds = Main.main.getCurrentDataSet(); 75 this.ds_area = ds.getDataSourceArea(); 61 76 } 62 77 … … 64 79 public void endTest() 65 80 { 66 Area a = Main.main.getCurrentDataSet().getDataSourceArea();81 //Area a = Main.ds.getDataSourceArea(); 67 82 Map<Node, Way> map = new HashMap<Node, Way>(); 68 for(Node en : endnodes_highway) 69 { 70 Boolean isexit = OsmUtils.getOsmBoolean(en.get("noexit")); 71 if("turning_circle".equals(en.get("highway")) || 72 (isexit != null && isexit) || en.get("barrier") != null) 73 continue; 74 for(MyWaySegment s : ways) 75 { 76 if(!s.isBoundary && !s.isAbandoned && s.highway && s.nearby(en, mindist) && (a == null || a.contains(en.getCoor()))) 83 long last = -1; 84 for (int iter = 0; iter < 1; iter++) { 85 last = System.currentTimeMillis(); 86 long last_print = -1; 87 int nr = 0; 88 Collection<MyWaySegment> tmp_ways = ways; 89 for(MyWaySegment s : tmp_ways) { 90 nr++; 91 long now = System.currentTimeMillis(); 92 if (now - last_print > 200) { 93 System.err.println("processing segment nr: " + nr + " of " + ways.size()); 94 last_print = now; 95 } 96 for(Node en : s.nearbyNodes(mindist)) { 97 if (en == null) 98 continue; 99 //if("turning_circle".equals(en.get("highway")) || 100 // (isexit != null && isexit) || en.get("barrier") != null) 101 // c4++; 102 if(!s.highway) 103 continue; 104 if (!endnodes_highway.contains(en)) 105 continue; 106 Boolean isexit = OsmUtils.getOsmBoolean(en.get("noexit")); 107 if("turning_circle".equals(en.get("highway")) || 108 (isexit != null && isexit) || en.get("barrier") != null) 109 continue; 110 // There's a small false-positive here. Imagine an intersection 111 // like a 't'. If the top part of the 't' is short enough, it 112 // will trigger the node at the very top of the 't' to be unconnected 113 // to the way that "crosses" the 't'. We should probably check that 114 // the ways to which 'en' belongs are not connected to 's.w'. 115 map.put(en, s.w); 116 } 117 } 118 System.out.println("p1 elapesd: " + (System.currentTimeMillis()-last)); 119 last = System.currentTimeMillis(); 120 } 121 for(Map.Entry<Node, Way> error : map.entrySet()) 122 { 123 errors.add(new TestError(this, Severity.WARNING, 124 tr("Way end node near other highway"), UNCONNECTED_WAYS, 125 Arrays.asList(error.getKey(), error.getValue()))); 126 } 127 map.clear(); 128 for(MyWaySegment s : ways) 129 { 130 for(Node en : s.nearbyNodes(mindist)) 131 { 132 if (endnodes_highway.contains(en) && !s.highway && !s.isArea()) { 77 133 map.put(en, s.w); 78 } 79 } 80 if(map.size() > 0) 81 { 82 for(Map.Entry<Node, Way> error : map.entrySet()) 83 { 84 errors.add(new TestError(this, Severity.WARNING, 85 tr("Way end node near other highway"), UNCONNECTED_WAYS, 86 Arrays.asList(error.getKey(), error.getValue()))); 87 } 88 } 89 map.clear(); 90 for(Node en : endnodes_highway) 91 { 92 for(MyWaySegment s : ways) 93 { 94 if(!s.isBoundary && !s.isAbandoned && !s.highway && s.nearby(en, mindist) && !s.isArea() && (a == null || a.contains(en.getCoor()))) 134 } else if (endnodes.contains(en) && !s.isArea()) { 95 135 map.put(en, s.w); 96 } 97 } 98 for(Node en : endnodes) 99 { 100 for(MyWaySegment s : ways) 101 { 102 if(!s.isBoundary && !s.isAbandoned && s.nearby(en, mindist) && !s.isArea() && (a == null || a.contains(en.getCoor()))) 103 map.put(en, s.w); 104 } 105 } 106 if(map.size() > 0) 107 { 108 for(Map.Entry<Node, Way> error : map.entrySet()) 109 { 110 errors.add(new TestError(this, Severity.WARNING, 111 tr("Way end node near other way"), UNCONNECTED_WAYS, 112 Arrays.asList(error.getKey(), error.getValue()))); 113 } 136 } 137 } 138 } 139 System.out.println("p2 elapesd: " + (System.currentTimeMillis()-last)); 140 last = System.currentTimeMillis(); 141 for(Map.Entry<Node, Way> error : map.entrySet()) 142 { 143 errors.add(new TestError(this, Severity.WARNING, 144 tr("Way end node near other way"), UNCONNECTED_WAYS, 145 Arrays.asList(error.getKey(), error.getValue()))); 114 146 } 115 147 /* the following two use a shorter distance */ … … 117 149 { 118 150 map.clear(); 119 for( Node en : middlenodes)120 { 121 for( MyWaySegment s : ways)151 for(MyWaySegment s : ways) 152 { 153 for(Node en : s.nearbyNodes(minmiddledist)) 122 154 { 123 if(!s.isBoundary && !s.isAbandoned && s.nearby(en, minmiddledist) && (a == null || a.contains(en.getCoor()))) 124 map.put(en, s.w); 155 if (!middlenodes.contains(en)) 156 continue; 157 map.put(en, s.w); 125 158 } 126 159 } 127 if(map.size() > 0) 128 { 129 for(Map.Entry<Node, Way> error : map.entrySet()) 160 System.out.println("p3 elapesd: " + (System.currentTimeMillis()-last)); 161 last = System.currentTimeMillis(); 162 for(Map.Entry<Node, Way> error : map.entrySet()) 163 { 164 errors.add(new TestError(this, Severity.OTHER, 165 tr("Way node near other way"), UNCONNECTED_WAYS, 166 Arrays.asList(error.getKey(), error.getValue()))); 167 } 168 map.clear(); 169 for(MyWaySegment s : ways) 170 { 171 for(Node en : s.nearbyNodes(minmiddledist)) 130 172 { 131 errors.add(new TestError(this, Severity.OTHER,132 tr("Way node near other way"), UNCONNECTED_WAYS,133 Arrays.asList(error.getKey(), error.getValue())));173 if (!othernodes.contains(en)) 174 continue; 175 map.put(en, s.w); 134 176 } 135 177 } 136 map.clear(); 137 for(Node en : othernodes) 138 { 139 for(MyWaySegment s : ways) 140 { 141 if(!s.isBoundary && !s.isAbandoned && s.nearby(en, minmiddledist) && (a == null || a.contains(en.getCoor()))) 142 map.put(en, s.w); 143 } 144 } 145 if(map.size() > 0) 146 { 147 for(Map.Entry<Node, Way> error : map.entrySet()) 148 { 149 errors.add(new TestError(this, Severity.OTHER, 150 tr("Connected way end node near other way"), UNCONNECTED_WAYS, 151 Arrays.asList(error.getKey(), error.getValue()))); 152 } 178 System.out.println("p4 elapesd: " + (System.currentTimeMillis()-last)); 179 last = System.currentTimeMillis(); 180 for(Map.Entry<Node, Way> error : map.entrySet()) 181 { 182 errors.add(new TestError(this, Severity.OTHER, 183 tr("Connected way end node near other way"), UNCONNECTED_WAYS, 184 Arrays.asList(error.getKey(), error.getValue()))); 153 185 } 154 186 } … … 156 188 endnodes = null; 157 189 super.endTest(); 190 System.out.println("p99 elapesd: " + (System.currentTimeMillis()-last)); 191 last = System.currentTimeMillis(); 158 192 } 159 193 … … 165 199 public boolean isBoundary = false; 166 200 public boolean highway; 201 private double len; 202 private Set<Node> nearbyNodeCache; 203 double nearbyNodeCacheDist = -1.0; 204 Node n1; 205 Node n2; 167 206 168 207 public MyWaySegment(Way w, Node n1, Node n2) … … 175 214 this.isBoundary = !this.highway && "administrative".equals(w.get("boundary")); 176 215 line = new Line2D.Double(n1.getEastNorth().east(), n1.getEastNorth().north(), 177 n2.getEastNorth().east(), n2.getEastNorth().north()); 216 n2.getEastNorth().east(), n2.getEastNorth().north()); 217 len = line.getP1().distance(line.getP2()); 218 this.n1 = n1; 219 this.n2 = n2; 178 220 } 179 221 180 222 public boolean nearby(Node n, double dist) 181 223 { 182 return !w.containsNode(n) 183 && line.ptSegDist(n.getEastNorth().east(), n.getEastNorth().north()) < dist; 224 // return !w.containsNode(n) 225 // && line.ptSegDist(n.getEastNorth().east(), n.getEastNorth().north()) < dist; 226 if (w == null) 227 Main.debug("way null"); 228 if (w.containsNode(n)) 229 return false; 230 EastNorth coord = n.getEastNorth(); 231 if (coord == null) 232 return false; 233 Point2D p = new Point2D.Double(coord.east(), coord.north()); 234 if (line.getP1().distance(p) > len+dist) 235 return false; 236 if (line.getP2().distance(p) > len+dist) 237 return false; 238 return line.ptSegDist(p) < dist; 239 } 240 public List<LatLon> getBounds(double fudge) 241 { 242 double x1 = n1.getCoor().lon(); 243 double x2 = n2.getCoor().lon(); 244 if (x1 > x2) { 245 double tmpx = x1; 246 x1 = x2; 247 x2 = tmpx; 248 } 249 double y1 = n1.getCoor().lat(); 250 double y2 = n2.getCoor().lat(); 251 if (y1 > y2) { 252 double tmpy = y1; 253 y1 = y2; 254 y2 = tmpy; 255 } 256 LatLon topLeft = new LatLon(y2+fudge, x1-fudge); 257 LatLon botRight = new LatLon(y1-fudge, x2+fudge); 258 List<LatLon> ret = new ArrayList<LatLon>(); 259 ret.add(topLeft); 260 ret.add(botRight); 261 return ret; 262 } 263 264 public Collection<Node> nearbyNodes(double dist) 265 { 266 // If you're looking for nodes that are farther 267 // away that we looked for last time, the cached 268 // result is no good 269 if (dist > nearbyNodeCacheDist) { 270 //if (nearbyNodeCacheDist != -1) 271 // System.out.println("destroyed MyWaySegment nearby node cache:" + dist + " > " + nearbyNodeCacheDist); 272 nearbyNodeCache = null; 273 } 274 if (nearbyNodeCache != null) { 275 // If we've cached an aread greater than the 276 // one now being asked for... 277 if (nearbyNodeCacheDist > dist) { 278 System.out.println("had to trim MyWaySegment nearby node cache."); 279 // Used the cached result and trim out 280 // the nodes that are not in the smaller 281 // area, but keep the old larger cache. 282 Set<Node> trimmed = new HashSet<Node>(nearbyNodeCache); 283 for (Node n : new HashSet<Node>(nearbyNodeCache)) { 284 if (!nearby(n, dist)) 285 trimmed.remove(n); 286 } 287 return trimmed; 288 } 289 return nearbyNodeCache; 290 } 291 /* 292 * We know that any point near the line must be at 293 * least as close as the other end of the line, plus 294 * a little fudge for the distance away ('dist'). 295 */ 296 297 // This needs to be a hash set because the searches 298 // overlap a bit and can return duplicate nodes. 299 nearbyNodeCache = null; 300 nodecache = ds.nodes; 301 List<LatLon> bounds = this.getBounds(dist); 302 List<Node> found_nodes = nodecache.search(bounds.get(0), bounds.get(1)); 303 if (found_nodes == null) 304 return Collections.emptySet(); 305 306 for (Node n : found_nodes) { 307 if (!nearby(n, dist) || 308 (ds_area != null && !ds_area.contains(n.getCoor()))) 309 continue; 310 // It is actually very rare for us to find a node 311 // so defer as much of the work as possible, like 312 // allocating the hash set 313 if (nearbyNodeCache == null) 314 nearbyNodeCache = new HashSet<Node>(); 315 nearbyNodeCache.add(n); 316 } 317 nearbyNodeCacheDist = dist; 318 if (nearbyNodeCache == null) 319 nearbyNodeCache = Collections.emptySet(); 320 return nearbyNodeCache; 184 321 } 185 322 … … 191 328 } 192 329 193 @Override194 public void visit(Way w)195 {330 List<MyWaySegment> getWaySegments(Way w) 331 { 332 List<MyWaySegment> ret = new ArrayList<MyWaySegment>(); 196 333 if (!w.isUsable() 197 334 || w.get("barrier") != null 198 335 || "cliff".equals(w.get("natural"))) 199 return ;336 return ret; 200 337 201 338 int size = w.getNodesCount(); 202 339 if(size < 2) 203 return ;340 return ret; 204 341 for(int i = 1; i < size; ++i) 205 342 { 206 343 if(i < size-1) 207 344 addNode(w.getNode(i), middlenodes); 208 ways.add(new MyWaySegment(w, w.getNode(i-1), w.getNode(i))); 209 } 345 MyWaySegment ws = new MyWaySegment(w, w.getNode(i-1), w.getNode(i)); 346 if (ws.isBoundary || ws.isAbandoned) 347 continue; 348 ret.add(ws); 349 } 350 return ret; 351 } 352 353 @Override 354 public void visit(Way w) 355 { 356 ways.addAll(getWaySegments(w)); 210 357 Set<Node> set = endnodes; 211 358 if(w.get("highway") != null || w.get("railway") != null) 212 359 set = endnodes_highway; 213 addNode(w.getNode(0), set); 214 addNode(w.getNode(size-1), set); 360 addNode(w.firstNode(), set); 361 addNode(w.lastNode(), set); 362 } 363 @Override 364 public void visit(Node n) 365 { 215 366 } 216 367 private void addNode(Node n, Set<Node> s)
Note:
See TracChangeset
for help on using the changeset viewer.