/* * 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. */ using System; using System.Collections.Generic; using Lucene.Net.Search; using Lucene.Net.Spatial.Tier; namespace Lucene.Net.Spatial.GeoHash { public class GeoHashDistanceFilter : DistanceFilter { private readonly double _lat; private readonly double _lng; private readonly String _geoHashField; /// /// Provide a distance filter based from a center point with a radius in miles /// /// The starting filter. /// The lat. /// The LNG. /// The miles. /// The geo hash field. public GeoHashDistanceFilter(Filter startingFilter, double lat, double lng, double miles, string geoHashField) : base(startingFilter, miles) { _lat = lat; _lng = lng; _geoHashField = geoHashField; } public override DocIdSet GetDocIdSet(Lucene.Net.Index.IndexReader reader) { var geoHashValues = FieldCache_Fields.DEFAULT.GetStrings(reader, _geoHashField); int docBase = NextDocBase; NextDocBase += reader.MaxDoc(); return new GeoHashFilteredDocIdSet(StartingFilter.GetDocIdSet(reader), geoHashValues, DistanceLookupCache, _lat, _lng, docBase, Distance, Distances); } internal class GeoHashFilteredDocIdSet : FilteredDocIdSet { public GeoHashFilteredDocIdSet(DocIdSet innerSet, string[] geoHashValues, Dictionary distanceLookupCache, double lat, double lng, int docBase, double distance, Dictionary distances) : base(innerSet) { _geoHashValues = geoHashValues; _distances = distances; _distance = distance; _docBase = docBase; _lng = lng; _lat = lat; _distanceLookupCache = distanceLookupCache; } private readonly double _lat; private readonly double _lng; private readonly int _docBase; private readonly string[] _geoHashValues; private readonly Dictionary _distances; private readonly Dictionary _distanceLookupCache; private readonly double _distance; public override bool Match(int docid) { String geoHash = _geoHashValues[docid]; double[] coords = GeoHashUtils.Decode(geoHash); double x = coords[0]; double y = coords[1]; Double cachedDistance = _distanceLookupCache[geoHash]; double d; if (cachedDistance > 0) { d = cachedDistance; } else { d = DistanceUtils.GetInstance().GetDistanceMi(_lat, _lng, x, y); _distanceLookupCache[geoHash] = d; } if (d < _distance) { _distances[docid + _docBase] = d; return true; } return false; } } public override bool Equals(object o) { if (this == o) return true; if (!(o is GeoHashDistanceFilter)) return false; var other = (GeoHashDistanceFilter) o; if (!StartingFilter.Equals(other.StartingFilter) || Distance != other.Distance || _lat != other._lat || _lng != other._lng || _geoHashField.Equals(other._geoHashField) ) { return false; } return true; } public override int GetHashCode() { int h = Distance.GetHashCode(); h ^= StartingFilter.GetHashCode(); h ^= _lat.GetHashCode(); h ^= _lng.GetHashCode(); h ^= _geoHashField.GetHashCode(); return h; } } }