package com.revolsys.geometry.index.quadtree;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
import com.revolsys.geometry.index.IdObjectIndex;
import com.revolsys.geometry.model.BoundingBox;
import com.revolsys.geometry.model.BoundingBoxProxy;
import com.revolsys.geometry.model.GeometryFactory;
import com.revolsys.visitor.CreateListVisitor;
public abstract class AbstractIdObjectQuadTree<T> implements IdObjectIndex<T> {
private final QuadTree<Integer> index;
public AbstractIdObjectQuadTree(final GeometryFactory geometryFactory) {
this.index = new QuadTree<>(geometryFactory);
}
public void add(final Collection<Integer> ids) {
for (final Integer id : ids) {
final T object = getObject(id);
add(object);
}
}
@Override
public T add(final T object) {
final BoundingBox envelope = getBoundingBox(object);
final int id = getId(object);
this.index.insertItem(envelope, id);
return object;
}
@Override
public void forEach(final BoundingBoxProxy boundingBoxProxy, final Consumer<? super T> action) {
final BoundingBox boundingBox = boundingBoxProxy.getBoundingBox();
this.index.forEach(boundingBox, (id) -> {
final T object = getObject(id);
final BoundingBox e = getBoundingBox(object);
if (e.intersects(boundingBox)) {
action.accept(object);
}
});
}
@Override
public void forEach(final BoundingBoxProxy boundingBoxProxy, final Predicate<? super T> filter,
final Consumer<? super T> action) {
final BoundingBox boundingBox = boundingBoxProxy.getBoundingBox();
this.index.forEach(boundingBox, (id) -> {
final T object = getObject(id);
final BoundingBox e = getBoundingBox(object);
if (e.intersects(boundingBox) && filter.test(object)) {
action.accept(object);
}
});
}
@Override
public Iterator<T> iterator() {
return queryAll().iterator();
}
@Override
public List<T> query(final BoundingBox envelope) {
final CreateListVisitor<T> visitor = new CreateListVisitor<>();
forEach(envelope, visitor);
return visitor.getList();
}
public List<T> queryAll() {
final List<Integer> ids = this.index.getAll();
return getObjects(ids);
}
@Override
public boolean remove(final T object) {
final BoundingBox envelope = getBoundingBox(object);
final int id = getId(object);
return this.index.removeItem(envelope, id);
}
public void removeAll(final Collection<T> objects) {
for (final T object : objects) {
remove(object);
}
}
}