Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge remote branch 'upstream/master'

  • Loading branch information...
commit cea66e31ee9d99ec478fa0d5be72c49c575c8002 2 parents 987b441 + aa0a421
@brycenz authored
View
86 src/main/java/org/neo4j/collections/rtree/RTreeIndex.java
@@ -26,7 +26,6 @@
import org.neo4j.collections.rtree.filter.SearchFilter;
import org.neo4j.collections.rtree.filter.SearchResults;
import org.neo4j.collections.rtree.search.Search;
-import org.neo4j.collections.rtree.search.SearchAll;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
@@ -244,8 +243,8 @@ public void warmUp() {
}
private class SearchEvaluator implements ReturnableEvaluator, StopEvaluator {
+
private SearchFilter filter;
- private TraversalPosition lastPosition;
private boolean isReturnableNode;
private boolean isStopNode;
@@ -254,21 +253,18 @@ public SearchEvaluator(SearchFilter filter) {
}
void checkPosition(TraversalPosition position) {
- if (!position.equals(lastPosition)) {
- Relationship rel = position.lastRelationshipTraversed();
- Node node = position.currentNode();
- if (rel == null) {
- isStopNode = false;
- isReturnableNode = false;
- } else if (rel.getType().equals(RTreeRelationshipTypes.RTREE_CHILD)) {
- isStopNode = filter.needsToVisit(getIndexNodeEnvelope(node));
- isReturnableNode = false;
- } else {
- isReturnableNode = filter.geometryMatches(node);
- isStopNode = !isReturnableNode;
- }
+ Relationship rel = position.lastRelationshipTraversed();
+ Node node = position.currentNode();
+ if (rel == null) {
+ isStopNode = false;
+ isReturnableNode = false;
+ } else if (rel.getType().equals(RTreeRelationshipTypes.RTREE_CHILD)) {
+ isReturnableNode = false;
+ isStopNode = !filter.needsToVisit(getIndexNodeEnvelope(node));
+ } else if (rel.getType().equals(RTreeRelationshipTypes.RTREE_REFERENCE)) {
+ isReturnableNode = filter.geometryMatches(node);
+ isStopNode = true;
}
- lastPosition = position;
}
@Override
@@ -316,6 +312,14 @@ public Node getIndexRoot() {
// Private methods
+ private Envelope getChildNodeEnvelope(Node child, RelationshipType relType) {
+ if (relType == RTreeRelationshipTypes.RTREE_REFERENCE) {
+ return getLeafNodeEnvelope(child);
+ } else {
+ return getIndexNodeEnvelope(child);
+ }
+ }
+
/**
* The leaf nodes belong to the domain model, and as such need to use the
* layers domain-specific GeometryEncoder for decoding the envelope.
@@ -332,15 +336,18 @@ private Envelope getLeafNodeEnvelope(Node geomNode) {
protected Envelope getIndexNodeEnvelope(Node indexNode) {
if (indexNode == null) indexNode = getIndexRoot();
if (!indexNode.hasProperty(PROP_BBOX)) {
- System.err.println("node[" + indexNode + "] has no bounding box property '" + PROP_BBOX + "'");
+ // this is ok after an index node split
return null;
}
- return bboxToEnvelope((double[]) indexNode.getProperty(PROP_BBOX));
+
+ double[] bbox = (double[]) indexNode.getProperty(PROP_BBOX);
+ // Envelope parameters: xmin, xmax, ymin, ymax
+ return new Envelope(bbox[0], bbox[2], bbox[1], bbox[3]);
}
private void visitInTx(SpatialIndexVisitor visitor, Long indexNodeId) {
Node indexNode = database.getNodeById(indexNodeId);
- if(!visitor.needsToVisit(getIndexNodeEnvelope(indexNode))) return;
+ if (!visitor.needsToVisit(getIndexNodeEnvelope(indexNode))) return;
if (indexNode.hasRelationship(RTreeRelationshipTypes.RTREE_CHILD, Direction.OUTGOING)) {
// Node is not a leaf
@@ -493,7 +500,7 @@ private Node chooseIndexNodeWithSmallestArea(List<Node> indexNodes) {
double smallestArea = -1;
for (Node indexNode : indexNodes) {
- double area = getArea(indexNode);
+ double area = getArea(getIndexNodeEnvelope(indexNode));
if (result == null || area < smallestArea) {
result = indexNode;
smallestArea = area;
@@ -559,9 +566,9 @@ private Node quadraticSplit(Node indexNode, RelationshipType relationshipType) {
Node seed2 = null;
double worst = Double.NEGATIVE_INFINITY;
for (Node e : entries) {
- Envelope eEnvelope = getLeafNodeEnvelope(e);
+ Envelope eEnvelope = getChildNodeEnvelope(e, relationshipType);
for (Node e1 : entries) {
- Envelope e1Envelope = getLeafNodeEnvelope(e1);
+ Envelope e1Envelope = getChildNodeEnvelope(e1, relationshipType);
double deadSpace = getArea(createEnvelope(eEnvelope, e1Envelope)) - getArea(eEnvelope) - getArea(e1Envelope);
if (deadSpace > worst) {
worst = deadSpace;
@@ -573,11 +580,11 @@ private Node quadraticSplit(Node indexNode, RelationshipType relationshipType) {
List<Node> group1 = new ArrayList<Node>();
group1.add(seed1);
- Envelope group1envelope = getLeafNodeEnvelope(seed1);
+ Envelope group1envelope = getChildNodeEnvelope(seed1, relationshipType);
List<Node> group2 = new ArrayList<Node>();
group2.add(seed2);
- Envelope group2envelope = getLeafNodeEnvelope(seed2);
+ Envelope group2envelope = getChildNodeEnvelope(seed2, relationshipType);
entries.remove(seed1);
entries.remove(seed2);
@@ -588,7 +595,7 @@ private Node quadraticSplit(Node indexNode, RelationshipType relationshipType) {
Node bestEntry = null;
double expansionMin = Double.POSITIVE_INFINITY;
for (Node e : entries) {
- Envelope nodeEnvelope = getLeafNodeEnvelope(e);
+ Envelope nodeEnvelope = getChildNodeEnvelope(e, relationshipType);
double expansion1 = getArea(createEnvelope(nodeEnvelope, group1envelope)) - getArea(group1envelope);
double expansion2 = getArea(createEnvelope(nodeEnvelope, group2envelope)) - getArea(group2envelope);
@@ -618,7 +625,7 @@ private Node quadraticSplit(Node indexNode, RelationshipType relationshipType) {
// insert the best candidate entry in the best group
bestGroup.add(bestEntry);
- bestGroupEnvelope.expandToInclude(getLeafNodeEnvelope(bestEntry));
+ bestGroupEnvelope.expandToInclude(getChildNodeEnvelope(bestEntry, relationshipType));
entries.remove(bestEntry);
}
@@ -648,22 +655,11 @@ private void createNewRoot(Node oldRoot, Node newIndexNode) {
layerNode.createRelationshipTo(newRoot, RTreeRelationshipTypes.RTREE_ROOT);
}
- private double[] envelopeToBBox(Envelope bounds) {
- return new double[]{ bounds.getMinX(), bounds.getMinY(), bounds.getMaxX(), bounds.getMaxY() };
- }
-
- protected Envelope bboxToEnvelope(double[] bbox) {
- // Envelope parameters: xmin, xmax, ymin, ymax
- return new Envelope(bbox[0], bbox[2], bbox[1], bbox[3]);
- }
-
private boolean addChild(Node parent, RelationshipType type, Node newChild) {
- double[] childBBox = null;
- if (type == RTreeRelationshipTypes.RTREE_REFERENCE) {
- childBBox = envelopeToBBox(envelopeDecoder.decodeEnvelope(newChild));
- } else {
- childBBox = (double[]) newChild.getProperty(PROP_BBOX);
- }
+ Envelope childEnvelope = getChildNodeEnvelope(newChild, type);
+ double[] childBBox = new double[] {
+ childEnvelope.getMinX(), childEnvelope.getMinY(),
+ childEnvelope.getMaxX(), childEnvelope.getMaxY() };
parent.createRelationshipTo(newChild, type);
return expandParentBoundingBoxAfterNewChild(parent, childBBox);
}
@@ -696,9 +692,9 @@ private boolean adjustParentBoundingBox(Node indexNode, RelationshipType relatio
Node childNode = iterator.next().getEndNode();
if (bbox == null) {
- bbox = new Envelope(getLeafNodeEnvelope(childNode));
+ bbox = new Envelope(getChildNodeEnvelope(childNode, relationshipType));
} else {
- bbox.expandToInclude(getLeafNodeEnvelope(childNode));
+ bbox.expandToInclude(getChildNodeEnvelope(childNode, relationshipType));
}
}
@@ -770,10 +766,6 @@ private Node getIndexNodeParent(Node indexNode) {
else return relationship.getStartNode();
}
- private double getArea(Node node) {
- return getArea(getLeafNodeEnvelope(node));
- }
-
private double getArea(Envelope e) {
return e.getWidth() * e.getHeight();
}
View
2  src/main/java/org/neo4j/collections/rtree/filter/AbstractSearchEnvelopeIntersection.java
@@ -24,6 +24,7 @@
import org.neo4j.graphdb.Node;
public abstract class AbstractSearchEnvelopeIntersection implements SearchFilter {
+
protected EnvelopeDecoder decoder;
protected Envelope referenceEnvelope;
@@ -43,6 +44,7 @@ public final boolean geometryMatches(Node geomNode) {
if (geomEnvelope.intersects(referenceEnvelope)) {
return onEnvelopeIntersection(geomNode, geomEnvelope);
}
+
return false;
}
View
5 src/main/java/org/neo4j/collections/rtree/filter/SearchFilter.java
@@ -23,6 +23,9 @@
import org.neo4j.graphdb.Node;
public interface SearchFilter {
+
boolean needsToVisit(Envelope envelope);
- boolean geometryMatches(Node geomNode);
+
+ boolean geometryMatches(Node geomNode);
+
}
View
12 src/test/java/org/neo4j/collections/rtree/TestSearch.java
@@ -67,22 +67,14 @@ public void myFirstTest() {
Envelope expectedBbox = new Envelope(0, 25, 0, 32);
assertEnvelopeEquals(bbox, expectedBbox);
-// Search search = new SearchInvalidEnvelopes(index.getEnvelopeDecoder());
-// index.executeSearch(search);
-// assertEquals(1, search.getResults().size());
-
- Search search = new SearchEqualEnvelopes(index.getEnvelopeDecoder(),
- new Envelope(0, 2, 0, 3));
+ Search search = new SearchEqualEnvelopes(index.getEnvelopeDecoder(), new Envelope(0, 2, 0, 3));
index.executeSearch(search);
assertEquals(1, search.getResults().size());
- search = new SearchCoveredByEnvelope(index.getEnvelopeDecoder(),
- new Envelope(9, 15, -1, 3));
+ search = new SearchCoveredByEnvelope(index.getEnvelopeDecoder(), new Envelope(9, 15, -1, 3));
index.executeSearch(search);
assertEquals(3, search.getResults().size());
- // TODO test index.removeAll(deleteGeomNodes, monitor)
-
index.clear(new NullListener());
assertEquals(0, index.count());
View
53 src/test/java/org/neo4j/collections/rtree/TestSearchFilter.java
@@ -21,24 +21,23 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
import org.junit.Test;
-import org.neo4j.collections.rtree.filter.SearchFilter;
import org.neo4j.collections.rtree.filter.SearchCoveredByEnvelope;
import org.neo4j.collections.rtree.filter.SearchEqualEnvelopes;
+import org.neo4j.collections.rtree.filter.SearchFilter;
+import org.neo4j.collections.rtree.filter.SearchResults;
import org.neo4j.graphdb.Node;
+
public class TestSearchFilter extends SpatialTestCase {
@Test
public void searchIndexWithFilter() {
- RTreeIndex index = new RTreeIndex(graphDb(), graphDb().getReferenceNode(),
+ RTreeIndex index = new RTreeIndex(graphDb(), graphDb().getReferenceNode(),
new EnvelopeDecoderFromDoubleArray("bbox"));
- assertTrue(index.isEmpty());
- assertEquals(0, index.count());
-
+ // equal bbox test
index.add(createGeomNode(0, 0, 2, 3));
index.add(createGeomNode(10, 0));
@@ -46,36 +45,30 @@ public void searchIndexWithFilter() {
index.add(createGeomNode(14, 2));
index.add(createGeomNode(25, 32));
- Node geomNode = createGeomNode(11, 1);
- index.add(geomNode);
-
assertFalse(index.isEmpty());
- assertEquals(6, index.count());
-
- assertTrue(index.isNodeIndexed(geomNode.getId()));
- index.remove(geomNode.getId(), false);
- assertFalse(index.isNodeIndexed(geomNode.getId()));
-
assertEquals(5, index.count());
- Envelope bbox = index.getBoundingBox();
- Envelope expectedBbox = new Envelope(0, 25, 0, 32);
- assertEnvelopeEquals(bbox, expectedBbox);
-
- SearchFilter filter = new SearchEqualEnvelopes(index.getEnvelopeDecoder(),
- new Envelope(0, 2, 0, 3));
- assertEquals(1, index.searchIndex(filter).count());
+ SearchFilter filter = new SearchEqualEnvelopes(index.getEnvelopeDecoder(), new Envelope(0, 2, 0, 3));
+ SearchResults results = index.searchIndex(filter);
- filter = new SearchCoveredByEnvelope(index.getEnvelopeDecoder(),
- new Envelope(9, 15, -1, 3));
- assertEquals(3, index.searchIndex(filter).count());
+ int count = 0;
+ for (Node node : results) {
+ System.out.println("found node: " + node.getId());
+ count++;
+ }
- // TODO test index.removeAll(deleteGeomNodes, monitor)
-
- index.clear(new NullListener());
- assertEquals(0, index.count());
+ assertEquals(1, count);
+
+ filter = new SearchCoveredByEnvelope(index.getEnvelopeDecoder(), new Envelope(9, 15, -1, 3));
+ results = index.searchIndex(filter);
+
+ count = 0;
+ for (Node node : results) {
+ System.out.println("found node: " + node.getId());
+ count++;
+ }
- debugIndexTree(index, graphDb().getReferenceNode());
+ assertEquals(3, count);
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.