QuadTree.Rect bound2 = this.host.isLive() ? rect : this.top.getBounds(); byte[] bbyte; bbyte = this.host.getQuadDynStateBuffer(bound2); result.setRect(rect); for(Rect rectPart : rects) { QuadTree.Rect bound2 = this.host.isLive() ? rectPart : this.top.getBounds(); byte[] bbyte; bbyte = this.host.getQuadDynStateBuffer(bound2);
boolean found = false; if (currentLeaf.x <= this.bounds.centerX && currentLeaf.y <= this.bounds.centerY) { found = this.southwest.nextLeaf(currentLeaf, nextLeaf); if (found) { if (nextLeaf.value == null) { nextLeaf.value = this.northwest.firstLeaf(); } if (nextLeaf.value == null) { nextLeaf.value = this.southeast.firstLeaf(); } if (nextLeaf.value == null) { nextLeaf.value = this.northeast.firstLeaf(); } return true; found = this.northwest.nextLeaf(currentLeaf, nextLeaf); if (found) { if (nextLeaf.value == null) { nextLeaf.value = this.southeast.firstLeaf(); } if (nextLeaf.value == null) { nextLeaf.value = this.northeast.firstLeaf(); } return true; found = this.southeast.nextLeaf(currentLeaf, nextLeaf); if (found) { if (nextLeaf.value == null) { nextLeaf.value = this.northeast.firstLeaf(); } return true; return this.northeast.nextLeaf(currentLeaf, nextLeaf);
/* default */ Collection<T> get(final Rect bounds, final Collection<T> values) { if (this.hasChilds) { if (this.northwest.bounds.intersects(bounds)) { this.northwest.get(bounds, values); } if (this.northeast.bounds.intersects(bounds)) { this.northeast.get(bounds, values); } if (this.southeast.bounds.intersects(bounds)) { this.southeast.get(bounds, values); } if (this.southwest.bounds.intersects(bounds)) { this.southwest.get(bounds, values); } return values; } // no more childs, so we must contain the closest object if (this.leaves != null) { for (Leaf<T> leaf : this.leaves) { if (bounds.containsOrEquals(leaf.x, leaf.y)) { if (leaf.value != null) { values.add(leaf.value); } else { values.addAll(leaf.values); } } } } return values; }
this.northwest.getElliptical(x1, y1, x2, y2, maxDistance, values); this.northeast.getElliptical(x1, y1, x2, y2, maxDistance, values); this.southeast.getElliptical(x1, y1, x2, y2, maxDistance, values); this.southwest.getElliptical(x1, y1, x2, y2, maxDistance, values);
/* default */ T get(final double x, final double y, final MutableDouble bestDistance) { if (this.hasChilds) { T closest = null; Node<T> bestChild = this.getChild(x, y); if (bestChild != null) { closest = bestChild.get(x, y, bestDistance); T value = this.northwest.get(x, y, bestDistance); if (value != null) { closest = value; } T value = this.northeast.get(x, y, bestDistance); if (value != null) { closest = value; } T value = this.southeast.get(x, y, bestDistance); if (value != null) { closest = value; } T value = this.southwest.get(x, y, bestDistance); if (value != null) { closest = value; }
/* default */ Collection<T> get(final double x, final double y, final double maxDistance, final Collection<T> values) { if (this.hasChilds) { if (this.northwest.bounds.calcDistance(x, y) <= maxDistance) { this.northwest.get(x, y, maxDistance, values); this.northeast.get(x, y, maxDistance, values); this.southeast.get(x, y, maxDistance, values); this.southwest.get(x, y, maxDistance, values);
if (this.hasChilds) { if (this.northwest.bounds.intersects(globalBounds)) { count += this.northwest.execute(globalBounds, executor); count += this.northeast.execute(globalBounds, executor); count += this.southeast.execute(globalBounds, executor); count += this.southwest.execute(globalBounds, executor);
/** * Gets all objects within an elliptical region. * * @param x1 first focus, longitude * @param y1 first focus, latitude * @param x2 second focus, longitude * @param y2 second focus, latitude * @param distance the maximal sum of the distances between an object and the two foci * @return the objects found in the elliptical region * @throws IllegalArgumentException if the distance is shorter than the distance between the foci */ public Collection<T> getElliptical( final double x1, final double y1, final double x2, final double y2, final double distance) { if ( Math.pow( distance , 2 ) < Math.pow( (x1 - x2), 2 ) + Math.pow( (y1 - y2) , 2 ) ) { throw new IllegalArgumentException( "wrong ellipse specification: distance must be greater than distance between foci." +" x1="+x1 +" y1="+y1 +" x2="+x2 +" y2="+y2 +" distance="+distance ); } return this.top.getElliptical(x1, y1, x2, y2, distance, new ArrayList<>()); }
public boolean remove(final double x, final double y, final T value) { if (this.hasChilds) return getChild(x, y).remove(x, y, value); if (this.leaves != null) { for (Leaf<T> leaf : this.leaves) { if (leaf.x == x && leaf.y == y) { if (leaf.value == value) { leaf.value = null; this.leaves.remove(leaf); return true; } if (leaf.values != null) { if (leaf.values.remove(value)) { if (leaf.values.size() == 0) { this.leaves.remove(leaf); } return true; } } } } } return false; }
/** * Associates the specified value with the specified coordinates in this * QuadTree. * * @param x x-coordinate where the specified value is to be associated. * @param y y-coordinate where the specified value is to be associated. * @param value value to be associated with the specified coordinates. * * @return true if insertion was successful and the data structure changed, * false otherwise. */ public boolean put(final double x, final double y, final T value) { if (!this.top.bounds.containsOrEquals(x, y)) { throw new IllegalArgumentException("cannot add a point at x=" + x + ", y=" + y + " with bounds " + this.top.bounds); } if (this.top.put(x, y, value)) { incrementSize(); return true; } return false; }
public void clear() { // we could as well just set everything to null and let the // garbage collection do its job. if (this.hasChilds) { this.northwest.clear(); this.northeast.clear(); this.southeast.clear(); this.southwest.clear(); this.northwest = null; this.northeast = null; this.southeast = null; this.southwest = null; this.hasChilds = false; } else { if (this.leaves != null) { this.leaves = null; } } }
/** * Gets all objects within a linear ring (including borders). * * Note by JI (sept '15): This method can be significant faster than calling {@link #getDisk(double, double, double)} * and a manual check on the returned elements for >= r_min. For randomly distributed points one can use the * following rule-of-thumb: if r_min/r_max > 0.4 this method is likely to be faster than retrieving all elements within r_max. * * @param x left-right location, longitude * @param y up-down location, latitude * @param r_min inner ring radius * @param r_max outer rind radius * @return objects within the ring */ public Collection<T> getRing(final double x, final double y, final double r_min, final double r_max) { return this.top.get(x, y, r_min, r_max, new ArrayList<>()); }
public boolean put(final double x, final double y, final T value) { return put(new Leaf<T>(x, y, value)); }
private Leaf<T> firstLeaf() { return this.top.firstLeaf(); }
/** @return the maximum x coordinate (left-right, longitude, easting) of the bounds of the QuadTree. */ public double getMaxEasting() { return this.top.getBounds().maxX; }
/** * Creates an empty QuadTree with the bounds minX/minY -- maxX/maxY. For * optimal performance, all points should be evenly distributed within this * rectangle. * * @param minX The smallest x coordinate (easting, longitude) expected * @param minY The smallest y coordinate (northing, latitude) expected * @param maxX The largest x coordinate (easting, longitude) expected * @param maxY The largest y coordinate (northing, latitude) expected */ public QuadTree(final double minX, final double minY, final double maxX, final double maxY) { this.top = new Node<T>(minX, minY, maxX, maxY); }
private Leaf<T> nextLeaf(final Leaf<T> currentLeaf) { return this.top.nextLeaf(currentLeaf); }
/** @return the minimum y coordinate (up-down, latitude, northing) of the bounds of the QuadTree. */ public double getMaxNorthing() { return this.top.getBounds().maxY; }
/** * Executes executor on all objects inside a certain boundary * * @param bounds The boundary in which the executor will be applied. * @param executor is executed on the fitting objects * @return the count of objects found within the bounds. */ public int execute(final Rect bounds, final Executor<T> executor) { if (bounds == null) { return this.top.execute(this.top.getBounds(), executor); } return this.top.execute(bounds, executor); }