/* * 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 org.apache.sis.geometry.GeneralEnvelope; import org.geotoolkit.filter.SpatialFilterType; import org.geotoolkit.index.tree.star.FileStarRTree; import org.geotoolkit.internal.tree.TreeAccessFile; import org.geotoolkit.referencing.crs.PredefinedCRS; import org.junit.Test; import org.opengis.geometry.Envelope; import org.opengis.referencing.crs.CoordinateReferenceSystem; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import static org.junit.Assert.assertTrue; import org.opengis.util.FactoryException; import org.apache.sis.util.Utilities; /** * Test static TreeX methods. * * Intersect test is already effectuate by tree test suite. * * @author Rémi Maréchal (Geomatys). */ public class TreeXTest extends TreeTest { private final Tree tree ; private TreeXElementMapperTest tXEM ; private final File treeFile; private static final CoordinateReferenceSystem CRS_TEST = PredefinedCRS.CARTESIAN_3D; public TreeXTest() throws StoreIndexException, IOException { treeFile = File.createTempFile("TreeX", "test", tempDir); tXEM = new TreeXElementMapperTest(); tree = new FileStarRTree(treeFile.toPath(), 4, CRS_TEST, tXEM); final GeneralEnvelope geTemp = new GeneralEnvelope(CRS_TEST); for(int z = 0; z <= 200; z += 20) { for(int y = 0; y <= 200; y += 20) { for(int x = 0; x <= 200; x += 20) { geTemp.setEnvelope(x-5, y-5, z-5, x+5, y+5, z+5); tree.insert(new GeneralEnvelope(geTemp)); } } } } /** * Find and return objects which match with them tree identifiers. * * @param tabID integer table which contain tree identifier return by search action. * @return objects which match with them tree identifiers. */ private List<Envelope> getresult(int[] tabID) { List<Envelope> lResult = new ArrayList<Envelope>(tabID.length); for (int i = 0, s = tabID.length; i < s; i++) { lResult.add(tXEM.getObjectFromTreeIdentifier(tabID[i])); } return lResult; } @Test public void readCRSTest() throws IOException, ClassNotFoundException, FactoryException { assertTrue(Utilities.equalsIgnoreMetadata(CRS_TEST, TreeAccessFile.getTreeCRS(treeFile))); } /** * Test result {@link Envelope} which contain specified search Envelope. * * @throws StoreIndexException */ @Test public void testContains() throws StoreIndexException { final List<Envelope> listRef = new ArrayList<Envelope>(); final GeneralEnvelope geTemp = new GeneralEnvelope(CRS_TEST); geTemp.setEnvelope(115, 135, 35, 125, 145, 45); listRef.add(new GeneralEnvelope(geTemp)); geTemp.setEnvelope(116, 136, 36, 124, 144, 44); int[] tabResult = TreeX.search(tree, geTemp, SpatialFilterType.CONTAINS); assertTrue(compareList(listRef, getresult(tabResult))); geTemp.setEnvelope(tree.getRoot().getBoundary()); tabResult = TreeX.search(tree, geTemp, SpatialFilterType.CONTAINS); assertTrue(tabResult.length == 0); } /** * Test result {@link Envelope} not within specified search Envelope. * * @throws StoreIndexException */ @Test public void testDisjoin() throws StoreIndexException { final List<Envelope> listRef = new ArrayList<Envelope>(); final GeneralEnvelope geTemp = new GeneralEnvelope(CRS_TEST); for(int z = 0; z <= 100; z += 20) { for(int y = 0; y <= 200; y += 20) { for(int x = 0; x<=200; x += 20) { geTemp.setEnvelope(x-5, y-5, z-5, x+5, y+5, z+5); listRef.add(new GeneralEnvelope(geTemp)); } } } geTemp.setEnvelope(-10, -10, 110, 210, 210, 210); int[] tabResult = TreeX.search(tree, geTemp, SpatialFilterType.DISJOINT); assertTrue(compareList(listRef, getresult(tabResult))); geTemp.setEnvelope(tree.getRoot().getBoundary()); tabResult = TreeX.search(tree, geTemp, SpatialFilterType.DISJOINT); assertTrue(tabResult.length == 0); } /** * Test result {@link Envelope} within specified search Envelope. * * @throws StoreIndexException */ @Test public void testWithin() throws StoreIndexException { final List<Envelope> listRef = new ArrayList<Envelope>(); final GeneralEnvelope geTemp = new GeneralEnvelope(CRS_TEST); for(int z = 0; z <= 200; z += 20) { for(int y = 0; y <= 200; y += 20) { geTemp.setEnvelope(195, y-5, z-5, 205, y+5, z+5); listRef.add(new GeneralEnvelope(geTemp)); } } geTemp.setEnvelope(180, -10, -10, 210, 210, 210); int[] tabresult = TreeX.search(tree, geTemp, SpatialFilterType.WITHIN); assertTrue(compareList(listRef, getresult(tabresult))); geTemp.setEnvelope(-10, 97, -10, 210, 104, 210); tabresult = TreeX.search(tree, geTemp, SpatialFilterType.WITHIN); assertTrue(tabresult.length == 0); } /** * Test result {@link Envelope} which touch specified search Envelope. * * @throws StoreIndexException */ @Test public void testTouches() throws StoreIndexException { final List<Envelope> listRef = new ArrayList<Envelope>(); final GeneralEnvelope geTemp = new GeneralEnvelope(CRS_TEST); for(int z = 0; z <= 200; z += 20) { for(int y = 0; y <= 200; y += 20) { for(int x = 140; x <= 160; x += 20) { geTemp.setEnvelope(x-5, y-5, z-5, x+5, y+5, z+5); listRef.add(new GeneralEnvelope(geTemp)); } } } geTemp.setEnvelope(145, -10, -10, 155, 210, 210); int[] tabresult = TreeX.search(tree, geTemp, SpatialFilterType.TOUCHES); assertTrue(compareList(listRef, getresult(tabresult))); geTemp.setEnvelope(144, -10, -10, 156, 210, 210); tabresult = TreeX.search(tree, geTemp, SpatialFilterType.TOUCHES); assertTrue(tabresult.length == 0); } /** * Test result {@link Envelope} which are equals to search Envelope. * * @throws StoreIndexException */ @Test public void testEquals() throws StoreIndexException { final List<Envelope> listRef = new ArrayList<Envelope>(); final GeneralEnvelope geTemp = new GeneralEnvelope(CRS_TEST); geTemp.setEnvelope(115, 135, 35, 125, 145, 45); listRef.add(new GeneralEnvelope(geTemp)); geTemp.setEnvelope(115, 135, 35, 125, 145, 45); int[] tabresult = TreeX.search(tree, geTemp, SpatialFilterType.EQUALS); assertTrue(compareList(listRef, getresult(tabresult))); geTemp.setEnvelope(tree.getRoot().getBoundary()); tabresult = TreeX.search(tree, geTemp, SpatialFilterType.EQUALS); assertTrue(tabresult.length == 0); } /** * Test result {@link Envelope} which overlaps specified search Envelope. * * @throws StoreIndexException */ @Test public void testOverlaps() throws StoreIndexException { final List<Envelope> listRef = new ArrayList<Envelope>(); final GeneralEnvelope geTemp = new GeneralEnvelope(CRS_TEST); for(int z = 0; z <= 200; z += 20) { for(int y = 0; y <= 200; y += 20) { for(int x = 140; x <= 160; x += 20) { geTemp.setEnvelope(x-5, y-5, z-5, x+5, y+5, z+5); listRef.add(new GeneralEnvelope(geTemp)); } } } geTemp.setEnvelope(144, -10, -10, 156, 210, 210); int[] tabresult = TreeX.search(tree, geTemp, SpatialFilterType.OVERLAPS); assertTrue(compareList(listRef, getresult(tabresult))); geTemp.setEnvelope(145, -10, -10, 155, 210, 210); tabresult = TreeX.search(tree, geTemp, SpatialFilterType.OVERLAPS); assertTrue(tabresult.length == 0); geTemp.setEnvelope(145, -10, -10, 165, 210, 210); tabresult = TreeX.search(tree, geTemp, SpatialFilterType.OVERLAPS); assertTrue(tabresult.length == 0); } } /** * Do link between datas inserted for this test and Tree identifier. * * @author Remi Marechal (Geomatys). * @see TreeElementMapper */ class TreeXElementMapperTest implements TreeElementMapper<Envelope> { private final List<Envelope> lData; private final List<Integer> lID; private boolean isClosed; public TreeXElementMapperTest() { this.lData = new ArrayList<Envelope>(); this.lID = new ArrayList<Integer>(); this.isClosed = false; } /** * {@inheritDoc } */ @Override public int getTreeIdentifier(Envelope object) { for (int i = 0, s = lData.size(); i < s; i++) { if (lData.get(i).equals(object)) { return lID.get(i); } } throw new IllegalStateException("impossible to found treeIdentifier."); } /** * {@inheritDoc } */ @Override public Envelope getEnvelope(Envelope object) { return object; } /** * {@inheritDoc } */ @Override public void setTreeIdentifier(Envelope object, int treeIdentifier) { lData.add(object); lID.add(treeIdentifier); } /** * {@inheritDoc } */ @Override public Envelope getObjectFromTreeIdentifier(int treeIdentifier) { for (int i = 0, l = lID.size(); i < l; i++) { if (lID.get(i) == treeIdentifier) { return lData.get(i); } } throw new IllegalStateException("impossible to found Data."); } /** * {@inheritDoc } */ @Override public void clear() { lData.clear(); lID.clear(); } /** * {@inheritDoc } */ @Override public void close() throws IOException { // do nothing isClosed = true; } /** * {@inheritDoc } */ @Override public boolean isClosed() { return isClosed; } @Override public void flush() throws IOException { // do nothing } @Override public Map<Integer, Envelope> getFullMap() throws IOException { return new HashMap<>(); } }