| /* |
| * 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.Analysis; |
| using Lucene.Net.Documents; |
| using Lucene.Net.Index; |
| using Lucene.Net.Search; |
| using Lucene.Net.Spatial.Tier; |
| using Lucene.Net.Spatial.Tier.Projectors; |
| using Lucene.Net.Store; |
| using Lucene.Net.Util; |
| using NUnit.Framework; |
| |
| namespace Lucene.Net.Contrib.Spatial.Test |
| { |
| [TestFixture] |
| public class TestCartesian |
| { |
| private Directory _directory; |
| private IndexSearcher _searcher; |
| // reston va |
| private double _lat = 38.969398; |
| private double _lng = -77.386398; |
| private const string LatField = "lat"; |
| private const string LngField = "lng"; |
| private readonly List<CartesianTierPlotter> _ctps = new List<CartesianTierPlotter>(); |
| |
| private readonly IProjector _projector = new SinusoidalProjector(); |
| |
| [SetUp] |
| protected void SetUp() |
| { |
| _directory = new RAMDirectory(); |
| |
| var writer = new IndexWriter(_directory, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED); |
| |
| SetUpPlotter(2, 15); |
| |
| AddData(writer); |
| } |
| |
| private void SetUpPlotter(int @base, int top) |
| { |
| |
| for (; @base <= top; @base++) |
| { |
| _ctps.Add(new CartesianTierPlotter(@base, _projector, CartesianTierPlotter.DefaltFieldPrefix)); |
| } |
| } |
| |
| private void AddData(IndexWriter writer) |
| { |
| AddPoint(writer, "McCormick & Schmick's Seafood Restaurant", 38.9579000, -77.3572000); |
| AddPoint(writer, "Jimmy's Old Town Tavern", 38.9690000, -77.3862000); |
| AddPoint(writer, "Ned Devine's", 38.9510000, -77.4107000); |
| AddPoint(writer, "Old Brogue Irish Pub", 38.9955000, -77.2884000); |
| AddPoint(writer, "Alf Laylah Wa Laylah", 38.8956000, -77.4258000); |
| AddPoint(writer, "Sully's Restaurant & Supper", 38.9003000, -77.4467000); |
| AddPoint(writer, "TGI Friday", 38.8725000, -77.3829000); |
| AddPoint(writer, "Potomac Swing Dance Club", 38.9027000, -77.2639000); |
| AddPoint(writer, "White Tiger Restaurant", 38.9027000, -77.2638000); |
| AddPoint(writer, "Jammin' Java", 38.9039000, -77.2622000); |
| AddPoint(writer, "Potomac Swing Dance Club", 38.9027000, -77.2639000); |
| AddPoint(writer, "WiseAcres Comedy Club", 38.9248000, -77.2344000); |
| AddPoint(writer, "Glen Echo Spanish Ballroom", 38.9691000, -77.1400000); |
| AddPoint(writer, "Whitlow's on Wilson", 38.8889000, -77.0926000); |
| AddPoint(writer, "Iota Club and Cafe", 38.8890000, -77.0923000); |
| AddPoint(writer, "Hilton Washington Embassy Row", 38.9103000, -77.0451000); |
| AddPoint(writer, "HorseFeathers, Bar & Grill", 39.01220000000001, -77.3942); |
| AddPoint(writer, "Marshall Island Airfield", 7.06, 171.2); |
| AddPoint(writer, "Midway Island", 25.7, -171.7); |
| AddPoint(writer, "North Pole Way", 55.0, 4.0); |
| |
| writer.Commit(); |
| writer.Close(); |
| } |
| |
| private void AddPoint(IndexWriter writer, String name, double lat, double lng) |
| { |
| Document doc = new Document(); |
| |
| doc.Add(new Field("name", name, Field.Store.YES, Field.Index.ANALYZED)); |
| |
| // convert the lat / long to lucene fields |
| doc.Add(new Field(LatField, NumericUtils.DoubleToPrefixCoded(lat), Field.Store.YES, Field.Index.NOT_ANALYZED)); |
| doc.Add(new Field(LngField, NumericUtils.DoubleToPrefixCoded(lng), Field.Store.YES, Field.Index.NOT_ANALYZED)); |
| |
| // add a default meta field to make searching all documents easy |
| doc.Add(new Field("metafile", "doc", Field.Store.YES, Field.Index.ANALYZED)); |
| |
| int ctpsize = _ctps.Count; |
| for (int i = 0; i < ctpsize; i++) |
| { |
| CartesianTierPlotter ctp = _ctps[i]; |
| var boxId = ctp.GetTierBoxId(lat, lng); |
| doc.Add(new Field(ctp.GetTierFieldName(), |
| NumericUtils.DoubleToPrefixCoded(boxId), |
| Field.Store.YES, |
| Field.Index.NOT_ANALYZED_NO_NORMS)); |
| } |
| writer.AddDocument(doc); |
| |
| } |
| |
| [Test] |
| public void TestAntiM() |
| { |
| _searcher = new IndexSearcher(_directory, true); |
| |
| const double miles = 6.0; |
| |
| Console.WriteLine("testAntiM"); |
| // create a distance query |
| var dq = new DistanceQueryBuilder(_lat, _lng, miles, LatField, LngField, CartesianTierPlotter.DefaltFieldPrefix, true); |
| |
| Console.WriteLine(dq); |
| //create a term query to search against all documents |
| Query tq = new TermQuery(new Term("metafile", "doc")); |
| |
| var dsort = new DistanceFieldComparatorSource(dq.DistanceFilter); |
| Sort sort = new Sort(new SortField("foo", dsort, false)); |
| |
| // Perform the search, using the term query, the distance filter, and the |
| // distance sort |
| TopDocs hits = _searcher.Search(tq, dq.Filter, 1000, sort); |
| int results = hits.TotalHits; |
| ScoreDoc[] scoreDocs = hits.ScoreDocs; |
| |
| // Get a list of distances |
| Dictionary<int, Double> distances = dq.DistanceFilter.Distances; |
| |
| |
| Console.WriteLine("Distance Filter filtered: " + distances.Count); |
| Console.WriteLine("Results: " + results); |
| Console.WriteLine("============================="); |
| Console.WriteLine("Distances should be 7 " + distances.Count); |
| Console.WriteLine("Results should be 7 " + results); |
| |
| Assert.AreEqual(7, distances.Count); // fixed a store of only needed distances |
| Assert.AreEqual(7, results); |
| |
| double lastDistance = 0; |
| for (int i = 0; i < results; i++) |
| { |
| Document d = _searcher.Doc(scoreDocs[i].Doc); |
| |
| String name = d.Get("name"); |
| double rsLat = NumericUtils.PrefixCodedToDouble(d.Get(LatField)); |
| double rsLng = NumericUtils.PrefixCodedToDouble(d.Get(LngField)); |
| Double geo_distance = distances[scoreDocs[i].Doc]; |
| |
| double distance = DistanceUtils.GetInstance().GetDistanceMi(_lat, _lng, rsLat, rsLng); |
| double llm = DistanceUtils.GetInstance().GetLLMDistance(_lat, _lng, rsLat, rsLng); |
| |
| Console.WriteLine("Name: " + name + ", Distance " + distance); |
| |
| Assert.IsTrue(Math.Abs((distance - llm)) < 1); |
| Assert.IsTrue((distance < miles)); |
| Assert.IsTrue(geo_distance >= lastDistance); |
| |
| lastDistance = geo_distance; |
| } |
| } |
| } |
| |
| [TestFixture] |
| public class TestCartesian2 |
| { |
| private Directory _directory; |
| private IndexSearcher _searcher; |
| // reston va |
| private double _lat = 55.6880508001; |
| private double _lng = 13.5871808352; // This passes: 13.6271808352 |
| private const string LatField = "lat"; |
| private const string LngField = "lng"; |
| private readonly List<CartesianTierPlotter> _ctps = new List<CartesianTierPlotter>(); |
| |
| private readonly IProjector _projector = new SinusoidalProjector(); |
| |
| [SetUp] |
| protected void SetUp() |
| { |
| _directory = new RAMDirectory(); |
| |
| var writer = new IndexWriter(_directory, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED); |
| |
| SetUpPlotter(2, 15); |
| |
| AddData(writer); |
| } |
| |
| private void SetUpPlotter(int @base, int top) |
| { |
| |
| for (; @base <= top; @base++) |
| { |
| _ctps.Add(new CartesianTierPlotter(@base, _projector, CartesianTierPlotter.DefaltFieldPrefix)); |
| } |
| } |
| |
| private void AddData(IndexWriter writer) |
| { |
| AddPoint(writer, "Within radius", 55.6880508001, 13.5717346673); |
| AddPoint(writer, "Within radius", 55.6821978456, 13.6076183965); |
| AddPoint(writer, "Within radius", 55.673251569, 13.5946697607); |
| AddPoint(writer, "Close but not in radius", 55.8634157297, 13.5497731987); |
| AddPoint(writer, "Faar away", 40.7137578228, -74.0126901936); |
| |
| writer.Commit(); |
| writer.Close(); |
| } |
| |
| private void AddPoint(IndexWriter writer, String name, double lat, double lng) |
| { |
| Document doc = new Document(); |
| |
| doc.Add(new Field("name", name, Field.Store.YES, Field.Index.ANALYZED)); |
| |
| // convert the lat / long to lucene fields |
| doc.Add(new Field(LatField, NumericUtils.DoubleToPrefixCoded(lat), Field.Store.YES, Field.Index.NOT_ANALYZED)); |
| doc.Add(new Field(LngField, NumericUtils.DoubleToPrefixCoded(lng), Field.Store.YES, Field.Index.NOT_ANALYZED)); |
| |
| // add a default meta field to make searching all documents easy |
| doc.Add(new Field("metafile", "doc", Field.Store.YES, Field.Index.ANALYZED)); |
| |
| int ctpsize = _ctps.Count; |
| for (int i = 0; i < ctpsize; i++) |
| { |
| CartesianTierPlotter ctp = _ctps[i]; |
| var boxId = ctp.GetTierBoxId(lat, lng); |
| doc.Add(new Field(ctp.GetTierFieldName(), |
| NumericUtils.DoubleToPrefixCoded(boxId), |
| Field.Store.YES, |
| Field.Index.NOT_ANALYZED_NO_NORMS)); |
| } |
| writer.AddDocument(doc); |
| |
| } |
| |
| [Test] |
| public void TestAntiM() |
| { |
| _searcher = new IndexSearcher(_directory, true); |
| |
| const double miles = 5.0; |
| |
| Console.WriteLine("testAntiM"); |
| // create a distance query |
| var dq = new DistanceQueryBuilder(_lat, _lng, miles, LatField, LngField, CartesianTierPlotter.DefaltFieldPrefix, true); |
| |
| Console.WriteLine(dq); |
| //create a term query to search against all documents |
| Query tq = new TermQuery(new Term("metafile", "doc")); |
| |
| var dsort = new DistanceFieldComparatorSource(dq.DistanceFilter); |
| Sort sort = new Sort(new SortField("foo", dsort, false)); |
| |
| // Perform the search, using the term query, the distance filter, and the |
| // distance sort |
| TopDocs hits = _searcher.Search(tq, dq.Filter, 1000, sort); |
| int results = hits.TotalHits; |
| ScoreDoc[] scoreDocs = hits.ScoreDocs; |
| |
| // Get a list of distances |
| Dictionary<int, Double> distances = dq.DistanceFilter.Distances; |
| |
| |
| Console.WriteLine("Distance Filter filtered: " + distances.Count); |
| Console.WriteLine("Results: " + results); |
| Console.WriteLine("============================="); |
| Console.WriteLine("Distances should be 3 " + distances.Count); |
| Console.WriteLine("Results should be 3 " + results); |
| |
| Assert.AreEqual(3, distances.Count); // fixed a store of only needed distances |
| Assert.AreEqual(3, results); |
| |
| double lastDistance = 0; |
| for (int i = 0; i < results; i++) |
| { |
| Document d = _searcher.Doc(scoreDocs[i].Doc); |
| |
| String name = d.Get("name"); |
| double rsLat = NumericUtils.PrefixCodedToDouble(d.Get(LatField)); |
| double rsLng = NumericUtils.PrefixCodedToDouble(d.Get(LngField)); |
| Double geo_distance = distances[scoreDocs[i].Doc]; |
| |
| double distance = DistanceUtils.GetInstance().GetDistanceMi(_lat, _lng, rsLat, rsLng); |
| double llm = DistanceUtils.GetInstance().GetLLMDistance(_lat, _lng, rsLat, rsLng); |
| |
| Console.WriteLine("Name: " + name + ", Distance " + distance); |
| |
| Assert.IsTrue(Math.Abs((distance - llm)) < 1); |
| Assert.IsTrue((distance < miles)); |
| Assert.IsTrue(geo_distance >= lastDistance); |
| |
| lastDistance = geo_distance; |
| } |
| } |
| } |
| |
| } |