add --shared
[pylucene.git] / lucene-java-3.4.0 / lucene / contrib / spatial / src / java / org / apache / lucene / spatial / geohash / GeoHashDistanceFilter.java
1 /**
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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 package org.apache.lucene.spatial.geohash;
19
20 import java.io.IOException;
21
22 import org.apache.lucene.index.IndexReader;
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.search.FilteredDocIdSet;
27 import org.apache.lucene.spatial.DistanceUtils;
28 import org.apache.lucene.spatial.tier.DistanceFilter;
29
30
31 /** <p><font color="red"><b>NOTE:</b> This API is still in
32  * flux and might change in incompatible ways in the next
33  * release.</font>
34  */
35
36 public class GeoHashDistanceFilter extends DistanceFilter {
37
38   /**
39    * 
40    */
41   private static final long serialVersionUID = 1L;
42   
43   private double lat;
44   private double lng;
45   private String geoHashField;
46   
47   /**
48    * Provide a distance filter based from a center point with a radius
49    * in miles
50    * @param startingFilter
51    * @param lat
52    * @param lng
53    * @param miles
54    */
55   public GeoHashDistanceFilter(Filter startingFilter, double lat, double lng, double miles, String geoHashField) {
56     super(startingFilter, miles);
57     this.lat = lat;
58     this.lng = lng;
59     this.geoHashField = geoHashField;
60   }
61
62   @Override
63   public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
64
65     final String[] geoHashValues = FieldCache.DEFAULT.getStrings(reader, geoHashField);
66
67     final int docBase = nextDocBase;
68     nextDocBase += reader.maxDoc();
69
70     return new FilteredDocIdSet(startingFilter.getDocIdSet(reader)) {
71       @Override
72       public boolean match(int doc) {
73         
74         String geoHash = geoHashValues[doc];
75         double[] coords = GeoHashUtils.decode(geoHash);
76         double x = coords[0];
77         double y = coords[1];
78       
79         // round off lat / longs if necessary
80         //      x = DistanceHandler.getPrecision(x, precise);
81         //      y = DistanceHandler.getPrecision(y, precise);
82         Double cachedDistance = distanceLookupCache.get(geoHash);
83         double d;
84       
85         if (cachedDistance != null) {
86           d = cachedDistance.doubleValue();
87         } else {
88           d = DistanceUtils.getDistanceMi(lat, lng, x, y);
89           distanceLookupCache.put(geoHash, d);
90         }
91
92         if (d < distance){
93           distances.put(doc+docBase, d);
94           return true;
95         } else {
96           return false;
97         }
98       }
99     };
100   }
101
102   /** Returns true if <code>o</code> is equal to this. */
103   @Override
104   public boolean equals(Object o) {
105     if (this == o) return true;
106     if (!(o instanceof GeoHashDistanceFilter)) return false;
107     GeoHashDistanceFilter other = (GeoHashDistanceFilter) o;
108
109     if (!this.startingFilter.equals(other.startingFilter) ||
110         this.distance != other.distance ||
111         this.lat != other.lat ||
112         this.lng != other.lng ||
113         !this.geoHashField.equals(other.geoHashField) ) {
114       return false;
115     }
116     return true;
117   }
118
119   /** Returns a hash code value for this object.*/
120   @Override
121   public int hashCode() {
122     int h = Double.valueOf(distance).hashCode();
123     h ^= startingFilter.hashCode();
124     h ^= Double.valueOf(lat).hashCode();
125     h ^= Double.valueOf(lng).hashCode();
126     h ^= geoHashField.hashCode();
127     
128     return h;
129   }
130 }