All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.lucene.spatial.SpatialStrategy Maven / Gradle / Ivy

There is a newer version: 9.11.1
Show newest version
/*
 * 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;

import org.locationtech.spatial4j.context.SpatialContext;
import org.locationtech.spatial4j.shape.Point;
import org.locationtech.spatial4j.shape.Rectangle;
import org.locationtech.spatial4j.shape.Shape;
import org.apache.lucene.document.Field;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.valuesource.ReciprocalFloatFunction;
import org.apache.lucene.search.Query;
import org.apache.lucene.spatial.query.SpatialArgs;

/**
 * The SpatialStrategy encapsulates an approach to indexing and searching based
 * on shapes.
 * 

* Different implementations will support different features. A strategy should * document these common elements: *

    *
  • Can it index more than one shape per field?
  • *
  • What types of shapes can be indexed?
  • *
  • What types of query shapes can be used?
  • *
  • What types of query operations are supported? * This might vary per shape.
  • *
  • Does it use some type of cache? When? *
* If a strategy only supports certain shapes at index or query time, then in * general it will throw an exception if given an incompatible one. It will not * be coerced into compatibility. *

* Note that a SpatialStrategy is not involved with the Lucene stored field * values of shapes, which is immaterial to indexing and search. *

* Thread-safe. *

* This API is marked as experimental, however it is quite stable. * * @lucene.experimental */ public abstract class SpatialStrategy { protected final SpatialContext ctx; private final String fieldName; /** * Constructs the spatial strategy with its mandatory arguments. */ public SpatialStrategy(SpatialContext ctx, String fieldName) { if (ctx == null) throw new IllegalArgumentException("ctx is required"); this.ctx = ctx; if (fieldName == null || fieldName.length() == 0) throw new IllegalArgumentException("fieldName is required"); this.fieldName = fieldName; } public SpatialContext getSpatialContext() { return ctx; } /** * The name of the field or the prefix of them if there are multiple * fields needed internally. * @return Not null. */ public String getFieldName() { return fieldName; } /** * Returns the IndexableField(s) from the {@code shape} that are to be * added to the {@link org.apache.lucene.document.Document}. These fields * are expected to be marked as indexed and not stored. *

* Note: If you want to store the shape as a string for retrieval in * search results, you could add it like this: *

document.add(new StoredField(fieldName,ctx.toString(shape)));
* The particular string representation used doesn't matter to the Strategy * since it doesn't use it. * * @return Not null nor will it have null elements. * @throws UnsupportedOperationException if given a shape incompatible with the strategy */ public abstract Field[] createIndexableFields(Shape shape); /** * See {@link #makeDistanceValueSource(org.locationtech.spatial4j.shape.Point, double)} called with * a multiplier of 1.0 (i.e. units of degrees). */ public ValueSource makeDistanceValueSource(Point queryPoint) { return makeDistanceValueSource(queryPoint, 1.0); } /** * Make a ValueSource returning the distance between the center of the * indexed shape and {@code queryPoint}. If there are multiple indexed shapes * then the closest one is chosen. The result is multiplied by {@code multiplier}, which * conveniently is used to get the desired units. */ public abstract ValueSource makeDistanceValueSource(Point queryPoint, double multiplier); /** * Make a Query based principally on {@link org.apache.lucene.spatial.query.SpatialOperation} * and {@link Shape} from the supplied {@code args}. It should be constant scoring of 1. * * @throws UnsupportedOperationException If the strategy does not support the shape in {@code args} * @throws org.apache.lucene.spatial.query.UnsupportedSpatialOperation If the strategy does not support the {@link * org.apache.lucene.spatial.query.SpatialOperation} in {@code args}. */ public abstract Query makeQuery(SpatialArgs args); /** * 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 ValueSource 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 return new ReciprocalFloatFunction(makeDistanceValueSource(queryShape.getCenter(), 1.0), 1f, c, c); } @Override public String toString() { return getClass().getSimpleName()+" field:"+fieldName+" ctx="+ctx; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy