org.apache.lucene.spatial.query.SpatialArgs.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.lucene.spatial.query.SpatialArgs.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.lucene.spatial.query;

import org.locationtech.spatial4j.context.SpatialContext;
import org.locationtech.spatial4j.shape.Point;
import org.locationtech.spatial4j.shape.Rectangle;
import org.locationtech.spatial4j.shape.Shape;

/**
 * Principally holds the query {@link Shape} and the {@link SpatialOperation}.
 * It's used as an argument to some methods on {@link org.apache.lucene.spatial.SpatialStrategy}.
 *
 * @lucene.experimental
 */
public class SpatialArgs {

    public static final double DEFAULT_DISTERRPCT = 0.025d;

    private SpatialOperation operation;
    private Shape shape;
    private Double distErrPct;
    private Double distErr;

    public SpatialArgs(SpatialOperation operation, Shape shape) {
        if (operation == null || shape == null)
            throw new NullPointerException("operation and shape are required");
        this.operation = operation;
        this.shape = shape;
    }

    /**
     * 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;
    }

    /**
     * Gets the error distance that specifies how precise the query shape is. This
     * looks at {@link #getDistErr()}, {@link #getDistErrPct()}, and {@code
     * defaultDistErrPct}.
     * @param defaultDistErrPct 0 to 0.5
     * @return {@code >= 0}
     */
    public double resolveDistErr(SpatialContext ctx, double defaultDistErrPct) {
        if (distErr != null)
            return distErr;
        double distErrPct = (this.distErrPct != null ? this.distErrPct : defaultDistErrPct);
        return calcDistanceFromErrPct(shape, distErrPct, ctx);
    }

    /** Check if the arguments make sense -- throw an exception if not */
    public void validate() throws IllegalArgumentException {
        if (distErr != null && distErrPct != null)
            throw new IllegalArgumentException("Only distErr or distErrPct can be specified.");
    }

    @Override
    public String toString() {
        return SpatialArgsParser.writeSpatialArgs(this);
    }

    //------------------------------------------------
    // Getters & Setters
    //------------------------------------------------

    public SpatialOperation getOperation() {
        return operation;
    }

    public void setOperation(SpatialOperation operation) {
        this.operation = operation;
    }

    public Shape getShape() {
        return shape;
    }

    public void setShape(Shape shape) {
        this.shape = shape;
    }

    /**
     * A measure of acceptable error of the shape as a fraction.  This effectively
     * inflates the size of the shape but should not shrink it.
     *
     * @return 0 to 0.5
     * @see #calcDistanceFromErrPct(org.locationtech.spatial4j.shape.Shape, double,
     *      org.locationtech.spatial4j.context.SpatialContext)
     */
    public Double getDistErrPct() {
        return distErrPct;
    }

    public void setDistErrPct(Double distErrPct) {
        if (distErrPct != null)
            this.distErrPct = distErrPct;
    }

    /**
     * The acceptable error of the shape.  This effectively inflates the
     * size of the shape but should not shrink it.
     *
     * @return {@code >= 0}
     */
    public Double getDistErr() {
        return distErr;
    }

    public void setDistErr(Double distErr) {
        this.distErr = distErr;
    }
}