/* XXL: The eXtensible and fleXible Library for data processing
Copyright (C) 2000-2013 Prof. Dr. Bernhard Seeger
Head of the Database Research Group
Department of Mathematics and Computer Science
University of Marburg
Germany
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; If not, see <http://www.gnu.org/licenses/>.
http://code.google.com/p/xxl/
*/
package xxl.core.spatial;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import xxl.core.collections.MapEntry;
import xxl.core.collections.containers.CounterContainer;
import xxl.core.cursors.Cursor;
import xxl.core.cursors.Cursors;
import xxl.core.cursors.mappers.Mapper;
import xxl.core.cursors.sources.io.FileInputCursor;
import xxl.core.functions.AbstractFunction;
import xxl.core.functions.Function;
import xxl.core.functions.Functional.UnaryFunction;
import xxl.core.indexStructures.ORTree;
import xxl.core.indexStructures.ORTree.IndexEntry;
import xxl.core.indexStructures.RTree;
import xxl.core.indexStructures.RTree.Node;
import xxl.core.io.converters.ConvertableConverter;
import xxl.core.spatial.histograms.utils.STHist;
import xxl.core.spatial.histograms.utils.SpatialHistogramBucket;
import xxl.core.spatial.histograms.utils.STHist.STHistBucket;
import xxl.core.spatial.points.DoublePoint;
import xxl.core.spatial.rectangles.DoublePointRectangle;
/**
*
*
*
* helper class for spatial histograms
*
*/
public class SpatialUtils {
/**
* factory funtcion for convertable converter
*/
public static final Function<Object, DoublePointRectangle> factoryFunction(final int dimension){
return new AbstractFunction<Object, DoublePointRectangle>() {
public DoublePointRectangle invoke() {
return new DoublePointRectangle(dimension);
}
};
}
/**
*
*/
public static SpatialHistogramBucket universeUnit(final int dimension) {
double[] lft = new double[dimension];
double[] rgt = new double[dimension];
for(int i = 0; i < dimension; i++){
lft[i] = 0;
rgt[i] = 1;
}
return new SpatialHistogramBucket(
lft, rgt);
}
public static List<SpatialHistogramBucket> readHistogram(String path, final int dimension){
FileInputCursor<SpatialHistogramBucket> rectangles = new FileInputCursor<>(new ConvertableConverter<>(new AbstractFunction<Object, SpatialHistogramBucket>() {
@Override
public SpatialHistogramBucket invoke() {
return new SpatialHistogramBucket(dimension);
}
}), new File(path));
List<SpatialHistogramBucket> histogram = new LinkedList<>();
while(rectangles.hasNext()){
histogram.add(rectangles.next());
}
return histogram;
}
public static void writeHistogram(List<SpatialHistogramBucket> histogram, String path) throws IOException{
DataOutputStream out = new DataOutputStream(new FileOutputStream(new File(path)));
for(SpatialHistogramBucket rec: histogram)
rec.write(out);
out.close();
}
/**
* computes simple histogram
* @param tree
* @param numberOfBuckets
* @return
*/
public static List<SpatialHistogramBucket> computeSimpleRTreeHistogram(RTree tree, int numberOfBuckets){
List<SpatialHistogramBucket> histogram = new ArrayList<SpatialHistogramBucket>(numberOfBuckets);
int numberOfNodes = Cursors.count(tree.query(1));
int hyperBucketSize = numberOfNodes/(numberOfBuckets) + 1; // remain part will be assigned to the last bucket
Cursor<MapEntry<DoublePointRectangle, RTree.Node>> nodes = getNodesAndMBRs(tree, 1);
for(;nodes.hasNext();){
int sum = 0;
SpatialHistogramBucket uni = null;
for(int i = 0; i < hyperBucketSize && nodes.hasNext(); i++){
MapEntry<DoublePointRectangle, RTree.Node> entry = nodes.next();
sum += entry.getValue().number();
if(uni == null){
uni = new SpatialHistogramBucket(entry.getKey());
}else{
uni.union(entry.getKey());
}
// compute avg
Iterator it = entry.getValue().entries();
while(it.hasNext()){
DoublePointRectangle rec = (DoublePointRectangle) tree.descriptor(it.next());
uni.updateAverage(rec);
}
}
uni.setWeight(sum);
histogram.add(uni);
}
if (histogram.size() > numberOfBuckets){ // one bucket more
SpatialHistogramBucket recF = histogram.get(histogram.size()-2);
recF.union(histogram.get(histogram.size()-1));
recF.setWeight(recF.getWeight()+histogram.get(histogram.size()-1).getWeight() );
histogram.remove(histogram.size()-1);
}
return histogram;
}
/**
* Note: RTree manages weighted rectangles @see {@link SpatialHistogramBucket}
* @param tree
* @param queryWindow
* @return
*/
@SuppressWarnings("rawtypes")
public static double computeEstimation(RTree tree, DoublePointRectangle queryWindow, int level){
if (tree.height() < level)
throw new RuntimeException("Check level");
double costs = 0d;
Cursor cursor = tree.query(queryWindow, level);
while(cursor.hasNext()){
Object result = cursor.next();
SpatialHistogramBucket rectangle = (SpatialHistogramBucket)( (level > 0) ?
((ORTree.IndexEntry) result).descriptor() :
result);
double overlap = rectangle.overlap(queryWindow)/ rectangle.area();
double localSel = overlap*rectangle.getWeight();
costs += localSel;
}
return costs;
}
/**
* Note: RTree manages weighted rectangles @see {@link SpatialHistogramBucket}
* @param tree
* @param queryWindow
* @return
*/
public static double computeEstimation(Iterator<SpatialHistogramBucket> histogram, DoublePointRectangle queryWindow){
double costs = 0d;
while(histogram.hasNext()){
SpatialHistogramBucket rectangle = histogram.next();
// extend rectnagles
if (rectangle.overlaps(queryWindow)){
DoublePointRectangle deltass = new DoublePointRectangle(rectangle);
deltass.intersect(queryWindow);
// compute left point
double[] leftR= (double[]) rectangle.getCorner(false).getPoint();
double[] rightR= (double[]) rectangle.getCorner(true).getPoint();
double[] left = (double[]) deltass.getCorner(false).getPoint();
double[] right = (double[]) deltass.getCorner(true).getPoint();
for(int i = 0; i <left.length; i++){
// low point
left[i] = ((left[i]-rectangle.getExtent()[i]) < leftR[i])? leftR[i] : (left[i]-rectangle.getExtent()[i]);
right[i] = ((right[i]+rectangle.getExtent()[i]) > rightR[i])? rightR[i] : (right[i]+rectangle.getExtent()[i]);
}
deltass = new DoublePointRectangle(left, right);
// for(int i = 0; i < rectangle.dimensions(); i++){
// area *= deltass.deltas()[i]; // + rectangle.getExtent()[i];
// }
double overlap = deltass.area()/rectangle.area();
double localSel = overlap*rectangle.getWeight();
costs += localSel;
}
// double overlap = rectangle.overlap(queryWindow)/ rectangle.area();
// double localSel = overlap*rectangle.getWeight();
// costs += localSel;
}
return costs;
}
public static int numberOfResults(RTree rtree, DoublePointRectangle queryRec){
return Cursors.count(rtree.query(queryRec));
}
/**
* Computes SSE distance based
*
* @param recs
* @param lp
* @return
*/
public static double computeSSEDist(DoublePointRectangle[] recs, int lp){
double[] dists = new double[recs.length];
double cost = 0;
double sum = 0;
for(int i = 0; i < recs.length; i++ ){
DoublePointRectangle rec = recs[i];
double dist = Double.MAX_VALUE;
for(int j = 0; j < recs.length; j++ ){
if (j != i){
double computedDist = recs[j].distance(rec, lp);
if(computedDist < dist )
dist = computedDist;
}
}
sum +=dist;
dists[i] = dist;
}
double avg = sum/recs.length;
for(double d : dists){
cost += Math.pow((d-avg), 2);
}
return cost;
}
/*
* extractes nodes from rtree
*/
@SuppressWarnings({ "serial", "unchecked" })
public static Cursor<RTree.Node> getNodes(RTree tree, int level){
if(level > tree.height() || level == 0)
throw new RuntimeException("check the level");
return new Mapper<Object, RTree.Node>(new AbstractFunction<Object, RTree.Node>() {
public RTree.Node invoke(Object argument){
//cast to ORTree.indexEntry
ORTree.IndexEntry entry = (ORTree.IndexEntry) argument;
RTree.Node node = (RTree.Node)entry.get();
return node;
}
}, tree.query(level));
}
/*
* extractes nodes from rtree
*/
@SuppressWarnings({ "serial", "unchecked" })
public static Cursor<SpatialHistogramBucket> getRectangles(final RTree tree, final int level){
if(level > tree.height())
throw new RuntimeException("check the level");
return new Mapper<Object, SpatialHistogramBucket>(new AbstractFunction<Object, SpatialHistogramBucket>() {
public SpatialHistogramBucket invoke(Object argument){
//cast to ORTree.indexEntry
// get entry
return new SpatialHistogramBucket((DoublePointRectangle)tree.descriptor(argument));
}
}, tree.query(level));
}
/*
* extractes nodes from rtree
*/
@SuppressWarnings({ "serial", "unchecked" })
public static Cursor<SpatialHistogramBucket> getRectanglesLevel1(final RTree tree){
return new Mapper<Object, SpatialHistogramBucket>(new AbstractFunction<Object, SpatialHistogramBucket>() {
public SpatialHistogramBucket invoke(Object argument){
//cast to ORTree.indexEntry
// get entry
RTree.Node node = (Node) ((IndexEntry)argument).get();
SpatialHistogramBucket rectangle = new SpatialHistogramBucket((DoublePointRectangle)tree.descriptor(argument), node.number());
Iterator it = node.entries();
while(it.hasNext()){
DoublePointRectangle rec = (DoublePointRectangle) tree.descriptor(it.next());
rectangle.updateAverage(rec);
}
return rectangle;
}
}, tree.query(1));
}
/*
* extractes nodes from rtree
*/
@SuppressWarnings({ "serial", "unchecked" })
public static Cursor<MapEntry<DoublePointRectangle, RTree.Node>> getNodesAndMBRs(RTree tree, int level){
if(level > tree.height() || level == 0)
throw new RuntimeException("check the level");
return new Mapper<Object, MapEntry<DoublePointRectangle, RTree.Node>>(new AbstractFunction<Object, MapEntry<DoublePointRectangle, RTree.Node>>() {
public MapEntry<DoublePointRectangle, RTree.Node> invoke(Object argument){
//cast to ORTree.indexEntry
ORTree.IndexEntry entry = (ORTree.IndexEntry) argument;
RTree.Node node = (RTree.Node)entry.get();
return new MapEntry<DoublePointRectangle, RTree.Node>((DoublePointRectangle)entry.descriptor(), node);
}
}, tree.query(level));
}
/*
* extractes nodes from rtree
*/
@SuppressWarnings({ "serial", "unchecked" })
public static Cursor<MapEntry<DoublePointRectangle, ORTree.IndexEntry>> getIndexEntriesAndMBRs(RTree tree, int level){
if(level > tree.height() || level == 0)
throw new RuntimeException("check the level");
return new Mapper<Object, MapEntry<DoublePointRectangle, ORTree.IndexEntry>>(new AbstractFunction<Object, MapEntry<DoublePointRectangle,ORTree.IndexEntry>>() {
public MapEntry<DoublePointRectangle,ORTree.IndexEntry> invoke(Object argument){
//cast to ORTree.indexEntry
ORTree.IndexEntry entry = (ORTree.IndexEntry) argument;
RTree.Node node = (RTree.Node)entry.get();
return new MapEntry<DoublePointRectangle,ORTree.IndexEntry>((DoublePointRectangle)entry.descriptor(), entry);
}
}, tree.query(level));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public static Comparator<DoublePointRectangle> getHilbert2DComparator(final DoublePointRectangle universe,
final int FILLING_CURVE_PRECISION ){
return (Comparator<DoublePointRectangle>) new Comparator() {
protected double uni[];
protected double uniDeltas[];
public int compare(Object o1, Object o2) {
if (uni == null) {
uni = (double[]) universe.getCorner(false).getPoint();
uniDeltas = universe.deltas();
}
double leftBorders1[] = (double[])
((DoublePointRectangle) o1).getCenter().getPoint();
double leftBorders2[] = (double[])
((DoublePointRectangle) o2).getCenter().getPoint();
double x1 = (leftBorders1[0] - uni[0]) / uniDeltas[0];
double y1 = (leftBorders1[1] - uni[1]) / uniDeltas[1];
double x2 = (leftBorders2[0] - uni[0]) / uniDeltas[0];
double y2 = (leftBorders2[1] - uni[1]) / uniDeltas[1];
long h1 = SpaceFillingCurves.hilbert2d(
(int) (x1 * FILLING_CURVE_PRECISION),
(int) (y1 * FILLING_CURVE_PRECISION));
long h2 = SpaceFillingCurves.hilbert2d(
(int) (x2 * FILLING_CURVE_PRECISION),
(int) (y2 * FILLING_CURVE_PRECISION));
return (h1 < h2) ? -1 : ((h1 == h2) ? 0 : +1);
}
};
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public static Comparator<DoublePointRectangle> getZCurve2DComparator(final DoublePointRectangle universe,
final int FILLING_CURVE_PRECISION){
return new Comparator() {
protected double uni[];
protected double uniDeltas[];
public int compare(Object o1, Object o2) {
if (uni == null) {
uni = (double[]) universe.getCorner(false).getPoint();
uniDeltas = universe.deltas();
}
double leftBorders1[] = (double[])
((DoublePointRectangle) o1).getCenter().getPoint();
double leftBorders2[] = (double[])
((DoublePointRectangle) o2).getCenter().getPoint();
double x1 = (leftBorders1[0] - uni[0]) / uniDeltas[0];
double y1 = (leftBorders1[1] - uni[1]) / uniDeltas[1];
double x2 = (leftBorders2[0] - uni[0]) / uniDeltas[0];
double y2 = (leftBorders2[1] - uni[1]) / uniDeltas[1];
long h1 = SpaceFillingCurves.peano2d(
(int) (x1 * FILLING_CURVE_PRECISION),
(int) (y1 * FILLING_CURVE_PRECISION));
long h2 = SpaceFillingCurves.peano2d(
(int) (x2 * FILLING_CURVE_PRECISION),
(int) (y2 * FILLING_CURVE_PRECISION));
return (h1 < h2) ? -1 : ((h1 == h2) ? 0 : 1);
}
};
}
/**
* Mapping function for Hilbert
*/
public static UnaryFunction<DoublePointRectangle, Long> hilbert2dSFC(final DoublePointRectangle universe,
final int FILLING_CURVE_PRECISION){
return new UnaryFunction<DoublePointRectangle, Long>() {
protected double uni[];
protected double uniDeltas[];
@Override
public Long invoke(DoublePointRectangle arg) {
if (uni == null) {
uni = (double[]) universe.getCorner(false).getPoint();
uniDeltas = universe.deltas();
}
double leftBorders[] = (double[])
((DoublePointRectangle) arg).getCenter().getPoint();
double x1 = (leftBorders[0] - uni[0]) / uniDeltas[0];
double y1 = (leftBorders[1] - uni[1]) / uniDeltas[1];
long h1 = SpaceFillingCurves.hilbert2d(
(int) (x1 * FILLING_CURVE_PRECISION),
(int) (y1 * FILLING_CURVE_PRECISION));
return h1;
}
};
}
/**
* Mapping function for Hilbert
*/
public static UnaryFunction<DoublePointRectangle, Long> zCruveSFC(final DoublePointRectangle universe,
final int BITS_PRO_DIM){
final int FILLING_CURVE_PRECISION = 1 << (BITS_PRO_DIM - 1);
return new UnaryFunction<DoublePointRectangle, Long>() {
protected double uni[];
protected double uniDeltas[];
@Override
public Long invoke(DoublePointRectangle arg) {
if (uni == null) {
uni = (double[]) universe.getCorner(false).getPoint();
uniDeltas = universe.deltas();
}
double[] center1 = (double[]) ((DoublePointRectangle) arg).getCenter().getPoint();
double[] normCenter1 = normalize(center1, uni, uniDeltas);
int[] coord1 = new int[normCenter1.length];
for(int i = 0; i < coord1.length; i++){
coord1[i] = (int) (normCenter1[i] * (FILLING_CURVE_PRECISION));
}
long h1 = SpaceFillingCurves.computeZCode(coord1, BITS_PRO_DIM);
return h1;
}
};
}
@SuppressWarnings("unchecked")
public static Comparator<DoublePointRectangle> getZCurveComparator(final DoublePointRectangle universe, final int BITS_PRO_DIM){
final int FILLING_CURVE_PRECISION = 1 << (BITS_PRO_DIM - 1);
return new Comparator() {
protected double uni[];
protected double uniDeltas[];
public int compare(Object o1, Object o2) {
if (uni == null) {
uni = (double[])universe.getCorner(false).getPoint();
uniDeltas = universe.deltas();
}
double center1[] = (double[])((DoublePointRectangle)o1).getCenter().getPoint();
double center2[] =(double[])((DoublePointRectangle)o2).getCenter().getPoint();
double[] normCenter1 = normalize(center1, uni, uniDeltas);
double[] normCenter2 = normalize(center2, uni, uniDeltas);
int[] coord1 = new int[normCenter1.length];
int[] coord2 = new int[normCenter1.length];
for(int i = 0; i < coord1.length; i++){
coord1[i] = (int) (normCenter1[i] * (FILLING_CURVE_PRECISION));
coord2[i] = (int) (normCenter2[i] * (FILLING_CURVE_PRECISION));
}
long h1 = SpaceFillingCurves.computeZCode(coord1, BITS_PRO_DIM);
long h2 = SpaceFillingCurves.computeZCode(coord2, BITS_PRO_DIM);
return (h1<h2)?-1: ((h1==h2)?0:+1);
}
};
}
@SuppressWarnings("unchecked")
public static Comparator<DoublePoint> getZCurvePointComparator(final DoublePointRectangle universe, final int BITS_PRO_DIM){
final int FILLING_CURVE_PRECISION = 1 << (BITS_PRO_DIM - 1);
return new Comparator() {
protected double uni[];
protected double uniDeltas[];
public int compare(Object o1, Object o2) {
if (uni == null) {
uni = (double[])universe.getCorner(false).getPoint();
uniDeltas = universe.deltas();
}
double center1[] =(double[])((DoublePointRectangle)o1).getCenter().getPoint();
double center2[] = (double[])((DoublePointRectangle)o2).getCenter().getPoint();
double[] normCenter1 = normalize(center1, uni, uniDeltas);
double[] normCenter2 = normalize(center2, uni, uniDeltas);
int[] coord1 = new int[normCenter1.length];
int[] coord2 = new int[normCenter1.length];
for(int i = 0; i < coord1.length; i++){
coord1[i] = (int) (normCenter1[i] * (FILLING_CURVE_PRECISION));
coord2[i] = (int) (normCenter2[i] * (FILLING_CURVE_PRECISION));
}
long h1 = SpaceFillingCurves.computeZCode(coord1, BITS_PRO_DIM);
long h2 = SpaceFillingCurves.computeZCode(coord2, BITS_PRO_DIM);
return (h1<h2)?-1: ((h1==h2)?0:+1);
}
};
}
public static UnaryFunction<DoublePointRectangle, Long> sfcZCurve2DFunction(final DoublePointRectangle universe,
final int FILLING_CURVE_PRECISION){
return new UnaryFunction<DoublePointRectangle, Long>() {
protected double uni[];
protected double uniDeltas[];
@Override
public Long invoke(DoublePointRectangle arg) {
if (uni == null) {
uni = (double[]) universe.getCorner(false).getPoint();
uniDeltas = universe.deltas();
}
double leftBorders[] = (double[])
((DoublePointRectangle) arg).getCenter().getPoint();
double x1 = (leftBorders[0] - uni[0]) / uniDeltas[0];
double y1 = (leftBorders[1] - uni[1]) / uniDeltas[1];
long h1 = SpaceFillingCurves.peano2d(
(int) (x1 * FILLING_CURVE_PRECISION),
(int) (y1 * FILLING_CURVE_PRECISION));
return h1;
}
};
}
/**
*
* @param point
* @param uni
* @param unideltas
* @return
*/
public static double[] normalize(double[] point, double[] uni, double[] unideltas){
double[] normPoint = new double[point.length];
for(int i = 0; i < normPoint.length; i++){
normPoint[i] = (point[i] - uni[i])/unideltas[i];
}
return normPoint;
}
/**
*
* @param recs
* @param dimension
* @param universe
* @return
*/
public static double[] computeQuerySides(Iterator<DoublePointRectangle> recs, int dimension,
DoublePointRectangle universe){
double[] querySides = new double[dimension];
int counter = 0;
while(recs.hasNext()){
DoublePointRectangle rec = recs.next();
double[] deltas = rec.deltas();
for (int i = 0; i < dimension; i++){
querySides[i] += deltas[i];
}
counter++;
}
for(int i = 0; i < dimension; i++ ){
querySides[i] /= (double)counter;
}
return querySides;
}
public static DoublePointRectangle computeUniverse(Iterator<DoublePointRectangle> rectangles){
DoublePointRectangle universe = null;
while(rectangles.hasNext()){
DoublePointRectangle item = rectangles.next();
if (universe == null)
universe = new DoublePointRectangle(item);
else
universe.union(item);
}
return universe;
}
/**
* computes average absolut error
* @param rtree
* @param queryIn
* @param histogram
*/
public static void estimationTest(RTree rtree, Iterator<DoublePointRectangle> queryIn,List<SpatialHistogramBucket> histogram){
double sumDiff =0;
int count = 0;
double error = 0;
double avgerror = 0;
double max = Double.MIN_VALUE;
double min = Double.MAX_VALUE;
while(queryIn.hasNext()){
DoublePointRectangle queryRec = queryIn.next();
double actualCount = Cursors.count(rtree.query(queryRec));
double estimation = 0;
double diff = 0;
if(histogram != null){
estimation = SpatialUtils.computeEstimation(histogram.iterator(), queryRec);
}else{
estimation = SpatialUtils.computeEstimation(rtree, queryRec, 1);
}
diff = Math.abs(actualCount-estimation);
avgerror += diff/(Math.max(1, actualCount));
count++;
sumDiff +=diff;
if (diff> max)
max = diff;
if (diff < min)
min = diff;
}
error = sumDiff/count;
System.out.println("Estimation Average Relative Error: " + avgerror/count);
System.out.println("Estimation Average Absolut Error: " + error);
System.out.println("Buckets Considered: " + histogram.size());
System.out.println("Max: " + max);
System.out.println("Min: " + min);
System.out.println("Queries issued: " + count);
}
public static void estimationTestSTHist(RTree rtree, Iterator<DoublePointRectangle> queryIn, List<STHist.STHistBucket> histogram ){
double sumDiff =0;
int count = 0;
double error = 0;
double avgerror = 0;
double max = Double.MIN_VALUE;
double min = Double.MAX_VALUE;
while(queryIn.hasNext()){
DoublePointRectangle queryRec = queryIn.next();
double actualCount = Cursors.count(rtree.query(queryRec));
double estimation = 0;
double diff = 0;
estimation = STHist.getSelectivity(histogram, queryRec);
diff = Math.abs(actualCount-estimation);
avgerror += diff/(Math.max(1, actualCount));
count++;
sumDiff +=diff;
if (diff> max)
max = diff;
if (diff < min)
min = diff;
}
error = sumDiff/count;
System.out.println("Estimation Average Relative Error: " + avgerror/count);
System.out.println("Estimation Average Absolut Error: " + error);
System.out.println("Buckets Considered: " + histogram.size());
System.out.println("Max: " + max);
System.out.println("Min: " + min);
System.out.println("Queries issued: " + count);
}
public static void queryCheck(Iterator<DoublePointRectangle> queries, RTree tree, CounterContainer counterC, double[] querySideLength){
int overallIO = 0;
int counter = 0;
counterC.reset();
int overallCandidates =0;
int leafsOverall = 0;
while(queries.hasNext() ){
DoublePointRectangle queryRec = queries.next();
Iterator<DoublePointRectangle> result = tree.query(queryRec);
int resultCounter = Cursors.count(result);
int leafs = tree.leafsTouched;
leafsOverall += leafs;
overallCandidates += resultCounter;
counter++;
overallIO += counterC.gets;
counterC.reset();
}
// gather statistic abpout first level
if(tree.height() > 0){
double volumeSum = 0;
double volumeExtended = 0;
Cursor levelCursor = tree.query(1);
while(levelCursor.hasNext() ){
DoublePointRectangle descriptor =
(DoublePointRectangle) (((IndexEntry) levelCursor.next()).descriptor());
volumeSum +=descriptor.area();
double[] sides = descriptor.deltas();
double extV = 1;
for(int i = 0; i < sides.length; i++){
extV *=(sides[i]+querySideLength[i]);
}
volumeExtended+=extV;
}
System.out.println("Sum. Volume Costs: " + volumeSum);
System.out.println("Sum. Ext Volume Costs: " + volumeExtended);
}
// gather costs per
System.out.println("Tree height: " + tree.height());
System.out.println("Overall IOs " + overallIO);
System.out.println("Overall Leafs " + leafsOverall);
System.out.println("Queries issued " + counter );
double ov = (double)overallIO;
double cn = (double)counter;
System.out.println("Avg IO pro Query " + (ov/cn));
System.out.println("Sum Results " + (overallCandidates));
System.out.println("Avg Results pro Query " + (overallCandidates/counter));
}
}