package com.revolsys.geometry.index.quadtree; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; import com.revolsys.geometry.util.BoundingBoxUtil; public class QuadTreeNode<T> extends AbstractQuadTreeNode<T> { private static final long serialVersionUID = 1L; private final List<double[]> boundingBoxes = new ArrayList<>(); private final List<T> items = new ArrayList<>(); public QuadTreeNode() { } public QuadTreeNode(final int level, final double minX, final double minY, final double maxX, final double maxY) { super(level, minX, minY, maxX, maxY); } @Override protected boolean add(final QuadTree<T> tree, final double minX, final double minY, final double maxX, final double maxY, final T item) { synchronized (this.nodes) { final double[] bounds = new double[] { minX, minY, maxX, maxY }; int i = 0; final List<T> items = this.items; for (final T oldItem : items) { if (tree.equalsItem(item, oldItem)) { this.boundingBoxes.set(i, bounds); items.set(i, item); return false; } i++; } this.boundingBoxes.add(bounds); items.add(item); return true; } } @Override protected void forEachItem(final QuadTree<T> tree, final Consumer<? super T> action) { synchronized (this.nodes) { for (final T item : this.items) { action.accept(item); } } } @Override protected void forEachItem(final QuadTree<T> tree, final double x, final double y, final Consumer<? super T> action) { synchronized (this.nodes) { int i = 0; for (final double[] itemBounds : this.boundingBoxes) { if (BoundingBoxUtil.intersects(itemBounds[0], itemBounds[1], itemBounds[2], itemBounds[3], x, y)) { final T item = this.items.get(i); action.accept(item); } i++; } } } @Override protected void forEachItem(final QuadTree<T> tree, final double minX, final double minY, final double maxX, final double maxY, final Consumer<? super T> action) { synchronized (this.nodes) { int i = 0; for (final double[] itemBounds : this.boundingBoxes) { if (BoundingBoxUtil.intersects(itemBounds[0], itemBounds[1], itemBounds[2], itemBounds[3], minX, minY, maxX, maxY)) { final T item = this.items.get(i); action.accept(item); } i++; } } } @Override public int getItemCount() { return this.items.size(); } @Override protected AbstractQuadTreeNode<T> newNode(final int level, final double minX, final double minY, final double maxX, final double maxY) { return new QuadTreeNode<>(level, minX, minY, maxX, maxY); } @Override protected boolean removeItem(final QuadTree<T> tree, final T item) { synchronized (this.nodes) { int i = 0; for (final T oldItem : this.items) { if (tree.equalsItem(item, oldItem)) { this.items.remove(i); this.boundingBoxes.remove(i); return true; } i++; } return false; } } }