/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2007-2008, Open Source Geospatial Foundation (OSGeo)
*
* 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;
* version 2.1 of the License.
*
* 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.
*/
package org.geotools.caching.spatialindex;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import junit.framework.TestCase;
/** A common test framework for spatial indexes.
* Creates a random 2-D data set in the unit square.
* Concrete tests must implement the createIndex method :
* <code>
* TypeOfIndex index ;
* protected AbstractSpatialIndex createIndex() {
* index = new TypeOfIndex() ;
* return index ;
* }
* </code>
*
* @author Christophe Rousson, SoC 2007, CRG-ULAVAL
*
*
*
*
* @source $URL$
*/
public abstract class AbstractSpatialIndexTest extends TestCase {
private static final String DATA_PREFIX = "Object: ";
protected AbstractSpatialIndex index;
int setSize = 1000;
protected ArrayList<Region> regions = new ArrayList<Region>(setSize);
protected Random generator = new Random();
protected Region universe = new Region(new double[] { 0, 0 }, new double[] { 1, 1 });
protected double meansize = 0.01;
protected void setUp() {
index = createIndex();
regions = new ArrayList<Region>(setSize);
double width = universe.getHigh(0) - universe.getLow(0);
double height = universe.getHigh(1) - universe.getLow(1);
//validate all nodes as data is only inserted into validated nodes
for (int i = 0; i < index.rootNode.getChildrenCount(); i ++){
NodeIdentifier child = index.rootNode.getChildIdentifier(i);
child.setValid(true);
}
for (int i = 0; i < setSize; i++) {
double centerx = (meansize) + (generator.nextDouble() * (width - (2 * meansize)));
double centery = (meansize) + (generator.nextDouble() * (height - (2 * meansize)));
double h = generator.nextDouble() * meansize * 2;
double w = generator.nextDouble() * meansize * 2;
Region reg = new Region(new double[] { centerx - (w / 2), centery - (h / 2) },
new double[] { centerx + (w / 2), centery + (h / 2) });
regions.add(reg);
index.insertData(DATA_PREFIX + i, reg);
}
}
public void testInsertion() {
Statistics stats = index.getStatistics();
//assertEquals(setSize, stats.getNumberOfData());
// data may be inserted more than once
assertTrue(stats.getNumberOfData() >= setSize);
}
public void testIntersectionQuery() {
HarvestingVisitor v = new HarvestingVisitor();
Region query = new Region(new double[] { 0, 0 }, new double[] { 1, 1 });
index.intersectionQuery(query, v);
assertEquals(index.getStatistics().getNumberOfNodes(), v.visited_nodes);
assertEquals(setSize, v.harvest.size());
Set<String> comp_result = noIndexQuery(regions, query, AbstractSpatialIndex.IntersectionQuery);
assertEquals(comp_result, v.harvest);
v = new HarvestingVisitor();
query = new Region(new double[] { .25, .25 }, new double[] { .75, .75 });
index.intersectionQuery(query, v);
assertTrue(v.harvest.size() < setSize);
comp_result = noIndexQuery(regions, query, AbstractSpatialIndex.IntersectionQuery);
assertEquals(comp_result, v.harvest);
}
public void testContainmentQuery() {
HarvestingVisitor v = new HarvestingVisitor();
Region query = new Region(new double[] { 0, 0 }, new double[] { 1, 1 });
index.containmentQuery(query, v);
assertEquals(setSize, v.harvest.size());
assertEquals(index.getStatistics().getNumberOfNodes(), v.visited_nodes);
Set<String> comp_result = noIndexQuery(regions, query, AbstractSpatialIndex.ContainmentQuery);
assertEquals(comp_result, v.harvest);
v = new HarvestingVisitor();
query = new Region(new double[] { .25, .25 }, new double[] { .75, .75 });
index.containmentQuery(query, v);
comp_result = noIndexQuery(regions, query, AbstractSpatialIndex.ContainmentQuery);
assertEquals(comp_result, v.harvest);
}
public void testPointQuery() {
HarvestingVisitor v = new HarvestingVisitor();
Point query = new Point(new double[] { generator.nextDouble(), generator.nextDouble() });
index.intersectionQuery(query, v);
Set<String> comp_result = noIndexQuery(regions, query, AbstractSpatialIndex.IntersectionQuery);
assertEquals(comp_result, v.harvest);
}
public void testQueryStrategy() {
// TODO:
}
public void testClear() {
index.clear();
HarvestingVisitor v = new HarvestingVisitor();
Region query = new Region(new double[] { 0, 0 }, new double[] { 1, 1 });
index.containmentQuery(query, v);
assertEquals(0, v.harvest.size());
assertEquals(index.getStatistics().getNumberOfNodes(), v.visited_nodes);
}
HashSet<String> noIndexQuery(ArrayList<Region> searchset, Shape query, int type) {
HashSet<String> harvest = new HashSet<String>();
for (int i = 0; i < setSize; i++) {
Region r = (Region) regions.get(i);
if (((type == AbstractSpatialIndex.IntersectionQuery) && (query.intersects(r)))
|| ((type == AbstractSpatialIndex.ContainmentQuery) && (query.contains(r)))) {
harvest.add("Object: " + i);
}
}
return harvest;
}
protected abstract AbstractSpatialIndex createIndex();
public class HarvestingVisitor implements Visitor {
public HashSet<Object> harvest = new HashSet<Object>(20);
public int visited_nodes = 0;
public void visitData(Data d) {
harvest.add(d.getData());
}
public void visitNode(Node n) {
visited_nodes++;
}
public boolean isDataVisitor() {
return true;
}
}
}