case BOX: if (position == 0) return new Geoshape.Point(shape.getBoundingBox().getMinY(), shape.getBoundingBox().getMinX()); else return new Geoshape.Point(shape.getBoundingBox().getMaxY(), shape.getBoundingBox().getMaxX()); case GEOMETRYCOLLECTION: return ((ShapeCollection<Shape>) shape).getShapes().stream()
@Override public boolean evaluate(Shape indexedShape, Shape queryShape) { Rectangle bbox = indexedShape.getBoundingBox(); return bbox.relate(queryShape) == SpatialRelation.WITHIN || bbox.equals(queryShape); } };
@Override public boolean evaluate(Shape indexedShape, Shape queryShape) { return indexedShape.getBoundingBox().relate(queryShape).intersects(); } };
protected Rectangle computeBoundingBox(Collection<? extends Shape> shapes, SpatialContext ctx) { if (shapes.isEmpty()) return ctx.makeRectangle(Double.NaN, Double.NaN, Double.NaN, Double.NaN); BBoxCalculator bboxCalc = new BBoxCalculator(ctx); for (Shape geom : shapes) { bboxCalc.expandRange(geom.getBoundingBox()); } return bboxCalc.getBoundary(); }
@Override public Rectangle getBoundingBox() { return s.getBoundingBox(); }
@Override public boolean evaluate(Shape indexedShape, Shape queryShape) { Rectangle bbox = indexedShape.getBoundingBox(); return bbox.relate(queryShape) == SpatialRelation.WITHIN || bbox.equals(queryShape); } };
@Override public Field[] createIndexableFields(Shape shape) { return createIndexableFields(shape.getBoundingBox()); }
@Override public Shape convert(Shape shape) { if (shape instanceof Point && (radiusDegrees != 0.0 || plusMinus != 0.0)) { Point point = (Point)shape; double radius = radiusDegrees; if (plusMinus > 0.0) { Random random = new Random(point.hashCode());//use hashCode so it's reproducibly random radius += random.nextDouble() * 2 * plusMinus - plusMinus; radius = Math.abs(radius);//can happen if configured plusMinus > radiusDegrees } shape = spatialStrategy.getSpatialContext().makeCircle(point, radius); } if (bbox) shape = shape.getBoundingBox(); return shape; } };
@Override public boolean evaluate(Shape indexedShape, Shape queryShape) { return indexedShape.getBoundingBox().relate(queryShape).intersects(); } };
@Override public Object execute(Object iThis, OIdentifiable iCurrentRecord, Object iCurrentResult, Object[] iParams, OCommandContext iContext) { Shape shape = factory.fromObject(iParams[0]); return factory.toDoc(shape.getBoundingBox()); }
@Override public Object evaluateRecord(OIdentifiable iRecord, ODocument iCurrentResult, OSQLFilterCondition iCondition, Object iLeft, Object iRight, OCommandContext iContext, final ODocumentSerializer serializer) { Shape shape = factory.fromDoc((ODocument) iLeft); // TODO { 'shape' : { 'type' : 'LineString' , 'coordinates' : [[1,2],[4,6]]} } // TODO is not translated in map but in array[ { 'type' : 'LineString' , 'coordinates' : [[1,2],[4,6]]} ] Object filter; if (iRight instanceof Collection) { filter = ((Collection) iRight).iterator().next(); } else { filter = iRight; } Shape shape1 = factory.fromObject(filter); return SpatialOperation.BBoxIntersects.evaluate(shape, shape1.getBoundingBox()); } }
public double getDistanceForLevel(int level) { if (level < 1 || level > getMaxLevels()) throw new IllegalArgumentException("Level must be in 1 to maxLevels range"); //TODO cache for each level Cell cell = getCell(ctx.getWorldBounds().getCenter(), level); Rectangle bbox = cell.getShape().getBoundingBox(); double width = bbox.getWidth(); double height = bbox.getHeight(); //Use standard cartesian hypotenuse. For geospatial, this answer is larger // than the correct one but it's okay to over-estimate. return Math.sqrt(width * width + height * height); }
@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); } } }
/** * Computes the distance given a shape and the {@code distErrPct}. The * algorithm is the fraction of the distance from the center of the query * shape to its closest bounding box corner. * * @param shape Mandatory. * @param distErrPct 0 to 0.5 * @param ctx Mandatory * @return A distance (in degrees). */ public static double calcDistanceFromErrPct(Shape shape, double distErrPct, SpatialContext ctx) { if (distErrPct < 0 || distErrPct > 0.5) { throw new IllegalArgumentException("distErrPct " + distErrPct + " must be between [0 to 0.5]"); } if (distErrPct == 0 || shape instanceof Point) { return 0; } Rectangle bbox = shape.getBoundingBox(); //Compute the distance from the center to a corner. Because the distance // to a bottom corner vs a top corner can vary in a geospatial scenario, // take the closest one (greater precision). Point ctr = bbox.getCenter(); double y = (ctr.getY() >= 0 ? bbox.getMaxY() : bbox.getMinY()); double diagonalDist = ctx.getDistCalc().distance(ctr, bbox.getMaxX(), y); return diagonalDist * distErrPct; }
@Override public OSpatialQueryContext build(Map<String, Object> query) throws Exception { Shape shape = parseShape(query); SpatialStrategy strategy = manager.strategy(); Number distance = (Number) query.get("distance"); if (distance != null) { shape = shape.getBuffered(distance.doubleValue(), factory.context()); } if (isOnlyBB(strategy)) { shape = shape.getBoundingBox(); } SpatialArgs args1 = new SpatialArgs(SpatialOperation.Intersects, shape); Query filterQuery = strategy.makeQuery(args1); BooleanQuery q = new BooleanQuery.Builder().add(filterQuery, BooleanClause.Occur.MUST) .add(new MatchAllDocsQuery(), BooleanClause.Occur.SHOULD).build(); return new OSpatialQueryContext(null, manager.searcher(), q); }
@Override public OSpatialQueryContext build(Map<String, Object> query) throws Exception { Shape shape = parseShape(query); SpatialStrategy strategy = manager.strategy(); SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects, shape.getBoundingBox()); Query filterQuery = strategy.makeQuery(args); BooleanQuery q = new BooleanQuery.Builder().add(filterQuery, BooleanClause.Occur.MUST) .add(new MatchAllDocsQuery(), BooleanClause.Occur.SHOULD).build(); return new OSpatialQueryContext(null, manager.searcher(), q); }
/** * Returns a ValueSource with values ranging from 1 to 0, depending inversely * on the distance from {@link #makeDistanceValueSource(org.locationtech.spatial4j.shape.Point,double)}. * The formula is {@code c/(d + c)} where 'd' is the distance and 'c' is * one tenth the distance to the farthest edge from the center. Thus the * scores will be 1 for indexed points at the center of the query shape and as * low as ~0.1 at its furthest edges. */ public final DoubleValuesSource makeRecipDistanceValueSource(Shape queryShape) { Rectangle bbox = queryShape.getBoundingBox(); double diagonalDist = ctx.getDistCalc().distance( ctx.makePoint(bbox.getMinX(), bbox.getMinY()), bbox.getMaxX(), bbox.getMaxY()); double distToEdge = diagonalDist * 0.5; float c = (float)distToEdge * 0.1f;//one tenth DoubleValuesSource distance = makeDistanceValueSource(queryShape.getCenter(), 1.0); return new ReciprocalDoubleValuesSource(c, distance); }
@Override public OSpatialQueryContext build(Map<String, Object> query) throws Exception { Shape shape = parseShape(query); SpatialStrategy strategy = manager.strategy(); if (isOnlyBB(strategy)) { shape = shape.getBoundingBox(); } SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects, shape); Query filterQuery = strategy.makeQuery(args); BooleanQuery q = new BooleanQuery.Builder().add(filterQuery, BooleanClause.Occur.MUST) .add(new MatchAllDocsQuery(), BooleanClause.Occur.SHOULD).build(); return new OSpatialQueryContext(null, manager.searcher(), q); }
@Override public OSpatialQueryContext build(Map<String, Object> query) throws Exception { Shape shape = parseShape(query); SpatialStrategy strategy = manager.strategy(); if (isOnlyBB(strategy)) { shape = shape.getBoundingBox(); } SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects, shape); Query filterQuery = strategy.makeQuery(args); BooleanQuery q = new BooleanQuery.Builder().add(filterQuery, BooleanClause.Occur.MUST) .add(new MatchAllDocsQuery(), BooleanClause.Occur.SHOULD).build(); return new OSpatialQueryContext(null, manager.searcher(), q); }
@Override public OSpatialQueryContext build(Map<String, Object> query) throws Exception { Shape shape = parseShape(query); SpatialStrategy strategy = manager.strategy(); if (isOnlyBB(strategy)) { shape = shape.getBoundingBox(); } SpatialArgs args = new SpatialArgs(SpatialOperation.IsWithin, shape); Query filterQuery = strategy.makeQuery(args); BooleanQuery q = new BooleanQuery.Builder().add(filterQuery, BooleanClause.Occur.MUST) .add(new MatchAllDocsQuery(), BooleanClause.Occur.SHOULD).build(); return new OSpatialQueryContext(null, manager.searcher(), q); }