You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by di...@apache.org on 2011/07/06 19:24:45 UTC

[Lucene.Net] svn commit: r1143507 - in /incubator/lucene.net/branches/Lucene.Net_2_9_4g: src/contrib/Spatial/ src/contrib/Spatial/Tier/Projectors/ test/contrib/Spatial/

Author: digy
Date: Wed Jul  6 17:24:44 2011
New Revision: 1143507

URL: http://svn.apache.org/viewvc?rev=1143507&view=rev
Log:
[LUCENENET-431] Spatial.Net Cartesian won't find docs in radius in certain cases

Modified:
    incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Contrib.Spatial.csproj
    incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Tier/Projectors/CartesianTierPlotter.cs
    incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Tier/Projectors/IProjector.cs
    incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Tier/Projectors/SinusoidalProjector.cs
    incubator/lucene.net/branches/Lucene.Net_2_9_4g/test/contrib/Spatial/Contrib.Spatial.Test.csproj
    incubator/lucene.net/branches/Lucene.Net_2_9_4g/test/contrib/Spatial/TestCartesian.cs

Modified: incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Contrib.Spatial.csproj
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Contrib.Spatial.csproj?rev=1143507&r1=1143506&r2=1143507&view=diff
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Contrib.Spatial.csproj (original)
+++ incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Contrib.Spatial.csproj Wed Jul  6 17:24:44 2011
@@ -36,7 +36,7 @@
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
-    <OutputPath>..\..\..\bin\contrib\Spatial\Debug\</OutputPath>
+    <OutputPath>..\..\..\bin\contrib\Spatial\</OutputPath>
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>

Modified: incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Tier/Projectors/CartesianTierPlotter.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Tier/Projectors/CartesianTierPlotter.cs?rev=1143507&r1=1143506&r2=1143507&view=diff
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Tier/Projectors/CartesianTierPlotter.cs (original)
+++ incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Tier/Projectors/CartesianTierPlotter.cs Wed Jul  6 17:24:44 2011
@@ -22,14 +22,14 @@ namespace Lucene.Net.Spatial.Tier.Projec
 	public class CartesianTierPlotter
 	{
 		public const String DefaltFieldPrefix = "_tier_";
+        public static double EARTH_CIRC_MILES= 28892.0d;
 
 		private readonly int _tierLevel;
 		private int _tierLength;
 		private int _tierBoxes;
 		private readonly IProjector _projector;
 		private readonly string _fieldPrefix;
-		private const double Idd = 180d;
-
+		
 		public CartesianTierPlotter(int tierLevel, IProjector projector, string fieldPrefix)
 		{
 			_tierLevel = tierLevel;
@@ -72,20 +72,21 @@ namespace Lucene.Net.Spatial.Tier.Projec
 		public double GetTierBoxId(double latitude, double longitude)
 		{
 			double[] coords = _projector.Coords(latitude, longitude);
+            double[] ranges = _projector.Range();
 
-			double id = GetBoxId(coords[0]) + (GetBoxId(coords[1]) / TierVerticalPosDivider);
+            double id = GetBoxCoord(coords[0], ranges[0]) + (GetBoxCoord(coords[1], ranges[1]) / TierVerticalPosDivider);
 			return id;
 		}
 
-		private double GetBoxId(double coord)
+        private double GetBoxCoord(double coord, double range)
 		{
-			return Math.Floor(coord / (Idd / _tierLength));
+            return Math.Floor(coord * (this._tierLength / range));
 		}
 
-		private double GetBoxId(double coord, int tierLen)
-		{
-			return Math.Floor(coord / (Idd / tierLen));
-		}
+        //private double GetBoxId(double coord, int tierLen)
+        //{
+        //    return Math.Floor(coord / (Idd / tierLen));
+        //}
 
 		/// <summary>
 		/// Get the string name representing current tier _localTier&lt;tiedId&gt;
@@ -116,26 +117,41 @@ namespace Lucene.Net.Spatial.Tier.Projec
 		/// </summary>
 		/// <param name="miles">The miles.</param>
 		/// <returns></returns>
-		public int BestFit(double miles)
-		{
-
-			//28,892 a rough circumference of the earth
-			const int circ = 28892;
-
-			double r = miles / 2.0;
-
-			double corner = r - Math.Sqrt(Math.Pow(r, 2) / 2.0d);
-			double times = circ / corner;
-			int bestFit = (int)Math.Ceiling(Log2(times)) + 1;
-
-			if (bestFit > 15)
-			{
-				// 15 is the granularity of about 1 mile
-				// finer granularity isn't accurate with standard java math
-				return 15;
-			}
-			return bestFit;
-		}
+        public int BestFit(double range)
+        {
+            double times = EARTH_CIRC_MILES / (2.0d * range);
+
+            int bestFit = (int)Math.Ceiling(Math.Log(times, 2));
+
+            if (bestFit > 15)
+            {
+                // 15 is the granularity of about 1 mile
+                // finer granularity isn't accurate with standard java math
+                return 15;
+            }
+            return bestFit;
+        }
+        //public int BestFit(double miles)
+        //{
+
+        //    //28,892 a rough circumference of the earth
+        //    const int circ = 28892;
+
+        //    double r = miles / 2.0;
+
+        //    double corner = r - Math.Sqrt(Math.Pow(r, 2) / 2.0d);
+        //    double times = circ / corner;
+        //    int bestFit = (int)Math.Ceiling(Log2(times)) + 1;
+
+        //    if (bestFit > 15)
+        //    {
+        //        // 15 is the granularity of about 1 mile
+        //        // finer granularity isn't accurate with standard java math
+        //        return 15;
+        //    }
+        //    return bestFit;
+        //}
+       
 
 		/// <summary>
 		/// A log to the base 2 formula.

Modified: incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Tier/Projectors/IProjector.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Tier/Projectors/IProjector.cs?rev=1143507&r1=1143506&r2=1143507&view=diff
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Tier/Projectors/IProjector.cs (original)
+++ incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Tier/Projectors/IProjector.cs Wed Jul  6 17:24:44 2011
@@ -21,5 +21,6 @@ namespace Lucene.Net.Spatial.Tier.Projec
 	{
 		string CoordsAsString(double latitude, double longitude);
 		double[] Coords(double latitude, double longitude);
+        double[] Range();
 	}
 }
\ No newline at end of file

Modified: incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Tier/Projectors/SinusoidalProjector.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Tier/Projectors/SinusoidalProjector.cs?rev=1143507&r1=1143506&r2=1143507&view=diff
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Tier/Projectors/SinusoidalProjector.cs (original)
+++ incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/Spatial/Tier/Projectors/SinusoidalProjector.cs Wed Jul  6 17:24:44 2011
@@ -26,6 +26,9 @@ namespace Lucene.Net.Spatial.Tier.Projec
 	/// </summary>
 	public class SinusoidalProjector : IProjector
 	{
+        public static double LATITUDE_RANGE= Math.PI;
+        public static double LONGITUDE_RANGE = 2* Math.PI;
+
 		public string CoordsAsString(double latitude, double longitude)
 		{
 			return null;
@@ -39,5 +42,10 @@ namespace Lucene.Net.Spatial.Tier.Projec
 			double[] r = {nlat, rlong};
 			return r;
 		}
+
+        public double[] Range() {
+            double[] ranges = { LATITUDE_RANGE, LONGITUDE_RANGE};
+            return ranges;
+        } 
 	}
 }
\ No newline at end of file

Modified: incubator/lucene.net/branches/Lucene.Net_2_9_4g/test/contrib/Spatial/Contrib.Spatial.Test.csproj
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_2_9_4g/test/contrib/Spatial/Contrib.Spatial.Test.csproj?rev=1143507&r1=1143506&r2=1143507&view=diff
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_2_9_4g/test/contrib/Spatial/Contrib.Spatial.Test.csproj (original)
+++ incubator/lucene.net/branches/Lucene.Net_2_9_4g/test/contrib/Spatial/Contrib.Spatial.Test.csproj Wed Jul  6 17:24:44 2011
@@ -36,7 +36,7 @@
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
-    <OutputPath>..\..\..\bin\contrib\Spatial\Debug\</OutputPath>
+    <OutputPath>..\..\..\bin\contrib\Spatial\</OutputPath>
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>

Modified: incubator/lucene.net/branches/Lucene.Net_2_9_4g/test/contrib/Spatial/TestCartesian.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_2_9_4g/test/contrib/Spatial/TestCartesian.cs?rev=1143507&r1=1143506&r2=1143507&view=diff
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_2_9_4g/test/contrib/Spatial/TestCartesian.cs (original)
+++ incubator/lucene.net/branches/Lucene.Net_2_9_4g/test/contrib/Spatial/TestCartesian.cs Wed Jul  6 17:24:44 2011
@@ -31,7 +31,7 @@ using Lucene.Net.Store;
 using Lucene.Net.Util;
 using NUnit.Framework;
 
-namespace Lucene.Net.Contrib.Spatial.Test
+namespace Lucene.Net.Spatial.Test
 {
 	[TestFixture]
 	public class TestCartesian
@@ -182,4 +182,139 @@ namespace Lucene.Net.Contrib.Spatial.Tes
 			}
 		}
 	}
+
+    [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;
+            }
+        }
+    }
 }