Changeset 11269 in josm for trunk/src/org
- Timestamp:
- 2016-11-17T19:58:39+01:00 (8 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/data/osm
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/osm/BBox.java
r11237 r11269 20 20 * Constructs a new (invalid) BBox 21 21 */ 22 protected BBox() { } 23 22 public BBox() { } 24 23 25 24 /** … … 31 30 */ 32 31 public BBox(final double x, final double y) { 33 xmax = xmin = x; 34 ymax = ymin = y; 35 sanity(); 32 if (!Double.isNaN(x) && !Double.isNaN(y)) { 33 xmin = x; 34 ymin = y; 35 xmax = x; 36 ymax = y; 37 } 36 38 } 37 39 38 40 /** 39 41 * Constructs a new {@code BBox} defined by points <code>a</code> and <code>b</code>. 40 * Result is minimal BBox containing both points .42 * Result is minimal BBox containing both points if they are both valid, else undefined 41 43 * 42 44 * @param a first point … … 59 61 } 60 62 63 /** 64 * Create minimal BBox so that {@code this.bounds(ax,ay)} and {@code this.bounds(bx,by)} will both return true 65 * @param ax left or right X value (-180 .. 180) 66 * @param ay top or bottom Y value (-90 .. 90) 67 * @param bx left or right X value (-180 .. 180) 68 * @param by top or bottom Y value (-90 .. 90) 69 */ 61 70 public BBox(double ax, double ay, double bx, double by) { 71 if (Double.isNaN(ax) || Double.isNaN(ay) || Double.isNaN(bx) || Double.isNaN(by)) { 72 return; // use default which is an invalid BBox 73 } 62 74 63 75 if (ax > bx) { … … 76 88 ymin = ay; 77 89 } 78 79 sanity(); 80 } 81 90 } 91 92 /** 93 * Create BBox for all nodes of the way with known coordinates. 94 * If no node has a known coordinate, an invalid BBox is returned. 95 * @param w the way 96 */ 82 97 public BBox(Way w) { 83 for (Node n : w.getNodes()) { 84 LatLon coor = n.getCoor(); 85 if (coor == null) { 86 continue; 87 } 88 add(coor); 89 } 90 } 91 98 w.getNodes().forEach((n) -> add(n.getCoor())); 99 } 100 101 /** 102 * Create BBox for a node. An invalid BBox is returned if the coordinates are not known. 103 * @param n the node 104 */ 92 105 public BBox(Node n) { 93 LatLon coor = n.getCoor(); 94 if (coor == null) { 95 xmin = xmax = ymin = ymax = 0; 96 } else { 97 xmin = xmax = coor.lon(); 98 ymin = ymax = coor.lat(); 99 } 100 } 101 102 private void sanity() { 103 if (xmin < -180.0) { 104 xmin = -180.0; 105 } 106 if (xmax > 180.0) { 107 xmax = 180.0; 108 } 109 if (ymin < -90.0) { 110 ymin = -90.0; 111 } 112 if (ymax > 90.0) { 113 ymax = 90.0; 114 } 115 } 116 106 if (n.isLatLonKnown()) 107 add(n.getCoor()); 108 } 109 110 /** 111 * Add a point to an existing BBox. Extends this bbox if necessary so that this.bounds(c) will return true 112 * if c is a valid LatLon instance. 113 * @param c a LatLon point 114 */ 117 115 public final void add(LatLon c) { 118 add(c.lon(), c.lat()); 116 if (c != null && c.isValid()) 117 add(c.lon(), c.lat()); 119 118 } 120 119 … … 125 124 */ 126 125 public final void add(double x, double y) { 126 if (Double.isNaN(x) || Double.isNaN(y)) 127 return; 127 128 xmin = Math.min(xmin, x); 128 129 xmax = Math.max(xmax, x); 129 130 ymin = Math.min(ymin, y); 130 131 ymax = Math.max(ymax, y); 131 sanity(); 132 } 133 134 public final void add(BBox box) { 135 xmin = Math.min(xmin, box.xmin); 136 xmax = Math.max(xmax, box.xmax); 137 ymin = Math.min(ymin, box.ymin); 138 ymax = Math.max(ymax, box.ymax); 139 sanity(); 140 } 141 132 } 133 134 /** 135 * Extends this bbox to include the bbox other. Does nothing if other is not valid. 136 * @param other a bbox 137 */ 138 public final void add(BBox other) { 139 if (other.isValid()) { 140 xmin = Math.min(xmin, other.xmin); 141 xmax = Math.max(xmax, other.xmax); 142 ymin = Math.min(ymin, other.ymin); 143 ymax = Math.max(ymax, other.ymax); 144 } 145 } 146 147 /** 148 * Extends this bbox to include the bbox of the primitive extended by extraSpace. 149 * @param primitive an OSM primitive 150 * @param extraSpace the value to extend the primitives bbox. Unit is in LatLon degrees. 151 */ 142 152 public void addPrimitive(OsmPrimitive primitive, double extraSpace) { 143 153 BBox primBbox = primitive.getBBox(); … … 285 295 } 286 296 297 /** 298 * @return true if the bbox covers a part of the planets surface 299 * Height and width must be non-negative, but may (both) be 0. 300 */ 301 public boolean isValid() { 302 return (xmin <= xmax && ymin <= ymax); 303 } 304 305 /** 306 * @return true if the bbox covers a part of the planets surface 307 */ 308 public boolean isInWorld() { 309 return !(xmin < -180.0 || xmax > 180.0 || ymin < -90.0 || ymax > 90.0); 310 } 311 287 312 @Override 288 313 public String toString() { -
trunk/src/org/openstreetmap/josm/data/osm/DataSet.java
r11115 r11269 504 504 tr("Unable to add primitive {0} to the dataset because it is already included", primitive.toString())); 505 505 506 primitive.updatePosition(); // Set cached bbox for way and relation (required for reindexWay and reinexRelation to work properly) 506 allPrimitives.add(primitive); 507 primitive.setDataset(this); 508 primitive.updatePosition(); // Set cached bbox for way and relation (required for reindexWay and reindexRelation to work properly) 507 509 boolean success = false; 508 510 if (primitive instanceof Node) { … … 515 517 if (!success) 516 518 throw new RuntimeException("failed to add primitive: "+primitive); 517 allPrimitives.add(primitive);518 primitive.setDataset(this);519 519 firePrimitivesAdded(Collections.singletonList(primitive), false); 520 520 } finally { -
trunk/src/org/openstreetmap/josm/data/osm/Node.java
r10919 r11269 330 330 @Override 331 331 public BBox getBBox() { 332 return new BBox(this); 332 return new BBox(lon, lat); 333 } 334 335 @Override 336 protected void addToBBox(BBox box, Set<PrimitiveId> visited) { 337 box.add(lon, lat); 333 338 } 334 339 -
trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
r11079 r11269 1417 1417 return false; 1418 1418 } 1419 1420 /** 1421 * If necessary, extend the bbox to contain this primitive 1422 * @param box a bbox instance 1423 * @param visited a set of visited members or null 1424 */ 1425 protected abstract void addToBBox(BBox box, Set<PrimitiveId> visited); 1419 1426 } -
trunk/src/org/openstreetmap/josm/data/osm/QuadBuckets.java
r11237 r11269 6 6 import java.util.Collection; 7 7 import java.util.Iterator; 8 import java.util.LinkedHashSet; 8 9 import java.util.List; 9 10 import java.util.NoSuchElementException; … … 167 168 168 169 boolean matches(final T o, final BBox searchBbox) { 169 if (o instanceof Node) {170 final LatLon latLon = ((Node) o).getCoor();171 // node without coords -> bbox[0,0,0,0]172 return searchBbox.bounds(latLon != null ? latLon : LatLon.ZERO);173 }174 170 return o.getBBox().intersects(searchBbox); 175 171 } … … 359 355 private QBLevel<T> searchCache; 360 356 private int size; 357 private Collection<T> invalidBBoxPrimitives; 361 358 362 359 /** … … 370 367 public final void clear() { 371 368 root = new QBLevel<>(); 369 invalidBBoxPrimitives = new LinkedHashSet<>(); 372 370 searchCache = null; 373 371 size = 0; … … 376 374 @Override 377 375 public boolean add(T n) { 378 root.add(n); 376 if (n.getBBox().isValid()) 377 root.add(n); 378 else 379 invalidBBoxPrimitives.add(n); 379 380 size++; 380 381 return true; … … 426 427 searchCache = null; // Search cache might point to one of removed buckets 427 428 QBLevel<T> bucket = root.findBucket(t.getBBox()); 428 if (bucket.removeContent(t)) { 429 boolean removed = bucket.removeContent(t); 430 if (!removed) 431 removed = invalidBBoxPrimitives.remove(o); 432 if (removed) 429 433 size--; 430 return true; 431 } else 432 return false; 434 return removed; 433 435 } 434 436 … … 437 439 @SuppressWarnings("unchecked") 438 440 T t = (T) o; 441 if (!t.getBBox().isValid()) 442 return invalidBBoxPrimitives.contains(o); 439 443 QBLevel<T> bucket = root.findBucket(t.getBBox()); 440 444 return bucket != null && bucket.content != null && bucket.content.contains(t); … … 466 470 private QBLevel<T> currentNode; 467 471 private int contentIndex; 472 private Iterator<T> invalidBBoxIterator = invalidBBoxPrimitives.iterator(); 473 boolean fromInvalidBBoxPrimitives; 468 474 QuadBuckets<T> qb; 469 475 … … 491 497 @Override 492 498 public boolean hasNext() { 493 if (this.peek() == null) 494 return false; 499 if (this.peek() == null) { 500 fromInvalidBBoxPrimitives = true; 501 return invalidBBoxIterator.hasNext(); 502 } 495 503 return true; 496 504 } … … 513 521 @Override 514 522 public T next() { 523 if (fromInvalidBBoxPrimitives) 524 return invalidBBoxIterator.next(); 515 525 T ret = peek(); 516 526 if (ret == null) … … 522 532 @Override 523 533 public void remove() { 524 // two uses 525 // 1. Back up to the thing we just returned 526 // 2. move the index back since we removed 527 // an element 528 contentIndex--; 529 T object = peek(); 530 if (currentNode.removeContent(object)) 534 if (fromInvalidBBoxPrimitives) { 535 invalidBBoxIterator.remove(); 531 536 qb.size--; 537 } else { 538 // two uses 539 // 1. Back up to the thing we just returned 540 // 2. move the index back since we removed 541 // an element 542 contentIndex--; 543 T object = peek(); 544 if (currentNode.removeContent(object)) 545 qb.size--; 546 547 } 532 548 } 533 549 } … … 555 571 public List<T> search(BBox searchBbox) { 556 572 List<T> ret = new ArrayList<>(); 573 if (!searchBbox.isValid()) { 574 return ret; 575 } 576 557 577 // Doing this cuts down search cost on a real-life data set by about 25% 558 578 if (searchCache == null) { -
trunk/src/org/openstreetmap/josm/data/osm/Relation.java
r11038 r11269 447 447 @Override 448 448 public BBox getBBox() { 449 RelationMember[] members = this.members; 450 451 if (members.length == 0) 452 return new BBox(0, 0, 0, 0); 453 if (getDataSet() == null) 454 return calculateBBox(new HashSet<PrimitiveId>()); 455 else { 456 if (bbox == null) { 457 bbox = calculateBBox(new HashSet<PrimitiveId>()); 458 } 459 if (bbox == null) 460 return new BBox(0, 0, 0, 0); // No real members 461 else 462 return new BBox(bbox); 463 } 464 } 465 466 private BBox calculateBBox(Set<PrimitiveId> visitedRelations) { 467 if (visitedRelations.contains(this)) 468 return null; 469 visitedRelations.add(this); 470 471 RelationMember[] members = this.members; 472 if (members.length == 0) 473 return null; 474 else { 475 BBox result = null; 476 for (RelationMember rm:members) { 477 BBox box = rm.isRelation() ? rm.getRelation().calculateBBox(visitedRelations) : rm.getMember().getBBox(); 478 if (box != null) { 479 if (result == null) { 480 result = box; 481 } else { 482 result.add(box); 483 } 484 } 485 } 486 return result; 449 if (getDataSet() != null && bbox != null) 450 return new BBox(bbox); // use cached value 451 452 BBox box = new BBox(); 453 addToBBox(box, new HashSet<PrimitiveId>()); 454 if (getDataSet() != null) 455 bbox = box; // set cache 456 return new BBox(box); 457 } 458 459 @Override 460 protected void addToBBox(BBox box, Set<PrimitiveId> visited) { 461 for (RelationMember rm : members) { 462 if (visited.add(rm.getMember())) 463 rm.getMember().addToBBox(box, visited); 487 464 } 488 465 } … … 490 467 @Override 491 468 public void updatePosition() { 492 bbox = calculateBBox(new HashSet<PrimitiveId>()); 469 bbox = null; // make sure that it is recalculated 470 bbox = getBBox(); 493 471 } 494 472 -
trunk/src/org/openstreetmap/josm/data/osm/Way.java
r10662 r11269 631 631 } 632 632 return new BBox(bbox); 633 } 634 635 @Override 636 protected void addToBBox(BBox box, Set<PrimitiveId> visited) { 637 box.add(getBBox()); 633 638 } 634 639
Note:
See TracChangeset
for help on using the changeset viewer.