/** * Returns the radius in kilometers of this circle. Only applicable to circle shapes. * @return */ public double getRadius() { Preconditions.checkArgument(getType()==Type.CIRCLE,"This shape is not a circle"); double radiusInDeg = ((Circle) shape).getRadius(); return DistanceUtils.degrees2Dist(radiusInDeg, DistanceUtils.EARTH_MEAN_RADIUS_KM); }
public void write(DataOutputStream dataOutput, Geoshape attribute) throws IOException { if (isJts(attribute.getShape())) { dataOutput.writeByte(0); // note geometries written with writeJtsGeom cannot be deserialized with readShape so to maintain backwards // compatibility with previously written geometries must maintain read/writeJtsGeom for the JtsGeometry case binaryCodec.writeJtsGeom(dataOutput, attribute.getShape()); } else { dataOutput.writeByte(1); binaryCodec.writeShape(dataOutput, attribute.getShape()); } }
/** * Constructs a point from its latitude and longitude information * @param latitude * @param longitude * @return */ public static Geoshape point(final double latitude, final double longitude) { Preconditions.checkArgument(isValidCoordinate(latitude, longitude), "Invalid coordinate provided"); return new Geoshape(getShapeFactory().pointXY(longitude, latitude)); }
@Override public Geoshape createObject(Map<String, Object> data) { final Geoshape shape; if (data.containsKey(FIELD_COORDINATES) && data.get(FIELD_COORDINATES) instanceof List) { final List<Number> coordinates = (List<Number>) data.get(FIELD_COORDINATES); if (coordinates.size() < 2) throw new RuntimeException("Expecting two coordinates when reading point"); shape = Geoshape.point(coordinates.get(1).doubleValue(), coordinates.get(0).doubleValue()); } else { try { final String json = mapWriter.writeValueAsString(data.get("geometry")); shape = new Geoshape(HELPER.getGeojsonReader().read(new StringReader(json))); } catch (IOException | ParseException e) { throw new RuntimeException("I/O exception reading geoshape", e); } } return shape; } }
final Multimap<String, Object> doc1 = getDocument("Hello world", 1001, 5.2, Geoshape.point(48.0, 0.0), Geoshape.polygon(Arrays.asList(new double[][] {{-0.1,47.9},{0.1,47.9},{0.1,48.1},{-0.1,48.1},{-0.1,47.9}})),Arrays.asList("1", "2", "3"), Sets.newHashSet("1", "2"), Instant.ofEpochSecond(1)); final Multimap<String, Object> doc2 = getDocument("Tomorrow is the world", 1010, 8.5, Geoshape.point(49.0, 1.0), Geoshape.line(Arrays.asList(new double[][] {{0.9,48.9},{0.9,49.1},{1.1,49.1},{1.1,48.9}})), Arrays.asList("4", "5", "6"), Sets.newHashSet("4", "5"), Instant.ofEpochSecond(2)); final Multimap<String, Object> doc3 = getDocument("Hello Bob, are you there?", -500, 10.1, Geoshape.point(47.0, 10.0), Geoshape.box(46.9, 9.9, 47.1, 10.1), Arrays.asList("7", "8", "9"), Sets.newHashSet("7", "8"), Instant.ofEpochSecond(3)); result = tx.queryStream(new IndexQuery(store, PredicateCondition.of(LOCATION, Geo.WITHIN, Geoshape.box(46.5, -0.5, 50.5, 10.5)))).collect(Collectors.toList()); assertEquals(3,result.size()); assertEquals(ImmutableSet.of("doc1", "doc2", "doc3"), ImmutableSet.copyOf(result)); result = tx.queryStream(new IndexQuery(store, PredicateCondition.of(LOCATION, Geo.WITHIN, Geoshape.circle(48.5, 0.5, 200.00)))).collect(Collectors.toList()); assertEquals(2, result.size()); assertEquals(ImmutableSet.of("doc1", "doc2"), ImmutableSet.copyOf(result)); result = tx.queryStream(new IndexQuery(store, PredicateCondition.of(BOUNDARY, Geo.WITHIN, Geoshape.box(46.5, -0.5, 50.5, 10.5)))).collect(Collectors.toList()); assertEquals(3,result.size()); assertEquals(ImmutableSet.of("doc1", "doc2", "doc3"), ImmutableSet.copyOf(result)); result = tx.queryStream(new IndexQuery(store, PredicateCondition.of(BOUNDARY, Geo.WITHIN, Geoshape.circle(48.5, 0.5, 200.00)))).collect(Collectors.toList()); assertEquals(2, result.size()); assertEquals(ImmutableSet.of("doc1", "doc2"), ImmutableSet.copyOf(result)); result = tx.queryStream(new IndexQuery(store, PredicateCondition.of(BOUNDARY, Geo.WITHIN, Geoshape.polygon(Arrays.asList(new double[][] {{-5.0,47.0},{5.0,47.0},{5.0,50.0},{-5.0,50.0},{-5.0,47.0}}))))).collect(Collectors.toList()); assertEquals(2, result.size()); result = tx.queryStream(new IndexQuery(store, PredicateCondition.of(BOUNDARY, Geo.DISJOINT, Geoshape.box(46.5, -0.5, 50.5, 10.5)))).collect(Collectors.toList()); assertEquals(0,result.size()); result = tx.queryStream(new IndexQuery(store, PredicateCondition.of(BOUNDARY, Geo.DISJOINT, Geoshape.circle(48.5, 0.5, 200.00)))).collect(Collectors.toList()); assertEquals(1, result.size());
private void testGeo(int i, int origNumV, int numV) { final double offset = (i * 50.0 / origNumV); final double bufferKm = 20; final double distance = Geoshape.point(0.0, 0.0).getPoint().distance(Geoshape.point(offset, offset).getPoint()) + bufferKm; assertCount(i + 1, tx.query().has("location", Geo.WITHIN, Geoshape.circle(0.0, 0.0, distance)).vertices()); assertCount(i + 1, tx.query().has("location", Geo.WITHIN, Geoshape.circle(0.0, 0.0, distance)).edges()); assertCount(i + 1, tx.query().has("location", Geo.INTERSECT, Geoshape.circle(0.0, 0.0, distance)).vertices()); assertCount(i + 1, tx.query().has("location", Geo.INTERSECT, Geoshape.circle(0.0, 0.0, distance)).edges()); assertCount(numV-(i + 1), tx.query().has("location", Geo.DISJOINT, Geoshape.circle(0.0, 0.0, distance)).vertices()); assertCount(numV-(i + 1), tx.query().has("location", Geo.DISJOINT, Geoshape.circle(0.0, 0.0, distance)).edges()); assertCount(i + 1, tx.query().has("boundary", Geo.INTERSECT, Geoshape.circle(0.0, 0.0, distance)).vertices()); assertCount(i + 1, tx.query().has("boundary", Geo.INTERSECT, Geoshape.circle(0.0, 0.0, distance)).edges()); if (i > 0) { assertCount(i, tx.query().has("boundary", Geo.WITHIN, Geoshape.circle(0.0, 0.0, distance-bufferKm)).vertices()); assertCount(i, tx.query().has("boundary", Geo.WITHIN, Geoshape.circle(0.0, 0.0, distance-bufferKm)).edges()); assertCount(numV-(i + 1), tx.query().has("boundary", Geo.DISJOINT, Geoshape.circle(0.0, 0.0, distance)).vertices()); assertCount(numV-(i + 1), tx.query().has("boundary", Geo.DISJOINT, Geoshape.circle(0.0, 0.0, distance)).edges()); assertCount(i % 2, tx.query().has("boundary", Geo.CONTAINS, Geoshape.point(-offset, -offset)).vertices()); assertCount(i % 2, tx.query().has("boundary", Geo.CONTAINS, Geoshape.point(-offset, -offset)).edges()); final double min = -Math.abs(offset); final double max = Math.abs(offset); final Geoshape bufferedBox = Geoshape.box(min-buffer, min-buffer, max+buffer, max+buffer); assertCount(i + 1, tx.query().has("location", Geo.WITHIN, bufferedBox).vertices()); assertCount(i + 1, tx.query().has("location", Geo.WITHIN, bufferedBox).edges()); assertCount(numV-(i + 1), tx.query().has("location", Geo.DISJOINT, bufferedBox).edges());
@SuppressWarnings("unchecked") private static Object convertGeoshape(Geoshape geoshape, Mapping mapping) { if (geoshape.getType() == Geoshape.Type.POINT && Mapping.PREFIX_TREE != mapping) { final Geoshape.Point p = geoshape.getPoint(); return new double[]{p.getLongitude(), p.getLatitude()}; } else if (geoshape.getType() == Geoshape.Type.BOX) { final Rectangle box = geoshape.getShape().getBoundingBox(); final Map<String,Object> map = new HashMap<>(); map.put("type", "envelope"); map.put("coordinates", new double[][] {{box.getMinX(),box.getMaxY()},{box.getMaxX(),box.getMinY()}}); return map; } else if (geoshape.getType() == Geoshape.Type.CIRCLE) { try { final Map<String,Object> map = geoshape.toMap(); map.put("radius", map.get("radius") + ((Map<String, String>) map.remove("properties")).get("radius_units")); return map; } catch (final IOException e) { throw new IllegalArgumentException("Invalid geoshape: " + geoshape, e); } } else { try { return geoshape.toMap(); } catch (final IOException e) { throw new IllegalArgumentException("Invalid geoshape: " + geoshape, e); } } }
switch (shape.getType()) { case CIRCLE: final Geoshape.Point center = shape.getPoint(); query = compat.geoDistance(key, center.getLatitude(), center.getLongitude(), shape.getRadius()); break; case BOX: final Geoshape.Point southwest = shape.getPoint(0); final Geoshape.Point northeast = shape.getPoint(1); query = compat.geoBoundingBox(key, southwest.getLatitude(), southwest.getLongitude(), northeast.getLatitude(), northeast.getLongitude()); break; case POLYGON: final List<List<Double>> points = IntStream.range(0, shape.size()) .mapToObj(i -> ImmutableList.of(shape.getPoint(i).getLongitude(), shape.getPoint(i).getLatitude())) .collect(Collectors.toList()); query = compat.geoPolygon(key, points); default: throw new IllegalArgumentException("Unsupported or invalid search shape type for geopoint: " + shape.getType()); final Geoshape shape = (Geoshape) value; final Map<String,Object> geo; switch (shape.getType()) { case CIRCLE: final Geoshape.Point center = shape.getPoint(); geo = ImmutableMap.of(ES_TYPE_KEY, "circle", ES_GEO_COORDS_KEY, ImmutableList.of(center.getLongitude(), center.getLatitude()),
"Relation not supported on geopoint types: " + predicate); final Geoshape geo = (Geoshape)value; if (geo.getType() == Geoshape.Type.CIRCLE && (predicate == Geo.INTERSECT || map == Mapping.DEFAULT)) { final Geoshape.Point center = geo.getPoint(); return ("{!geofilt sfield=" + key + " pt=" + center.getLatitude() + "," + center.getLongitude() + " d=" + geo.getRadius() + "} distErrPct=0"); //distance in kilometers } else if (geo.getType() == Geoshape.Type.BOX && (predicate == Geo.INTERSECT || map == Mapping.DEFAULT)) { final Geoshape.Point southwest = geo.getPoint(0); final Geoshape.Point northeast = geo.getPoint(1); return (key + ":[" + southwest.getLatitude() + "," + southwest.getLongitude() + " TO " + northeast.getLatitude() + "," + northeast.getLongitude() + "]"); return key + ":\"" + SPATIAL_PREDICATES.get(predicate) + "(" + geo + ")\" distErrPct=0"; } else { throw new IllegalArgumentException("Unsupported or invalid search shape type: " + geo.getType());
case "Point": { double[] parsedCoordinates = convertCollection(coordinates); return point(parsedCoordinates[1], parsedCoordinates[0]); return circle(parsedCoordinates[1], parsedCoordinates[0], radius.doubleValue()); return box(min(p0[1], p1[1], p2[1], p3[1]), min(p0[0], p1[0], p2[0], p3[0]), max(p0[1], p1[1], p2[1], p3[1]), max(p0[0], p1[0], p2[0], p3[0])); return new Geoshape(HELPER.getGeojsonReader().read(new StringReader(json)));
final double distance = Geoshape.point(0.0, 0.0).getPoint().distance(Geoshape.point(offset, offset).getPoint()) + 20; assertCount(5, tx.query().has("location", Geo.INTERSECT, Geoshape.circle(0.0, 0.0, distance)).has("text", Text.CONTAINS, words[0]).vertices()); assertCount(5, tx.query().has("boundary", Geo.INTERSECT, Geoshape.circle(0.0, 0.0, distance)).has("text", Text.CONTAINS, words[0]).vertices());
public Geoshape.Point getPoint(Geoshape geoshape, int position) { Shape shape = geoshape.getShape(); if (position < 0 || position >= size(shape)) throw new ArrayIndexOutOfBoundsException("Invalid position: " + position); switch(getType(shape)) { case POINT: case CIRCLE: return geoshape.getPoint(); case BOX: if (position == 0) .skip(position) .findFirst() .map(entry -> getPoint(new Geoshape(entry.getKey()), entry.getValue())) .orElse(null); default:
@Override public void serialize(Geoshape value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { switch(value.getType()) { case POINT: jgen.writeStartObject(); jgen.writeFieldName(FIELD_TYPE); jgen.writeString(Type.POINT.toString()); jgen.writeFieldName(FIELD_COORDINATES); jgen.writeStartArray(); jgen.writeNumber(value.getPoint().getLongitude()); jgen.writeNumber(value.getPoint().getLatitude()); jgen.writeEndArray(); jgen.writeEndObject(); break; default: jgen.writeRawValue(toGeoJson(value)); break; } }
public static Multimap<String, Object> getRandomDocument() { final StringBuilder s = new StringBuilder(); for (int i = 0; i < 3; i++) s.append(RandomGenerator.randomString(5, 8)).append(" "); final Multimap<String, Object> values = HashMultimap.create(); values.put(TEXT, s.toString()); values.put(NAME, s.toString()); values.put(TIME, Math.abs(random.nextLong())); values.put(WEIGHT, random.nextDouble()); values.put(LOCATION, Geoshape.point(random.nextDouble() * 180 - 90, random.nextDouble() * 360 - 180)); return values; }
v.property(VertexProperty.Cardinality.single, "time", i); offset = (i % 2 == 0 ? 1 : -1) * (i * 50.0 / numV); v.property(VertexProperty.Cardinality.single, "location", Geoshape.point(0.0 + offset, 0.0 + offset)); if (i % 2 == 0) { v.property(VertexProperty.Cardinality.single, "boundary", Geoshape.line(Arrays.asList(new double[][] { {offset-0.1, offset-0.1}, {offset+0.1, offset-0.1}, {offset+0.1, offset+0.1}, {offset-0.1, offset+0.1}}))); } else { v.property(VertexProperty.Cardinality.single, "boundary", Geoshape.polygon(Arrays.asList(new double[][] {{offset-0.1,offset-0.1},{offset+0.1,offset-0.1},{offset+0.1,offset+0.1},{offset-0.1,offset+0.1},{offset-0.1,offset-0.1}}))); e.property("category", i % numCategories); e.property("group", i % numGroups); e.property("location", Geoshape.point(0.0 + offset, 0.0 + offset)); if (i % 2 == 0) { e.property("boundary", Geoshape.line(Arrays.asList(new double[][] { {offset-0.1, offset-0.1}, {offset+0.1, offset-0.1}, {offset+0.1, offset+0.1}, {offset-0.1, offset+0.1}}))); } else { e.property("boundary", Geoshape.polygon(Arrays.asList(new double[][] {{offset-0.1,offset-0.1},{offset+0.1,offset-0.1},{offset+0.1,offset+0.1},{offset-0.1,offset+0.1},{offset-0.1,offset-0.1}})));
@Test public void clearStorageTest() throws Exception { final String store = "vertex"; initialize(store); final Multimap<String, Object> doc1 = getDocument("Hello world", 1001, 5.2, Geoshape.point(48.0, 0.0), Geoshape.polygon(Arrays.asList(new double[][] {{-0.1,47.9},{0.1,47.9},{0.1,48.1},{-0.1,48.1},{-0.1,47.9}})),Arrays.asList("1", "2", "3"), Sets.newHashSet("1", "2"), Instant.ofEpochSecond(1)); add(store, "doc1", doc1, true); clopen(); assertTrue(index.exists()); tearDown(); setUp(); assertFalse(index.exists()); }
public static MultiShapeBuilder<Shape> getGeometryCollectionBuilder() { return getShapeFactory().multiShape(Shape.class); }
@Test public void largeTest() throws Exception { final int numDoc = 30000; final String store = "vertex"; initialize(store); for (int i = 1; i <= numDoc; i++) { add(store, "doc" + i, getRandomDocument(), true); } clopen(); final long time = System.currentTimeMillis(); Stream<String> result = tx.queryStream(new IndexQuery(store, And.of(PredicateCondition.of(WEIGHT, Cmp.GREATER_THAN_EQUAL, 0.2), PredicateCondition.of(WEIGHT, Cmp.LESS_THAN, 0.6), PredicateCondition.of(LOCATION, Geo.WITHIN, Geoshape.circle(48.5, 0.5, 1000.00))))); final long oldResultSize = result.count(); System.out.println(oldResultSize + " vs " + (numDoc / 1000 * 2.4622623015)); System.out.println("Query time on " + numDoc + " docs (ms): " + (System.currentTimeMillis() - time)); result = tx.queryStream(new IndexQuery(store, And.of(PredicateCondition.of(WEIGHT, Cmp.GREATER_THAN_EQUAL, 0.2), PredicateCondition.of(WEIGHT, Cmp.LESS_THAN, 0.6), PredicateCondition.of(LOCATION, Geo.WITHIN, Geoshape.circle(48.5, 0.5, 1000.00))), numDoc / 1000)); assertEquals(numDoc / 1000, result.count()); result = tx.queryStream(new IndexQuery(store, And.of(PredicateCondition.of(WEIGHT, Cmp.GREATER_THAN_EQUAL, 0.2), PredicateCondition.of(WEIGHT, Cmp.LESS_THAN, 0.6), PredicateCondition.of(LOCATION, Geo.WITHIN, Geoshape.circle(48.5, 0.5, 1000.00))), numDoc / 1000 * 100)); assertEquals(oldResultSize, result.count()); }