use of org.neo4j.gis.spatial.index.curves.SpaceFillingCurve in project neo4j by neo4j.
the class EntityValueIndexCursorTestBase method assertSameDerivedValue.
protected void assertSameDerivedValue(PointValue p1, PointValue p2) {
ConfiguredSpaceFillingCurveSettingsCache settingsFactory = new ConfiguredSpaceFillingCurveSettingsCache(Config.defaults());
SpaceFillingCurveSettings spaceFillingCurveSettings = settingsFactory.forCRS(CoordinateReferenceSystem.WGS84);
SpaceFillingCurve curve = spaceFillingCurveSettings.curve();
assertEquals(curve.derivedValueFor(p1.coordinate()), curve.derivedValueFor(p2.coordinate()));
}
use of org.neo4j.gis.spatial.index.curves.SpaceFillingCurve in project neo4j by neo4j.
the class GenericKeyStateTest method comparePointsMustOnlyReturnZeroForEqualPoints.
@Test
void comparePointsMustOnlyReturnZeroForEqualPoints() {
PointValue firstPoint = random.randomValues().nextPointValue();
PointValue equalPoint = Values.point(firstPoint);
CoordinateReferenceSystem crs = firstPoint.getCoordinateReferenceSystem();
SpaceFillingCurve curve = noSpecificIndexSettings.forCrs(crs);
Long spaceFillingCurveValue = curve.derivedValueFor(firstPoint.coordinate());
PointValue centerPoint = Values.pointValue(crs, curve.centerPointFor(spaceFillingCurveValue));
GenericKey firstKey = newKeyState();
firstKey.writeValue(firstPoint, NEUTRAL);
GenericKey equalKey = newKeyState();
equalKey.writeValue(equalPoint, NEUTRAL);
GenericKey centerKey = newKeyState();
centerKey.writeValue(centerPoint, NEUTRAL);
GenericKey noCoordsKey = newKeyState();
noCoordsKey.writeValue(equalPoint, NEUTRAL);
GeometryType.setNoCoordinates(noCoordsKey);
assertEquals(0, firstKey.compareValueTo(equalKey), "expected keys to be equal");
assertEquals(firstPoint.compareTo(centerPoint) != 0, firstKey.compareValueTo(centerKey) != 0, "expected keys to be equal if and only if source points are equal");
assertEquals(0, firstKey.compareValueTo(noCoordsKey), "expected keys to be equal");
}
use of org.neo4j.gis.spatial.index.curves.SpaceFillingCurve in project neo4j by neo4j.
the class SpatialIndexValueTestUtil method pointsWithSameValueOnSpaceFillingCurve.
public static Pair<PointValue, PointValue> pointsWithSameValueOnSpaceFillingCurve(Config config) {
ConfiguredSpaceFillingCurveSettingsCache configuredCache = new ConfiguredSpaceFillingCurveSettingsCache(config);
SpaceFillingCurveSettings spaceFillingCurveSettings = configuredCache.forCRS(CoordinateReferenceSystem.WGS84);
SpaceFillingCurve curve = spaceFillingCurveSettings.curve();
double[] origin = { 0.0, 0.0 };
Long spaceFillingCurveMapForOrigin = curve.derivedValueFor(origin);
double[] centerPointForOriginTile = curve.centerPointFor(spaceFillingCurveMapForOrigin);
PointValue originValue = Values.pointValue(CoordinateReferenceSystem.WGS84, origin);
PointValue centerPointValue = Values.pointValue(CoordinateReferenceSystem.WGS84, centerPointForOriginTile);
assertThat(origin).as("need non equal points for this test").isNotEqualTo(centerPointValue);
return Pair.of(originValue, centerPointValue);
}
use of org.neo4j.gis.spatial.index.curves.SpaceFillingCurve in project neo4j by neo4j.
the class IndexOrderTestBase method shouldNodeIndexScanInOrderWithPointsWithinSameTile.
@ParameterizedTest
@EnumSource(value = IndexOrder.class, names = { "ASCENDING", "DESCENDING" })
void shouldNodeIndexScanInOrderWithPointsWithinSameTile(IndexOrder indexOrder) throws Exception {
Config config = Config.defaults();
IndexSpecificSpaceFillingCurveSettings indexSettings = IndexSpecificSpaceFillingCurveSettings.fromConfig(config);
SpaceFillingCurve curve = indexSettings.forCrs(WGS84);
// given
// Many random points that all are close enough to each other to belong to the same tile on the space filling curve.
int nbrOfValues = 10000;
PointValue origin = Values.pointValue(WGS84, 0.0, 0.0);
Long derivedValueForCenterPoint = curve.derivedValueFor(origin.coordinate());
double[] centerPoint = curve.centerPointFor(derivedValueForCenterPoint);
double xWidthMultiplier = curve.getTileWidth(0, curve.getMaxLevel()) / 2;
double yWidthMultiplier = curve.getTileWidth(1, curve.getMaxLevel()) / 2;
List<Pair<Long, Value>> expected = new ArrayList<>();
try (KernelTransaction tx = beginTransaction()) {
// NOTE: strings come after points in natural ascending sort order
expected.add(entityWithProp(tx, "a"));
expected.add(entityWithProp(tx, "b"));
for (int i = 0; i < nbrOfValues / 8; i++) {
double x1 = (random.nextDouble() * 2 - 1) * xWidthMultiplier;
double x2 = (random.nextDouble() * 2 - 1) * xWidthMultiplier;
double y1 = (random.nextDouble() * 2 - 1) * yWidthMultiplier;
double y2 = (random.nextDouble() * 2 - 1) * yWidthMultiplier;
expected.add(entityWithProp(tx, Values.pointValue(WGS84, centerPoint[0] + x1, centerPoint[1] + y1)));
expected.add(entityWithProp(tx, Values.pointValue(WGS84, centerPoint[0] + x1, centerPoint[1] + y2)));
expected.add(entityWithProp(tx, Values.pointValue(WGS84, centerPoint[0] + x2, centerPoint[1] + y1)));
expected.add(entityWithProp(tx, Values.pointValue(WGS84, centerPoint[0] + x2, centerPoint[1] + y2)));
}
tx.commit();
}
createIndex();
// when
try (KernelTransaction tx = beginTransaction()) {
IndexReadSession index = tx.dataRead().indexReadSession(tx.schemaRead().indexGetForName(INDEX_NAME));
try (var cursor = getEntityValueIndexCursor(tx)) {
for (int i = 0; i < nbrOfValues / 8; i++) {
double x1 = (random.nextDouble() * 2 - 1) * xWidthMultiplier;
double x2 = (random.nextDouble() * 2 - 1) * xWidthMultiplier;
double y1 = (random.nextDouble() * 2 - 1) * yWidthMultiplier;
double y2 = (random.nextDouble() * 2 - 1) * yWidthMultiplier;
expected.add(entityWithProp(tx, Values.pointValue(WGS84, centerPoint[0] + x1, centerPoint[1] + y1)));
expected.add(entityWithProp(tx, Values.pointValue(WGS84, centerPoint[0] + x1, centerPoint[1] + y2)));
expected.add(entityWithProp(tx, Values.pointValue(WGS84, centerPoint[0] + x2, centerPoint[1] + y1)));
expected.add(entityWithProp(tx, Values.pointValue(WGS84, centerPoint[0] + x2, centerPoint[1] + y2)));
}
expected.add(entityWithProp(tx, "c"));
expected.add(entityWithProp(tx, "d"));
entityIndexScan(tx, index, cursor, constrained(indexOrder, true));
assertResultsInOrder(expected, cursor, indexOrder);
}
}
}
use of org.neo4j.gis.spatial.index.curves.SpaceFillingCurve in project neo4j by neo4j.
the class GenericNativeIndexReader method query.
@Override
public void query(QueryContext context, IndexProgressor.EntityValueClient client, IndexQueryConstraints constraints, PropertyIndexQuery... query) {
PropertyIndexQuery.GeometryRangePredicate geometryRangePredicate = getGeometryRangePredicateIfAny(query);
if (geometryRangePredicate != null) {
validateQuery(constraints, query);
try {
// If there's a GeometryRangeQuery among the predicates then this query changes from a straight-forward: build from/to and seek...
// into a query that is split into multiple sub-queries. Predicates both before and after will have to be accompanied each sub-query.
BridgingIndexProgressor multiProgressor = new BridgingIndexProgressor(client, descriptor.schema().getPropertyIds());
client.initialize(descriptor, multiProgressor, query, constraints, false);
double[] from = geometryRangePredicate.from() == null ? null : geometryRangePredicate.from().coordinate();
double[] to = geometryRangePredicate.to() == null ? null : geometryRangePredicate.to().coordinate();
CoordinateReferenceSystem crs = geometryRangePredicate.crs();
SpaceFillingCurve curve = spaceFillingCurveSettings.forCrs(crs);
List<SpaceFillingCurve.LongRange> ranges = curve.getTilesIntersectingEnvelope(from, to, configuration);
for (SpaceFillingCurve.LongRange range : ranges) {
// Here's a sub-query that we'll have to do for this geometry range. Build this query from all predicates
// and when getting to the geometry range predicate that sparked these sub-query chenanigans, swap in this sub-query in its place.
GenericKey treeKeyFrom = layout.newKey();
GenericKey treeKeyTo = layout.newKey();
initializeFromToKeys(treeKeyFrom, treeKeyTo);
boolean needFiltering = initializeRangeForGeometrySubQuery(treeKeyFrom, treeKeyTo, query, crs, range);
startSeekForInitializedRange(multiProgressor, treeKeyFrom, treeKeyTo, query, constraints, needFiltering, context.cursorContext());
}
} catch (IllegalArgumentException e) {
// Invalid query ranges will cause this state (eg. min>max)
client.initialize(descriptor, IndexProgressor.EMPTY, query, constraints, false);
}
} else {
super.query(context, client, constraints, query);
}
}
Aggregations