You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@lucene.apache.org by Robert Muir <rc...@gmail.com> on 2012/06/28 11:52:24 UTC

Re: svn commit: r1354841 - in /lucene/dev/trunk/lucene/spatial/src: java/org/apache/lucene/spatial/bbox/ test-files/ test-files/data/ test/org/apache/lucene/spatial/ test/org/apache/lucene/spatial/bbox/

This break's hudson's "javadocs-lint" check, because it adds new java
packages without package.html.

On Thu, Jun 28, 2012 at 3:36 AM,  <ry...@apache.org> wrote:
> Author: ryan
> Date: Thu Jun 28 07:36:12 2012
> New Revision: 1354841
>
> URL: http://svn.apache.org/viewvc?rev=1354841&view=rev
> Log:
> LUCENE-4175: adding bbox strategy
>
> Added:
>    lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/
>    lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/AreaSimilarity.java
>    lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxFieldInfo.java
>    lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarity.java
>    lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarityValueSource.java
>    lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxStrategy.java
>    lucene/dev/trunk/lucene/spatial/src/test-files/data/simple-bbox.txt
>    lucene/dev/trunk/lucene/spatial/src/test-files/simple-Queries-BBox.txt
>    lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/bbox/
>    lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/bbox/TestBBoxStrategy.java
> Modified:
>    lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/SpatialTestCase.java
>    lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/StrategyTestCase.java
>
> Added: lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/AreaSimilarity.java
> URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/AreaSimilarity.java?rev=1354841&view=auto
> ==============================================================================
> --- lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/AreaSimilarity.java (added)
> +++ lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/AreaSimilarity.java Thu Jun 28 07:36:12 2012
> @@ -0,0 +1,214 @@
> +/*
> + * 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.bbox;
> +
> +import org.apache.lucene.search.Explanation;
> +
> +import com.spatial4j.core.shape.Rectangle;
> +
> +/**
> + * The algorithm is implemented as envelope on envelope overlays rather than
> + * complex polygon on complex polygon overlays.
> + * <p/>
> + * <p/>
> + * Spatial relevance scoring algorithm:
> + * <p/>
> + * <br/>  queryArea = the area of the input query envelope
> + * <br/>  targetArea = the area of the target envelope (per Lucene document)
> + * <br/>  intersectionArea = the area of the intersection for the query/target envelopes
> + * <br/>  queryPower = the weighting power associated with the query envelope (default = 1.0)
> + * <br/>  targetPower =  the weighting power associated with the target envelope (default = 1.0)
> + * <p/>
> + * <br/>  queryRatio  = intersectionArea / queryArea;
> + * <br/>  targetRatio = intersectionArea / targetArea;
> + * <br/>  queryFactor  = Math.pow(queryRatio,queryPower);
> + * <br/>  targetFactor = Math.pow(targetRatio,targetPower);
> + * <br/>  score = queryFactor * targetFactor;
> + * <p/>
> + * original:
> + * http://geoportal.svn.sourceforge.net/svnroot/geoportal/Geoportal/trunk/src/com/esri/gpt/catalog/lucene/SpatialRankingValueSource.java
> + */
> +public class AreaSimilarity implements BBoxSimilarity {
> +  /**
> +   * Properties associated with the query envelope
> +   */
> +  private final Rectangle queryExtent;
> +  private final double queryArea;
> +
> +  private final double targetPower;
> +  private final double queryPower;
> +
> +  public AreaSimilarity(Rectangle queryExtent, double queryPower, double targetPower) {
> +    this.queryExtent = queryExtent;
> +    this.queryArea = queryExtent.getArea();
> +
> +    this.queryPower = queryPower;
> +    this.targetPower = targetPower;
> +
> +//  if (this.qryMinX > queryExtent.getMaxX()) {
> +//    this.qryCrossedDateline = true;
> +//    this.qryArea = Math.abs(qryMaxX + 360.0 - qryMinX) * Math.abs(qryMaxY - qryMinY);
> +//  } else {
> +//    this.qryArea = Math.abs(qryMaxX - qryMinX) * Math.abs(qryMaxY - qryMinY);
> +//  }
> +  }
> +
> +  public AreaSimilarity(Rectangle queryExtent) {
> +    this(queryExtent, 2.0, 0.5);
> +  }
> +
> +
> +  public String getDelimiterQueryParameters() {
> +    return queryExtent.toString() + ";" + queryPower + ";" + targetPower;
> +  }
> +
> +  @Override
> +  public double score(Rectangle target, Explanation exp) {
> +    if (target == null || queryArea <= 0) {
> +      return 0;
> +    }
> +    double targetArea = target.getArea();
> +    if (targetArea <= 0) {
> +      return 0;
> +    }
> +    double score = 0;
> +
> +    double top = Math.min(queryExtent.getMaxY(), target.getMaxY());
> +    double bottom = Math.max(queryExtent.getMinY(), target.getMinY());
> +    double height = top - bottom;
> +    double width = 0;
> +
> +    // queries that cross the date line
> +    if (queryExtent.getCrossesDateLine()) {
> +      // documents that cross the date line
> +      if (target.getCrossesDateLine()) {
> +        double left = Math.max(queryExtent.getMinX(), target.getMinX());
> +        double right = Math.min(queryExtent.getMaxX(), target.getMaxX());
> +        width = right + 360.0 - left;
> +      } else {
> +        double qryWestLeft = Math.max(queryExtent.getMinX(), target.getMaxX());
> +        double qryWestRight = Math.min(target.getMaxX(), 180.0);
> +        double qryWestWidth = qryWestRight - qryWestLeft;
> +        if (qryWestWidth > 0) {
> +          width = qryWestWidth;
> +        } else {
> +          double qryEastLeft = Math.max(target.getMaxX(), -180.0);
> +          double qryEastRight = Math.min(queryExtent.getMaxX(), target.getMaxX());
> +          double qryEastWidth = qryEastRight - qryEastLeft;
> +          if (qryEastWidth > 0) {
> +            width = qryEastWidth;
> +          }
> +        }
> +      }
> +    } else { // queries that do not cross the date line
> +
> +      if (target.getCrossesDateLine()) {
> +        double tgtWestLeft = Math.max(queryExtent.getMinX(), target.getMinX());
> +        double tgtWestRight = Math.min(queryExtent.getMaxX(), 180.0);
> +        double tgtWestWidth = tgtWestRight - tgtWestLeft;
> +        if (tgtWestWidth > 0) {
> +          width = tgtWestWidth;
> +        } else {
> +          double tgtEastLeft = Math.max(queryExtent.getMinX(), -180.0);
> +          double tgtEastRight = Math.min(queryExtent.getMaxX(), target.getMaxX());
> +          double tgtEastWidth = tgtEastRight - tgtEastLeft;
> +          if (tgtEastWidth > 0) {
> +            width = tgtEastWidth;
> +          }
> +        }
> +      } else {
> +        double left = Math.max(queryExtent.getMinX(), target.getMinX());
> +        double right = Math.min(queryExtent.getMaxX(), target.getMaxX());
> +        width = right - left;
> +      }
> +    }
> +
> +
> +    // calculate the score
> +    if ((width > 0) && (height > 0)) {
> +      double intersectionArea = width * height;
> +      double queryRatio = intersectionArea / queryArea;
> +      double targetRatio = intersectionArea / targetArea;
> +      double queryFactor = Math.pow(queryRatio, queryPower);
> +      double targetFactor = Math.pow(targetRatio, targetPower);
> +      score = queryFactor * targetFactor * 10000.0;
> +
> +      if (exp!=null) {
> +//        StringBuilder sb = new StringBuilder();
> +//        sb.append("\nscore=").append(score);
> +//        sb.append("\n  query=").append();
> +//        sb.append("\n  target=").append(target.toString());
> +//        sb.append("\n  intersectionArea=").append(intersectionArea);
> +//
> +//        sb.append(" queryArea=").append(queryArea).append(" targetArea=").append(targetArea);
> +//        sb.append("\n  queryRatio=").append(queryRatio).append(" targetRatio=").append(targetRatio);
> +//        sb.append("\n  queryFactor=").append(queryFactor).append(" targetFactor=").append(targetFactor);
> +//        sb.append(" (queryPower=").append(queryPower).append(" targetPower=").append(targetPower).append(")");
> +
> +        exp.setValue((float)score);
> +        exp.setDescription(this.getClass().getSimpleName());
> +
> +        Explanation e = null;
> +
> +        exp.addDetail( e = new Explanation((float)intersectionArea, "IntersectionArea") );
> +        e.addDetail(new Explanation((float)width,  "width; Query: "+queryExtent.toString()));
> +        e.addDetail(new Explanation((float)height, "height; Target: "+target.toString()));
> +
> +        exp.addDetail( e = new Explanation((float)queryFactor, "Query") );
> +        e.addDetail(new Explanation((float)queryArea, "area"));
> +        e.addDetail(new Explanation((float)queryRatio, "ratio"));
> +        e.addDetail(new Explanation((float)queryPower, "power"));
> +
> +        exp.addDetail( e = new Explanation((float)targetFactor, "Target") );
> +        e.addDetail(new Explanation((float)targetArea, "area"));
> +        e.addDetail(new Explanation((float)targetRatio, "ratio"));
> +        e.addDetail(new Explanation((float)targetPower, "power"));
> +      }
> +    }
> +    else if(exp !=null) {
> +      exp.setValue(0);
> +      exp.setDescription("Shape does not intersect");
> +    }
> +    return score;
> +  }
> +
> +
> +  /**
> +   * Determines if this ValueSource is equal to another.
> +   *
> +   * @param o the ValueSource to compare
> +   * @return <code>true</code> if the two objects are based upon the same query envelope
> +   */
> +  @Override
> +  public boolean equals(Object o) {
> +    if (o.getClass() != AreaSimilarity.class)
> +      return false;
> +
> +    AreaSimilarity other = (AreaSimilarity) o;
> +    return getDelimiterQueryParameters().equals(other.getDelimiterQueryParameters());
> +  }
> +
> +  /**
> +   * Returns the ValueSource hash code.
> +   *
> +   * @return the hash code
> +   */
> +  @Override
> +  public int hashCode() {
> +    return getDelimiterQueryParameters().hashCode();
> +  }
> +}
>
> Added: lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxFieldInfo.java
> URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxFieldInfo.java?rev=1354841&view=auto
> ==============================================================================
> --- lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxFieldInfo.java (added)
> +++ lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxFieldInfo.java Thu Jun 28 07:36:12 2012
> @@ -0,0 +1,57 @@
> +/*
> + * 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.bbox;
> +
> +import org.apache.lucene.spatial.SpatialFieldInfo;
> +
> +
> +/**
> + * The Bounding Box gets stored as four fields for x/y min/max and a flag
> + * that says if the box crosses the dateline (xdl)
> + */
> +public class BBoxFieldInfo implements SpatialFieldInfo {
> +
> +  public static final String SUFFIX_MINX = "__minX";
> +  public static final String SUFFIX_MAXX = "__maxX";
> +  public static final String SUFFIX_MINY = "__minY";
> +  public static final String SUFFIX_MAXY = "__maxY";
> +  public static final String SUFFIX_XDL  = "__xdl";
> +
> +  public String bbox = "bbox";
> +  public String minX = "bbox.minx";
> +  public String minY = "bbox.miny";
> +  public String maxX = "bbox.maxx";
> +  public String maxY = "bbox.maxy";
> +  public String xdl  = "bbox.xdl"; // crosses dateline
> +
> +  public BBoxFieldInfo() {
> +
> +  }
> +
> +  public BBoxFieldInfo( String p ) {
> +    this.setFieldsPrefix( p );
> +  }
> +
> +  public void setFieldsPrefix(String prefix) {
> +    bbox = prefix;
> +    minX = prefix + SUFFIX_MINX;
> +    maxX = prefix + SUFFIX_MAXX;
> +    minY = prefix + SUFFIX_MINY;
> +    maxY = prefix + SUFFIX_MAXY;
> +    xdl  = prefix + SUFFIX_XDL;
> +  }
> +}
>
> Added: lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarity.java
> URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarity.java?rev=1354841&view=auto
> ==============================================================================
> --- lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarity.java (added)
> +++ lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarity.java Thu Jun 28 07:36:12 2012
> @@ -0,0 +1,28 @@
> +/*
> + * 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.bbox;
> +
> +import org.apache.lucene.search.Explanation;
> +
> +import com.spatial4j.core.shape.Rectangle;
> +
> +
> +
> +public interface BBoxSimilarity {
> +
> +  public double score(Rectangle extent, Explanation exp);
> +}
>
> Added: lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarityValueSource.java
> URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarityValueSource.java?rev=1354841&view=auto
> ==============================================================================
> --- lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarityValueSource.java (added)
> +++ lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarityValueSource.java Thu Jun 28 07:36:12 2012
> @@ -0,0 +1,134 @@
> +/*
> + * 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.bbox;
> +
> +import java.io.IOException;
> +import java.util.Map;
> +
> +import org.apache.lucene.index.AtomicReader;
> +import org.apache.lucene.index.AtomicReaderContext;
> +import org.apache.lucene.queries.function.FunctionValues;
> +import org.apache.lucene.queries.function.ValueSource;
> +import org.apache.lucene.search.Explanation;
> +import org.apache.lucene.search.FieldCache;
> +import org.apache.lucene.util.Bits;
> +
> +import com.spatial4j.core.shape.Rectangle;
> +import com.spatial4j.core.shape.simple.RectangleImpl;
> +
> +/**
> + * An implementation of the Lucene ValueSource model to support spatial relevance ranking.
> + */
> +public class BBoxSimilarityValueSource extends ValueSource {
> +
> +  private final BBoxFieldInfo field;
> +  private final BBoxSimilarity similarity;
> +
> +  /**
> +   * Constructor.
> +   *
> +   * @param queryEnvelope the query envelope
> +   * @param queryPower the query power (scoring algorithm)
> +   * @param targetPower the target power (scoring algorithm)
> +   */
> +  public BBoxSimilarityValueSource(BBoxSimilarity similarity, BBoxFieldInfo field) {
> +    this.similarity = similarity;
> +    this.field = field;
> +  }
> +
> +  /**
> +   * Returns the ValueSource description.
> +   *
> +   * @return the description
> +   */
> +  @Override
> +  public String description() {
> +    return "BBoxSimilarityValueSource(" + similarity + ")";
> +  }
> +
> +
> +  /**
> +   * Returns the DocValues used by the function query.
> +   *
> +   * @param reader the index reader
> +   * @return the values
> +   */
> +  @Override
> +  public FunctionValues getValues(Map context, AtomicReaderContext readerContext) throws IOException {
> +    AtomicReader reader = readerContext.reader();
> +    final double[] minX = FieldCache.DEFAULT.getDoubles(reader, field.minX, true);
> +    final double[] minY = FieldCache.DEFAULT.getDoubles(reader, field.minY, true);
> +    final double[] maxX = FieldCache.DEFAULT.getDoubles(reader, field.maxX, true);
> +    final double[] maxY = FieldCache.DEFAULT.getDoubles(reader, field.maxY, true);
> +
> +    final Bits validMinX = FieldCache.DEFAULT.getDocsWithField(reader, field.minX);
> +    final Bits validMaxX = FieldCache.DEFAULT.getDocsWithField(reader, field.maxX);
> +
> +    return new FunctionValues() {
> +      @Override
> +      public float floatVal(int doc) {
> +        // make sure it has minX and area
> +        if (validMinX.get(doc) && validMaxX.get(doc)) {
> +          Rectangle rect = new RectangleImpl(
> +              minX[doc], maxX[doc],
> +              minY[doc], maxY[doc]);
> +          return (float) similarity.score(rect, null);
> +        }
> +        return 0;
> +      }
> +
> +      public Explanation explain(int doc) {
> +        // make sure it has minX and area
> +        if (validMinX.get(doc) && validMaxX.get(doc)) {
> +          Rectangle rect = new RectangleImpl(
> +              minX[doc], maxX[doc],
> +              minY[doc], maxY[doc]);
> +          Explanation exp = new Explanation();
> +          similarity.score(rect, exp);
> +          return exp;
> +        }
> +        return new Explanation(0, "No BBox");
> +      }
> +
> +      @Override
> +      public String toString(int doc) {
> +        return description() + "=" + floatVal(doc);
> +      }
> +    };
> +  }
> +
> +  /**
> +   * Determines if this ValueSource is equal to another.
> +   *
> +   * @param o the ValueSource to compare
> +   * @return <code>true</code> if the two objects are based upon the same query envelope
> +   */
> +  @Override
> +  public boolean equals(Object o) {
> +    if (o.getClass() != BBoxSimilarityValueSource.class) {
> +      return false;
> +    }
> +
> +    BBoxSimilarityValueSource other = (BBoxSimilarityValueSource) o;
> +    return similarity.equals(other.similarity);
> +  }
> +
> +  @Override
> +  public int hashCode() {
> +    return BBoxSimilarityValueSource.class.hashCode() + similarity.hashCode();
> +  }
> +}
>
> Added: lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxStrategy.java
> URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxStrategy.java?rev=1354841&view=auto
> ==============================================================================
> --- lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxStrategy.java (added)
> +++ lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxStrategy.java Thu Jun 28 07:36:12 2012
> @@ -0,0 +1,472 @@
> +/*
> + * 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.bbox;
> +
> +import java.text.NumberFormat;
> +import java.util.Locale;
> +
> +import org.apache.lucene.document.Field;
> +import org.apache.lucene.document.FieldType;
> +import org.apache.lucene.index.FieldInfo.IndexOptions;
> +import org.apache.lucene.index.IndexableField;
> +import org.apache.lucene.index.Term;
> +import org.apache.lucene.queries.function.FunctionQuery;
> +import org.apache.lucene.queries.function.ValueSource;
> +import org.apache.lucene.search.BooleanClause;
> +import org.apache.lucene.search.BooleanQuery;
> +import org.apache.lucene.search.ConstantScoreQuery;
> +import org.apache.lucene.search.Filter;
> +import org.apache.lucene.search.NumericRangeQuery;
> +import org.apache.lucene.search.Query;
> +import org.apache.lucene.search.QueryWrapperFilter;
> +import org.apache.lucene.search.TermQuery;
> +import org.apache.lucene.spatial.SpatialStrategy;
> +import org.apache.lucene.spatial.util.NumericFieldInfo;
> +
> +import com.spatial4j.core.context.*;
> +import com.spatial4j.core.exception.UnsupportedSpatialOperation;
> +import com.spatial4j.core.query.*;
> +import com.spatial4j.core.shape.*;
> +
> +
> +/**
> + * original:
> + * http://geoportal.svn.sourceforge.net/svnroot/geoportal/Geoportal/trunk/src/com/esri/gpt/catalog/lucene/SpatialClauseAdapter.java
> + */
> +public class BBoxStrategy extends SpatialStrategy<BBoxFieldInfo> {
> +  public double queryPower = 1.0;
> +  public double targetPower = 1.0f;
> +
> +  public NumericFieldInfo finfo = null;
> +
> +  public BBoxStrategy(SpatialContext ctx) {
> +    super(ctx);
> +  }
> +
> +  //---------------------------------
> +  // Indexing
> +  //---------------------------------
> +
> +  @Override
> +  public IndexableField[] createFields(BBoxFieldInfo fieldInfo,
> +      Shape shape, boolean index, boolean store) {
> +
> +    Rectangle bbox = shape.getBoundingBox();
> +    IndexableField[] fields = new IndexableField[store?6:5];
> +    fields[0] = finfo.createDouble(fieldInfo.minX, bbox.getMinX());
> +    fields[1] = finfo.createDouble(fieldInfo.maxX, bbox.getMaxX());
> +    fields[2] = finfo.createDouble(fieldInfo.minY, bbox.getMinY());
> +    fields[3] = finfo.createDouble(fieldInfo.maxY, bbox.getMaxY());
> +
> +    FieldType ft = new FieldType();
> +    ft.setIndexed(index);
> +    ft.setStored(store);
> +    ft.setTokenized(false);
> +    ft.setOmitNorms(true);
> +    ft.setIndexOptions(IndexOptions.DOCS_ONLY);
> +    ft.freeze();
> +
> +    Field xdl = new Field( fieldInfo.xdl, bbox.getCrossesDateLine()?"T":"F", ft );
> +    fields[4] = xdl;
> +    if( store ) {
> +      FieldType ff = new FieldType();
> +      ff.setIndexed(false);
> +      ff.setStored(true);
> +      ff.setOmitNorms(true);
> +      ff.setIndexOptions(IndexOptions.DOCS_ONLY);
> +      ff.freeze();
> +
> +      NumberFormat nf = NumberFormat.getInstance( Locale.US );
> +      nf.setMaximumFractionDigits( 5 );
> +      nf.setMinimumFractionDigits( 5 );
> +      nf.setGroupingUsed(false);
> +      String ext =
> +        nf.format( bbox.getMinX() ) + ' ' +
> +        nf.format( bbox.getMinY() ) + ' ' +
> +        nf.format( bbox.getMaxX() ) + ' ' +
> +        nf.format( bbox.getMaxY() ) + ' ';
> +      fields[5] = new Field( fieldInfo.bbox, ext, ff );
> +    }
> +    return fields;
> +  }
> +
> +  @Override
> +  public IndexableField createField(BBoxFieldInfo fieldInfo, Shape shape,
> +      boolean index, boolean store) {
> +    throw new UnsupportedOperationException("BBOX is poly field");
> +  }
> +
> +  @Override
> +  public boolean isPolyField() {
> +    return true;
> +  }
> +
> +  //---------------------------------
> +  // Query Builder
> +  //---------------------------------
> +
> +  @Override
> +  public ValueSource makeValueSource(SpatialArgs args, BBoxFieldInfo fields) {
> +    return new BBoxSimilarityValueSource(
> +        new AreaSimilarity(args.getShape().getBoundingBox(), queryPower, targetPower), fields );
> +  }
> +
> +
> +  @Override
> +  public Filter makeFilter(SpatialArgs args, BBoxFieldInfo fieldInfo) {
> +    Query spatial = makeSpatialQuery(args, fieldInfo);
> +    return new QueryWrapperFilter( spatial );
> +  }
> +
> +  @Override
> +  public Query makeQuery(SpatialArgs args, BBoxFieldInfo fieldInfo) {
> +    BooleanQuery bq = new BooleanQuery();
> +    Query spatial = makeSpatialQuery(args, fieldInfo);
> +    bq.add(new ConstantScoreQuery(spatial), BooleanClause.Occur.MUST);
> +
> +    // This part does the scoring
> +    Query spatialRankingQuery = new FunctionQuery(makeValueSource(args, fieldInfo));
> +    bq.add(spatialRankingQuery, BooleanClause.Occur.MUST);
> +    return bq;
> +  }
> +
> +
> +  private Query makeSpatialQuery(SpatialArgs args, BBoxFieldInfo fieldInfo) {
> +    Rectangle bbox = args.getShape().getBoundingBox();
> +    Query spatial = null;
> +
> +    // Useful for understanding Relations:
> +    // http://edndoc.esri.com/arcsde/9.1/general_topics/understand_spatial_relations.htm
> +    SpatialOperation op = args.getOperation();
> +         if( op == SpatialOperation.BBoxIntersects ) spatial = makeIntersects(bbox, fieldInfo);
> +    else if( op == SpatialOperation.BBoxWithin     ) spatial = makeWithin(bbox, fieldInfo);
> +    else if( op == SpatialOperation.Contains       ) spatial = makeContains(bbox, fieldInfo);
> +    else if( op == SpatialOperation.Intersects     ) spatial = makeIntersects(bbox, fieldInfo);
> +    else if( op == SpatialOperation.IsEqualTo      ) spatial = makeEquals(bbox, fieldInfo);
> +    else if( op == SpatialOperation.IsDisjointTo   ) spatial = makeDisjoint(bbox, fieldInfo);
> +    else if( op == SpatialOperation.IsWithin       ) spatial = makeWithin(bbox, fieldInfo);
> +    else if( op == SpatialOperation.Overlaps       ) spatial = makeIntersects(bbox, fieldInfo);
> +    else {
> +        throw new UnsupportedSpatialOperation(op);
> +    }
> +    return spatial;
> +  }
> +
> +
> +  //-------------------------------------------------------------------------------
> +  //
> +  //-------------------------------------------------------------------------------
> +
> +  /**
> +   * Constructs a query to retrieve documents that fully contain the input envelope.
> +   *
> +   * @return the spatial query
> +   */
> +  Query makeContains(Rectangle bbox, BBoxFieldInfo fieldInfo) {
> +
> +    // general case
> +    // docMinX <= queryExtent.getMinX() AND docMinY <= queryExtent.getMinY() AND docMaxX >= queryExtent.getMaxX() AND docMaxY >= queryExtent.getMaxY()
> +
> +    // Y conditions
> +    // docMinY <= queryExtent.getMinY() AND docMaxY >= queryExtent.getMaxY()
> +    Query qMinY = NumericRangeQuery.newDoubleRange(fieldInfo.minY, finfo.precisionStep, null, bbox.getMinY(), false, true);
> +    Query qMaxY = NumericRangeQuery.newDoubleRange(fieldInfo.maxY, finfo.precisionStep, bbox.getMaxY(), null, true, false);
> +    Query yConditions = this.makeQuery(new Query[]{qMinY, qMaxY}, BooleanClause.Occur.MUST);
> +
> +    // X conditions
> +    Query xConditions = null;
> +
> +    // queries that do not cross the date line
> +    if (!bbox.getCrossesDateLine()) {
> +
> +      // X Conditions for documents that do not cross the date line,
> +      // documents that contain the min X and max X of the query envelope,
> +      // docMinX <= queryExtent.getMinX() AND docMaxX >= queryExtent.getMaxX()
> +      Query qMinX = NumericRangeQuery.newDoubleRange(fieldInfo.minX, finfo.precisionStep, null, bbox.getMinX(), false, true);
> +      Query qMaxX = NumericRangeQuery.newDoubleRange(fieldInfo.maxX, finfo.precisionStep, bbox.getMaxX(), null, true, false);
> +      Query qMinMax = this.makeQuery(new Query[]{qMinX, qMaxX}, BooleanClause.Occur.MUST);
> +      Query qNonXDL = this.makeXDL(false, qMinMax, fieldInfo);
> +
> +      // X Conditions for documents that cross the date line,
> +      // the left portion of the document contains the min X of the query
> +      // OR the right portion of the document contains the max X of the query,
> +      // docMinXLeft <= queryExtent.getMinX() OR docMaxXRight >= queryExtent.getMaxX()
> +      Query qXDLLeft = NumericRangeQuery.newDoubleRange(fieldInfo.minX, finfo.precisionStep, null, bbox.getMinX(), false, true);
> +      Query qXDLRight = NumericRangeQuery.newDoubleRange(fieldInfo.maxX, finfo.precisionStep, bbox.getMaxX(), null, true, false);
> +      Query qXDLLeftRight = this.makeQuery(new Query[]{qXDLLeft, qXDLRight}, BooleanClause.Occur.SHOULD);
> +      Query qXDL = this.makeXDL(true, qXDLLeftRight, fieldInfo);
> +
> +      // apply the non-XDL and XDL conditions
> +      xConditions = this.makeQuery(new Query[]{qNonXDL, qXDL}, BooleanClause.Occur.SHOULD);
> +
> +      // queries that cross the date line
> +    } else {
> +
> +      // No need to search for documents that do not cross the date line
> +
> +      // X Conditions for documents that cross the date line,
> +      // the left portion of the document contains the min X of the query
> +      // AND the right portion of the document contains the max X of the query,
> +      // docMinXLeft <= queryExtent.getMinX() AND docMaxXRight >= queryExtent.getMaxX()
> +      Query qXDLLeft = NumericRangeQuery.newDoubleRange(fieldInfo.minX, finfo.precisionStep, null, bbox.getMinX(), false, true);
> +      Query qXDLRight = NumericRangeQuery.newDoubleRange(fieldInfo.maxX, finfo.precisionStep, bbox.getMaxX(), null, true, false);
> +      Query qXDLLeftRight = this.makeQuery(new Query[]{qXDLLeft, qXDLRight}, BooleanClause.Occur.MUST);
> +
> +      xConditions = this.makeXDL(true, qXDLLeftRight, fieldInfo);
> +    }
> +
> +    // both X and Y conditions must occur
> +    return this.makeQuery(new Query[]{xConditions, yConditions}, BooleanClause.Occur.MUST);
> +  }
> +
> +  /**
> +   * Constructs a query to retrieve documents that are disjoint to the input envelope.
> +   *
> +   * @return the spatial query
> +   */
> +  Query makeDisjoint(Rectangle bbox, BBoxFieldInfo fieldInfo) {
> +
> +    // general case
> +    // docMinX > queryExtent.getMaxX() OR docMaxX < queryExtent.getMinX() OR docMinY > queryExtent.getMaxY() OR docMaxY < queryExtent.getMinY()
> +
> +    // Y conditions
> +    // docMinY > queryExtent.getMaxY() OR docMaxY < queryExtent.getMinY()
> +    Query qMinY = NumericRangeQuery.newDoubleRange(fieldInfo.minY, finfo.precisionStep, bbox.getMaxY(), null, false, false);
> +    Query qMaxY = NumericRangeQuery.newDoubleRange(fieldInfo.maxY, finfo.precisionStep, null, bbox.getMinY(), false, false);
> +    Query yConditions = this.makeQuery(new Query[]{qMinY, qMaxY}, BooleanClause.Occur.SHOULD);
> +
> +    // X conditions
> +    Query xConditions = null;
> +
> +    // queries that do not cross the date line
> +    if (!bbox.getCrossesDateLine()) {
> +
> +      // X Conditions for documents that do not cross the date line,
> +      // docMinX > queryExtent.getMaxX() OR docMaxX < queryExtent.getMinX()
> +      Query qMinX = NumericRangeQuery.newDoubleRange(fieldInfo.minX, finfo.precisionStep, bbox.getMaxX(), null, false, false);
> +      Query qMaxX = NumericRangeQuery.newDoubleRange(fieldInfo.maxX, finfo.precisionStep, null, bbox.getMinX(), false, false);
> +      Query qMinMax = this.makeQuery(new Query[]{qMinX, qMaxX}, BooleanClause.Occur.SHOULD);
> +      Query qNonXDL = this.makeXDL(false, qMinMax, fieldInfo);
> +
> +      // X Conditions for documents that cross the date line,
> +      // both the left and right portions of the document must be disjoint to the query
> +      // (docMinXLeft > queryExtent.getMaxX() OR docMaxXLeft < queryExtent.getMinX()) AND
> +      // (docMinXRight > queryExtent.getMaxX() OR docMaxXRight < queryExtent.getMinX())
> +      // where: docMaxXLeft = 180.0, docMinXRight = -180.0
> +      // (docMaxXLeft  < queryExtent.getMinX()) equates to (180.0  < queryExtent.getMinX()) and is ignored
> +      // (docMinXRight > queryExtent.getMaxX()) equates to (-180.0 > queryExtent.getMaxX()) and is ignored
> +      Query qMinXLeft = NumericRangeQuery.newDoubleRange(fieldInfo.minX, finfo.precisionStep, bbox.getMaxX(), null, false, false);
> +      Query qMaxXRight = NumericRangeQuery.newDoubleRange(fieldInfo.maxX, finfo.precisionStep, null, bbox.getMinX(), false, false);
> +      Query qLeftRight = this.makeQuery(new Query[]{qMinXLeft, qMaxXRight}, BooleanClause.Occur.MUST);
> +      Query qXDL = this.makeXDL(true, qLeftRight, fieldInfo);
> +
> +      // apply the non-XDL and XDL conditions
> +      xConditions = this.makeQuery(new Query[]{qNonXDL, qXDL}, BooleanClause.Occur.SHOULD);
> +
> +      // queries that cross the date line
> +    } else {
> +
> +      // X Conditions for documents that do not cross the date line,
> +      // the document must be disjoint to both the left and right query portions
> +      // (docMinX > queryExtent.getMaxX()Left OR docMaxX < queryExtent.getMinX()) AND (docMinX > queryExtent.getMaxX() OR docMaxX < queryExtent.getMinX()Left)
> +      // where: queryExtent.getMaxX()Left = 180.0, queryExtent.getMinX()Left = -180.0
> +      Query qMinXLeft = NumericRangeQuery.newDoubleRange(fieldInfo.minX, finfo.precisionStep, 180.0, null, false, false);
> +      Query qMaxXLeft = NumericRangeQuery.newDoubleRange(fieldInfo.maxX, finfo.precisionStep, null, bbox.getMinX(), false, false);
> +      Query qMinXRight = NumericRangeQuery.newDoubleRange(fieldInfo.minX, finfo.precisionStep, bbox.getMaxX(), null, false, false);
> +      Query qMaxXRight = NumericRangeQuery.newDoubleRange(fieldInfo.maxX, finfo.precisionStep, null, -180.0, false, false);
> +      Query qLeft = this.makeQuery(new Query[]{qMinXLeft, qMaxXLeft}, BooleanClause.Occur.SHOULD);
> +      Query qRight = this.makeQuery(new Query[]{qMinXRight, qMaxXRight}, BooleanClause.Occur.SHOULD);
> +      Query qLeftRight = this.makeQuery(new Query[]{qLeft, qRight}, BooleanClause.Occur.MUST);
> +
> +      // No need to search for documents that do not cross the date line
> +
> +      xConditions = this.makeXDL(false, qLeftRight, fieldInfo);
> +    }
> +
> +    // either X or Y conditions should occur
> +    return this.makeQuery(new Query[]{xConditions, yConditions}, BooleanClause.Occur.SHOULD);
> +  }
> +
> +  /**
> +   * Constructs a query to retrieve documents that equal the input envelope.
> +   *
> +   * @return the spatial query
> +   */
> +  Query makeEquals(Rectangle bbox, BBoxFieldInfo fieldInfo) {
> +
> +    // docMinX = queryExtent.getMinX() AND docMinY = queryExtent.getMinY() AND docMaxX = queryExtent.getMaxX() AND docMaxY = queryExtent.getMaxY()
> +    Query qMinX = NumericRangeQuery.newDoubleRange(fieldInfo.minX, finfo.precisionStep, bbox.getMinX(), bbox.getMinX(), true, true);
> +    Query qMinY = NumericRangeQuery.newDoubleRange(fieldInfo.minY, finfo.precisionStep, bbox.getMinY(), bbox.getMinY(), true, true);
> +    Query qMaxX = NumericRangeQuery.newDoubleRange(fieldInfo.maxX, finfo.precisionStep, bbox.getMaxX(), bbox.getMaxX(), true, true);
> +    Query qMaxY = NumericRangeQuery.newDoubleRange(fieldInfo.maxY, finfo.precisionStep, bbox.getMaxY(), bbox.getMaxY(), true, true);
> +    BooleanQuery bq = new BooleanQuery();
> +    bq.add(qMinX, BooleanClause.Occur.MUST);
> +    bq.add(qMinY, BooleanClause.Occur.MUST);
> +    bq.add(qMaxX, BooleanClause.Occur.MUST);
> +    bq.add(qMaxY, BooleanClause.Occur.MUST);
> +    return bq;
> +  }
> +
> +  /**
> +   * Constructs a query to retrieve documents that intersect the input envelope.
> +   *
> +   * @return the spatial query
> +   */
> +  Query makeIntersects(Rectangle bbox, BBoxFieldInfo fieldInfo) {
> +
> +    // the original intersects query does not work for envelopes that cross the date line,
> +    // switch to a NOT Disjoint query
> +
> +    // MUST_NOT causes a problem when it's the only clause type within a BooleanQuery,
> +    // to get round it we add all documents as a SHOULD
> +
> +    // there must be an envelope, it must not be disjoint
> +    Query qDisjoint = makeDisjoint(bbox, fieldInfo);
> +    Query qIsNonXDL = this.makeXDL(false, fieldInfo);
> +    Query qIsXDL = this.makeXDL(true, fieldInfo);
> +    Query qHasEnv = this.makeQuery(new Query[]{qIsNonXDL, qIsXDL}, BooleanClause.Occur.SHOULD);
> +    BooleanQuery qNotDisjoint = new BooleanQuery();
> +    qNotDisjoint.add(qHasEnv, BooleanClause.Occur.MUST);
> +    qNotDisjoint.add(qDisjoint, BooleanClause.Occur.MUST_NOT);
> +
> +    //Query qDisjoint = makeDisjoint();
> +    //BooleanQuery qNotDisjoint = new BooleanQuery();
> +    //qNotDisjoint.add(new MatchAllDocsQuery(),BooleanClause.Occur.SHOULD);
> +    //qNotDisjoint.add(qDisjoint,BooleanClause.Occur.MUST_NOT);
> +    return qNotDisjoint;
> +  }
> +
> +  /**
> +   * Makes a boolean query based upon a collection of queries and a logical operator.
> +   *
> +   * @param queries the query collection
> +   * @param occur the logical operator
> +   * @return the query
> +   */
> +  BooleanQuery makeQuery(Query[] queries, BooleanClause.Occur occur) {
> +    BooleanQuery bq = new BooleanQuery();
> +    for (Query query : queries) {
> +      bq.add(query, occur);
> +    }
> +    return bq;
> +  }
> +
> +  /**
> +   * Constructs a query to retrieve documents are fully within the input envelope.
> +   *
> +   * @return the spatial query
> +   */
> +  Query makeWithin(Rectangle bbox, BBoxFieldInfo fieldInfo) {
> +
> +    // general case
> +    // docMinX >= queryExtent.getMinX() AND docMinY >= queryExtent.getMinY() AND docMaxX <= queryExtent.getMaxX() AND docMaxY <= queryExtent.getMaxY()
> +
> +    // Y conditions
> +    // docMinY >= queryExtent.getMinY() AND docMaxY <= queryExtent.getMaxY()
> +    Query qMinY = NumericRangeQuery.newDoubleRange(fieldInfo.minY, finfo.precisionStep, bbox.getMinY(), null, true, false);
> +    Query qMaxY = NumericRangeQuery.newDoubleRange(fieldInfo.maxY, finfo.precisionStep, null, bbox.getMaxY(), false, true);
> +    Query yConditions = this.makeQuery(new Query[]{qMinY, qMaxY}, BooleanClause.Occur.MUST);
> +
> +    // X conditions
> +    Query xConditions = null;
> +
> +    // X Conditions for documents that cross the date line,
> +    // the left portion of the document must be within the left portion of the query,
> +    // AND the right portion of the document must be within the right portion of the query
> +    // docMinXLeft >= queryExtent.getMinX() AND docMaxXLeft <= 180.0
> +    // AND docMinXRight >= -180.0 AND docMaxXRight <= queryExtent.getMaxX()
> +    Query qXDLLeft = NumericRangeQuery.newDoubleRange(fieldInfo.minX, finfo.precisionStep, bbox.getMinX(), null, true, false);
> +    Query qXDLRight = NumericRangeQuery.newDoubleRange(fieldInfo.maxX, finfo.precisionStep, null, bbox.getMaxX(), false, true);
> +    Query qXDLLeftRight = this.makeQuery(new Query[]{qXDLLeft, qXDLRight}, BooleanClause.Occur.MUST);
> +    Query qXDL = this.makeXDL(true, qXDLLeftRight, fieldInfo);
> +
> +    // queries that do not cross the date line
> +    if (!bbox.getCrossesDateLine()) {
> +
> +      // X Conditions for documents that do not cross the date line,
> +      // docMinX >= queryExtent.getMinX() AND docMaxX <= queryExtent.getMaxX()
> +      Query qMinX = NumericRangeQuery.newDoubleRange(fieldInfo.minX, finfo.precisionStep, bbox.getMinX(), null, true, false);
> +      Query qMaxX = NumericRangeQuery.newDoubleRange(fieldInfo.maxX, finfo.precisionStep, null, bbox.getMaxX(), false, true);
> +      Query qMinMax = this.makeQuery(new Query[]{qMinX, qMaxX}, BooleanClause.Occur.MUST);
> +      Query qNonXDL = this.makeXDL(false, qMinMax, fieldInfo);
> +
> +      // apply the non-XDL or XDL X conditions
> +      if ((bbox.getMinX() <= -180.0) && bbox.getMaxX() >= 180.0) {
> +        xConditions = this.makeQuery(new Query[]{qNonXDL, qXDL}, BooleanClause.Occur.SHOULD);
> +      } else {
> +        xConditions = qNonXDL;
> +      }
> +
> +      // queries that cross the date line
> +    } else {
> +
> +      // X Conditions for documents that do not cross the date line
> +
> +      // the document should be within the left portion of the query
> +      // docMinX >= queryExtent.getMinX() AND docMaxX <= 180.0
> +      Query qMinXLeft = NumericRangeQuery.newDoubleRange(fieldInfo.minX, finfo.precisionStep, bbox.getMinX(), null, true, false);
> +      Query qMaxXLeft = NumericRangeQuery.newDoubleRange(fieldInfo.maxX, finfo.precisionStep, null, 180.0, false, true);
> +      Query qLeft = this.makeQuery(new Query[]{qMinXLeft, qMaxXLeft}, BooleanClause.Occur.MUST);
> +
> +      // the document should be within the right portion of the query
> +      // docMinX >= -180.0 AND docMaxX <= queryExtent.getMaxX()
> +      Query qMinXRight = NumericRangeQuery.newDoubleRange(fieldInfo.minX, finfo.precisionStep, -180.0, null, true, false);
> +      Query qMaxXRight = NumericRangeQuery.newDoubleRange(fieldInfo.maxX, finfo.precisionStep, null, bbox.getMaxX(), false, true);
> +      Query qRight = this.makeQuery(new Query[]{qMinXRight, qMaxXRight}, BooleanClause.Occur.MUST);
> +
> +      // either left or right conditions should occur,
> +      // apply the left and right conditions to documents that do not cross the date line
> +      Query qLeftRight = this.makeQuery(new Query[]{qLeft, qRight}, BooleanClause.Occur.SHOULD);
> +      Query qNonXDL = this.makeXDL(false, qLeftRight, fieldInfo);
> +
> +      // apply the non-XDL and XDL conditions
> +      xConditions = this.makeQuery(new Query[]{qNonXDL, qXDL}, BooleanClause.Occur.SHOULD);
> +    }
> +
> +    // both X and Y conditions must occur
> +    return this.makeQuery(new Query[]{xConditions, yConditions}, BooleanClause.Occur.MUST);
> +  }
> +
> +  /**
> +   * Constructs a query to retrieve documents that do or do not cross the date line.
> +   *
> +   * @param crossedDateLine <code>true</true> for documents that cross the date line
> +   * @return the query
> +   */
> +  Query makeXDL(boolean crossedDateLine, BBoxFieldInfo fieldInfo) {
> +    // The 'T' and 'F' values match solr fields
> +    return new TermQuery(new Term(fieldInfo.xdl, crossedDateLine ? "T" : "F"));
> +  }
> +
> +  /**
> +   * Constructs a query to retrieve documents that do or do not cross the date line
> +   * and match the supplied spatial query.
> +   *
> +   * @param crossedDateLine <code>true</true> for documents that cross the date line
> +   * @param query the spatial query
> +   * @return the query
> +   */
> +  Query makeXDL(boolean crossedDateLine, Query query, BBoxFieldInfo fieldInfo) {
> +    BooleanQuery bq = new BooleanQuery();
> +    bq.add(this.makeXDL(crossedDateLine, fieldInfo), BooleanClause.Occur.MUST);
> +    bq.add(query, BooleanClause.Occur.MUST);
> +    return bq;
> +  }
> +}
> +
> +
> +
>
> Added: lucene/dev/trunk/lucene/spatial/src/test-files/data/simple-bbox.txt
> URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial/src/test-files/data/simple-bbox.txt?rev=1354841&view=auto
> ==============================================================================
> --- lucene/dev/trunk/lucene/spatial/src/test-files/data/simple-bbox.txt (added)
> +++ lucene/dev/trunk/lucene/spatial/src/test-files/data/simple-bbox.txt Thu Jun 28 07:36:12 2012
> @@ -0,0 +1,5 @@
> +#id    name    shape
> +C5     CenterAt5       -5 -5 5 5
> +C10    CenterAt10      -10 -10 10 10
> +NW15   NorthWest       15 15 20 20
> +
>
> Added: lucene/dev/trunk/lucene/spatial/src/test-files/simple-Queries-BBox.txt
> URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial/src/test-files/simple-Queries-BBox.txt?rev=1354841&view=auto
> ==============================================================================
> --- lucene/dev/trunk/lucene/spatial/src/test-files/simple-Queries-BBox.txt (added)
> +++ lucene/dev/trunk/lucene/spatial/src/test-files/simple-Queries-BBox.txt Thu Jun 28 07:36:12 2012
> @@ -0,0 +1,13 @@
> +C5 @ IsWithin(-6 -6 6 6)
> +C5 @ BBoxWithin(-6 -6 6 6)
> +C10 @ Contains(-6 -6 6 6)
> +C10 @ IsEqualTo(-10 -10 10 10)
> +C5 C10 @ Intersects(-2 -2 2 2)
> +C5 C10 @ Overlaps(-2 -2 2 2)
> +C5 C10 @ BBoxIntersects(-2 -2 2 2)
> +NW15 @ IsDisjointTo(-10 -10 10 10)
> +
> +
> +
> +
> +
>
> Modified: lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/SpatialTestCase.java
> URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/SpatialTestCase.java?rev=1354841&r1=1354840&r2=1354841&view=diff
> ==============================================================================
> --- lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/SpatialTestCase.java (original)
> +++ lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/SpatialTestCase.java Thu Jun 28 07:36:12 2012
> @@ -109,6 +109,22 @@ public abstract class SpatialTestCase ex
>       this.numFound = numFound;
>       this.results = results;
>     }
> +
> +    public StringBuilder toDebugString() {
> +      StringBuilder str = new StringBuilder();
> +      str.append("found: ").append(numFound).append('[');
> +      for(SearchResult r : results) {
> +        String id = r.document.get("id");
> +        str.append(id).append(", ");
> +      }
> +      str.append(']');
> +      return str;
> +    }
> +
> +    @Override
> +    public String toString() {
> +      return "[found:"+numFound+" "+results+"]";
> +    }
>   }
>
>   protected static class SearchResult {
> @@ -120,6 +136,11 @@ public abstract class SpatialTestCase ex
>       this.score = score;
>       this.document = document;
>     }
> +
> +    @Override
> +    public String toString() {
> +      return "["+score+"="+document+"]";
> +    }
>   }
>  }
>
>
> Modified: lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/StrategyTestCase.java
> URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/StrategyTestCase.java?rev=1354841&r1=1354840&r2=1354841&view=diff
> ==============================================================================
> --- lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/StrategyTestCase.java (original)
> +++ lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/StrategyTestCase.java Thu Jun 28 07:36:12 2012
> @@ -36,6 +36,7 @@ import java.util.logging.Logger;
>
>  public abstract class StrategyTestCase<T extends SpatialFieldInfo> extends SpatialTestCase {
>
> +  public static final String DATA_SIMPLE_BBOX = "simple-bbox.txt";
>   public static final String DATA_STATES_POLY = "states-poly.txt";
>   public static final String DATA_STATES_BBOX = "states-bbox.txt";
>   public static final String DATA_COUNTRIES_POLY = "countries-poly.txt";
> @@ -44,8 +45,8 @@ public abstract class StrategyTestCase<T
>
>   public static final String QTEST_States_IsWithin_BBox   = "states-IsWithin-BBox.txt";
>   public static final String QTEST_States_Intersects_BBox = "states-Intersects-BBox.txt";
> -
>   public static final String QTEST_Cities_IsWithin_BBox = "cities-IsWithin-BBox.txt";
> +  public static final String QTEST_Simple_Queries_BBox = "simple-Queries-BBox.txt";
>
>   private Logger log = Logger.getLogger(getClass().getName());
>
> @@ -112,8 +113,12 @@ public abstract class StrategyTestCase<T
>         Iterator<String> ids = q.ids.iterator();
>         for (SearchResult r : got.results) {
>           String id = r.document.get("id");
> +          if(!ids.hasNext()) {
> +            Assert.fail(msg + " :: Did not get enough results.  Expect" + q.ids+", got: "+got.toDebugString());
> +          }
>           Assert.assertEquals( "out of order: " + msg, ids.next(), id);
>         }
> +
>         if (ids.hasNext()) {
>           Assert.fail(msg + " :: expect more results then we got: " + ids.next());
>         }
>
> Added: lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/bbox/TestBBoxStrategy.java
> URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/bbox/TestBBoxStrategy.java?rev=1354841&view=auto
> ==============================================================================
> --- lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/bbox/TestBBoxStrategy.java (added)
> +++ lucene/dev/trunk/lucene/spatial/src/test/org/apache/lucene/spatial/bbox/TestBBoxStrategy.java Thu Jun 28 07:36:12 2012
> @@ -0,0 +1,66 @@
> +/*
> + * 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.bbox;
> +
> +import com.spatial4j.core.context.simple.SimpleSpatialContext;
> +import org.apache.lucene.spatial.SpatialMatchConcern;
> +import org.apache.lucene.spatial.StrategyTestCase;
> +import org.apache.lucene.spatial.util.NumericFieldInfo;
> +import org.junit.Before;
> +import org.junit.Test;
> +
> +import java.io.IOException;
> +
> +public class TestBBoxStrategy extends StrategyTestCase<BBoxFieldInfo> {
> +
> +  @Before
> +  @Override
> +  public void setUp() throws Exception {
> +    super.setUp();
> +    this.ctx = SimpleSpatialContext.GEO_KM;
> +
> +    BBoxStrategy s = new BBoxStrategy(ctx);
> +    s.finfo = new NumericFieldInfo();
> +
> +    this.strategy = s;
> +    this.fieldInfo = new BBoxFieldInfo("bbox");
> +  }
> +
> +  @Test
> +  public void testBasicOperaions() throws IOException {
> +    getAddAndVerifyIndexedDocuments(DATA_SIMPLE_BBOX);
> +
> +    executeQueries(SpatialMatchConcern.EXACT, QTEST_Simple_Queries_BBox);
> +  }
> +
> +  @Test
> +  public void testStatesBBox() throws IOException {
> +    getAddAndVerifyIndexedDocuments(DATA_STATES_BBOX);
> +
> +    executeQueries(SpatialMatchConcern.FILTER, QTEST_States_IsWithin_BBox);
> +    executeQueries(SpatialMatchConcern.FILTER, QTEST_States_Intersects_BBox);
> +  }
> +
> +  @Test
> +  public void testCitiesWithinBBox() throws IOException {
> +    getAddAndVerifyIndexedDocuments(DATA_WORLD_CITIES_POINTS);
> +
> +    executeQueries(SpatialMatchConcern.FILTER, QTEST_Cities_IsWithin_BBox);
> +  }
> +
> +}
>
>



-- 
lucidimagination.com

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@lucene.apache.org
For additional commands, e-mail: dev-help@lucene.apache.org