use of de.fhg.igd.geom.Localizable in project hale by halestudio.
the class Node method split.
/**
* Splits this node into two nodes and adds them to the parent node.
* (Quadratic Split)
*
* @return the new second Node
*/
private Node<T> split() {
// choose two entries to be the first
// elements of the groups
Localizable[] seeds = pickSeeds();
// calculate minimum fill factor
int minSize = calculateMinSize();
// save this._children
List<Localizable> children = _children;
// assign each entry to a new Node
// this node will be group 0
Node<T> group0 = this;
_boundingBox = new BoundingBox();
_children = new ArrayList<Localizable>(_pageSize);
group0.plainAdd(seeds[0]);
Node<T> group1 = new Node<T>(_pageSize, this, _tree);
group1._isLeaf = this.isLeaf();
group1.plainAdd(seeds[1]);
// add next entries until nothing is left
while (children.size() > 0) {
// add all remaining entries to it
if (minSize - group0._children.size() == children.size()) {
for (Localizable c : children) {
group0.plainAdd(c);
}
break;
} else if (minSize - group1._children.size() == children.size()) {
for (Localizable c : children) {
group1.plainAdd(c);
}
break;
}
Localizable next = null;
double min = Double.NEGATIVE_INFINITY;
double dd0 = 0.0, dd1 = 0.0;
int ii = -1;
// the least cost
for (int i = 0; i < children.size(); ++i) {
Localizable l = children.get(i);
BoundingBox eb = l.getBoundingBox();
// calculate how much group 0 had to be extended if
// we would add the child to it
BoundingBox bb = new BoundingBox(group0.getBoundingBox());
bb.add(eb);
double d0 = calcPseudoVolume(bb) - calcPseudoVolume(group0);
// calculate the same for group 2
bb = new BoundingBox(group1.getBoundingBox());
bb.add(eb);
double d1 = calcPseudoVolume(bb) - calcPseudoVolume(group1);
// calculate the least cost
double diff = Math.abs(d1 - d0);
if (diff > min) {
next = l;
ii = i;
min = diff;
// remember the cost
dd0 = d0;
dd1 = d1;
}
}
// we must have a next entity now
assert next != null;
// remove entry from the list of Localizables
children.remove(ii);
// add result to one of the groups
if (dd0 < dd1) {
group0.plainAdd(next);
} else if (dd1 < dd0) {
group1.plainAdd(next);
} else {
double a0 = calcPseudoVolume(group0);
double a1 = calcPseudoVolume(group1);
if (a0 < a1) {
group0.plainAdd(next);
} else if (a1 < a0) {
group1.plainAdd(next);
} else {
if (group1._children.size() < group0._children.size()) {
group1.plainAdd(next);
} else {
group0.plainAdd(next);
}
}
}
}
return group1;
}
use of de.fhg.igd.geom.Localizable in project hale by halestudio.
the class Node method chooseLeaf.
/**
* Select a leaf node in which to place a new index entry.
*
* @param loc the localizable to find a leaf for
* @return the leaf node
*/
@SuppressWarnings({ "unchecked", "null" })
private Node<T> chooseLeaf(final Localizable loc) {
// if this is a leaf, return this
if (this.isLeaf()) {
return this;
}
// we're a node, so there must be children
assert _children != null;
// Guttman: find the smallest enlargement and find the
// bounding box with the smallest volume
double max = Double.POSITIVE_INFINITY;
Node<T> child = null;
for (Localizable l : _children) {
// l must be a Node, because this is no leaf (see above)
assert l instanceof Node;
Node<T> n = (Node<T>) l;
// calculate enlargement
BoundingBox larger = new BoundingBox(n.getBoundingBox());
larger.add(loc.getBoundingBox());
double nvolume = calcPseudoVolume(n);
double enlargement = calcPseudoVolume(larger) - nvolume;
if (enlargement < max) {
// use the one with the smallest enlargement
max = enlargement;
child = n;
} else if (enlargement < max + 0.000001) {
// always be set to n
assert child != null;
// use the one with the smallest volume
if (nvolume < calcPseudoVolume(child)) {
child = n;
}
}
}
// because there's always at least one child
assert child != null;
// descend
return child.chooseLeaf(loc);
}
use of de.fhg.igd.geom.Localizable in project hale by halestudio.
the class Node method condenseTree.
/**
* Eliminate l if it has too few entries. Propagate elimination upwards.
* Adjust BoundingBoxes.
*
* @param l the Leaf from which an entry has been deleted
*/
@SuppressWarnings("unchecked")
private void condenseTree(Node<T> l) {
// the list of deleted nodes
List<Node<T>> q = new ArrayList<Node<T>>();
Node<T> n = l;
while (n._parent != null) {
// eliminate under-full node
int minSize = calculateMinSize();
if (n._children.size() < minSize) {
n._parent._children.remove(n);
q.add(n);
} else {
// adjust BoundingBox of n (the element from which an
// entry has been deleted)
n._boundingBox = new BoundingBox();
for (Localizable c : n._children) {
n._boundingBox.add(c.getBoundingBox());
}
}
n = n._parent;
}
// adjust the bounding box of the root
n._boundingBox = new BoundingBox();
for (Localizable c : n._children) {
n._boundingBox.add(c.getBoundingBox());
}
// re-insert orphaned entries
for (Node<T> no : q) {
if (no.isLeaf()) {
// re-insert the leaf's children as usual
for (Localizable c : no.getChildren()) {
_tree.insert((T) c);
}
} else {
// insert the children of all leafs we can
// find in "no"
insertChildrenOfAllLeafs(no, _tree);
}
}
}
use of de.fhg.igd.geom.Localizable in project hale by halestudio.
the class Node method pickSeeds.
/**
* Finds the first entries of two splitted groups (Quadratic Split)
*
* @return the two entries
*/
private Localizable[] pickSeeds() {
Localizable[] result = new Localizable[2];
int ii = -1, jj = -1;
double min = Double.NEGATIVE_INFINITY;
for (int i = 0; i < _children.size() - 1; ++i) {
for (int j = i + 1; j < _children.size(); ++j) {
Localizable e1 = _children.get(i);
Localizable e2 = _children.get(j);
// compose a new bounding box
BoundingBox bb = new BoundingBox(e1.getBoundingBox());
bb.add(e2.getBoundingBox());
// calculate waste
double d = calcPseudoVolume(bb) - calcPseudoVolume(e1) - calcPseudoVolume(e2);
if (d > min) {
result[0] = e1;
ii = i;
result[1] = e2;
jj = j;
min = d;
}
}
}
// result must not be empty
assert result[0] != null;
assert result[1] != null;
// remove entries from the list of Localizables
// make sure that we remove the correct element jj if
// ii has been removed before
_children.remove(ii);
_children.remove(ii < jj ? jj - 1 : jj);
return result;
}
use of de.fhg.igd.geom.Localizable in project hale by halestudio.
the class Node method find.
/**
* Returns a list of all Localizables that have any relation to the given
* Localizable loc.
*
* @param loc the Localizable to match
* @param ignoreZ true if the z coordinate should be ignored during
* candidate search
* @return a list of Localizables (containing only leafs of this tree and no
* nodes)
*/
@SuppressWarnings("unchecked")
private List<T> find(final Localizable loc, boolean ignoreZ) {
List<T> result = new ArrayList<T>();
BoundingBox theirs = loc.getBoundingBox();
for (Localizable l : _children) {
BoundingBox ours = l.getBoundingBox();
if (relate(ours, theirs, ignoreZ)) {
if (l instanceof Node) {
// descend
result.addAll(((Node<T>) l).find(loc, ignoreZ));
} else {
// add leaf
result.add((T) l);
}
}
}
return result;
}
Aggregations