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 2009/12/13 20:39:52 UTC

svn commit: r890098 [2/2] - in /incubator/lucene.net/trunk/C#/contrib/Spatial.Net: Spatial.Net/ Spatial.Net/GeoHash/ Spatial.Net/Geometry/ Spatial.Net/Geometry/Shape/ Spatial.Net/Properties/ Spatial.Net/Tier/ Spatial.Net/Tier/Projectors/ Spatial.Net/Ut...

Added: incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/DistanceFilter.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Spatial.Net/Tier/DistanceFilter.cs?rev=890098&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/DistanceFilter.cs (added)
+++ incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/DistanceFilter.cs Sun Dec 13 19:39:51 2009
@@ -0,0 +1,74 @@
+/* 
+ * 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;
+
+namespace Lucene.Net.Spatial.Tier
+{
+	public abstract class DistanceFilter : Filter
+	{
+		protected Filter StartingFilter;
+		protected Precision Precision;
+		protected double Distance;
+
+		protected int NextDocBase;
+		protected Dictionary<string, double> DistanceLookupCache;
+
+		protected DistanceFilter(Filter startingFilter, double distance)
+		{
+			if (startingFilter == null)
+			{
+				throw new ArgumentNullException("startingFilter", "Please provide a non-null startingFilter; you can use QueryWrapperFilter(MatchAllDocsQuery) as a no-op filter");
+			}
+
+			StartingFilter = startingFilter;
+			Distance = distance;
+
+			// NOTE: neither of the distance filters use precision
+			// now - if we turn that on, we'll need to pass top
+			// reader into here
+			// setPrecision(reader.maxDoc());
+
+			/* store calculated distances for reuse by other components */
+			Distances = new Dictionary<int, Double>();
+
+			// create an intermediate cache to avoid recomputing distances for the same point 
+			DistanceLookupCache = new Dictionary<string, double>();
+		}
+
+		public Dictionary<int, double> Distances { get; set; }
+
+		public double GetDistance(int docid)
+		{
+			return Distances.ContainsKey(docid) ? Distances[docid]: 0;
+		}
+
+		/// <summary>
+		/// You must call this before re-using this DistanceFilter across searches
+		/// </summary>
+		public void Reset()
+		{
+			NextDocBase = 0;
+		}
+
+		public abstract bool Equals(Object o);
+
+		public abstract int GetHashCode();
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/DistanceHandler.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Spatial.Net/Tier/DistanceHandler.cs?rev=890098&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/DistanceHandler.cs (added)
+++ incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/DistanceHandler.cs Sun Dec 13 19:39:51 2009
@@ -0,0 +1,112 @@
+/* 
+ * 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;
+
+namespace Lucene.Net.Spatial.Tier
+{
+	public enum Precision
+	{
+		EXACT,
+		TWOFEET,
+		TWENTYFEET,
+		TWOHUNDREDFEET,
+	}
+
+	/// <summary>
+	/// Provide a high level access point to distances
+	/// Used by DistanceSortSource and DistanceQuery
+	/// </summary>
+	public class DistanceHandler
+	{
+		private readonly Dictionary<int, double> _distances;
+		private readonly Dictionary<string, double> _distanceLookupCache;
+		private readonly Precision? _precision;
+
+		public DistanceHandler(Dictionary<int, double> distances, Dictionary<string, double> distanceLookupCache, Precision precision)
+		{
+			_distances = distances;
+			_distanceLookupCache = distanceLookupCache;
+			_precision = precision;
+		}
+
+		public static double GetPrecision(double x, Precision? thisPrecision)
+		{
+			if(thisPrecision.HasValue)
+			{
+				double dif = 0;
+
+				switch (thisPrecision)
+				{
+					case Precision.EXACT:
+						return x;
+					case Precision.TWOFEET:
+						dif = x%0.0001;
+						break;
+					case Precision.TWENTYFEET:
+						dif = x%0.001;
+						break;
+					case Precision.TWOHUNDREDFEET:
+						dif = x%0.01;
+						break;
+				}
+				return x - dif;
+			}
+			return x;
+		}
+
+		public Precision GetPrecision()
+		{
+			return _precision.Value;
+		}
+
+		public double GetDistance(int docid, double centerLat, double centerLng, double lat, double lng)
+		{
+			// check to see if we have distances
+			// if not calculate the distance
+			if (_distances == null)
+			{
+				return DistanceUtils.GetInstance().GetDistanceMi(centerLat, centerLng, lat, lng);
+			}
+
+			// check to see if the doc id has a cached distance
+			double docd;
+			_distances.TryGetValue(docid, out docd);
+			if (docd > 0) return docd;
+
+			//check to see if we have a precision code
+			// and if another lat/long has been calculated at
+			// that rounded location
+			if (_precision.HasValue)
+			{
+				double xLat = GetPrecision(lat, _precision);
+				double xLng = GetPrecision(lng, _precision);
+
+				String k = xLat + "," + xLng;
+
+				Double d;
+				_distanceLookupCache.TryGetValue(k, out d);
+				if (d > 0) return d;
+			}
+
+			//all else fails calculate the distances    
+			return DistanceUtils.GetInstance().GetDistanceMi(centerLat, centerLng, lat, lng);
+		}
+
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/DistanceQueryBuilder.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Spatial.Net/Tier/DistanceQueryBuilder.cs?rev=890098&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/DistanceQueryBuilder.cs (added)
+++ incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/DistanceQueryBuilder.cs Sun Dec 13 19:39:51 2009
@@ -0,0 +1,135 @@
+/* 
+ * 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 Lucene.Net.Search;
+using Lucene.Net.Spatial.GeoHash;
+
+namespace Lucene.Net.Spatial.Tier
+{
+	public class DistanceQueryBuilder
+	{
+		/// <summary>
+		/// Create a distance query using
+		/// a boundary box wrapper around a more precise
+		/// DistanceFilter.
+		/// </summary>
+		/// <param name="lat">The lat.</param>
+		/// <param name="lng">The Lng.</param>
+		/// <param name="miles">The miles.</param>
+		/// <param name="latField">The lat field.</param>
+		/// <param name="lngField">The Lng field.</param>
+		/// <param name="tierFieldPrefix">The tier field prefix.</param>
+		/// <param name="needPrecise">if set to <c>true</c> [need precise].</param>
+		public DistanceQueryBuilder(double lat, double lng, double miles, string latField, string lngField, string tierFieldPrefix, bool needPrecise)
+		{
+			Lat = lat;
+			Lng = lng;
+			Miles = miles;
+
+			var cpf = new CartesianPolyFilterBuilder(tierFieldPrefix);
+			Filter cartesianFilter = cpf.GetBoundingArea(lat, lng, miles);
+
+			/* create precise distance filter */
+			if (needPrecise)
+			{
+				_filter = DistanceFilter = new LatLongDistanceFilter(cartesianFilter, miles, lat, lng, latField, lngField);
+			}
+			else
+			{
+				_filter = cartesianFilter;
+				DistanceFilter = null;
+			}
+		}
+
+		/// <summary>
+		/// Create a distance query using
+		/// a boundary box wrapper around a more precise
+		/// DistanceFilter.
+		/// </summary>
+		/// <param name="lat">The lat.</param>
+		/// <param name="lng">The Lng.</param>
+		/// <param name="miles">The miles.</param>
+		/// <param name="geoHashFieldPrefix">The geo hash field prefix.</param>
+		/// <param name="tierFieldPrefix">The tier field prefix.</param>
+		/// <param name="needPrecise">if set to <c>true</c> [need precise].</param>
+		public DistanceQueryBuilder(double lat, double lng, double miles, string geoHashFieldPrefix, String tierFieldPrefix, bool needPrecise)
+		{
+
+			Lat = lat;
+			Lng = lng;
+			Miles = miles;
+
+			var cpf = new CartesianPolyFilterBuilder(tierFieldPrefix);
+			Filter cartesianFilter = cpf.GetBoundingArea(lat, lng, miles);
+
+			/* create precise distance filter */
+			if (needPrecise)
+			{
+				_filter = DistanceFilter = new GeoHashDistanceFilter(cartesianFilter, lat, lng, miles, geoHashFieldPrefix);
+			}
+			else
+			{
+				_filter = cartesianFilter;
+				DistanceFilter = null;
+			}
+		}
+
+
+		public double Lat { get; private set; }
+		public double Lng { get; private set; }
+		public double Miles { get; private set; }
+		public DistanceFilter DistanceFilter { get; private set; }
+
+		private readonly Filter _filter;
+		public Filter Filter
+		{
+			get
+			{
+				if (DistanceFilter != null)
+				{
+					DistanceFilter.Reset();
+				}
+
+				return _filter;
+			}
+		}
+
+		public Filter GetFilter(Query query)
+		{
+			throw new NotImplementedException("Relies on ChainedFilter (contrib/misc). Do we need this?"); //{{rogchap}}
+			// Chain the Query (as filter) with our distance filter
+			/*if (_distanceFilter != null)
+			{
+				_distanceFilter.Reset();
+			}
+			var qf = new QueryWrapperFilter(query);
+			return new ChainedFilter(new [] { qf, _filter }, ChainedFilter.AND);
+			 */
+		}
+
+		public Query GetQuery(Query query)
+		{
+			return new ConstantScoreQuery(GetFilter(query));
+		}
+
+		public override string ToString()
+		{
+			return "DistanceQuery lat: " + Lat + " lng: " + Lng + " miles: " + Miles;
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/DistanceUtils.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Spatial.Net/Tier/DistanceUtils.cs?rev=890098&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/DistanceUtils.cs (added)
+++ incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/DistanceUtils.cs Sun Dec 13 19:39:51 2009
@@ -0,0 +1,51 @@
+/* 
+ * 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 Lucene.Net.Spatial.Geometry;
+using Lucene.Net.Spatial.Geometry.Shape;
+
+namespace Lucene.Net.Spatial.Tier
+{
+	public class DistanceUtils
+	{
+		private static readonly DistanceUtils Instance = new DistanceUtils();
+
+		public static DistanceUtils GetInstance()
+		{
+			return Instance;
+		}
+
+		public double GetDistanceMi(double x1, double y1, double x2, double y2)
+		{
+			return GetLLMDistance(x1, y1, x2, y2);
+		}
+
+		public Rectangle GetBoundary(double x1, double y1, double miles)
+		{
+			var box = LLRect.CreateBox(new FloatLatLng(x1, y1), miles, miles);
+			return box.ToRectangle();
+		}
+
+		public double GetLLMDistance(double x1, double y1, double x2, double y2)
+		{
+
+			LatLng p1 = new FloatLatLng(x1, y1);
+			LatLng p2 = new FloatLatLng(x2, y2);
+			return p1.ArcDistance(p2, DistanceUnits.MILES);
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/LatLongDistanceFilter.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Spatial.Net/Tier/LatLongDistanceFilter.cs?rev=890098&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/LatLongDistanceFilter.cs (added)
+++ incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/LatLongDistanceFilter.cs Sun Dec 13 19:39:51 2009
@@ -0,0 +1,134 @@
+/* 
+ * 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.Collections.Generic;
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+
+namespace Lucene.Net.Spatial.Tier
+{
+	public class LatLongDistanceFilter : DistanceFilter
+	{
+		private readonly double _lat;
+		private readonly double _lng;
+		private readonly string _latField;
+		private readonly string _lngField;
+
+		public LatLongDistanceFilter(Filter startingFilter, double distance, double lat, double lng, string latField, string lngField) : base(startingFilter, distance)
+		{
+			_lat = lat;
+			_lngField = lngField;
+			_latField = latField;
+			_lng = lng;
+		}
+
+		public override DocIdSet GetDocIdSet(IndexReader reader)
+		{
+			double[] latIndex = FieldCache_Fields.DEFAULT.GetDoubles(reader, _latField);
+			double[] lngIndex = FieldCache_Fields.DEFAULT.GetDoubles(reader, _lngField);
+
+			int docBase = NextDocBase;
+			NextDocBase += reader.MaxDoc();
+
+			return new LatLongFilteredDocIdSet(StartingFilter.GetDocIdSet(reader), latIndex, lngIndex, DistanceLookupCache, _lat, _lng, Distance, docBase, Distances);
+		}
+
+		internal class LatLongFilteredDocIdSet : FilteredDocIdSet
+		{
+			private readonly double _lat;
+			private readonly double _lng;
+			private readonly int _docBase;
+			private readonly double _distance;
+			private readonly double[] _latIndex;
+			private readonly double[] _lngIndex;
+			private readonly Dictionary<string, double> _distanceLookupCache;
+			private readonly Dictionary<int, double> _distances;
+
+			public LatLongFilteredDocIdSet(DocIdSet innerSet, double[] latIndex, double[] lngIndex, Dictionary<string, double> distanceLookupCache, double lat, double lng, double distance, int docBase, Dictionary<int, double> distances)
+				: base(innerSet)
+			{
+				_latIndex = latIndex;
+				_distances = distances;
+				_docBase = docBase;
+				_distance = distance;
+				_lng = lng;
+				_lat = lat;
+				_distanceLookupCache = distanceLookupCache;
+				_lngIndex = lngIndex;
+			}
+
+			public override bool Match(int docid)
+			{
+				double x = _latIndex[docid];
+				double y = _lngIndex[docid];
+
+				string ck = x + "," + y;
+				double cachedDistance = _distanceLookupCache.ContainsKey(ck) ? _distanceLookupCache[ck] : 0;
+
+				double d;
+				if (cachedDistance > 0)
+				{
+					d = cachedDistance;
+				}
+				else
+				{
+					d = DistanceUtils.GetInstance().GetDistanceMi(_lat, _lng, x, y);
+					_distanceLookupCache[ck] = d;
+				}
+
+				if (d < _distance)
+				{
+					// Save distances, so they can be pulled for
+					// sorting after filtering is done:
+					_distances[docid + _docBase] = d;
+					return true;
+				}
+
+				return false;
+			}
+
+		}
+
+		public override bool Equals(object o)
+		{
+			if (this == o) return true;
+			if (!(o is LatLongDistanceFilter)) return false;
+
+			var other = (LatLongDistanceFilter) o;
+
+			if (!StartingFilter.Equals(other.StartingFilter) || Distance != other.Distance || _lat != other._lat ||
+			    _lng != other._lng || !_latField.Equals(other._latField) || !_lngField.Equals(other._lngField))
+			{
+				return false;
+			}
+
+			return true;
+		}
+
+		public override int GetHashCode()
+		{
+			int h = Distance.GetHashCode();
+			h ^= StartingFilter.GetHashCode();
+			h ^= _lat.GetHashCode();
+			h ^= _lng.GetHashCode();
+			h ^= _latField.GetHashCode();
+			h ^= _lngField.GetHashCode();
+
+			return h;
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/Package.html
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Spatial.Net/Tier/Package.html?rev=890098&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/Package.html (added)
+++ incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/Package.html Sun Dec 13 19:39:51 2009
@@ -0,0 +1,22 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ 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.
+-->
+<html>
+<body>
+Support for filtering based upon geographic location.
+</body>
+</html>

Added: incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/Projectors/CartesianTierPlotter.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Spatial.Net/Tier/Projectors/CartesianTierPlotter.cs?rev=890098&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/Projectors/CartesianTierPlotter.cs (added)
+++ incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/Projectors/CartesianTierPlotter.cs Sun Dec 13 19:39:51 2009
@@ -0,0 +1,150 @@
+/* 
+ * 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;
+
+namespace Lucene.Net.Spatial.Tier.Projectors
+{
+	public class CartesianTierPlotter
+	{
+		public const String DefaltFieldPrefix = "_tier_";
+
+		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;
+			_fieldPrefix = fieldPrefix;
+			_projector = projector;
+
+			SetTierLength();
+			SetTierBoxes();
+			SetTierVerticalPosDivider();
+		}
+
+		public int TierVerticalPosDivider{ get; private set; }
+
+		private void SetTierLength()
+		{
+			_tierLength = (int)Math.Pow(2, _tierLevel);
+		}
+
+		private void SetTierBoxes()
+		{
+			_tierBoxes = (int)Math.Pow(_tierLength, 2);
+		}
+
+		private void SetTierVerticalPosDivider()
+		{
+			// ceiling of log base 10 of tierLen
+			TierVerticalPosDivider = Convert.ToInt32(Math.Ceiling(Math.Log10(_tierLength)));
+			// 
+			TierVerticalPosDivider = (int)Math.Pow(10, TierVerticalPosDivider);
+		}
+
+		/// <summary>
+		/// TierBoxId is latitude box id + longitude box id
+		/// where latitude box id, and longitude box id are transposed in to position
+		/// coordinates.
+		/// </summary>
+		/// <param name="latitude">The latitude.</param>
+		/// <param name="longitude">The longitude.</param>
+		/// <returns></returns>
+		public double GetTierBoxId(double latitude, double longitude)
+		{
+			double[] coords = _projector.Coords(latitude, longitude);
+
+			double id = GetBoxId(coords[0]) + (GetBoxId(coords[1]) / TierVerticalPosDivider);
+			return id;
+		}
+
+		private double GetBoxId(double coord)
+		{
+			return Math.Floor(coord / (Idd / _tierLength));
+		}
+
+		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;
+		/// </summary>
+		public String GetTierFieldName()
+		{
+			return _fieldPrefix + _tierLevel;
+		}
+
+		/// <summary>
+		/// Get the string name representing tierId _localTier&lt;tierId&gt;
+		/// </summary>
+		/// <param name="tierId">The tier id.</param>
+		public string GetTierFieldName(int tierId)
+		{
+			return _fieldPrefix + tierId;
+		}
+
+		/// <summary>
+		/// Find the tier with the best fit for a bounding box
+		/// Best fit is defined as the ceiling of
+		/// log2 (circumference of earth / distance) 
+		/// distance is defined as the smallest box fitting
+		/// the corner between a radius and a bounding box.
+		///
+		/// Distances less than a mile return 15, finer granularity is
+		/// in accurate
+		/// </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;
+		}
+
+		/// <summary>
+		/// A log to the base 2 formula.
+		/// <code>Math.Log(value) / Math.Log(2)</code>
+		/// </summary>
+		/// <param name="value">The value.</param>
+		public double Log2(double value)
+		{
+			return Math.Log(value) / Math.Log(2);
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/Projectors/IProjector.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Spatial.Net/Tier/Projectors/IProjector.cs?rev=890098&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/Projectors/IProjector.cs (added)
+++ incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/Projectors/IProjector.cs Sun Dec 13 19:39:51 2009
@@ -0,0 +1,25 @@
+/* 
+ * 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.
+ */
+
+namespace Lucene.Net.Spatial.Tier.Projectors
+{
+	public interface IProjector
+	{
+		string CoordsAsString(double latitude, double longitude);
+		double[] Coords(double latitude, double longitude);
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/Projectors/SinusoidalProjector.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Spatial.Net/Tier/Projectors/SinusoidalProjector.cs?rev=890098&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/Projectors/SinusoidalProjector.cs (added)
+++ incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/Projectors/SinusoidalProjector.cs Sun Dec 13 19:39:51 2009
@@ -0,0 +1,43 @@
+/* 
+ * 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 Lucene.Net.Spatial.Utils;
+
+namespace Lucene.Net.Spatial.Tier.Projectors
+{
+	/// <summary>
+	/// Based on Sinusoidal Projections
+	/// Project a latitude / longitude on a 2D cartesian map
+	/// </summary>
+	public class SinusoidalProjector : IProjector
+	{
+		public string CoordsAsString(double latitude, double longitude)
+		{
+			return null;
+		}
+
+		public double[] Coords(double latitude, double longitude)
+		{
+			double rlat = MathHelper.ToRadians(latitude);
+			double rlong = MathHelper.ToRadians(longitude);
+			double nlat = rlong * Math.Cos(rlat);
+			double[] r = {nlat, rlong};
+			return r;
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/Shape.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Spatial.Net/Tier/Shape.cs?rev=890098&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/Shape.cs (added)
+++ incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Tier/Shape.cs Sun Dec 13 19:39:51 2009
@@ -0,0 +1,43 @@
+/* 
+ * 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.Collections.Generic;
+
+namespace Lucene.Net.Spatial.Tier
+{
+	public class Shape
+	{
+		public Shape(string tierId)
+		{
+			Area = new List<double>();
+			TierId = tierId;
+		}
+
+		public List<double> Area { get; private set; }
+		public string TierId { get; private set; }
+
+		public void AddBox(double boxId)
+		{
+			Area.Add(boxId);
+		}
+
+		public bool IsInside(double boxId)
+		{
+			return Area.Contains(boxId);
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Utils/BitwiseHelper.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Spatial.Net/Utils/BitwiseHelper.cs?rev=890098&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Utils/BitwiseHelper.cs (added)
+++ incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Utils/BitwiseHelper.cs Sun Dec 13 19:39:51 2009
@@ -0,0 +1,29 @@
+/* 
+ * 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;
+
+namespace Lucene.Net.Spatial.Utils
+{
+	public class BitwiseHelper
+	{
+		public static long ZeroFillRightShift(long i, int amountToShift)
+		{
+			return (i ^ ((int)Math.Pow(2, amountToShift) - 1)) >> amountToShift;
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Utils/MathHelper.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Spatial.Net/Utils/MathHelper.cs?rev=890098&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Utils/MathHelper.cs (added)
+++ incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Spatial.Net/Utils/MathHelper.cs Sun Dec 13 19:39:51 2009
@@ -0,0 +1,35 @@
+/* 
+ * 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.
+ */
+
+namespace Lucene.Net.Spatial.Utils
+{
+	public static class MathHelper
+	{
+		public static double PI
+		{
+			get
+			{
+				return 3.141592653589793;
+			}
+		}
+
+		public static double ToRadians(double degrees)
+		{
+			return degrees * PI / 180.0;
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Tests/Properties/AssemblyInfo.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Tests/Properties/AssemblyInfo.cs?rev=890098&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Tests/Properties/AssemblyInfo.cs (added)
+++ incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Tests/Properties/AssemblyInfo.cs Sun Dec 13 19:39:51 2009
@@ -0,0 +1,59 @@
+/*
+ * 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.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Apache Lucene.Net (Spitial Tests)")]
+[assembly: AssemblyDescription("The Apache Software Foundation Lucene.Net a full-text search engine library")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("The Apache Software Foundation")]
+[assembly: AssemblyProduct("Spitial Tests")]
+[assembly: AssemblyCopyright("Copyright 2009 The Apache Software Foundation")]
+[assembly: AssemblyTrademark("Copyright 2009 The Apache Software Foundation")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("5d64af8f-cf79-484d-9fc4-57da1b6c49fc")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyInformationalVersionAttribute("2.9.0")]
+
+[assembly: AssemblyVersion("2.9.1.002")]
+[assembly: AssemblyFileVersion("2.9.1.002")]
+
+
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyKeyName("")]

Added: incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Tests/Properties/_svn/entries
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Tests/Properties/_svn/entries?rev=890098&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Tests/Properties/_svn/entries (added)
+++ incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Tests/Properties/_svn/entries Sun Dec 13 19:39:51 2009
@@ -0,0 +1,35 @@
+10
+
+dir
+0
+https://svn.apache.org/repos/asf/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Tests/Properties
+https://svn.apache.org/repos/asf
+add
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+AssemblyInfo.cs
+file
+
+
+
+add
+

Added: incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Tests/TestCartesian.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Tests/TestCartesian.cs?rev=890098&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Tests/TestCartesian.cs (added)
+++ incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Tests/TestCartesian.cs Sun Dec 13 19:39:51 2009
@@ -0,0 +1,185 @@
+/* 
+ * 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 System.Text;
+using Lucene.Net.Analysis;
+using Lucene.Net.Documents;
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Search.Function;
+using Lucene.Net.Spatial.GeoHash;
+using Lucene.Net.Spatial.Geometry;
+using Lucene.Net.Spatial.Tier;
+using Lucene.Net.Spatial.Tier.Projectors;
+using Lucene.Net.Store;
+using Lucene.Net.Util;
+using NUnit.Framework;
+
+namespace Tests
+{
+	[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 &amp; 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 &amp; 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;
+			}
+		}
+	}
+}

Added: incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Tests/Tests.csproj
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Tests/Tests.csproj?rev=890098&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Tests/Tests.csproj (added)
+++ incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Tests/Tests.csproj Sun Dec 13 19:39:51 2009
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{19FC2A6B-4DE9-403F-8CEF-10850F57B96E}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Tests</RootNamespace>
+    <AssemblyName>Tests</AssemblyName>
+    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkSubset>
+    </TargetFrameworkSubset>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Lucene.Net, Version=2.9.1.2, Culture=neutral, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\src\Lucene.Net\bin\Release\Lucene.Net.dll</HintPath>
+    </Reference>
+    <Reference Include="nunit.framework, Version=2.4.3.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>SharedLibs\NUnit\nunit.framework.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="TestCartesian.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Spatial.Net\Spatial.Net.csproj">
+      <Project>{35C347F4-24B2-4BE5-8117-A0E3001551CE}</Project>
+      <Name>Spatial.Net</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Tests/Tests.sln
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/contrib/Spatial.Net/Tests/Tests.sln?rev=890098&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Tests/Tests.sln (added)
+++ incubator/lucene.net/trunk/C#/contrib/Spatial.Net/Tests/Tests.sln Sun Dec 13 19:39:51 2009
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests.csproj", "{19FC2A6B-4DE9-403F-8CEF-10850F57B96E}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{19FC2A6B-4DE9-403F-8CEF-10850F57B96E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{19FC2A6B-4DE9-403F-8CEF-10850F57B96E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{19FC2A6B-4DE9-403F-8CEF-10850F57B96E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{19FC2A6B-4DE9-403F-8CEF-10850F57B96E}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal