/*
* Copyright (c) 2016 Vivid Solutions.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
*
* http://www.eclipse.org/org/documents/edl-v10.php.
*/
package org.locationtech.jts.index;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.locationtech.jts.geom.Envelope;
/**
* @version 1.7
*/
public class SpatialIndexTester
{
private static boolean VERBOSE = false;
private SpatialIndex index;
private ArrayList sourceData;
private boolean isSuccess = true;
public SpatialIndexTester() {
}
public boolean isSuccess()
{
return isSuccess;
}
public void setSpatialIndex(SpatialIndex index)
{
this.index = index;
}
public SpatialIndex getSpatialIndex()
{
return index;
}
public void init() {
sourceData = new ArrayList();
addSourceData(0, sourceData);
addSourceData(OFFSET, sourceData);
if (VERBOSE) {
//System.out.println("===============================");
//System.out.println("Grid Extent: " + (CELL_EXTENT * CELLS_PER_GRID_SIDE));
//System.out.println("Cell Extent: " + CELL_EXTENT);
//System.out.println("Feature Extent: " + FEATURE_EXTENT);
//System.out.println("Cells Per Grid Side: " + CELLS_PER_GRID_SIDE);
//System.out.println("Offset For 2nd Set Of Features: " + OFFSET);
//System.out.println("Feature Count: " + sourceData.size());
}
insert(sourceData, index);
}
public void run()
{
doTest(index, QUERY_ENVELOPE_EXTENT_1, sourceData);
doTest(index, QUERY_ENVELOPE_EXTENT_2, sourceData);
}
private void insert(List sourceData, SpatialIndex index) {
for (Iterator i = sourceData.iterator(); i.hasNext(); ) {
Envelope envelope = (Envelope) i.next();
index.insert(envelope, envelope);
}
}
private static final double CELL_EXTENT = 20.31;
private static final int CELLS_PER_GRID_SIDE = 10;
private static final double FEATURE_EXTENT = 10.1;
private static final double OFFSET = 5.03;
private static final double QUERY_ENVELOPE_EXTENT_1 = 1.009;
private static final double QUERY_ENVELOPE_EXTENT_2 = 11.7;
private void addSourceData(double offset, List sourceData) {
for (int i = 0; i < CELLS_PER_GRID_SIDE; i++) {
double minx = (i * CELL_EXTENT) + offset;
double maxx = minx + FEATURE_EXTENT;
for (int j = 0; j < CELLS_PER_GRID_SIDE; j++) {
double miny = (j * CELL_EXTENT) + offset;
double maxy = miny + FEATURE_EXTENT;
Envelope e = new Envelope(minx, maxx, miny, maxy);
sourceData.add(e);
}
}
}
private void doTest(SpatialIndex index, double queryEnvelopeExtent, List sourceData) {
int extraMatchCount = 0;
int expectedMatchCount = 0;
int actualMatchCount = 0;
int queryCount = 0;
for (int x = 0; x < CELL_EXTENT * CELLS_PER_GRID_SIDE; x+= queryEnvelopeExtent) {
for (int y = 0; y < CELL_EXTENT * CELLS_PER_GRID_SIDE; y+= queryEnvelopeExtent) {
Envelope queryEnvelope = new Envelope(x, x+queryEnvelopeExtent, y, y+queryEnvelopeExtent);
List expectedMatches = intersectingEnvelopes(queryEnvelope, sourceData);
List actualMatches = index.query(queryEnvelope);
// since index returns candidates only, it may return more than the expected value
if (expectedMatches.size() > actualMatches.size()) {
isSuccess = false;
}
extraMatchCount += (actualMatches.size() - expectedMatches.size());
expectedMatchCount += expectedMatches.size();
actualMatchCount += actualMatches.size();
compare(expectedMatches, actualMatches);
queryCount++;
}
}
if (VERBOSE) {
//System.out.println("---------------");
//System.out.println("Envelope Extent: " + queryEnvelopeExtent);
//System.out.println("Expected Matches: " + expectedMatchCount);
//System.out.println("Actual Matches: " + actualMatchCount);
//System.out.println("Extra Matches: " + extraMatchCount);
//System.out.println("Query Count: " + queryCount);
//System.out.println("Average Expected Matches: " + (expectedMatchCount/(double)queryCount));
//System.out.println("Average Actual Matches: " + (actualMatchCount/(double)queryCount));
//System.out.println("Average Extra Matches: " + (extraMatchCount/(double)queryCount));
}
}
private void compare(List expectedEnvelopes, List actualEnvelopes) {
//Don't use #containsAll because we want to check using
//==, not #equals. [Jon Aquino]
for (Iterator i = expectedEnvelopes.iterator(); i.hasNext(); ) {
Envelope expected = (Envelope) i.next();
boolean found = false;
for (Iterator j = actualEnvelopes.iterator(); j.hasNext(); ) {
Envelope actual = (Envelope) j.next();
if (actual.equals(expected)) {
found = true;
break;
}
}
if (! found)
isSuccess = false;
}
}
private List intersectingEnvelopes(Envelope queryEnvelope, List envelopes) {
ArrayList intersectingEnvelopes = new ArrayList();
for (Iterator i = envelopes.iterator(); i.hasNext(); ) {
Envelope candidate = (Envelope) i.next();
if (candidate.intersects(queryEnvelope)) { intersectingEnvelopes.add(candidate); }
}
return intersectingEnvelopes;
}
}