Skip to content

Commit

Permalink
LUCENE-4167 migrate com.spatial4j.core.query to Lucene spatial. migra…
Browse files Browse the repository at this point in the history
…te UnsupportedSpatialOperation too.

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/branches/branch_4x@1355240 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
dsmiley committed Jun 29, 2012
1 parent 91d0d2a commit c027d29
Show file tree
Hide file tree
Showing 18 changed files with 485 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package org.apache.lucene.spatial;

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
Expand All @@ -15,17 +17,15 @@
* limitations under the License.
*/

package org.apache.lucene.spatial;

import com.spatial4j.core.context.SpatialContext;
import com.spatial4j.core.query.SpatialArgs;
import com.spatial4j.core.shape.Shape;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.queries.function.FunctionQuery;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.FilteredQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.spatial.query.SpatialArgs;

/**
* must be thread safe
Expand Down Expand Up @@ -72,8 +72,8 @@ public IndexableField[] createFields(T fieldInfo, Shape shape, boolean index, bo
/**
* Make a query which has a score based on the distance from the data to the query shape.
* The default implementation constructs a {@link FilteredQuery} based on
* {@link #makeFilter(com.spatial4j.core.query.SpatialArgs, SpatialFieldInfo)} and
* {@link #makeValueSource(com.spatial4j.core.query.SpatialArgs, SpatialFieldInfo)}.
* {@link #makeFilter(org.apache.lucene.spatial.query.SpatialArgs, SpatialFieldInfo)} and
* {@link #makeValueSource(org.apache.lucene.spatial.query.SpatialArgs, SpatialFieldInfo)}.
*/
public Query makeQuery(SpatialArgs args, T fieldInfo) {
Filter filter = makeFilter(args, fieldInfo);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package org.apache.lucene.spatial.prefix;

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
Expand All @@ -15,10 +17,7 @@
* limitations under the License.
*/

package org.apache.lucene.spatial.prefix;

import com.spatial4j.core.distance.DistanceCalculator;
import com.spatial4j.core.query.SpatialArgs;
import com.spatial4j.core.shape.Point;
import com.spatial4j.core.shape.Shape;
import org.apache.lucene.analysis.TokenStream;
Expand All @@ -32,6 +31,7 @@
import org.apache.lucene.spatial.SpatialStrategy;
import org.apache.lucene.spatial.prefix.tree.Node;
import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree;
import org.apache.lucene.spatial.query.SpatialArgs;
import org.apache.lucene.spatial.util.CachedDistanceValueSource;

import java.util.Iterator;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package org.apache.lucene.spatial.prefix;

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
Expand All @@ -15,15 +17,13 @@
* limitations under the License.
*/

package org.apache.lucene.spatial.prefix;

import com.spatial4j.core.exception.UnsupportedSpatialOperation;
import com.spatial4j.core.query.SpatialArgs;
import com.spatial4j.core.query.SpatialOperation;
import com.spatial4j.core.shape.Shape;
import org.apache.lucene.search.Filter;
import org.apache.lucene.spatial.SimpleSpatialFieldInfo;
import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree;
import org.apache.lucene.spatial.query.SpatialArgs;
import org.apache.lucene.spatial.query.SpatialOperation;
import org.apache.lucene.spatial.query.UnsupportedSpatialOperation;

/**
* Based on {@link RecursivePrefixTreeFilter}.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package org.apache.lucene.spatial.prefix;

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
Expand All @@ -15,18 +17,16 @@
* limitations under the License.
*/

package org.apache.lucene.spatial.prefix;

import com.spatial4j.core.exception.UnsupportedSpatialOperation;
import com.spatial4j.core.query.SpatialArgs;
import com.spatial4j.core.query.SpatialOperation;
import com.spatial4j.core.shape.Shape;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.TermsFilter;
import org.apache.lucene.search.Filter;
import org.apache.lucene.spatial.SimpleSpatialFieldInfo;
import org.apache.lucene.spatial.prefix.tree.Node;
import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree;
import org.apache.lucene.spatial.query.SpatialArgs;
import org.apache.lucene.spatial.query.SpatialOperation;
import org.apache.lucene.spatial.query.UnsupportedSpatialOperation;

import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package org.apache.lucene.spatial.prefix.tree;

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
Expand All @@ -15,8 +17,6 @@
* limitations under the License.
*/

package org.apache.lucene.spatial.prefix.tree;

import com.spatial4j.core.context.SpatialContext;
import com.spatial4j.core.shape.Point;
import com.spatial4j.core.shape.Shape;
Expand Down Expand Up @@ -63,7 +63,7 @@ public String toString() {
}

/**
* See {@link com.spatial4j.core.query.SpatialArgs#getDistPrecision()}.
* See {@link org.apache.lucene.spatial.query.SpatialArgs#getDistPrecision()}.
* A grid level looked up via {@link #getLevelForDistance(double)} is returned.
*
* @param precision 0-0.5
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package org.apache.lucene.spatial.query;

/*
* 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.
*/

import com.spatial4j.core.context.SpatialContext;
import com.spatial4j.core.context.simple.SimpleSpatialContext;
import com.spatial4j.core.exception.InvalidSpatialArgument;
import com.spatial4j.core.shape.Shape;

/**
* @lucene.experimental
*/
public class SpatialArgs {

public static final double DEFAULT_DIST_PRECISION = 0.025d;

private SpatialOperation operation;
private Shape shape;
private double distPrecision = DEFAULT_DIST_PRECISION;

// Useful for 'distance' calculations
private Double min;
private Double max;

public SpatialArgs(SpatialOperation operation) {
this.operation = operation;
}

public SpatialArgs(SpatialOperation operation, Shape shape) {
this.operation = operation;
this.shape = shape;
}

/**
* Check if the arguments make sense -- throw an exception if not
*/
public void validate() throws InvalidSpatialArgument {
if (operation.isTargetNeedsArea() && !shape.hasArea()) {
throw new InvalidSpatialArgument(operation + " only supports geometry with area");
}
}

public String toString( SpatialContext context ) {
StringBuilder str = new StringBuilder();
str.append( operation.getName() ).append( '(' );
str.append( context.toString( shape ) );
if( min != null ) {
str.append(" min=").append(min);
}
if( max != null ) {
str.append(" max=").append(max);
}
str.append(" distPrec=").append(String.format("%.2f%%", distPrecision/100d));
str.append( ')' );
return str.toString();
}

@Override
public String toString()
{
return toString( SimpleSpatialContext.GEO_KM );
}

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

public SpatialOperation getOperation() {
return operation;
}

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

/**
* Considers {@link SpatialOperation#BBoxWithin} in returning the shape.
*/
public Shape getShape() {
if (shape != null && (operation == SpatialOperation.BBoxWithin || operation == SpatialOperation.BBoxIntersects))
return shape.getBoundingBox();
return shape;
}

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

/**
* The fraction of the distance from the center of the query shape to its nearest edge that is considered acceptable
* error. The algorithm for computing the distance to the nearest edge is actually a little different. It normalizes
* the shape to a square given it's bounding box area:
* <pre>sqrt(shape.bbox.area)/2</pre>
* And the error distance is beyond the shape such that the shape is a minimum shape.
*/
public Double getDistPrecision() {
return distPrecision;
}

public void setDistPrecision(Double distPrecision) {
if (distPrecision != null)
this.distPrecision = distPrecision;
}

public Double getMin() {
return min;
}

public void setMin(Double min) {
this.min = min;
}

public Double getMax() {
return max;
}

public void setMax(Double max) {
this.max = max;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package org.apache.lucene.spatial.query;

/*
* 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.
*/

import com.spatial4j.core.context.SpatialContext;
import com.spatial4j.core.exception.InvalidShapeException;
import com.spatial4j.core.exception.InvalidSpatialArgument;
import com.spatial4j.core.shape.Shape;

import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

/**
* @lucene.experimental
*/
public class SpatialArgsParser
{
public SpatialArgs parse(String v, SpatialContext ctx) throws InvalidSpatialArgument, InvalidShapeException {
int idx = v.indexOf('(');
int edx = v.lastIndexOf(')');

if (idx < 0 || idx > edx) {
throw new InvalidSpatialArgument("missing parens: " + v, null);
}

SpatialOperation op = SpatialOperation.get(v.substring(0, idx).trim());

String body = v.substring(idx + 1, edx).trim();
if (body.length() < 1) {
throw new InvalidSpatialArgument("missing body : " + v, null);
}

Shape shape = ctx.readShape(body);
SpatialArgs args = new SpatialArgs(op,shape);

if (v.length() > (edx + 1)) {
body = v.substring( edx+1 ).trim();
if (body.length() > 0) {
Map<String,String> aa = parseMap(body);
args.setMin(readDouble(aa.remove("min")) );
args.setMax(readDouble(aa.remove("max")));
args.setDistPrecision(readDouble(aa.remove("distPrec")));
if (!aa.isEmpty()) {
throw new InvalidSpatialArgument("unused parameters: " + aa, null);
}
}
}
return args;
}

protected static Double readDouble(String v) {
return v == null ? null : Double.valueOf(v);
}

protected static boolean readBool(String v, boolean defaultValue) {
return v == null ? defaultValue : Boolean.parseBoolean(v);
}

protected static Map<String,String> parseMap(String body) {
Map<String,String> map = new HashMap<String,String>();
StringTokenizer st = new StringTokenizer(body, " \n\t");
while (st.hasMoreTokens()) {
String a = st.nextToken();
int idx = a.indexOf('=');
if (idx > 0) {
String k = a.substring(0, idx);
String v = a.substring(idx + 1);
map.put(k, v);
} else {
map.put(a, a);
}
}
return map;
}
}
Loading

0 comments on commit c027d29

Please sign in to comment.