/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2009-2012, Geomatys
*
* 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.geotoolkit.index.tree;
import java.io.IOException;
import java.util.Arrays;
import org.apache.sis.geometry.GeneralEnvelope;
import org.apache.sis.util.ArgumentChecks;
import org.geotoolkit.filter.SpatialFilterType;
import static org.geotoolkit.filter.SpatialFilterType.*;
import static org.geotoolkit.internal.tree.TreeUtilities.*;
import org.opengis.geometry.Envelope;
import org.apache.sis.util.Utilities;
/**
* Logics operate.
*
* @author Rémi Maréchal (Geomatys).
*/
public final class TreeX {
private TreeX() {
}
/**
* Effectuate different logics operations on tree.
*
* @param tree
* @param areaSearch area of search.
* @param logicFilter different logic operation.
* @return integer table which contain all tree identifier from data which match with search criterion. (area and logic filter)
* @throws StoreIndexException if problem during search action.
* @see SpatialFilterType
* @see Tree#searchID(org.opengis.geometry.Envelope)
*/
public static int[] search(final Tree tree, final Envelope regionSearch, final SpatialFilterType logicFilter) throws StoreIndexException {
ArgumentChecks.ensureNonNull("TreeX search : tree", tree);
ArgumentChecks.ensureNonNull("TreeX search : Envelope", regionSearch);
ArgumentChecks.ensureNonNull("TreeX search : SpatialFilterType", logicFilter);
if (!Utilities.equalsIgnoreMetadata(regionSearch.getCoordinateReferenceSystem(), tree.getCrs()))
throw new IllegalArgumentException("TreeX search : the 2 CRS within tree and region search should be equals.");
final TreeElementMapper tEM = tree.getTreeElementMapper();
TreeIdentifierIterator iterSearch = tree.search(regionSearch);
int tabResultLength = 100;
int[] tabResult = new int[tabResultLength];
int currentPosition = 0;
try {
switch (logicFilter) {
case INTERSECTS : case BBOX : {
return tree.searchID(regionSearch);
}
case CONTAINS : {
while (iterSearch.hasNext()) {
final int currentTreeID = iterSearch.nextInt();
final Envelope env = tEM.getEnvelope(tEM.getObjectFromTreeIdentifier(currentTreeID));
if (contains(getCoords(env), getCoords(regionSearch), true)) {
if (currentPosition == tabResultLength) {
tabResultLength = tabResultLength << 1;
final int[] tabTemp = tabResult;
tabResult = new int[tabResultLength];
System.arraycopy(tabTemp, 0, tabResult, 0, currentPosition);
}
tabResult[currentPosition++] = currentTreeID;
}
}
} break;
case DISJOINT : {
final GeneralEnvelope treeExtends = new GeneralEnvelope(tree.getCrs());
treeExtends.setEnvelope(tree.getExtent());
final TreeIdentifierIterator allIter = tree.search(treeExtends);
while (allIter.hasNext()) {
final int currentTreeID = allIter.nextInt();
final Envelope env = tEM.getEnvelope(tEM.getObjectFromTreeIdentifier(currentTreeID));
if (!intersects(getCoords(env), getCoords(regionSearch), true)) {
if (currentPosition == tabResultLength) {
tabResultLength = tabResultLength << 1;
final int[] tabTemp = tabResult;
tabResult = new int[tabResultLength];
System.arraycopy(tabTemp, 0, tabResult, 0, currentPosition);
}
tabResult[currentPosition++] = currentTreeID;
}
}
} break;
case WITHIN : {
while (iterSearch.hasNext()) {
final int currentTreeID = iterSearch.nextInt();
final Envelope env = tEM.getEnvelope(tEM.getObjectFromTreeIdentifier(currentTreeID));
if (contains(getCoords(regionSearch), getCoords(env), true)) {
if (currentPosition == tabResultLength) {
tabResultLength = tabResultLength << 1;
final int[] tabTemp = tabResult;
tabResult = new int[tabResultLength];
System.arraycopy(tabTemp, 0, tabResult, 0, currentPosition);
}
tabResult[currentPosition++] = currentTreeID;
}
}
} break;
case TOUCHES : {
while (iterSearch.hasNext()) {
final int currentTreeID = iterSearch.nextInt();
final Envelope env = tEM.getEnvelope(tEM.getObjectFromTreeIdentifier(currentTreeID));
if (touches(getCoords(regionSearch), getCoords(env))) {
if (currentPosition == tabResultLength) {
tabResultLength = tabResultLength << 1;
final int[] tabTemp = tabResult;
tabResult = new int[tabResultLength];
System.arraycopy(tabTemp, 0, tabResult, 0, currentPosition);
}
tabResult[currentPosition++] = currentTreeID;
}
}
} break;
case EQUALS : {
while (iterSearch.hasNext()) {
final int currentTreeID = iterSearch.nextInt();
final Envelope env = tEM.getEnvelope(tEM.getObjectFromTreeIdentifier(currentTreeID));
if (arrayEquals(getCoords(env), getCoords(regionSearch), 1E-9)) {
if (currentPosition == tabResultLength) {
tabResultLength = tabResultLength << 1;
final int[] tabTemp = tabResult;
tabResult = new int[tabResultLength];
System.arraycopy(tabTemp, 0, tabResult, 0, currentPosition);
}
tabResult[currentPosition++] = currentTreeID;
}
}
} break;
case OVERLAPS : {
while (iterSearch.hasNext()) {
final int currentTreeID = iterSearch.nextInt();
final Envelope envelop = tEM.getEnvelope(tEM.getObjectFromTreeIdentifier(currentTreeID));
final double[] env = getCoords(envelop);
if (intersects(getCoords(regionSearch), env, false)
&& !contains(env, getCoords(regionSearch), true)
&& !contains(getCoords(regionSearch), env, true)) {
if (currentPosition == tabResultLength) {
tabResultLength = tabResultLength << 1;
final int[] tabTemp = tabResult;
tabResult = new int[tabResultLength];
System.arraycopy(tabTemp, 0, tabResult, 0, currentPosition);
}
tabResult[currentPosition++] = currentTreeID;
}
}
} break;
default : throw new IllegalStateException("not implemented yet");
}
return Arrays.copyOf(tabResult, currentPosition);
} catch (IOException ex) {
throw new StoreIndexException(ex);
}
}
}