
org.wowtools.neo4j.rtree.internal.edit.RTree Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of neo4j-rtree Show documentation
Show all versions of neo4j-rtree Show documentation
a spatial index for neo4j 4.x.
The newest version!
package org.wowtools.neo4j.rtree.internal.edit;
/*
* #%L
* Conversant RTree
* ~~
* Conversantmedia.com © 2016, Conversant, Inc. Conversant® is a trademark of Conversant, Inc.
* ~~
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.Transaction;
import org.wowtools.neo4j.rtree.internal.define.Labels;
import org.wowtools.neo4j.rtree.internal.define.Relationships;
import org.wowtools.neo4j.rtree.pojo.RectNd;
import java.util.Collection;
import java.util.Iterator;
import java.util.function.Consumer;
/**
* Data structure to make range searching more efficient. Indexes multi-dimensional information
* such as geographical coordinates or rectangles. Groups information and represents them with a
* minimum bounding rectangle (mbr). When searching through the tree, any query that does not
* intersect an mbr can ignore any data entries in that mbr.
* More information can be found here @see https://en.wikipedia.org/wiki/R-tree
*
* Created by jcairns on 4/30/15.
*/
public final class RTree implements SpatialSearch {
private static final double EPSILON = 1e-12;
private final int mMin;
private final int mMax;
private final RectBuilder builder;
private final TxCell txCell;
private long rootNodeId = -1;
private final long metadataNodeId;
public RTree(final RectBuilder builder, String name, final int mMin, final int mMax, TxCell txCell) {
this.mMin = mMin;
this.mMax = mMax;
this.builder = builder;
this.txCell = txCell;
//构造METADATA节点
org.neo4j.graphdb.Node metadataNode = txCell.getTx().createNode(Labels.METADATA);
metadataNode.setProperty("mMin", mMin);
metadataNode.setProperty("mMax", mMax);
metadataNode.setProperty("name", name);
metadataNodeId = metadataNode.getId();
}
public RTree(final RectBuilder builder, long metadataNodeId, final int mMin, final int mMax, TxCell txCell) {
this.mMin = mMin;
this.mMax = mMax;
this.builder = builder;
this.txCell = txCell;
this.metadataNodeId = metadataNodeId;
//查找root
org.neo4j.graphdb.Node metadataNode = txCell.getTx().getNodeById(metadataNodeId);
Iterator iterator = metadataNode.getRelationships(Direction.OUTGOING, Relationships.RTREE_METADATA_TO_ROOT).iterator();
if (iterator.hasNext()) {
rootNodeId = iterator.next().getEndNodeId();
}
}
@Override
public int search(final RectNd rect, final RectNd[] t) {
throw new UnsupportedOperationException();
}
@Override
public void search(RectNd rect, Consumer consumer) {
throw new UnsupportedOperationException();
}
@Override
public void search(RectNd rect, Collection collection) {
throw new UnsupportedOperationException();
}
@Override
public int intersects(final RectNd rect, final RectNd[] t) {
Node root = txCell.getNodeFromNeo4j(rootNodeId);
if (root != null) {
return root.intersects(rect, t, 0);
}
return 0;
}
@Override
public void intersects(RectNd rect, Consumer consumer) {
Node root = txCell.getNodeFromNeo4j(rootNodeId);
if (root != null) {
root.intersects(rect, consumer);
}
}
@Override
public void add(final RectNd t) {
Node root;
if (rootNodeId != -1) {
root = txCell.getNodeFromNeo4j(rootNodeId);
root = root.add(t);
} else {
root = NodeOfLeaf.create(builder, mMin, mMax, txCell);
root.add(t);
}
long newRootId = root.getNeoNodeId();
if (rootNodeId != newRootId) {
//root节点变化,修改metadata节点指向
rootNodeId = newRootId;
Transaction tx = txCell.getTx();
org.neo4j.graphdb.Node metadataNode = tx.getNodeById(metadataNodeId);
for (Relationship relationship : metadataNode.getRelationships(Relationships.RTREE_METADATA_TO_ROOT)) {
relationship.delete();
}
metadataNode.createRelationshipTo(tx.getNodeById(rootNodeId), Relationships.RTREE_METADATA_TO_ROOT);
}
}
@Override
public void remove(final RectNd t) {
Node root = txCell.getNodeFromNeo4j(rootNodeId);
if (root != null) {
root.remove(t);
}
}
@Override
public void update(final RectNd told, final RectNd tnew) {
Node root = txCell.getNodeFromNeo4j(rootNodeId);
if (root != null) {
root.update(told, tnew);
}
}
@Override
public int getEntryCount() {
Node root = txCell.getNodeFromNeo4j(rootNodeId);
if (root != null) {
return root.totalSize();
}
return 0;
}
/**
* returns whether or not the HyperRect will enclose all of the data entries in t
*
* @param t Data entries to be evaluated
* @return boolean - Whether or not all entries lie inside rect
*/
@Override
public boolean contains(final RectNd t) {
Node root = txCell.getNodeFromNeo4j(rootNodeId);
if (root != null) {
final RectNd bbox = builder.getBBox(t);
return root.contains(bbox, t);
}
return false;
}
public static boolean isEqual(final double a, final double b) {
return isEqual(a, b, EPSILON);
}
static boolean isEqual(final double a, final double b, final double eps) {
return Math.abs(a - b) <= ((Math.abs(a) < Math.abs(b) ? Math.abs(b) : Math.abs(a)) * eps);
}
@Override
public void forEach(Consumer consumer) {
Node root = txCell.getNodeFromNeo4j(rootNodeId);
if (root != null) {
root.forEach(consumer);
}
}
public Node getRoot() {
Node root = txCell.getNodeFromNeo4j(rootNodeId);
return root;
}
public long getMetadataNodeId() {
return metadataNodeId;
}
public int getmMin() {
return mMin;
}
public int getmMax() {
return mMax;
}
public long getRootNodeId() {
return rootNodeId;
}
/**
* Different methods for splitting nodes in an RTree.
*
* AXIAL has been shown to give good performance for many general spatial problems,
*
*
* Created by ewhite on 10/28/15.
*/
public enum Split {
AXIAL,
// LINEAR,
// QUADRATIC,
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy