/*
***************************************************************************************
* Copyright (C) 2006 EsperTech, Inc. All rights reserved. *
* http://www.espertech.com/esper *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
***************************************************************************************
*/
package com.espertech.esper.spatial.quadtree.prqdfilterindex;
import com.espertech.esper.spatial.quadtree.core.*;
import com.espertech.esper.spatial.quadtree.pointregion.PointRegionQuadTree;
import com.espertech.esper.spatial.quadtree.pointregion.PointRegionQuadTreeNode;
import com.espertech.esper.spatial.quadtree.pointregion.PointRegionQuadTreeNodeBranch;
import com.espertech.esper.spatial.quadtree.pointregion.PointRegionQuadTreeNodeLeaf;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import static com.espertech.esper.spatial.quadtree.prqdfilterindex.PointRegionQuadTreeFilterIndexCheckBB.checkBB;
public class PointRegionQuadTreeFilterIndexDelete {
public static void delete(double x, double y, PointRegionQuadTree<Object> tree) {
PointRegionQuadTreeNode<Object> root = tree.getRoot();
checkBB(root.getBb(), x, y);
PointRegionQuadTreeNode<Object> replacement = deleteFromNode(x, y, root, tree);
tree.setRoot(replacement);
}
private static <L> PointRegionQuadTreeNode<Object> deleteFromNode(double x, double y, PointRegionQuadTreeNode<Object> node, PointRegionQuadTree<Object> tree) {
if (node instanceof PointRegionQuadTreeNodeLeaf) {
PointRegionQuadTreeNodeLeaf<Object> leaf = (PointRegionQuadTreeNodeLeaf<Object>) node;
boolean removed = deleteFromPoints(x, y, leaf.getPoints());
if (removed) {
leaf.decCount();
if (leaf.getCount() == 0) {
leaf.setPoints(null);
}
}
return leaf;
}
PointRegionQuadTreeNodeBranch<Object> branch = (PointRegionQuadTreeNodeBranch<Object>) node;
QuadrantEnum quadrant = node.getBb().getQuadrant(x, y);
if (quadrant == QuadrantEnum.NW) {
branch.setNw(deleteFromNode(x, y, branch.getNw(), tree));
} else if (quadrant == QuadrantEnum.NE) {
branch.setNe(deleteFromNode(x, y, branch.getNe(), tree));
} else if (quadrant == QuadrantEnum.SW) {
branch.setSw(deleteFromNode(x, y, branch.getSw(), tree));
} else {
branch.setSe(deleteFromNode(x, y, branch.getSe(), tree));
}
if (!(branch.getNw() instanceof PointRegionQuadTreeNodeLeaf) || !(branch.getNe() instanceof PointRegionQuadTreeNodeLeaf) || !(branch.getSw() instanceof PointRegionQuadTreeNodeLeaf) || !(branch.getSe() instanceof PointRegionQuadTreeNodeLeaf)) {
return branch;
}
PointRegionQuadTreeNodeLeaf<Object> nwLeaf = (PointRegionQuadTreeNodeLeaf<Object>) branch.getNw();
PointRegionQuadTreeNodeLeaf<Object> neLeaf = (PointRegionQuadTreeNodeLeaf<Object>) branch.getNe();
PointRegionQuadTreeNodeLeaf<Object> swLeaf = (PointRegionQuadTreeNodeLeaf<Object>) branch.getSw();
PointRegionQuadTreeNodeLeaf<Object> seLeaf = (PointRegionQuadTreeNodeLeaf<Object>) branch.getSe();
int total = nwLeaf.getCount() + neLeaf.getCount() + swLeaf.getCount() + seLeaf.getCount();
if (total >= tree.getLeafCapacity()) {
return branch;
}
Collection<XYPointWValue<L>> collection = new LinkedList<>();
int count = mergeChildNodes(collection, nwLeaf.getPoints());
count += mergeChildNodes(collection, neLeaf.getPoints());
count += mergeChildNodes(collection, swLeaf.getPoints());
count += mergeChildNodes(collection, seLeaf.getPoints());
return new PointRegionQuadTreeNodeLeaf<>(branch.getBb(), branch.getLevel(), collection, count);
}
private static <L> boolean deleteFromPoints(double x, double y, Object points) {
if (points == null) {
return false;
}
if (!(points instanceof Collection)) {
XYPointWValue<L> point = (XYPointWValue<L>) points;
return point.getX() == x && point.getY() == y;
}
Collection<XYPointWValue<L>> collection = (Collection<XYPointWValue<L>>) points;
Iterator<XYPointWValue<L>> it = collection.iterator();
for (; it.hasNext(); ) {
XYPointWValue<L> point = it.next();
if (point.getX() == x && point.getY() == y) {
it.remove();
return true;
}
}
return false;
}
private static <L> int mergeChildNodes(Collection<XYPointWValue<L>> target, Object points) {
if (points == null) {
return 0;
}
if (points instanceof XYPointWValue) {
XYPointWValue<L> p = (XYPointWValue<L>) points;
target.add(p);
return 1;
}
Collection<XYPointWValue<L>> coll = (Collection<XYPointWValue<L>>) points;
for (XYPointWValue<L> p : coll) {
target.add(p);
}
return coll.size();
}
}