use of org.geotoolkit.index.tree.TreeElementMapper in project geotoolkit by Geomatys.
the class SQLRtreeManager method get.
public static synchronized Tree<NamedEnvelope> get(final Path directory, final Object owner) {
Tree<NamedEnvelope> tree = CACHED_TREES.get(directory);
if (tree == null || tree.isClosed()) {
if (existTree(directory)) {
TreeElementMapper treeMapper = null;
try {
if (PGDataSource.isSetPGDataSource()) {
if (PGDataSource.isPostgres) {
DataSource ds = PGDataSource.getDataSource();
treeMapper = new LucenePostgresSQLTreeEltMapper(DEFAULT_CRS, ds, directory);
byte[] data = TreeAccessSQLByteArray.getData(directory, ds);
tree = new PGTreeWrapper(data, directory, ds, treeMapper);
} else {
DataSource ds = PGDataSource.getDataSource();
treeMapper = new LuceneHSQLTreeEltMapper(DEFAULT_CRS, ds, directory);
byte[] data = TreeAccessSQLByteArray.getData(directory, ds);
tree = new PGTreeWrapper(data, directory, ds, treeMapper);
}
} else {
// derby DB as default
final Path treeFile = directory.resolve("tree.bin");
DataSource ds = LuceneDerbySQLTreeEltMapper.getDataSource(directory);
treeMapper = new LuceneDerbySQLTreeEltMapper(DEFAULT_CRS, ds);
tree = new FileStarRTree<>(treeFile.toFile().toPath(), treeMapper);
}
} catch (Exception e) {
if (treeMapper != null) {
try {
treeMapper.close();
} catch (Exception bis) {
e.addSuppressed(bis);
}
}
LOGGER.log(Level.SEVERE, "Cannot re-open RTRee", e);
return null;
}
} else {
tree = buildNewTree(directory);
}
final List<Object> owners = new ArrayList<>();
owners.add(owner);
TREE_OWNERS.put(directory, owners);
CACHED_TREES.put(directory, tree);
} else {
// look if the owner is already registered
final List<Object> owners = TREE_OWNERS.get(directory);
if (!owners.contains(owner)) {
owners.add(owner);
}
}
return tree;
}
use of org.geotoolkit.index.tree.TreeElementMapper in project geotoolkit by Geomatys.
the class LuceneOGCWeight method scorer.
@Override
public Scorer scorer(LeafReaderContext context) throws IOException {
// final SortedDocValues values = context.reader().getSortedDocValues(IDENTIFIER_FIELD_NAME);
final LeafReader reader = context.reader();
boolean treeSearch = false;
boolean reverse = false;
boolean distanceFilter = false;
final Set<String> treeMatching = new HashSet<>();
if (tree != null) {
/*
* For distance buffer filter no envelope only mode
*/
List<Expression<Object, ?>> expressions = filter.getExpressions();
Expression e2 = (expressions.size() >= 2) ? expressions.get(1) : null;
if (filter instanceof DistanceOperator) {
distanceFilter = true;
reverse = filter.getOperatorType() == DistanceOperatorName.BEYOND;
final DistanceOperator sp = (DistanceOperator) filter;
if (e2 instanceof Literal) {
try {
final Literal lit = (Literal) e2;
Quantity distance = sp.getDistance();
final GeneralEnvelope bound = getExtendedReprojectedEnvelope(lit.getValue(), tree.getCrs(), distance.getUnit().toString(), distance.getValue().doubleValue());
final int[] resultID = tree.searchID(bound);
Arrays.sort(resultID);
treeMatching.clear();
TreeElementMapper<NamedEnvelope> tem = tree.getTreeElementMapper();
for (int id : resultID) {
final NamedEnvelope env = tem.getObjectFromTreeIdentifier(id);
if (env != null) {
treeMatching.add(env.getId());
}
}
treeSearch = true;
} catch (FactoryException ex) {
throw new IOException(ex);
} catch (StoreIndexException ex) {
Throwable cause = ex.getCause();
if (cause instanceof IOException) {
throw (IOException) cause;
} else {
throw new IOException(ex);
}
}
} else {
LOGGER.log(Level.WARNING, "Not a literal for spatial filter:{0}", e2);
}
} else if (filter instanceof BinarySpatialOperator) {
final BinarySpatialOperator sp = (BinarySpatialOperator) filter;
if (e2 instanceof Literal) {
final Literal lit = (Literal) e2;
final Envelope boundFilter = getReprojectedEnvelope(lit.getValue(), tree.getCrs());
try {
if (filterType == SpatialFilterType.CROSSES || !envelopeOnly) {
if (filterType == SpatialFilterType.DISJOINT) {
reverse = true;
}
final int[] resultID = tree.searchID(boundFilter);
Arrays.sort(resultID);
final TreeElementMapper<NamedEnvelope> tem = tree.getTreeElementMapper();
treeMatching.clear();
for (int id : resultID) {
final NamedEnvelope env = tem.getObjectFromTreeIdentifier(id);
if (env != null) {
treeMatching.add(env.getId());
}
}
treeSearch = true;
envelopeOnly = false;
} else {
final int[] resultID = TreeX.search(tree, boundFilter, filterType);
Arrays.sort(resultID);
final TreeElementMapper<NamedEnvelope> tem = tree.getTreeElementMapper();
treeMatching.clear();
for (int id : resultID) {
final NamedEnvelope env = tem.getObjectFromTreeIdentifier(id);
if (env != null) {
treeMatching.add(env.getId());
}
}
treeSearch = true;
}
} catch (StoreIndexException ex) {
Throwable cause = ex.getCause();
if (cause instanceof IOException) {
throw (IOException) cause;
} else {
throw new IOException(ex);
}
}
} else {
LOGGER.log(Level.WARNING, "Not a literal for spatial filter:{0}", e2);
}
} else {
LOGGER.log(Level.WARNING, "not a spatial operator:{0}", filter.getClass().getName());
}
} else {
LOGGER.finer("Null R-tree in spatial search");
}
final BitSet set = new FixedBitSet(reader.maxDoc());
Bits b = reader.getLiveDocs();
if (b == null) {
b = new Bits.MatchAllBits(reader.maxDoc());
}
for (int i = 0; i < b.length(); i++) {
if (b.get(i)) {
final int docId = i;
final Document doc = reader.document(docId, ID_FIELDS);
final String id = doc.get(IDENTIFIER_FIELD_NAME);
final boolean match = treeMatching.contains(id);
if (treeSearch && reverse && !match) {
set.set(docId);
} else if (!treeSearch || match) {
if (envelopeOnly && !distanceFilter) {
set.set(docId);
} else {
final Document geoDoc = reader.document(docId, GEOMETRY_FIELDS);
if (filter.test(geoDoc)) {
set.set(docId);
}
}
}
}
}
return new ConstantScoreScorer(this, boost, scoreMode, new BitSetIterator(set, 5));
}
use of org.geotoolkit.index.tree.TreeElementMapper in project geotoolkit by Geomatys.
the class TreeDemo method main.
public static void main(String[] args) throws StoreIndexException, IOException, ClassNotFoundException {
/*
* In these examples we'll show how to build and create a RTree according to our use case.
* 2 RTree storage are made, the first where RTree is stored in computer memory
* and the second where RTree is stored in file on hard drive at a path stipulated by the user.
*
* RTree which is stored in computer memory :
* - advantages : all RTree action are faster than the others because do not require hard drive access.
* - inconvenients : computer RAM memory limits data number which should be inserted.
*
* RTree which is stored on hard drive :
* - advantages : there is no data number limit of insertions.
* - inconvenients : all RTree action are slower than the others because require hard drive access.
*/
/*
* First example RTree stored in our computer memory.
* In this example user has to know he can't insert too many elements, to not overflow memory.
* For this example we choose StarRTree.
*/
/*
* In each RTree we need another object called TreeElementMapper.
* This Object allows to link Integer identifier stored in RTree and datas.
* (It is an internal operation). User should just override some methods from TreeElementMapper.
* TreeElementMapper uses Generic template and user may specify the type.
* In the present example we are working with Envelope type object. Moreover to store Envelope object we use an Envelope table.
* User can choose List or Map or other object according to his needs.
*/
final TreeElementMapper<Envelope> demoMemoryTreeEltMapper = new TreeElementMapper<Envelope>() {
private int currentSize = 100;
private Envelope[] envelopes = new Envelope[currentSize];
private boolean isClose = false;
/**
* {@inheritDoc }
*/
@Override
public int getTreeIdentifier(final Envelope object) throws IOException {
int i = 0;
for (Envelope env : envelopes) {
if (env.equals(object))
return i + 1;
i++;
}
throw new IllegalStateException("getTreeIdentifier : impossible to find tree identifier from Envelope object.");
}
/**
* {@inheritDoc }
*/
@Override
public Envelope getEnvelope(final Envelope object) throws IOException {
return object;
}
/**
* {@inheritDoc }
*/
@Override
public void setTreeIdentifier(final Envelope object, final int treeIdentifier) throws IOException {
final int envID = treeIdentifier - 1;
if (envID >= currentSize) {
currentSize = currentSize << 1;
envelopes = Arrays.copyOf(envelopes, currentSize);
}
envelopes[envID] = object;
}
/**
* {@inheritDoc }
*/
@Override
public Envelope getObjectFromTreeIdentifier(final int treeIdentifier) throws IOException {
final int envID = treeIdentifier - 1;
if (envID >= currentSize)
throw new IllegalStateException("getObjectFromTreeIdentifier : impossible to find object from identifier.");
return envelopes[envID];
}
/**
* {@inheritDoc }
*/
@Override
public void clear() throws IOException {
currentSize = 100;
envelopes = new Envelope[currentSize];
}
/**
* {@inheritDoc }
*/
@Override
public void close() throws IOException {
// no stream to close.
isClose = true;
}
/**
* {@inheritDoc }
*/
@Override
public boolean isClosed() {
return isClose;
}
@Override
public void flush() throws IOException {
// do nothing
}
@Override
public Map<Integer, Envelope> getFullMap() throws IOException {
return new HashMap<>();
}
};
/*
* After creating TreeElementMapper object we create RTree.
*/
final Tree demoMemoryRTree = new MemoryStarRTree<Envelope>(5, DEMO_CRS, demoMemoryTreeEltMapper);
/*
* get datas.
*/
Envelope[] insertedEnvelope = createData(20);
/*
* Now insert data in RTree.
*/
for (Envelope data : insertedEnvelope) {
demoMemoryRTree.insert(data);
}
System.out.println("Tree Demo : " + demoMemoryRTree.toString());
/*
* Now we should search.
*/
final GeneralEnvelope envelopeSearch = new GeneralEnvelope(DEMO_CRS);
envelopeSearch.setEnvelope(-45, -50, 110, 75);
/*
* There is two way to search.
* First, we can get a table of data identifiers which matches with the search area.
*/
int[] treeIdentifierResult = demoMemoryRTree.searchID(envelopeSearch);
System.out.println("identifiers which match : " + Arrays.toString(treeIdentifierResult));
/*
* To obtain data you have to ask data from TreeElementMapper as below.
*/
final Envelope[] resultData = new Envelope[treeIdentifierResult.length];
for (int id = 0; id < treeIdentifierResult.length; id++) {
resultData[id] = demoMemoryTreeEltMapper.getObjectFromTreeIdentifier(treeIdentifierResult[id]);
}
/*
* Secondly, we can get an iterator which iterates on each treeIdentifier search result.
*/
TreeIdentifierIterator treeIterator = demoMemoryRTree.search(envelopeSearch);
/*
* And we can get data object result as below.
*/
List<Envelope> listDataResult = new ArrayList<Envelope>();
while (treeIterator.hasNext()) {
listDataResult.add(demoMemoryTreeEltMapper.getObjectFromTreeIdentifier(treeIterator.nextInt()));
}
/*
* Moreover we can also remove some elements in index RTree.
*/
int idEnv = 1;
for (Envelope env : insertedEnvelope) {
demoMemoryRTree.remove(env);
if (idEnv % 5 == 0) {
System.out.println("RTree : during remove action after " + idEnv + " elements : " + demoMemoryRTree.toString());
}
idEnv++;
}
/**
********************************
*/
/*
* Second example: RTree stored on user computer hard disk.
* If the user doesn't know if there is enought memory on his computer or
* if he knows that all the data overflow memory, he may choose to store RTree
* on his computer hard drive.
*/
/*
* Build the 2 files to store RTree.
* One to store RTree architecture.
* The other to store TreeElementMapper architecture.
*/
final File treeFile = File.createTempFile("tree", "bin");
final File treeELTMapperFile = File.createTempFile("mapper", "bin");
/*
* First, like previously, we have to begin creating an appropriate
* TreeElementMapper to link treeIdentifier and stored object.
* In our case we would store elements on hard drive, then we would override
* a TreeElementMapper implementation called FileTreeElementMapper.
* See DemoFileTreeElementMapper class.
*/
TreeElementMapper<Envelope> demoFileTreeEltMapper = new DemoFileTreeElementMapper(treeELTMapperFile, DEMO_CRS);
/*
* Be carefull it exists 2 ways to open a FileRTree.
* If tree has never been built previously, the user should open RTree in writing action.(see Javadoc)
* Unlike if a tree has already been saved on a filled file,
* the user should open RTree in reading/writing and use constructor in accordance with it.
*/
/*
* First, we make an RTree as if it has never been created before.
*/
Tree<Envelope> demoFileRTree = new FileStarRTree<Envelope>(treeFile.toPath(), 4, DEMO_CRS, demoFileTreeEltMapper);
/*
* At this step the RTree is empty and we can fill it like previously.
*/
/*
* get datas.
*/
insertedEnvelope = createData(20);
/*
* Now insert data in RTree.
*/
for (Envelope data : insertedEnvelope) {
demoFileRTree.insert(data);
}
/*
* At this step we can use search or remove action freely.
* But if we want to save the RTree to re-open it later we MUST call close method
* on RTree and TreeElementMapper to finish to write Tree informations.
*
* Be carefull not to open an RTree in reading if it has not been closed before.
*
* In this example we close RTree and TreeElementMapper to re-open it after.
*/
demoFileRTree.close();
demoFileTreeEltMapper.close();
/*
* Re-open RTree.
*/
/*
* First we open again TreeElementMapper.
*/
demoFileTreeEltMapper = new DemoFileTreeElementMapper(treeELTMapperFile, DEMO_CRS);
/*
* Then RTree.
*/
demoFileRTree = new FileStarRTree<Envelope>(treeFile.toPath(), demoFileTreeEltMapper);
/*
* At this step we can use search or remove action freely.
* Moreover we can also add some data as below.
*/
// five new datas.
insertedEnvelope = createData(5);
System.out.println("RTree : before re-inserting datas : " + demoFileRTree.toString());
/*
* Now insert data in RTree.
*/
for (Envelope data : insertedEnvelope) {
demoFileRTree.insert(data);
}
System.out.println("RTree : after re-inserting datas : " + demoFileRTree.toString());
/*
* Like previously if we want to save changes and re-open RTree afterwards we call close() methods.
*/
demoFileRTree.close();
demoFileTreeEltMapper.close();
}
use of org.geotoolkit.index.tree.TreeElementMapper in project geotoolkit by Geomatys.
the class SQLRtreeManager method buildNewTree.
private static Tree buildNewTree(final Path directory) {
if (Files.exists(directory)) {
TreeElementMapper treeMapper = null;
try {
// creating tree (R-Tree)------------------------------------------------
final Path treeFile = directory.resolve("tree.bin");
Files.createFile(treeFile);
// postgres
if (PGDataSource.isSetPGDataSource()) {
if (PGDataSource.isPostgres) {
treeMapper = LucenePostgresSQLTreeEltMapper.createTreeEltMapperWithDB(directory);
return new PGTreeWrapper(directory, PGDataSource.getDataSource(), treeMapper, DEFAULT_CRS);
} else {
treeMapper = LuceneHSQLTreeEltMapper.createTreeEltMapperWithDB(directory);
return new PGTreeWrapper(directory, PGDataSource.getDataSource(), treeMapper, DEFAULT_CRS);
}
} else {
treeMapper = LuceneDerbySQLTreeEltMapper.createTreeEltMapperWithDB(directory);
return new FileStarRTree(treeFile.toFile().toPath(), 5, DEFAULT_CRS, treeMapper);
}
} catch (SQLException | IOException | StoreIndexException ex) {
if (treeMapper != null) {
try {
treeMapper.close();
} catch (Exception bis) {
ex.addSuppressed(bis);
}
}
LOGGER.log(Level.WARNING, "Unable to create RTree", ex);
}
}
return null;
}
Aggregations