21 package org.matsim.core.utils.collections;
23 import java.io.Serializable;
38 public class QuadTree<T>
implements Serializable {
43 protected Node<T>
top = null;
56 transient volatile Collection<T>
values = null;
58 private void incrementSize() { this.modCount++; this.size++; this.values = null; }
59 private void decrementSize() { this.modCount++; this.size--; this.values = null; }
71 public QuadTree(
final double minX,
final double minY,
final double maxX,
final double maxY) {
72 this.top =
new Node<>(minX, minY, maxX, maxY);
86 public boolean put(
final double x,
final double y,
final T value) {
87 if (!this.top.bounds.containsOrEquals(x, y)) {
88 throw new IllegalArgumentException(
"cannot add a point at x=" + x +
", y=" + y +
" with bounds " + this.top.bounds);
90 if (this.top.put(x, y, value)) {
108 public boolean remove(
final double x,
final double y,
final T value) {
109 if (this.top.remove(x, y, value)) {
131 return this.top.get(x, y,
new MutableDouble(Double.POSITIVE_INFINITY));
142 public Collection<T>
getDisk(
final double x,
final double y,
final double distance) {
143 return this.top.get(x, y, distance * distance,
new ArrayList<>());
159 public Collection<T>
getRing(
final double x,
final double y,
final double rMin,
final double rMax) {
160 return this.top.get(x, y, rMin * rMin, rMax * rMax,
new ArrayList<>());
179 final double distance) {
180 if ( Math.pow( distance , 2 ) < Math.pow( (x1 - x2), 2 ) + Math.pow( (y1 - y2) , 2 ) ) {
181 throw new IllegalArgumentException(
"wrong ellipse specification: distance must be greater than distance between foci." 186 +
" distance="+distance );
188 return this.top.getElliptical(x1, y1, x2, y2, distance,
new ArrayList<>());
200 public Collection<T>
getRectangle(
final Rect bounds,
final Collection<T> values1) {
201 return this.top.get(bounds, values1);
215 public Collection<T>
getRectangle(
final double minX,
final double minY,
final double maxX,
final double maxY,
final Collection<T> values1) {
216 return getRectangle(
new Rect(minX, minY, maxX, maxY), values1);
226 public int execute(
final Rect bounds,
final Executor<T> executor) {
227 if (bounds == null) {
228 return this.top.execute(this.top.getBounds(), executor);
230 return this.top.execute(bounds, executor);
243 public int execute(
final double minX,
final double minY,
final double maxX,
final double maxY,
final Executor<T> executor) {
244 return execute(
new Rect(minX, minY, maxX, maxY), executor);
258 return this.top.getBounds().minX;
263 return this.top.getBounds().maxX;
268 return this.top.getBounds().minY;
273 return this.top.getBounds().maxY;
286 if (this.values == null) {
287 this.values =
new AbstractCollection<>() {
289 public Iterator<T> iterator() {
290 return new Iterator<>() {
292 private Leaf<T> currentLeaf =
firstLeaf();
293 private int nextIndex = 0;
294 private T next = first();
297 if (this.currentLeaf == null) {
306 public boolean hasNext() {
307 return this.next != null;
312 if (this.next == null) {
316 throw new ConcurrentModificationException();
318 T current = this.next;
323 private void loadNext() {
324 boolean searching =
true;
326 int size = this.currentLeaf.value != null ? 1 : this.currentLeaf.values.size();
327 if (this.nextIndex < size) {
329 this.next = this.currentLeaf.value != null ? this.currentLeaf.value : this.currentLeaf.values.get(this.nextIndex - 1);
332 this.currentLeaf =
nextLeaf(this.currentLeaf);
333 if (this.currentLeaf == null) {
344 public void remove() {
345 throw new UnsupportedOperationException();
361 return this.top.firstLeaf();
364 private Leaf<T>
nextLeaf(
final Leaf<T> currentLeaf) {
365 return this.top.nextLeaf(currentLeaf);
396 public static class Rect implements Serializable {
397 private static final long serialVersionUID = -837712701959689133L;
405 public Rect(
final double minX,
final double minY,
final double maxX,
final double maxY) {
406 this.minX = Math.min(minX, maxX);
407 this.minY = Math.min(minY, maxY);
408 this.maxX = Math.max(minX, maxX);
409 this.maxY = Math.max(minY, maxY);
410 this.centerX = (minX + maxX) / 2;
411 this.centerY = (minY + maxY) / 2;
427 if (this.minX <= x && x <= this.maxX) {
430 distanceX = Math.min(Math.abs(
this.minX - x), Math.abs(this.maxX - x));
432 if (this.minY <= y && y <= this.maxY) {
435 distanceY = Math.min(Math.abs(
this.minY - y), Math.abs(this.maxY - y));
438 return Math.sqrt(distanceX * distanceX + distanceY * distanceY);
454 if (this.minX <= x && x <= this.maxX) {
457 distanceX = Math.min(Math.abs(
this.minX - x), Math.abs(this.maxX - x));
459 if (this.minY <= y && y <= this.maxY) {
462 distanceY = Math.min(Math.abs(
this.minY - y), Math.abs(this.maxY - y));
465 return distanceX * distanceX + distanceY * distanceY;
476 double distanceX = Math.max(Math.abs(
this.minX - x), Math.abs(this.maxX - x));
477 double distanceY = Math.max(Math.abs(
this.minY - y), Math.abs(this.maxY - y));
479 return distanceX * distanceX + distanceY * distanceY;
491 public boolean contains(
final double x,
final double y) {
492 return (x >= this.minX &&
499 return (x >= this.minX &&
513 return (rect.
minX >=
this.minX &&
514 rect.
minY >=
this.minY &&
515 rect.
maxX <=
this.maxX &&
516 rect.
maxY <=
this.maxY);
527 if ((this.maxX-this.minX) < 0 || (this.maxY-this.minY) < 0) {
530 return (other.
maxX >=
this.minX &&
531 other.
maxY >=
this.minY &&
532 other.
minX <=
this.maxX &&
533 other.
minY <=
this.maxY);
550 double tx1 = this.minX;
551 double ty1 = this.minY;
552 double tx2 = this.maxX;
553 double ty2 = this.maxY;
554 if (this.minX < r.
minX) tx1 = r.
minX;
555 if (this.minY < r.
minY) ty1 = r.
minY;
559 if(tx2-tx1 <=0.f || ty2-ty1 <= 0.f)
return null;
561 return new Rect(tx1, ty1, tx2, ty2);
571 return new Rect( Math.min(
this.minX, r.minX),
572 Math.min(this.minY, r.minY),
573 Math.max(this.maxX, r.maxX),
574 Math.max(this.maxY, r.maxY));
588 scaleY *= this.centerY - this.minY;
589 scaleX *= this.centerX - this.minX;
590 return new Rect(this.minX - scaleX, this.minY-scaleY, this.maxX + scaleX, this.maxY + scaleY);
595 return "topLeft: ("+minX+
","+minY+
") bottomRight: ("+maxX+
","+maxY+
")";
600 protected static class Leaf<T>
implements Serializable {
601 private static final long serialVersionUID = -6527830222532634476L;
602 final public double x;
603 final public double y;
614 public Leaf(
final double x,
final double y,
final T value) {
622 protected static class Node<T>
implements Serializable {
623 private static final long serialVersionUID = 8151154226742383421L;
625 private static final int MAX_CHILDS = 128;
627 private ArrayList<Leaf<T>> leaves = null;
629 private boolean hasChilds =
false;
636 public Node(
final double minX,
final double minY,
final double maxX,
final double maxY) {
637 this.bounds =
new Rect(minX, minY, maxX, maxY);
641 if (this.hasChilds)
return getChild(leaf.
x, leaf.
y).put(leaf);
642 if (this.leaves == null) {
643 this.leaves =
new ArrayList<>();
644 this.leaves.add(leaf);
647 for (
Leaf<T> l : this.leaves) {
648 if (l.x == leaf.
x && l.y == leaf.
y) {
649 if (leaf.
value == l.value) {
652 if (l.values != null) {
653 if (l.values.contains(leaf.
value)) {
656 l.values.add(leaf.
value);
659 if (l.value == null) {
660 l.value = leaf.
value;
663 l.values =
new ArrayList<>(3);
664 l.values.add(l.value);
666 l.values.add(leaf.
value);
672 if (this.leaves.size() < MAX_CHILDS) {
673 this.leaves.add(leaf);
677 return getChild(leaf.
x, leaf.
y).put(leaf);
680 public boolean put(
final double x,
final double y,
final T
value) {
684 public boolean remove(
final double x,
final double y,
final T
value) {
685 if (this.hasChilds)
return getChild(x, y).remove(x, y,
value);
686 if (this.leaves != null) {
687 for (
Leaf<T> leaf : this.leaves) {
688 if (leaf.x == x && leaf.y == y) {
689 if (leaf.value ==
value) {
691 this.leaves.remove(leaf);
694 if (leaf.values != null) {
695 if (leaf.values.remove(
value)) {
696 if (leaf.values.isEmpty()) {
697 this.leaves.remove(leaf);
711 if (this.hasChilds) {
712 this.northwest.
clear();
713 this.northeast.
clear();
714 this.southeast.
clear();
715 this.southwest.
clear();
716 this.northwest = null;
717 this.northeast = null;
718 this.southeast = null;
719 this.southwest = null;
720 this.hasChilds =
false;
722 if (this.leaves != null) {
728 T
get(
final double x,
final double y,
final MutableDouble bestDistanceSqr) {
729 if (this.hasChilds) {
731 Node<T> bestChild = this.getChild(x, y);
732 if (bestChild != null) {
733 closest = bestChild.get(x, y, bestDistanceSqr);
735 if (bestChild != this.northwest && this.northwest.
bounds.calcDistanceSqr(x, y) < bestDistanceSqr.value) {
736 T
value = this.northwest.get(x, y, bestDistanceSqr);
737 if (value != null) { closest =
value; }
739 if (bestChild != this.northeast && this.northeast.
bounds.calcDistanceSqr(x, y) < bestDistanceSqr.value) {
740 T
value = this.northeast.get(x, y, bestDistanceSqr);
741 if (value != null) { closest =
value; }
743 if (bestChild != this.southeast && this.southeast.
bounds.calcDistanceSqr(x, y) < bestDistanceSqr.value) {
744 T
value = this.southeast.get(x, y, bestDistanceSqr);
745 if (value != null) { closest =
value; }
747 if (bestChild != this.southwest && this.southwest.
bounds.calcDistanceSqr(x, y) < bestDistanceSqr.value) {
748 T
value = this.southwest.get(x, y, bestDistanceSqr);
749 if (value != null) { closest =
value; }
755 if (this.leaves != null) {
756 for (
Leaf<T> leaf : this.leaves) {
757 double deltaX = leaf.x - x;
758 double deltaY = leaf.y - y;
759 double distanceSqr = deltaX * deltaX + deltaY * deltaY;
760 if (distanceSqr < bestDistanceSqr.value) {
761 bestDistanceSqr.value = distanceSqr;
762 closest = leaf.value != null ? leaf.value : leaf.values.get(0);
774 final double maxDistance,
775 final Collection<T> values) {
776 assert Math.pow( maxDistance , 2 ) >= Math.pow( (x1 - x2), 2 ) + Math.pow( (y1 - y2) , 2 );
777 if (this.hasChilds) {
793 final double nw1 = this.northwest.
bounds.calcDistance(x1, y1);
794 if ( nw1 <= maxDistance && nw1 + this.northwest.
bounds.calcDistance(x2, y2) <= maxDistance) {
795 this.northwest.getElliptical(x1, y1, x2, y2, maxDistance, values);
797 final double ne1 = this.northeast.
bounds.calcDistance(x1, y1);
798 if (ne1 <= maxDistance && ne1 + this.northeast.
bounds.calcDistance(x2, y2) <= maxDistance) {
799 this.northeast.getElliptical(x1, y1, x2, y2, maxDistance, values);
801 final double se1 = this.southeast.
bounds.calcDistance(x1, y1);
802 if (se1 <= maxDistance && se1 + this.southeast.
bounds.calcDistance(x2, y2) <= maxDistance) {
803 this.southeast.getElliptical(x1, y1, x2, y2, maxDistance, values);
805 final double sw1 = this.southwest.
bounds.calcDistance(x1, y1);
806 if (sw1 <= maxDistance && sw1 + this.southwest.
bounds.calcDistance(x2, y2) <= maxDistance) {
807 this.southwest.getElliptical(x1, y1, x2, y2, maxDistance, values);
812 if (this.leaves != null) {
813 for (
Leaf<T> leaf : this.leaves) {
814 final double distance1 = Math.sqrt(
815 (leaf.x - x1) * (leaf.x - x1)
816 + (leaf.y - y1) * (leaf.y - y1));
819 if (distance1 <= maxDistance) {
820 final double distance2 = Math.sqrt(
821 (leaf.x - x2) * (leaf.x - x2)
822 + (leaf.y - y2) * (leaf.y - y2));
823 if (distance1 + distance2 <= maxDistance) {
824 if (leaf.value != null) {
825 values.add(leaf.value);
827 values.addAll(leaf.values);
836 Collection<T>
get(
final double x,
final double y,
final double maxDistanceSqr,
final Collection<T>
values) {
837 if (this.hasChilds) {
838 if (this.northwest.
bounds.calcDistanceSqr(x, y) <= maxDistanceSqr) {
839 this.northwest.get(x, y, maxDistanceSqr, values);
841 if (this.northeast.
bounds.calcDistanceSqr(x, y) <= maxDistanceSqr) {
842 this.northeast.get(x, y, maxDistanceSqr, values);
844 if (this.southeast.
bounds.calcDistanceSqr(x, y) <= maxDistanceSqr) {
845 this.southeast.get(x, y, maxDistanceSqr, values);
847 if (this.southwest.
bounds.calcDistanceSqr(x, y) <= maxDistanceSqr) {
848 this.southwest.get(x, y, maxDistanceSqr, values);
853 if (this.leaves != null) {
854 for (
Leaf<T> leaf : this.leaves) {
855 double distanceSqr = (leaf.x - x) * (leaf.x - x) + (leaf.y - y) * (leaf.y - y);
856 if (distanceSqr <= maxDistanceSqr) {
857 if (leaf.value != null) {
858 values.add(leaf.value);
860 values.addAll(leaf.values);
868 Collection<T>
get(
final double x,
final double y,
final double rMinSqr,
final double rMaxSqr,
870 if (this.hasChilds) {
871 stepIntoSqr(this.northwest, x, y, rMinSqr, rMaxSqr, values);
872 stepIntoSqr(this.northeast, x, y, rMinSqr, rMaxSqr, values);
873 stepIntoSqr(this.southeast, x, y, rMinSqr, rMaxSqr, values);
874 stepIntoSqr(this.southwest, x, y, rMinSqr, rMaxSqr, values);
878 if (this.leaves != null) {
879 for (
Leaf<T> leaf : this.leaves) {
880 double distanceSqr = (leaf.x - x) * (leaf.x - x) + (leaf.y - y) * (leaf.y - y);
881 if (distanceSqr <= rMaxSqr && distanceSqr >= rMinSqr) {
882 if (leaf.value != null) {
883 values.add(leaf.value);
885 values.addAll(leaf.values);
893 private void stepIntoSqr(
Node<T> node,
double x,
double y,
double rMinSqr,
double rMaxSqr, Collection<T> values) {
894 double minDistanceSqr = node.
bounds.calcDistanceSqr(x, y);
895 double maxDistanceSqr = node.
bounds.calcMaxDistanceSqr(x, y);
897 if (minDistanceSqr <= rMaxSqr && maxDistanceSqr >= rMinSqr) {
898 node.get(x, y, rMinSqr, rMaxSqr, values);
902 Collection<T>
get(
final Rect bounds,
final Collection<T>
values) {
903 if (this.hasChilds) {
904 if (this.northwest.
bounds.intersects(bounds)) {
905 this.northwest.get(bounds, values);
907 if (this.northeast.
bounds.intersects(bounds)) {
908 this.northeast.get(bounds, values);
910 if (this.southeast.
bounds.intersects(bounds)) {
911 this.southeast.get(bounds, values);
913 if (this.southwest.
bounds.intersects(bounds)) {
914 this.southwest.get(bounds, values);
919 if (this.leaves != null) {
920 for (
Leaf<T> leaf : this.leaves) {
921 if (bounds.containsOrEquals(leaf.x, leaf.y)) {
922 if (leaf.value != null) {
923 values.add(leaf.value);
925 values.addAll(leaf.values);
935 if (this.hasChilds) {
936 if (this.northwest.
bounds.intersects(globalBounds)) {
937 count += this.northwest.execute(globalBounds, executor);
939 if (this.northeast.
bounds.intersects(globalBounds)) {
940 count += this.northeast.execute(globalBounds, executor);
942 if (this.southeast.
bounds.intersects(globalBounds)) {
943 count += this.southeast.execute(globalBounds, executor);
945 if (this.southwest.
bounds.intersects(globalBounds)) {
946 count += this.southwest.execute(globalBounds, executor);
951 if (this.leaves != null) {
952 for (
Leaf<T> leaf : this.leaves) {
953 if (globalBounds.
contains(leaf.x, leaf.y)) {
954 if (leaf.value != null) {
956 executor.
execute(leaf.x, leaf.y, leaf.value);
958 count += leaf.values.size();
959 for (T
object : leaf.values) executor.
execute(leaf.x, leaf.y,
object);
968 this.northwest =
new Node<>(this.bounds.minX, this.bounds.centerY, this.bounds.centerX, this.bounds.maxY);
969 this.northeast =
new Node<>(this.bounds.centerX, this.bounds.centerY, this.bounds.maxX, this.bounds.maxY);
970 this.southeast =
new Node<>(this.bounds.centerX, this.bounds.minY, this.bounds.maxX, this.bounds.centerY);
971 this.southwest =
new Node<>(this.bounds.minX, this.bounds.minY, this.bounds.centerX, this.bounds.centerY);
972 this.hasChilds =
true;
973 if (this.leaves != null) {
974 for (
Leaf<T> leaf : this.leaves) {
975 getChild(leaf.x, leaf.y).
put(leaf);
982 if (this.hasChilds) {
983 if (x < this.bounds.centerX) {
984 if (y < this.bounds.centerY)
985 return this.southwest;
986 return this.northwest;
988 if (y < this.bounds.centerY)
989 return this.southeast;
990 return this.northeast;
996 if (this.hasChilds) {
997 Leaf<T> leaf = this.southwest.firstLeaf();
998 if (leaf == null) { leaf = this.northwest.firstLeaf(); }
999 if (leaf == null) { leaf = this.southeast.firstLeaf(); }
1000 if (leaf == null) { leaf = this.northeast.firstLeaf(); }
1003 return (this.leaves == null || this.leaves.isEmpty()) ? null : this.leaves.get(0);
1007 if (this.hasChilds) {
1008 if (currentLeaf.
x <=
this.bounds.centerX && currentLeaf.
y <=
this.bounds.centerY) {
1009 boolean found = this.southwest.nextLeaf(currentLeaf, nextLeaf);
1011 if (nextLeaf.
value == null) { nextLeaf.
value = this.northwest.firstLeaf(); }
1012 if (nextLeaf.
value == null) { nextLeaf.
value = this.southeast.firstLeaf(); }
1013 if (nextLeaf.
value == null) { nextLeaf.
value = this.northeast.firstLeaf(); }
1017 if (currentLeaf.
x <=
this.bounds.centerX && currentLeaf.
y >=
this.bounds.centerY) {
1018 boolean found = this.northwest.nextLeaf(currentLeaf, nextLeaf);
1020 if (nextLeaf.
value == null) { nextLeaf.
value = this.southeast.firstLeaf(); }
1021 if (nextLeaf.
value == null) { nextLeaf.
value = this.northeast.firstLeaf(); }
1025 if (currentLeaf.
x >=
this.bounds.centerX && currentLeaf.
y <=
this.bounds.centerY) {
1026 boolean found = this.southeast.nextLeaf(currentLeaf, nextLeaf);
1028 if (nextLeaf.
value == null) { nextLeaf.
value = this.northeast.firstLeaf(); }
1032 if (currentLeaf.
x >=
this.bounds.centerX && currentLeaf.
y >=
this.bounds.centerY) {
1033 return this.northeast.nextLeaf(currentLeaf, nextLeaf);
1037 if (this.leaves != null) {
1038 int idx = this.leaves.indexOf(currentLeaf);
1040 if (idx + 1 < this.leaves.size()) {
1041 nextLeaf.
value = this.leaves.get(idx + 1);
1052 return nextLeaf.
value;
1062 void execute(
double x,
double y, T
object);
void stepIntoSqr(Node< T > node, double x, double y, double rMinSqr, double rMaxSqr, Collection< T > values)
Rect scale(double scaleX, double scaleY)
void execute(double x, double y, T object)
Collection< T > getRing(final double x, final double y, final double rMin, final double rMax)
Leaf< T > nextLeaf(final Leaf< T > currentLeaf)
boolean contains(final double x, final double y)
Collection< T > getRectangle(final Rect bounds, final Collection< T > values1)
Rect intersection(final Rect r)
boolean put(final Leaf< T > leaf)
double calcMaxDistanceSqr(final double x, final double y)
int execute(final double minX, final double minY, final double maxX, final double maxY, final Executor< T > executor)
Node< T > getChild(final double x, final double y)
boolean intersects(final Rect other)
boolean containsOrEquals(final double x, final double y)
boolean put(final double x, final double y, final T value)
Collection< T > getRectangle(final double minX, final double minY, final double maxX, final double maxY, final Collection< T > values1)
boolean containsOrEquals(final Rect rect)
MutableDouble(final double value)
static final long serialVersionUID
Leaf< T > nextLeaf(final Leaf< T > currentLeaf)
T getClosest(final double x, final double y)
int execute(final Rect bounds, final Executor< T > executor)
boolean put(final double x, final double y, final T value)
QuadTree(final double minX, final double minY, final double maxX, final double maxY)
Leaf(final double x, final double y, final T value)
Node(final double minX, final double minY, final double maxX, final double maxY)
Collection< T > getElliptical(final double x1, final double y1, final double x2, final double y2, final double distance)
Collection< T > getDisk(final double x, final double y, final double distance)
Rect(final double minX, final double minY, final double maxX, final double maxY)
double calcDistanceSqr(final double x, final double y)
MutableLeaf(final Leaf< T > value)
double calcDistance(final double x, final double y)