2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package org.apache.lucene.spatial.tier;
20 import java.io.IOException;
21 import org.apache.lucene.index.IndexReader;
22 import org.apache.lucene.search.FilteredDocIdSet;
23 import org.apache.lucene.search.FieldCache;
24 import org.apache.lucene.search.Filter;
25 import org.apache.lucene.search.DocIdSet;
26 import org.apache.lucene.spatial.DistanceUtils;
30 * <p><font color="red"><b>NOTE:</b> This API is still in
31 * flux and might change in incompatible ways in the next
34 public class LatLongDistanceFilter extends DistanceFilter {
39 private static final long serialVersionUID = 1L;
49 * Provide a distance filter based from a center point with a radius
51 * @param startingFilter Filter to start from
58 public LatLongDistanceFilter(Filter startingFilter, double lat, double lng, double miles, String latField, String lngField) {
59 super(startingFilter, miles);
62 this.latField = latField;
63 this.lngField = lngField;
67 public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
69 final double[] latIndex = FieldCache.DEFAULT.getDoubles(reader, latField);
70 final double[] lngIndex = FieldCache.DEFAULT.getDoubles(reader, lngField);
72 final int docBase = nextDocBase;
73 nextDocBase += reader.maxDoc();
75 return new FilteredDocIdSet(startingFilter.getDocIdSet(reader)) {
77 protected boolean match(int doc) {
78 double x = latIndex[doc];
79 double y = lngIndex[doc];
81 // round off lat / longs if necessary
82 // x = DistanceHandler.getPrecision(x, precise);
83 // y = DistanceHandler.getPrecision(y, precise);
85 String ck = Double.toString(x)+","+Double.toString(y);
86 Double cachedDistance = distanceLookupCache.get(ck);
89 if (cachedDistance != null){
90 d = cachedDistance.doubleValue();
92 d = DistanceUtils.getDistanceMi(lat, lng, x, y);
93 distanceLookupCache.put(ck, d);
97 // Save distances, so they can be pulled for
98 // sorting after filtering is done:
99 distances.put(doc+docBase, d);
108 /** Returns true if <code>o</code> is equal to this. */
110 public boolean equals(Object o) {
111 if (this == o) return true;
112 if (!(o instanceof LatLongDistanceFilter)) return false;
113 LatLongDistanceFilter other = (LatLongDistanceFilter) o;
115 if (!this.startingFilter.equals(other.startingFilter) ||
116 this.distance != other.distance ||
117 this.lat != other.lat ||
118 this.lng != other.lng ||
119 !this.latField.equals(other.latField) ||
120 !this.lngField.equals(other.lngField)) {
126 /** Returns a hash code value for this object.*/
128 public int hashCode() {
129 int h = Double.valueOf(distance).hashCode();
130 h ^= startingFilter.hashCode();
131 h ^= Double.valueOf(lat).hashCode();
132 h ^= Double.valueOf(lng).hashCode();
133 h ^= latField.hashCode();
134 h ^= lngField.hashCode();