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 double area(Rectangle rect) { return rect.getArea(null); }
public SpatialRelation relate(Rectangle r) { //Check BBox for disjoint & within. SpatialRelation bboxR = bbox.relate(r); if (bboxR == DISJOINT || bboxR == WITHIN) return bboxR; //Either CONTAINS, INTERSECTS, or DISJOINT Point scratch = new PointImpl(0, 0, null); Point prC = r.getCenter(); SpatialRelation result = linePrimary.relate(r, prC, scratch); if (result == DISJOINT) return DISJOINT; SpatialRelation resultOpp = linePerp.relate(r, prC, scratch); if (resultOpp == DISJOINT) return DISJOINT; if (result == resultOpp)//either CONTAINS or INTERSECTS return result; return INTERSECTS; }
double top = Math.min(queryExtent.getMaxY(), target.getMaxY()); double bottom = Math.max(queryExtent.getMinY(), target.getMinY()); double height = top - bottom; if (height < 0) { if (a.getCrossesDateLine() == b.getCrossesDateLine()) { double left = Math.max(a.getMinX(), b.getMinX()); double right = Math.min(a.getMaxX(), b.getMaxX()); if (!a.getCrossesDateLine()) {//both don't if (left <= right) { width = right - left; } else if (isGeo && (Math.abs(a.getMinX()) == 180 || Math.abs(a.getMaxX()) == 180) && (Math.abs(b.getMinX()) == 180 || Math.abs(b.getMaxX()) == 180)) { width = 0;//both adjacent to dateline } else { if (!a.getCrossesDateLine()) {//then flip a = target; b = queryExtent; double qryWestLeft = Math.max(a.getMinX(), b.getMinX()); double qryWestRight = b.getMaxX(); if (qryWestLeft < qryWestRight) width += qryWestRight - qryWestLeft; double qryEastLeft = b.getMinX(); double qryEastRight = Math.min(a.getMaxX(), b.getMaxX()); if (qryEastLeft < qryEastRight)
final Point cornerPt = ctx.makePoint(inputRect.getMinX(), inputRect.getMinY()); final CellIterator cellIterator = grid.getTreeCellIterator(cornerPt, facetLevel); Cell cornerCell = null; assert cornerRect.hasArea(); double heatMinX = cornerRect.getMinX();//note: we might change this below... final double cellWidth = cornerRect.getWidth(); final Rectangle worldRect = ctx.getWorldBounds(); final int columns = calcRowsOrCols(cellWidth, heatMinX, inputRect.getWidth(), inputRect.getMinX(), worldRect.getWidth()); final double heatMinY = cornerRect.getMinY(); final double cellHeight = cornerRect.getHeight(); final int rows = calcRowsOrCols(cellHeight, heatMinY, inputRect.getHeight(), inputRect.getMinY(), worldRect.getHeight()); assert rows > 0 && columns > 0; if (columns > MAX_ROWS_OR_COLUMNS || rows > MAX_ROWS_OR_COLUMNS || columns * rows > maxCells) { if (columns * cellWidth + halfCellWidth > worldRect.getWidth()) { heatMinX = worldRect.getMinX(); if (Math.abs(heatMaxX - worldRect.getMaxX()) < halfCellWidth) {//numeric conditioning issue heatMaxX = worldRect.getMaxX(); } else if (heatMaxX > worldRect.getMaxX()) {//wraps dateline (won't happen if !geo) heatMaxX = heatMaxX - worldRect.getMaxX() + worldRect.getMinX(); if (Math.abs(heatMaxY - worldRect.getMaxY()) < halfCellHeight) {//numeric conditioning issue heatMaxY = worldRect.getMaxY(); intersectInterval(heatMinY, heatMaxY, cellHeight, rows, rect.getMinY(), rect.getMaxY(), pair); final int startRow = pair[0];
/** Deconstruct the node or list object argument and make a SpatialMatch */ @Override protected SpatialMatch getSpatialMatch(Double latitude, Double longitude, int limit) { SpatialMatch match = new SpatialMatch(SpatialQuery.ctx.getWorldBounds().getMinY(), SpatialQuery.ctx.getWorldBounds().getMinX(), SpatialQuery.ctx.getWorldBounds().getMaxY(), longitude, limit, getSpatialOperation()); return match; }
/** Deconstruct the node or list object argument and make a SpatialMatch */ @Override protected SpatialMatch getSpatialMatch(Double latitude, Double longitude, int limit) { SpatialMatch match = new SpatialMatch(SpatialQuery.ctx.getWorldBounds().getMinY(), SpatialQuery.ctx.getWorldBounds().getMinX(), latitude, SpatialQuery.ctx.getWorldBounds() .getMaxX(), limit, getSpatialOperation()); return match; }
/** Deconstruct the node or list object argument and make a SpatialMatch */ @Override protected SpatialMatch getSpatialMatch(Double latitude, Double longitude, int limit) { SpatialMatch match = new SpatialMatch(latitude, SpatialQuery.ctx .getWorldBounds().getMinX(), SpatialQuery.ctx.getWorldBounds() .getMaxY(), SpatialQuery.ctx.getWorldBounds().getMaxX(), limit, getSpatialOperation()); return match; }
/** Deconstruct the node or list object argument and make a SpatialMatch */ @Override protected SpatialMatch getSpatialMatch(Double latitude, Double longitude, int limit) { SpatialMatch match = new SpatialMatch(SpatialQuery.ctx.getWorldBounds().getMinY(), longitude, SpatialQuery.ctx.getWorldBounds().getMaxY(), SpatialQuery.ctx.getWorldBounds() .getMaxX(), limit, getSpatialOperation()); return match; }
if (enclosingBox.getWidth() == 360) { return relateRectangleCircleWrapsPole(r, ctx); if (!enclosingBox.getCrossesDateLine() && !r.getCrossesDateLine()) { return super.relateRectanglePhase2(r, bboxSect); if (r.getWidth() == 360) { return SpatialRelation.INTERSECTS; if (cornersIntersect == 4) { SpatialRelation xIntersect = r.relateXRange(enclosingBox.getMinX(), enclosingBox.getMaxX()); if (xIntersect == SpatialRelation.WITHIN) return SpatialRelation.CONTAINS; if ( r.relateYRange(getYAxis(), getYAxis()).intersects() // at y vertical && r.relateXRange(enclosingBox.getMinX(), enclosingBox.getMaxX()).intersects() ) return SpatialRelation.INTERSECTS; if (r.relateXRange(getXAxis(), getXAxis()).intersects()) { // at x horizontal double yTop = getCenter().getY()+ radiusDEG; assert yTop <= 90; double yBot = getCenter().getY()- radiusDEG; assert yBot >= -90; if (r.relateYRange(yBot, yTop).intersects())//back bottom return SpatialRelation.INTERSECTS;
/** * 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; }
double yTopOverlap = yTop - 90; assert yTopOverlap <= 90; if (r.getMinY() >= 90 - yTopOverlap) return SpatialRelation.CONTAINS; } else { double yBotOverlap = -90 - yBot; assert yBotOverlap <= 90; if (r.getMaxY() <= -90 + yBotOverlap) return SpatialRelation.CONTAINS; } else { if (r.getWidth() == 360) return SpatialRelation.INTERSECTS; if (cornersIntersect == 4) {//all double backX = frontX <= 0 ? frontX + 180 : frontX - 180; if (r.relateXRange(backX, backX).intersects()) return SpatialRelation.INTERSECTS; else return SpatialRelation.CONTAINS; } else if (cornersIntersect == 0) {//none if (r.relateXRange(frontX, frontX).intersects()) return SpatialRelation.INTERSECTS; else
@Override public void visit(Cell cell, int count) { final double heatMinX = heatmap.region.getMinX(); final Rectangle rect = (Rectangle) cell.getShape(); if (cell.getLevel() == facetLevel) {//heatmap level; count it directly if (rect.getMinX() >= heatMinX) { column = (int) Math.round((rect.getMinX() - heatMinX) / cellWidth); } else { // due to dateline wrap column = (int) Math.round((rect.getMinX() + 360 - heatMinX) / cellWidth); int row = (int) Math.round((rect.getMinY() - heatMinY) / cellHeight); } else if (rect.relate(heatmap.region) == SpatialRelation.CONTAINS) {//containing ancestor allCellsAncestorCount[0] += count;
public GeohashPrefixTree(SpatialContext ctx, int maxLevels) { super(ctx, maxLevels); Rectangle bounds = ctx.getWorldBounds(); if (bounds.getMinX() != -180) throw new IllegalArgumentException("Geohash only supports lat-lon world bounds. Got "+bounds); int MAXP = getMaxLevelsPossible(); if (maxLevels <= 0 || maxLevels > MAXP) throw new IllegalArgumentException("maxLevels must be [1-"+MAXP+"] but got "+ maxLevels); }
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); }
@Override public Point getCenter() { return bbox.getCenter(); }
public static void printRectangleDetails(Rectangle r){ System.out.println("Rectangle 1: " + "\n" + "Width: " + r.width + "\n" + "Height: " + r.height + "\n" + "Color: " + r.color + "\n" + "Area and Perimeter: " + r.getArea(r.width, r.height) + ", " + r.getPerimeter(r.width, r.height)); }