/*
***************************************************************************************
* 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.mxcifrowindex;
import com.espertech.esper.spatial.quadtree.core.QuadrantAppliesEnum;
import com.espertech.esper.spatial.quadtree.mxcif.MXCIFQuadTree;
import com.espertech.esper.spatial.quadtree.mxcif.MXCIFQuadTreeNode;
import com.espertech.esper.spatial.quadtree.mxcif.MXCIFQuadTreeNodeBranch;
import com.espertech.esper.spatial.quadtree.mxcif.MXCIFQuadTreeNodeLeaf;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
public class MXCIFQuadTreeRowIndexRemove {
/**
* Remove value.
*
* @param x x
* @param y y
* @param width width
* @param height height
* @param value value to remove
* @param tree quadtree
*/
public static void remove(double x, double y, double width, double height, Object value, MXCIFQuadTree<Object> tree) {
MXCIFQuadTreeNode<Object> root = tree.getRoot();
MXCIFQuadTreeNode<Object> replacement = removeFromNode(x, y, width, height, value, root, tree);
tree.setRoot(replacement);
}
private static MXCIFQuadTreeNode<Object> removeFromNode(double x, double y, double width, double height, Object value, MXCIFQuadTreeNode<Object> node, MXCIFQuadTree<Object> tree) {
if (node instanceof MXCIFQuadTreeNodeLeaf) {
MXCIFQuadTreeNodeLeaf<Object> leaf = (MXCIFQuadTreeNodeLeaf<Object>) node;
boolean removed = removeFromPoints(x, y, width, height, value, leaf.getData());
if (removed) {
leaf.decCount();
if (leaf.getCount() == 0) {
leaf.setData(null);
}
}
return leaf;
}
MXCIFQuadTreeNodeBranch<Object> branch = (MXCIFQuadTreeNodeBranch<Object>) node;
QuadrantAppliesEnum quadrant = node.getBb().getQuadrantApplies(x, y, width, height);
if (quadrant == QuadrantAppliesEnum.NW) {
branch.setNw(removeFromNode(x, y, width, height, value, branch.getNw(), tree));
} else if (quadrant == QuadrantAppliesEnum.NE) {
branch.setNe(removeFromNode(x, y, width, height, value, branch.getNe(), tree));
} else if (quadrant == QuadrantAppliesEnum.SW) {
branch.setSw(removeFromNode(x, y, width, height, value, branch.getSw(), tree));
} else if (quadrant == QuadrantAppliesEnum.SE) {
branch.setSe(removeFromNode(x, y, width, height, value, branch.getSe(), tree));
} else if (quadrant == QuadrantAppliesEnum.SOME) {
boolean removed = removeFromPoints(x, y, width, height, value, branch.getData());
if (removed) {
branch.decCount();
if (branch.getCount() == 0) {
branch.setData(null);
}
}
}
if (!(branch.getNw() instanceof MXCIFQuadTreeNodeLeaf) || !(branch.getNe() instanceof MXCIFQuadTreeNodeLeaf) || !(branch.getSw() instanceof MXCIFQuadTreeNodeLeaf) || !(branch.getSe() instanceof MXCIFQuadTreeNodeLeaf)) {
return branch;
}
MXCIFQuadTreeNodeLeaf<Object> nwLeaf = (MXCIFQuadTreeNodeLeaf<Object>) branch.getNw();
MXCIFQuadTreeNodeLeaf<Object> neLeaf = (MXCIFQuadTreeNodeLeaf<Object>) branch.getNe();
MXCIFQuadTreeNodeLeaf<Object> swLeaf = (MXCIFQuadTreeNodeLeaf<Object>) branch.getSw();
MXCIFQuadTreeNodeLeaf<Object> seLeaf = (MXCIFQuadTreeNodeLeaf<Object>) branch.getSe();
int total = branch.getCount() + nwLeaf.getCount() + neLeaf.getCount() + swLeaf.getCount() + seLeaf.getCount();
if (total >= tree.getLeafCapacity()) {
return branch;
}
Collection<XYWHRectangleMultiType> collection = new LinkedList<>();
int count = mergeChildNodes(collection, branch.getData());
count += mergeChildNodes(collection, nwLeaf.getData());
count += mergeChildNodes(collection, neLeaf.getData());
count += mergeChildNodes(collection, swLeaf.getData());
count += mergeChildNodes(collection, seLeaf.getData());
return new MXCIFQuadTreeNodeLeaf<>(branch.getBb(), branch.getLevel(), collection, count);
}
private static boolean removeFromPoints(double x, double y, double width, double height, Object value, Object data) {
if (data == null) {
return false;
}
if (!(data instanceof Collection)) {
XYWHRectangleMultiType rectangle = (XYWHRectangleMultiType) data;
if (rectangle.coordinateEquals(x, y, width, height)) {
boolean removed = rectangle.remove(value);
if (removed) {
return true;
}
}
return false;
}
Collection<XYWHRectangleMultiType> collection = (Collection<XYWHRectangleMultiType>) data;
Iterator<XYWHRectangleMultiType> it = collection.iterator();
for (; it.hasNext(); ) {
XYWHRectangleMultiType rectangle = it.next();
if (rectangle.coordinateEquals(x, y, width, height)) {
boolean removed = rectangle.remove(value);
if (removed) {
if (rectangle.isEmpty()) {
it.remove();
}
return true;
}
}
}
return false;
}
private static int mergeChildNodes(Collection<XYWHRectangleMultiType> target, Object data) {
if (data == null) {
return 0;
}
if (data instanceof XYWHRectangleMultiType) {
XYWHRectangleMultiType r = (XYWHRectangleMultiType) data;
target.add(r);
return r.count();
}
Collection<XYWHRectangleMultiType> coll = (Collection<XYWHRectangleMultiType>) data;
int total = 0;
for (XYWHRectangleMultiType r : coll) {
target.add(r);
total += r.count();
}
return total;
}
}