You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by sy...@apache.org on 2015/02/09 02:27:56 UTC
[6/6] lucenenet git commit: Moving the 3.0 spatial module to serve as
a basis to Lucene.Net.Spatial
Moving the 3.0 spatial module to serve as a basis to Lucene.Net.Spatial
Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/c9f901b2
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/c9f901b2
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/c9f901b2
Branch: refs/heads/master
Commit: c9f901b24237da82dbb137f709eaa5f0e2398192
Parents: 150651b
Author: Itamar Syn-Hershko <it...@code972.com>
Authored: Mon Feb 9 03:25:27 2015 +0200
Committer: Itamar Syn-Hershko <it...@code972.com>
Committed: Mon Feb 9 03:25:27 2015 +0200
----------------------------------------------------------------------
src/Lucene.Net.Spatial/BBox/AreaSimilarity.cs | 231 +++++++++
src/Lucene.Net.Spatial/BBox/BBoxSimilarity.cs | 30 ++
.../BBox/BBoxSimilarityValueSource.cs | 122 +++++
src/Lucene.Net.Spatial/BBox/BBoxStrategy.cs | 485 +++++++++++++++++++
.../BBox/DistanceSimilarity.cs | 63 +++
.../Contrib.Spatial.NTS.csproj | 202 ++++++++
src/Lucene.Net.Spatial/Contrib.Spatial.csproj | 202 ++++++++
src/Lucene.Net.Spatial/Overview.html | 41 ++
.../Prefix/PointPrefixTreeFieldCacheProvider.cs | 51 ++
.../Prefix/PrefixTreeStrategy.cs | 176 +++++++
.../Prefix/RecursivePrefixTreeFilter.cs | 189 ++++++++
.../Prefix/RecursivePrefixTreeStrategy.cs | 62 +++
.../Prefix/TermQueryPrefixTreeStrategy.cs | 56 +++
.../Prefix/Tree/GeohashPrefixTree.cs | 158 ++++++
src/Lucene.Net.Spatial/Prefix/Tree/Node.cs | 222 +++++++++
.../Prefix/Tree/QuadPrefixTree.cs | 323 ++++++++++++
.../Prefix/Tree/SpatialPrefixTree.cs | 276 +++++++++++
.../Prefix/Tree/SpatialPrefixTreeFactory.cs | 102 ++++
.../Properties/AssemblyInfo.cs | 63 +++
src/Lucene.Net.Spatial/Queries/SpatialArgs.cs | 142 ++++++
.../Queries/SpatialArgsParser.cs | 140 ++++++
.../Queries/SpatialOperation.cs | 116 +++++
.../Queries/UnsupportedSpatialOperation.cs | 29 ++
src/Lucene.Net.Spatial/SpatialStrategy.cs | 150 ++++++
src/Lucene.Net.Spatial/Util/Bits.cs | 92 ++++
.../Util/CachingDoubleValueSource.cs | 101 ++++
.../Util/CompatibilityExtensions.cs | 296 +++++++++++
src/Lucene.Net.Spatial/Util/FixedBitSet.cs | 454 +++++++++++++++++
src/Lucene.Net.Spatial/Util/FunctionQuery.cs | 215 ++++++++
.../Util/ReciprocalFloatFunction.cs | 100 ++++
src/Lucene.Net.Spatial/Util/ShapeFieldCache.cs | 55 +++
.../Util/ShapeFieldCacheDistanceValueSource.cs | 116 +++++
.../Util/ShapeFieldCacheProvider.cs | 105 ++++
.../Util/TermsEnumCompatibility.cs | 140 ++++++
src/Lucene.Net.Spatial/Util/TermsFilter.cs | 117 +++++
.../Util/ValueSourceFilter.cs | 72 +++
.../Vector/DistanceValueSource.cs | 118 +++++
.../Vector/PointVectorStrategy.cs | 260 ++++++++++
src/contrib/Spatial/BBox/AreaSimilarity.cs | 231 ---------
src/contrib/Spatial/BBox/BBoxSimilarity.cs | 30 --
.../Spatial/BBox/BBoxSimilarityValueSource.cs | 122 -----
src/contrib/Spatial/BBox/BBoxStrategy.cs | 485 -------------------
src/contrib/Spatial/BBox/DistanceSimilarity.cs | 63 ---
src/contrib/Spatial/Contrib.Spatial.NTS.csproj | 202 --------
src/contrib/Spatial/Contrib.Spatial.csproj | 202 --------
src/contrib/Spatial/Overview.html | 41 --
.../Prefix/PointPrefixTreeFieldCacheProvider.cs | 51 --
.../Spatial/Prefix/PrefixTreeStrategy.cs | 176 -------
.../Spatial/Prefix/RecursivePrefixTreeFilter.cs | 189 --------
.../Prefix/RecursivePrefixTreeStrategy.cs | 62 ---
.../Prefix/TermQueryPrefixTreeStrategy.cs | 56 ---
.../Spatial/Prefix/Tree/GeohashPrefixTree.cs | 158 ------
src/contrib/Spatial/Prefix/Tree/Node.cs | 222 ---------
.../Spatial/Prefix/Tree/QuadPrefixTree.cs | 323 ------------
.../Spatial/Prefix/Tree/SpatialPrefixTree.cs | 276 -----------
.../Prefix/Tree/SpatialPrefixTreeFactory.cs | 102 ----
src/contrib/Spatial/Properties/AssemblyInfo.cs | 63 ---
src/contrib/Spatial/Queries/SpatialArgs.cs | 142 ------
.../Spatial/Queries/SpatialArgsParser.cs | 140 ------
src/contrib/Spatial/Queries/SpatialOperation.cs | 116 -----
.../Queries/UnsupportedSpatialOperation.cs | 29 --
src/contrib/Spatial/SpatialStrategy.cs | 150 ------
src/contrib/Spatial/Util/Bits.cs | 92 ----
.../Spatial/Util/CachingDoubleValueSource.cs | 101 ----
.../Spatial/Util/CompatibilityExtensions.cs | 296 -----------
src/contrib/Spatial/Util/FixedBitSet.cs | 454 -----------------
src/contrib/Spatial/Util/FunctionQuery.cs | 215 --------
.../Spatial/Util/ReciprocalFloatFunction.cs | 100 ----
src/contrib/Spatial/Util/ShapeFieldCache.cs | 55 ---
.../Util/ShapeFieldCacheDistanceValueSource.cs | 116 -----
.../Spatial/Util/ShapeFieldCacheProvider.cs | 105 ----
.../Spatial/Util/TermsEnumCompatibility.cs | 140 ------
src/contrib/Spatial/Util/TermsFilter.cs | 117 -----
src/contrib/Spatial/Util/ValueSourceFilter.cs | 72 ---
.../Spatial/Vector/DistanceValueSource.cs | 118 -----
.../Spatial/Vector/PointVectorStrategy.cs | 260 ----------
76 files changed, 5872 insertions(+), 5872 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c9f901b2/src/Lucene.Net.Spatial/BBox/AreaSimilarity.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/BBox/AreaSimilarity.cs b/src/Lucene.Net.Spatial/BBox/AreaSimilarity.cs
new file mode 100644
index 0000000..fde6e10
--- /dev/null
+++ b/src/Lucene.Net.Spatial/BBox/AreaSimilarity.cs
@@ -0,0 +1,231 @@
+/*
+ * 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 Spatial4n.Core.Context;
+using Spatial4n.Core.Shapes;
+
+namespace Lucene.Net.Spatial.BBox
+{
+ /// <summary>
+ /// The algorithm is implemented as envelope on envelope overlays rather than
+ /// complex polygon on complex polygon overlays.
+ /// <p/>
+ /// <p/>
+ /// Spatial relevance scoring algorithm:
+ /// <p/>
+ /// <br/> queryArea = the area of the input query envelope
+ /// <br/> targetArea = the area of the target envelope (per Lucene document)
+ /// <br/> intersectionArea = the area of the intersection for the query/target envelopes
+ /// <br/> queryPower = the weighting power associated with the query envelope (default = 1.0)
+ /// <br/> targetPower = the weighting power associated with the target envelope (default = 1.0)
+ /// <p/>
+ /// <br/> queryRatio = intersectionArea / queryArea;
+ /// <br/> targetRatio = intersectionArea / targetArea;
+ /// <br/> queryFactor = Math.pow(queryRatio,queryPower);
+ /// <br/> targetFactor = Math.pow(targetRatio,targetPower);
+ /// <br/> score = queryFactor /// targetFactor;
+ /// <p/>
+ /// Based on Geoportal's
+ /// <a href="http://geoportal.svn.sourceforge.net/svnroot/geoportal/Geoportal/trunk/src/com/esri/gpt/catalog/lucene/SpatialRankingValueSource.java">
+ /// SpatialRankingValueSource</a>.
+ ///
+ /// @lucene.experimental
+ /// </summary>
+ public class AreaSimilarity : BBoxSimilarity
+ {
+ /*
+ * Properties associated with the query envelope
+ */
+ private readonly Rectangle queryExtent;
+ private readonly double queryArea;
+
+ private readonly double targetPower;
+ private readonly double queryPower;
+
+ public AreaSimilarity(Rectangle queryExtent, double queryPower, double targetPower)
+ {
+ this.queryExtent = queryExtent;
+ this.queryArea = queryExtent.GetArea(null);
+
+ this.queryPower = queryPower;
+ this.targetPower = targetPower;
+
+ // if (this.qryMinX > queryExtent.getMaxX()) {
+ // this.qryCrossedDateline = true;
+ // this.qryArea = Math.abs(qryMaxX + 360.0 - qryMinX) * Math.abs(qryMaxY - qryMinY);
+ // } else {
+ // this.qryArea = Math.abs(qryMaxX - qryMinX) * Math.abs(qryMaxY - qryMinY);
+ // }
+ }
+
+ public AreaSimilarity(Rectangle queryExtent)
+ : this(queryExtent, 2.0, 0.5)
+ {
+ }
+
+ public String GetDelimiterQueryParameters()
+ {
+ return queryExtent + ";" + queryPower + ";" + targetPower;
+ }
+
+ public double Score(Rectangle target, Explanation exp)
+ {
+ if (target == null || queryArea <= 0)
+ {
+ return 0;
+ }
+ double targetArea = target.GetArea(null);
+ if (targetArea <= 0)
+ {
+ return 0;
+ }
+ double score = 0;
+
+ double top = Math.Min(queryExtent.GetMaxY(), target.GetMaxY());
+ double bottom = Math.Max(queryExtent.GetMinY(), target.GetMinY());
+ double height = top - bottom;
+ double width = 0;
+
+ // queries that cross the date line
+ if (queryExtent.GetCrossesDateLine())
+ {
+ // documents that cross the date line
+ if (target.GetCrossesDateLine())
+ {
+ double left = Math.Max(queryExtent.GetMinX(), target.GetMinX());
+ double right = Math.Min(queryExtent.GetMaxX(), target.GetMaxX());
+ width = right + 360.0 - left;
+ }
+ else
+ {
+ double qryWestLeft = Math.Max(queryExtent.GetMinX(), target.GetMaxX());
+ double qryWestRight = Math.Min(target.GetMaxX(), 180.0);
+ double qryWestWidth = qryWestRight - qryWestLeft;
+ if (qryWestWidth > 0)
+ {
+ width = qryWestWidth;
+ }
+ else
+ {
+ double qryEastLeft = Math.Max(target.GetMaxX(), -180.0);
+ double qryEastRight = Math.Min(queryExtent.GetMaxX(), target.GetMaxX());
+ double qryEastWidth = qryEastRight - qryEastLeft;
+ if (qryEastWidth > 0)
+ {
+ width = qryEastWidth;
+ }
+ }
+ }
+ }
+ else
+ { // queries that do not cross the date line
+
+ if (target.GetCrossesDateLine())
+ {
+ double tgtWestLeft = Math.Max(queryExtent.GetMinX(), target.GetMinX());
+ double tgtWestRight = Math.Min(queryExtent.GetMaxX(), 180.0);
+ double tgtWestWidth = tgtWestRight - tgtWestLeft;
+ if (tgtWestWidth > 0)
+ {
+ width = tgtWestWidth;
+ }
+ else
+ {
+ double tgtEastLeft = Math.Max(queryExtent.GetMinX(), -180.0);
+ double tgtEastRight = Math.Min(queryExtent.GetMaxX(), target.GetMaxX());
+ double tgtEastWidth = tgtEastRight - tgtEastLeft;
+ if (tgtEastWidth > 0)
+ {
+ width = tgtEastWidth;
+ }
+ }
+ }
+ else
+ {
+ double left = Math.Max(queryExtent.GetMinX(), target.GetMinX());
+ double right = Math.Min(queryExtent.GetMaxX(), target.GetMaxX());
+ width = right - left;
+ }
+ }
+
+
+ // calculate the score
+ if ((width > 0) && (height > 0))
+ {
+ double intersectionArea = width * height;
+ double queryRatio = intersectionArea / queryArea;
+ double targetRatio = intersectionArea / targetArea;
+ double queryFactor = Math.Pow(queryRatio, queryPower);
+ double targetFactor = Math.Pow(targetRatio, targetPower);
+ score = queryFactor * targetFactor * 10000.0;
+
+ if (exp != null)
+ {
+ // StringBuilder sb = new StringBuilder();
+ // sb.append("\nscore=").append(score);
+ // sb.append("\n query=").append();
+ // sb.append("\n target=").append(target.toString());
+ // sb.append("\n intersectionArea=").append(intersectionArea);
+ //
+ // sb.append(" queryArea=").append(queryArea).append(" targetArea=").append(targetArea);
+ // sb.append("\n queryRatio=").append(queryRatio).append(" targetRatio=").append(targetRatio);
+ // sb.append("\n queryFactor=").append(queryFactor).append(" targetFactor=").append(targetFactor);
+ // sb.append(" (queryPower=").append(queryPower).append(" targetPower=").append(targetPower).append(")");
+
+ exp.Value = (float) score;
+ exp.Description = GetType().Name;
+
+ Explanation e = null;
+
+ exp.AddDetail(e = new Explanation((float)intersectionArea, "IntersectionArea"));
+ e.AddDetail(new Explanation((float)width, "width; Query: " + queryExtent));
+ e.AddDetail(new Explanation((float)height, "height; Target: " + target));
+
+ exp.AddDetail(e = new Explanation((float)queryFactor, "Query"));
+ e.AddDetail(new Explanation((float)queryArea, "area"));
+ e.AddDetail(new Explanation((float)queryRatio, "ratio"));
+ e.AddDetail(new Explanation((float)queryPower, "power"));
+
+ exp.AddDetail(e = new Explanation((float)targetFactor, "Target"));
+ e.AddDetail(new Explanation((float)targetArea, "area"));
+ e.AddDetail(new Explanation((float)targetRatio, "ratio"));
+ e.AddDetail(new Explanation((float)targetPower, "power"));
+ }
+ }
+ else if (exp != null)
+ {
+ exp.Value = 0;
+ exp.Description = "Shape does not intersect";
+ }
+ return score;
+ }
+
+ public override bool Equals(object obj)
+ {
+ var other = obj as AreaSimilarity;
+ if (other == null) return false;
+ return GetDelimiterQueryParameters().Equals(other.GetDelimiterQueryParameters());
+ }
+
+ public override int GetHashCode()
+ {
+ return GetDelimiterQueryParameters().GetHashCode();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c9f901b2/src/Lucene.Net.Spatial/BBox/BBoxSimilarity.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/BBox/BBoxSimilarity.cs b/src/Lucene.Net.Spatial/BBox/BBoxSimilarity.cs
new file mode 100644
index 0000000..a18baa4
--- /dev/null
+++ b/src/Lucene.Net.Spatial/BBox/BBoxSimilarity.cs
@@ -0,0 +1,30 @@
+/*
+ * 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.Search;
+using Spatial4n.Core.Shapes;
+
+namespace Lucene.Net.Spatial.BBox
+{
+ /// <summary>
+ /// Abstraction of the calculation used to determine how similar two Bounding Boxes are.
+ /// </summary>
+ public interface BBoxSimilarity
+ {
+ double Score(Rectangle extent, Explanation exp);
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c9f901b2/src/Lucene.Net.Spatial/BBox/BBoxSimilarityValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/BBox/BBoxSimilarityValueSource.cs b/src/Lucene.Net.Spatial/BBox/BBoxSimilarityValueSource.cs
new file mode 100644
index 0000000..6939274
--- /dev/null
+++ b/src/Lucene.Net.Spatial/BBox/BBoxSimilarityValueSource.cs
@@ -0,0 +1,122 @@
+/*
+ * 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.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Search.Function;
+using Lucene.Net.Spatial.Util;
+using Spatial4n.Core.Shapes;
+using Spatial4n.Core.Shapes.Impl;
+
+namespace Lucene.Net.Spatial.BBox
+{
+ public class BBoxSimilarityValueSource : ValueSource
+ {
+ private readonly BBoxStrategy strategy;
+ private readonly BBoxSimilarity similarity;
+
+ public BBoxSimilarityValueSource(BBoxStrategy strategy, BBoxSimilarity similarity)
+ {
+ this.strategy = strategy;
+ this.similarity = similarity;
+ }
+
+ private class BBoxSimilarityValueSourceDocValues : DocValues
+ {
+ private readonly BBoxSimilarityValueSource _enclosingInstance;
+ private readonly Rectangle rect;
+ private readonly double[] minX;
+ private readonly double[] minY;
+ private readonly double[] maxX;
+ private readonly double[] maxY;
+
+ private readonly IBits validMinX, validMaxX;
+
+ public BBoxSimilarityValueSourceDocValues(IndexReader reader, BBoxSimilarityValueSource enclosingInstance)
+ {
+ _enclosingInstance = enclosingInstance;
+ rect = _enclosingInstance.strategy.GetSpatialContext().MakeRectangle(0, 0, 0, 0); //reused
+
+ minX = FieldCache_Fields.DEFAULT.GetDoubles(reader, enclosingInstance.strategy.field_minX/*, true*/);
+ minY = FieldCache_Fields.DEFAULT.GetDoubles(reader, enclosingInstance.strategy.field_minY/*, true*/);
+ maxX = FieldCache_Fields.DEFAULT.GetDoubles(reader, enclosingInstance.strategy.field_maxX/*, true*/);
+ maxY = FieldCache_Fields.DEFAULT.GetDoubles(reader, enclosingInstance.strategy.field_maxY/*, true*/);
+
+ validMinX = FieldCache_Fields.DEFAULT.GetDocsWithField(reader, enclosingInstance.strategy.field_minX);
+ validMaxX = FieldCache_Fields.DEFAULT.GetDocsWithField(reader, enclosingInstance.strategy.field_maxX);
+ }
+
+ public override float FloatVal(int doc)
+ {
+ // make sure it has minX and area
+ if (validMinX.Get(doc) && validMaxX.Get(doc))
+ {
+ rect.Reset(
+ minX[doc], maxX[doc],
+ minY[doc], maxY[doc]);
+ return (float) _enclosingInstance.similarity.Score(rect, null);
+ }
+ else
+ {
+ return (float) _enclosingInstance.similarity.Score(null, null);
+ }
+ }
+
+ public override Explanation Explain(int doc)
+ {
+ // make sure it has minX and area
+ if (validMinX.Get(doc) && validMaxX.Get(doc))
+ {
+ rect.Reset(
+ minX[doc], maxX[doc],
+ minY[doc], maxY[doc]);
+ var exp = new Explanation();
+ _enclosingInstance.similarity.Score(rect, exp);
+ return exp;
+ }
+ return new Explanation(0, "No BBox");
+ }
+
+ public override string ToString(int doc)
+ {
+ return _enclosingInstance.Description() + "=" + FloatVal(doc);
+ }
+ }
+
+ public override DocValues GetValues(IndexReader reader)
+ {
+ return new BBoxSimilarityValueSourceDocValues(reader, this);
+ }
+
+ public override string Description()
+ {
+ return "BBoxSimilarityValueSource(" + similarity + ")";
+ }
+
+ public override bool Equals(object o)
+ {
+ var other = o as BBoxSimilarityValueSource;
+ if (other == null) return false;
+ return similarity.Equals(other.similarity);
+ }
+
+ public override int GetHashCode()
+ {
+ return typeof(BBoxSimilarityValueSource).GetHashCode() + similarity.GetHashCode();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c9f901b2/src/Lucene.Net.Spatial/BBox/BBoxStrategy.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/BBox/BBoxStrategy.cs b/src/Lucene.Net.Spatial/BBox/BBoxStrategy.cs
new file mode 100644
index 0000000..f14af08
--- /dev/null
+++ b/src/Lucene.Net.Spatial/BBox/BBoxStrategy.cs
@@ -0,0 +1,485 @@
+/*
+ * 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.Documents;
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Search.Function;
+using Lucene.Net.Spatial.Queries;
+using Lucene.Net.Spatial.Util;
+using Spatial4n.Core.Context;
+using Spatial4n.Core.Shapes;
+
+namespace Lucene.Net.Spatial.BBox
+{
+ public class BBoxStrategy : SpatialStrategy
+ {
+ public static String SUFFIX_MINX = "__minX";
+ public static String SUFFIX_MAXX = "__maxX";
+ public static String SUFFIX_MINY = "__minY";
+ public static String SUFFIX_MAXY = "__maxY";
+ public static String SUFFIX_XDL = "__xdl";
+
+ /*
+ * The Bounding Box gets stored as four fields for x/y min/max and a flag
+ * that says if the box crosses the dateline (xdl).
+ */
+ public readonly String field_bbox;
+ public readonly String field_minX;
+ public readonly String field_minY;
+ public readonly String field_maxX;
+ public readonly String field_maxY;
+ public readonly String field_xdl; // crosses dateline
+
+ public readonly double queryPower = 1.0;
+ public readonly double targetPower = 1.0f;
+ public int precisionStep = 8; // same as solr default
+
+ public BBoxStrategy(SpatialContext ctx, String fieldNamePrefix)
+ : base(ctx, fieldNamePrefix)
+ {
+ field_bbox = fieldNamePrefix;
+ field_minX = fieldNamePrefix + SUFFIX_MINX;
+ field_maxX = fieldNamePrefix + SUFFIX_MAXX;
+ field_minY = fieldNamePrefix + SUFFIX_MINY;
+ field_maxY = fieldNamePrefix + SUFFIX_MAXY;
+ field_xdl = fieldNamePrefix + SUFFIX_XDL;
+ }
+
+ public void SetPrecisionStep(int p)
+ {
+ precisionStep = p;
+ if (precisionStep <= 0 || precisionStep >= 64)
+ precisionStep = int.MaxValue;
+ }
+
+ //---------------------------------
+ // Indexing
+ //---------------------------------
+
+ public override AbstractField[] CreateIndexableFields(Shape shape)
+ {
+ var rect = shape as Rectangle;
+ if (rect != null)
+ return CreateIndexableFields(rect);
+ throw new InvalidOperationException("Can only index Rectangle, not " + shape);
+ }
+
+ public AbstractField[] CreateIndexableFields(Rectangle bbox)
+ {
+ var fields = new AbstractField[5];
+ fields[0] = DoubleField(field_minX, bbox.GetMinX());
+ fields[1] = DoubleField(field_maxX, bbox.GetMaxX());
+ fields[2] = DoubleField(field_minY, bbox.GetMinY());
+ fields[3] = DoubleField(field_maxY, bbox.GetMaxY());
+ fields[4] = new Field(field_xdl, bbox.GetCrossesDateLine() ? "T" : "F", Field.Store.NO,
+ Field.Index.NOT_ANALYZED_NO_NORMS) {OmitNorms = true, OmitTermFreqAndPositions = true};
+ return fields;
+ }
+
+ private AbstractField DoubleField(string field, double value)
+ {
+ var f = new NumericField(field, precisionStep, Field.Store.NO, true)
+ {OmitNorms = true, OmitTermFreqAndPositions = true};
+ f.SetDoubleValue(value);
+ return f;
+ }
+
+ public override ValueSource MakeDistanceValueSource(Point queryPoint)
+ {
+ return new BBoxSimilarityValueSource(this, new DistanceSimilarity(this.GetSpatialContext(), queryPoint));
+ }
+
+ public ValueSource MakeBBoxAreaSimilarityValueSource(Rectangle queryBox)
+ {
+ return new BBoxSimilarityValueSource(
+ this, new AreaSimilarity(queryBox, queryPower, targetPower));
+ }
+
+ public override ConstantScoreQuery MakeQuery(SpatialArgs args)
+ {
+ return new ConstantScoreQuery(new QueryWrapperFilter(MakeSpatialQuery(args)));
+ }
+
+ public Query MakeQueryWithValueSource(SpatialArgs args, ValueSource valueSource)
+ {
+
+ var bq = new BooleanQuery();
+ var spatial = MakeFilter(args);
+ bq.Add(new ConstantScoreQuery(spatial), Occur.MUST);
+
+ // This part does the scoring
+ Query spatialRankingQuery = new FunctionQuery(valueSource);
+ bq.Add(spatialRankingQuery, Occur.MUST);
+ return bq;
+ }
+
+ public override Filter MakeFilter(SpatialArgs args)
+ {
+ return new QueryWrapperFilter(MakeSpatialQuery(args));
+ }
+
+ private Query MakeSpatialQuery(SpatialArgs args)
+ {
+ var bbox = args.Shape as Rectangle;
+ if (bbox == null)
+ throw new InvalidOperationException("Can only query by Rectangle, not " + args.Shape);
+
+ Query spatial = null;
+
+ // Useful for understanding Relations:
+ // http://edndoc.esri.com/arcsde/9.1/general_topics/understand_spatial_relations.htm
+ SpatialOperation op = args.Operation;
+ if (op == SpatialOperation.BBoxIntersects) spatial = MakeIntersects(bbox);
+ else if (op == SpatialOperation.BBoxWithin) spatial = MakeWithin(bbox);
+ else if (op == SpatialOperation.Contains) spatial = MakeContains(bbox);
+ else if (op == SpatialOperation.Intersects) spatial = MakeIntersects(bbox);
+ else if (op == SpatialOperation.IsEqualTo) spatial = MakeEquals(bbox);
+ else if (op == SpatialOperation.IsDisjointTo) spatial = MakeDisjoint(bbox);
+ else if (op == SpatialOperation.IsWithin) spatial = MakeWithin(bbox);
+ else if (op == SpatialOperation.Overlaps) spatial = MakeIntersects(bbox);
+ else
+ {
+ throw new UnsupportedSpatialOperation(op);
+ }
+ return spatial;
+ }
+
+ //-------------------------------------------------------------------------------
+ //
+ //-------------------------------------------------------------------------------
+
+ /// <summary>
+ /// Constructs a query to retrieve documents that fully contain the input envelope.
+ /// </summary>
+ /// <param name="bbox"></param>
+ /// <returns>The spatial query</returns>
+ protected Query MakeContains(Rectangle bbox)
+ {
+
+ // general case
+ // docMinX <= queryExtent.GetMinX() AND docMinY <= queryExtent.GetMinY() AND docMaxX >= queryExtent.GetMaxX() AND docMaxY >= queryExtent.GetMaxY()
+
+ // Y conditions
+ // docMinY <= queryExtent.GetMinY() AND docMaxY >= queryExtent.GetMaxY()
+ Query qMinY = NumericRangeQuery.NewDoubleRange(field_minY, precisionStep, null, bbox.GetMinY(), false, true);
+ Query qMaxY = NumericRangeQuery.NewDoubleRange(field_maxY, precisionStep, bbox.GetMaxY(), null, true, false);
+ Query yConditions = this.MakeQuery(new Query[] { qMinY, qMaxY }, Occur.MUST);
+
+ // X conditions
+ Query xConditions = null;
+
+ // queries that do not cross the date line
+ if (!bbox.GetCrossesDateLine())
+ {
+
+ // X Conditions for documents that do not cross the date line,
+ // documents that contain the min X and max X of the query envelope,
+ // docMinX <= queryExtent.GetMinX() AND docMaxX >= queryExtent.GetMaxX()
+ Query qMinX = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, null, bbox.GetMinX(), false, true);
+ Query qMaxX = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, bbox.GetMaxX(), null, true, false);
+ Query qMinMax = this.MakeQuery(new Query[] { qMinX, qMaxX }, Occur.MUST);
+ Query qNonXDL = this.MakeXDL(false, qMinMax);
+
+ // X Conditions for documents that cross the date line,
+ // the left portion of the document contains the min X of the query
+ // OR the right portion of the document contains the max X of the query,
+ // docMinXLeft <= queryExtent.GetMinX() OR docMaxXRight >= queryExtent.GetMaxX()
+ Query qXDLLeft = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, null, bbox.GetMinX(), false, true);
+ Query qXDLRight = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, bbox.GetMaxX(), null, true, false);
+ Query qXDLLeftRight = this.MakeQuery(new Query[] { qXDLLeft, qXDLRight }, Occur.SHOULD);
+ Query qXDL = this.MakeXDL(true, qXDLLeftRight);
+
+ // apply the non-XDL and XDL conditions
+ xConditions = this.MakeQuery(new Query[] { qNonXDL, qXDL }, Occur.SHOULD);
+
+ // queries that cross the date line
+ }
+ else
+ {
+
+ // No need to search for documents that do not cross the date line
+
+ // X Conditions for documents that cross the date line,
+ // the left portion of the document contains the min X of the query
+ // AND the right portion of the document contains the max X of the query,
+ // docMinXLeft <= queryExtent.GetMinX() AND docMaxXRight >= queryExtent.GetMaxX()
+ Query qXDLLeft = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, null, bbox.GetMinX(), false, true);
+ Query qXDLRight = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, bbox.GetMaxX(), null, true, false);
+ Query qXDLLeftRight = this.MakeQuery(new Query[] { qXDLLeft, qXDLRight }, Occur.MUST);
+
+ xConditions = this.MakeXDL(true, qXDLLeftRight);
+ }
+
+ // both X and Y conditions must occur
+ return this.MakeQuery(new Query[] { xConditions, yConditions }, Occur.MUST);
+ }
+
+ /// <summary>
+ /// Constructs a query to retrieve documents that are disjoint to the input envelope.
+ /// </summary>
+ /// <param name="bbox"></param>
+ /// <returns>the spatial query</returns>
+ Query MakeDisjoint(Rectangle bbox)
+ {
+
+ // general case
+ // docMinX > queryExtent.GetMaxX() OR docMaxX < queryExtent.GetMinX() OR docMinY > queryExtent.GetMaxY() OR docMaxY < queryExtent.GetMinY()
+
+ // Y conditions
+ // docMinY > queryExtent.GetMaxY() OR docMaxY < queryExtent.GetMinY()
+ Query qMinY = NumericRangeQuery.NewDoubleRange(field_minY, precisionStep, bbox.GetMaxY(), null, false, false);
+ Query qMaxY = NumericRangeQuery.NewDoubleRange(field_maxY, precisionStep, null, bbox.GetMinY(), false, false);
+ Query yConditions = this.MakeQuery(new Query[] { qMinY, qMaxY }, Occur.SHOULD);
+
+ // X conditions
+ Query xConditions = null;
+
+ // queries that do not cross the date line
+ if (!bbox.GetCrossesDateLine())
+ {
+
+ // X Conditions for documents that do not cross the date line,
+ // docMinX > queryExtent.GetMaxX() OR docMaxX < queryExtent.GetMinX()
+ Query qMinX = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, bbox.GetMaxX(), null, false, false);
+ Query qMaxX = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, null, bbox.GetMinX(), false, false);
+ Query qMinMax = this.MakeQuery(new Query[] { qMinX, qMaxX }, Occur.SHOULD);
+ Query qNonXDL = this.MakeXDL(false, qMinMax);
+
+ // X Conditions for documents that cross the date line,
+ // both the left and right portions of the document must be disjoint to the query
+ // (docMinXLeft > queryExtent.GetMaxX() OR docMaxXLeft < queryExtent.GetMinX()) AND
+ // (docMinXRight > queryExtent.GetMaxX() OR docMaxXRight < queryExtent.GetMinX())
+ // where: docMaxXLeft = 180.0, docMinXRight = -180.0
+ // (docMaxXLeft < queryExtent.GetMinX()) equates to (180.0 < queryExtent.GetMinX()) and is ignored
+ // (docMinXRight > queryExtent.GetMaxX()) equates to (-180.0 > queryExtent.GetMaxX()) and is ignored
+ Query qMinXLeft = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, bbox.GetMaxX(), null, false, false);
+ Query qMaxXRight = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, null, bbox.GetMinX(), false, false);
+ Query qLeftRight = this.MakeQuery(new Query[] { qMinXLeft, qMaxXRight }, Occur.MUST);
+ Query qXDL = this.MakeXDL(true, qLeftRight);
+
+ // apply the non-XDL and XDL conditions
+ xConditions = this.MakeQuery(new Query[] { qNonXDL, qXDL }, Occur.SHOULD);
+
+ // queries that cross the date line
+ }
+ else
+ {
+
+ // X Conditions for documents that do not cross the date line,
+ // the document must be disjoint to both the left and right query portions
+ // (docMinX > queryExtent.GetMaxX()Left OR docMaxX < queryExtent.GetMinX()) AND (docMinX > queryExtent.GetMaxX() OR docMaxX < queryExtent.GetMinX()Left)
+ // where: queryExtent.GetMaxX()Left = 180.0, queryExtent.GetMinX()Left = -180.0
+ Query qMinXLeft = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, 180.0, null, false, false);
+ Query qMaxXLeft = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, null, bbox.GetMinX(), false, false);
+ Query qMinXRight = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, bbox.GetMaxX(), null, false, false);
+ Query qMaxXRight = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, null, -180.0, false, false);
+ Query qLeft = this.MakeQuery(new Query[] { qMinXLeft, qMaxXLeft }, Occur.SHOULD);
+ Query qRight = this.MakeQuery(new Query[] { qMinXRight, qMaxXRight }, Occur.SHOULD);
+ Query qLeftRight = this.MakeQuery(new Query[] { qLeft, qRight }, Occur.MUST);
+
+ // No need to search for documents that do not cross the date line
+
+ xConditions = this.MakeXDL(false, qLeftRight);
+ }
+
+ // either X or Y conditions should occur
+ return this.MakeQuery(new Query[] { xConditions, yConditions }, Occur.SHOULD);
+ }
+
+ /*
+ * Constructs a query to retrieve documents that equal the input envelope.
+ *
+ * @return the spatial query
+ */
+ public Query MakeEquals(Rectangle bbox)
+ {
+
+ // docMinX = queryExtent.GetMinX() AND docMinY = queryExtent.GetMinY() AND docMaxX = queryExtent.GetMaxX() AND docMaxY = queryExtent.GetMaxY()
+ Query qMinX = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, bbox.GetMinX(), bbox.GetMinX(), true, true);
+ Query qMinY = NumericRangeQuery.NewDoubleRange(field_minY, precisionStep, bbox.GetMinY(), bbox.GetMinY(), true, true);
+ Query qMaxX = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, bbox.GetMaxX(), bbox.GetMaxX(), true, true);
+ Query qMaxY = NumericRangeQuery.NewDoubleRange(field_maxY, precisionStep, bbox.GetMaxY(), bbox.GetMaxY(), true, true);
+
+ var bq = new BooleanQuery
+ {
+ {qMinX, Occur.MUST},
+ {qMinY, Occur.MUST},
+ {qMaxX, Occur.MUST},
+ {qMaxY, Occur.MUST}
+ };
+ return bq;
+ }
+
+ /// <summary>
+ /// Constructs a query to retrieve documents that intersect the input envelope.
+ /// </summary>
+ /// <param name="bbox"></param>
+ /// <returns>the spatial query</returns>
+ Query MakeIntersects(Rectangle bbox)
+ {
+
+ // the original intersects query does not work for envelopes that cross the date line,
+ // switch to a NOT Disjoint query
+
+ // MUST_NOT causes a problem when it's the only clause type within a BooleanQuery,
+ // to get round it we add all documents as a SHOULD
+
+ // there must be an envelope, it must not be disjoint
+ Query qDisjoint = MakeDisjoint(bbox);
+ Query qIsNonXDL = this.MakeXDL(false);
+ Query qIsXDL = this.MakeXDL(true);
+ Query qHasEnv = this.MakeQuery(new Query[] { qIsNonXDL, qIsXDL }, Occur.SHOULD);
+ var qNotDisjoint = new BooleanQuery {{qHasEnv, Occur.MUST}, {qDisjoint, Occur.MUST_NOT}};
+
+ //Query qDisjoint = makeDisjoint();
+ //BooleanQuery qNotDisjoint = new BooleanQuery();
+ //qNotDisjoint.add(new MatchAllDocsQuery(),BooleanClause.Occur.SHOULD);
+ //qNotDisjoint.add(qDisjoint,BooleanClause.Occur.MUST_NOT);
+ return qNotDisjoint;
+ }
+
+ /*
+ * Makes a boolean query based upon a collection of queries and a logical operator.
+ *
+ * @param queries the query collection
+ * @param occur the logical operator
+ * @return the query
+ */
+ BooleanQuery MakeQuery(Query[] queries, Occur occur)
+ {
+ var bq = new BooleanQuery();
+ foreach (Query query in queries)
+ {
+ bq.Add(query, occur);
+ }
+ return bq;
+ }
+
+ /*
+ * Constructs a query to retrieve documents are fully within the input envelope.
+ *
+ * @return the spatial query
+ */
+ Query MakeWithin(Rectangle bbox)
+ {
+
+ // general case
+ // docMinX >= queryExtent.GetMinX() AND docMinY >= queryExtent.GetMinY() AND docMaxX <= queryExtent.GetMaxX() AND docMaxY <= queryExtent.GetMaxY()
+
+ // Y conditions
+ // docMinY >= queryExtent.GetMinY() AND docMaxY <= queryExtent.GetMaxY()
+ Query qMinY = NumericRangeQuery.NewDoubleRange(field_minY, precisionStep, bbox.GetMinY(), null, true, false);
+ Query qMaxY = NumericRangeQuery.NewDoubleRange(field_maxY, precisionStep, null, bbox.GetMaxY(), false, true);
+ Query yConditions = this.MakeQuery(new Query[] { qMinY, qMaxY }, Occur.MUST);
+
+ // X conditions
+ Query xConditions = null;
+
+ // X Conditions for documents that cross the date line,
+ // the left portion of the document must be within the left portion of the query,
+ // AND the right portion of the document must be within the right portion of the query
+ // docMinXLeft >= queryExtent.GetMinX() AND docMaxXLeft <= 180.0
+ // AND docMinXRight >= -180.0 AND docMaxXRight <= queryExtent.GetMaxX()
+ Query qXDLLeft = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, bbox.GetMinX(), null, true, false);
+ Query qXDLRight = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, null, bbox.GetMaxX(), false, true);
+ Query qXDLLeftRight = this.MakeQuery(new Query[] { qXDLLeft, qXDLRight }, Occur.MUST);
+ Query qXDL = this.MakeXDL(true, qXDLLeftRight);
+
+ // queries that do not cross the date line
+ if (!bbox.GetCrossesDateLine())
+ {
+
+ // X Conditions for documents that do not cross the date line,
+ // docMinX >= queryExtent.GetMinX() AND docMaxX <= queryExtent.GetMaxX()
+ Query qMinX = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, bbox.GetMinX(), null, true, false);
+ Query qMaxX = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, null, bbox.GetMaxX(), false, true);
+ Query qMinMax = this.MakeQuery(new Query[] { qMinX, qMaxX }, Occur.MUST);
+ Query qNonXDL = this.MakeXDL(false, qMinMax);
+
+ // apply the non-XDL or XDL X conditions
+ if ((bbox.GetMinX() <= -180.0) && bbox.GetMaxX() >= 180.0)
+ {
+ xConditions = this.MakeQuery(new Query[] { qNonXDL, qXDL }, Occur.SHOULD);
+ }
+ else
+ {
+ xConditions = qNonXDL;
+ }
+
+ // queries that cross the date line
+ }
+ else
+ {
+
+ // X Conditions for documents that do not cross the date line
+
+ // the document should be within the left portion of the query
+ // docMinX >= queryExtent.GetMinX() AND docMaxX <= 180.0
+ Query qMinXLeft = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, bbox.GetMinX(), null, true, false);
+ Query qMaxXLeft = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, null, 180.0, false, true);
+ Query qLeft = this.MakeQuery(new Query[] { qMinXLeft, qMaxXLeft }, Occur.MUST);
+
+ // the document should be within the right portion of the query
+ // docMinX >= -180.0 AND docMaxX <= queryExtent.GetMaxX()
+ Query qMinXRight = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, -180.0, null, true, false);
+ Query qMaxXRight = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, null, bbox.GetMaxX(), false, true);
+ Query qRight = this.MakeQuery(new Query[] { qMinXRight, qMaxXRight }, Occur.MUST);
+
+ // either left or right conditions should occur,
+ // apply the left and right conditions to documents that do not cross the date line
+ Query qLeftRight = this.MakeQuery(new Query[] { qLeft, qRight }, Occur.SHOULD);
+ Query qNonXDL = this.MakeXDL(false, qLeftRight);
+
+ // apply the non-XDL and XDL conditions
+ xConditions = this.MakeQuery(new Query[] { qNonXDL, qXDL }, Occur.SHOULD);
+ }
+
+ // both X and Y conditions must occur
+ return this.MakeQuery(new Query[] { xConditions, yConditions }, Occur.MUST);
+ }
+
+ /*
+ * Constructs a query to retrieve documents that do or do not cross the date line.
+ *
+ *
+ * @param crossedDateLine <code>true</true> for documents that cross the date line
+ * @return the query
+ */
+ public Query MakeXDL(bool crossedDateLine)
+ {
+ // The 'T' and 'F' values match solr fields
+ return new TermQuery(new Term(field_xdl, crossedDateLine ? "T" : "F"));
+ }
+
+ /*
+ * Constructs a query to retrieve documents that do or do not cross the date line
+ * and match the supplied spatial query.
+ *
+ * @param crossedDateLine <code>true</true> for documents that cross the date line
+ * @param query the spatial query
+ * @return the query
+ */
+ public Query MakeXDL(bool crossedDateLine, Query query)
+ {
+ var bq = new BooleanQuery
+ {{this.MakeXDL(crossedDateLine), Occur.MUST}, {query, Occur.MUST}};
+ return bq;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c9f901b2/src/Lucene.Net.Spatial/BBox/DistanceSimilarity.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/BBox/DistanceSimilarity.cs b/src/Lucene.Net.Spatial/BBox/DistanceSimilarity.cs
new file mode 100644
index 0000000..9b7c88b
--- /dev/null
+++ b/src/Lucene.Net.Spatial/BBox/DistanceSimilarity.cs
@@ -0,0 +1,63 @@
+/*
+ * 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.Search;
+using Spatial4n.Core.Context;
+using Spatial4n.Core.Distance;
+using Spatial4n.Core.Shapes;
+
+namespace Lucene.Net.Spatial.BBox
+{
+ /// <summary>
+ /// Returns the distance between the center of the indexed rectangle and the
+ /// query shape.
+ /// </summary>
+ public class DistanceSimilarity : BBoxSimilarity
+ {
+ private readonly Point queryPoint;
+ private readonly DistanceCalculator distCalc;
+ private readonly double nullValue;
+
+ public DistanceSimilarity(SpatialContext ctx, Point queryPoint)
+ {
+ this.queryPoint = queryPoint;
+ this.distCalc = ctx.GetDistCalc();
+ this.nullValue = (ctx.IsGeo() ? 180 : double.MaxValue);
+ }
+
+ public double Score(Rectangle indexRect, Explanation exp)
+ {
+ double score;
+ if (indexRect == null)
+ {
+ score = nullValue;
+ }
+ else
+ {
+ score = distCalc.Distance(queryPoint, indexRect.GetCenter());
+ }
+ if (exp != null)
+ {
+ exp.Value = (float) score;
+ exp.Description = GetType().Name;
+ exp.AddDetail(new Explanation(-1f, "" + queryPoint));
+ exp.AddDetail(new Explanation(-1f, "" + indexRect));
+ }
+ return score;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c9f901b2/src/Lucene.Net.Spatial/Contrib.Spatial.NTS.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/Contrib.Spatial.NTS.csproj b/src/Lucene.Net.Spatial/Contrib.Spatial.NTS.csproj
new file mode 100644
index 0000000..fc4e1b3
--- /dev/null
+++ b/src/Lucene.Net.Spatial/Contrib.Spatial.NTS.csproj
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ 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.
+
+-->
+<Project ToolsVersion="4.0" 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>{02D030D0-C7B5-4561-8BDD-41408B2E2F41}</ProjectGuid>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Lucene.Net.Spatial</RootNamespace>
+ <AssemblyName>Lucene.Net.Contrib.Spatial.NTS</AssemblyName>
+ <FileAlignment>512</FileAlignment>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <Framework>$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", ""))</Framework>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\..\build\bin\contrib\Spatial.NTS\$(Configuration.Replace("35", ""))\$(Framework)\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;$(Framework)</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <DocumentationFile>
+ </DocumentationFile>
+ <NoWarn>618</NoWarn>
+ <OutputType>Library</OutputType>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug35|AnyCPU' ">
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <Framework>$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", ""))</Framework>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\..\build\bin\contrib\Spatial.NTS\$(Configuration.Replace("35", ""))\$(Framework)\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;$(Framework)</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <DocumentationFile>
+ </DocumentationFile>
+ <NoWarn>618</NoWarn>
+ <OutputType>Library</OutputType>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <Framework>$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", ""))</Framework>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\..\build\bin\contrib\Spatial.NTS\$(Configuration.Replace("35", ""))\$(Framework)\</OutputPath>
+ <DefineConstants>TRACE;$(Framework)</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <DocumentationFile>..\..\..\build\bin\contrib\Spatial.NTS\Release\NET40\Lucene.Net.Contrib.Spatial.NTS.xml</DocumentationFile>
+ <NoWarn>618</NoWarn>
+ <DebugSymbols>true</DebugSymbols>
+ <OutputType>Library</OutputType>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release35|AnyCPU' ">
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <Framework>$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", ""))</Framework>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\..\build\bin\contrib\Spatial.NTS\$(Configuration.Replace("35", ""))\$(Framework)\</OutputPath>
+ <DefineConstants>TRACE;$(Framework)</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <DocumentationFile>..\..\..\build\bin\contrib\Spatial.NTS\Release\NET35\Lucene.Net.Contrib.Spatial.NTS.xml</DocumentationFile>
+ <NoWarn>618</NoWarn>
+ <DebugSymbols>true</DebugSymbols>
+ <OutputType>Library</OutputType>
+ </PropertyGroup>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>Lucene.Net.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Spatial4n.Core.NTS">
+ <HintPath>..\..\..\lib\Spatial4n\$(Framework)\Spatial4n.Core.NTS.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Condition="'$(Framework)' == 'NET35'" Include="System.Core" />
+ <Reference Include="System.Data" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BBox\AreaSimilarity.cs" />
+ <Compile Include="BBox\BBoxSimilarity.cs" />
+ <Compile Include="BBox\BBoxSimilarityValueSource.cs" />
+ <Compile Include="BBox\BBoxStrategy.cs" />
+ <Compile Include="BBox\DistanceSimilarity.cs" />
+ <Compile Include="Prefix\PointPrefixTreeFieldCacheProvider.cs" />
+ <Compile Include="Prefix\PrefixTreeStrategy.cs" />
+ <Compile Include="Prefix\RecursivePrefixTreeFilter.cs" />
+ <Compile Include="Prefix\RecursivePrefixTreeStrategy.cs" />
+ <Compile Include="Prefix\TermQueryPrefixTreeStrategy.cs" />
+ <Compile Include="Prefix\Tree\GeohashPrefixTree.cs" />
+ <Compile Include="Prefix\Tree\Node.cs" />
+ <Compile Include="Prefix\Tree\QuadPrefixTree.cs" />
+ <Compile Include="Prefix\Tree\SpatialPrefixTree.cs" />
+ <Compile Include="Prefix\Tree\SpatialPrefixTreeFactory.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Queries\SpatialArgs.cs" />
+ <Compile Include="Queries\SpatialArgsParser.cs" />
+ <Compile Include="Queries\SpatialOperation.cs" />
+ <Compile Include="Queries\UnsupportedSpatialOperation.cs" />
+ <Compile Include="SpatialStrategy.cs" />
+ <Compile Include="Util\Bits.cs" />
+ <Compile Include="Util\ReciprocalFloatFunction.cs" />
+ <Compile Include="Util\ShapeFieldCacheDistanceValueSource.cs" />
+ <Compile Include="Util\CachingDoubleValueSource.cs" />
+ <Compile Include="Util\CompatibilityExtensions.cs" />
+ <Compile Include="Util\FixedBitSet.cs" />
+ <Compile Include="Util\FunctionQuery.cs" />
+ <Compile Include="Util\ShapeFieldCache.cs" />
+ <Compile Include="Util\ShapeFieldCacheProvider.cs" />
+ <Compile Include="Util\TermsEnumCompatibility.cs" />
+ <Compile Include="Util\TermsFilter.cs" />
+ <Compile Include="Util\ValueSourceFilter.cs" />
+ <Compile Include="Vector\DistanceValueSource.cs" />
+ <Compile Include="Vector\PointVectorStrategy.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\core\Lucene.Net.csproj">
+ <Project>{5D4AD9BE-1FFB-41AB-9943-25737971BF57}</Project>
+ <Name>Lucene.Net</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include=".NETFramework,Version=v4.0">
+ <Visible>False</Visible>
+ <ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Lucene.Net.snk" />
+ </ItemGroup>
+ <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
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c9f901b2/src/Lucene.Net.Spatial/Contrib.Spatial.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/Contrib.Spatial.csproj b/src/Lucene.Net.Spatial/Contrib.Spatial.csproj
new file mode 100644
index 0000000..ff13d0c
--- /dev/null
+++ b/src/Lucene.Net.Spatial/Contrib.Spatial.csproj
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ 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.
+
+-->
+<Project ToolsVersion="4.0" 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>{35C347F4-24B2-4BE5-8117-A0E3001551CE}</ProjectGuid>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Lucene.Net.Spatial</RootNamespace>
+ <AssemblyName>Lucene.Net.Contrib.Spatial</AssemblyName>
+ <FileAlignment>512</FileAlignment>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <Framework>$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", ""))</Framework>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\..\build\bin\contrib\Spatial\$(Configuration.Replace("35", ""))\$(Framework)\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;$(Framework)</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <DocumentationFile>
+ </DocumentationFile>
+ <NoWarn>618</NoWarn>
+ <OutputType>Library</OutputType>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug35|AnyCPU' ">
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <Framework>$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", ""))</Framework>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\..\build\bin\contrib\Spatial\$(Configuration.Replace("35", ""))\$(Framework)\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;$(Framework)</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <DocumentationFile>
+ </DocumentationFile>
+ <NoWarn>618</NoWarn>
+ <OutputType>Library</OutputType>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <Framework>$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", ""))</Framework>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\..\build\bin\contrib\Spatial\$(Configuration.Replace("35", ""))\$(Framework)\</OutputPath>
+ <DefineConstants>TRACE;$(Framework)</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <DocumentationFile>..\..\..\build\bin\contrib\Spatial\$(Configuration.Replace("35", ""))\$(Framework)\Lucene.Net.Contrib.Spatial.XML</DocumentationFile>
+ <NoWarn>618</NoWarn>
+ <DebugSymbols>true</DebugSymbols>
+ <OutputType>Library</OutputType>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release35|AnyCPU' ">
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <Framework>$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", ""))</Framework>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\..\build\bin\contrib\Spatial\$(Configuration.Replace("35", ""))\$(Framework)\</OutputPath>
+ <DefineConstants>TRACE;$(Framework)</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <DocumentationFile>..\..\..\build\bin\contrib\Spatial\$(Configuration.Replace("35", ""))\$(Framework)\Lucene.Net.Contrib.Spatial.XML</DocumentationFile>
+ <NoWarn>618</NoWarn>
+ <DebugSymbols>true</DebugSymbols>
+ <OutputType>Library</OutputType>
+ </PropertyGroup>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>Lucene.Net.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Spatial4n.Core">
+ <HintPath>..\..\..\lib\Spatial4n\$(Framework)\Spatial4n.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Condition="'$(Framework)' == 'NET35'" Include="System.Core" />
+ <Reference Include="System.Data" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BBox\AreaSimilarity.cs" />
+ <Compile Include="BBox\BBoxSimilarity.cs" />
+ <Compile Include="BBox\BBoxSimilarityValueSource.cs" />
+ <Compile Include="BBox\BBoxStrategy.cs" />
+ <Compile Include="BBox\DistanceSimilarity.cs" />
+ <Compile Include="Prefix\PointPrefixTreeFieldCacheProvider.cs" />
+ <Compile Include="Prefix\PrefixTreeStrategy.cs" />
+ <Compile Include="Prefix\RecursivePrefixTreeFilter.cs" />
+ <Compile Include="Prefix\RecursivePrefixTreeStrategy.cs" />
+ <Compile Include="Prefix\TermQueryPrefixTreeStrategy.cs" />
+ <Compile Include="Prefix\Tree\GeohashPrefixTree.cs" />
+ <Compile Include="Prefix\Tree\Node.cs" />
+ <Compile Include="Prefix\Tree\QuadPrefixTree.cs" />
+ <Compile Include="Prefix\Tree\SpatialPrefixTree.cs" />
+ <Compile Include="Prefix\Tree\SpatialPrefixTreeFactory.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Queries\SpatialArgs.cs" />
+ <Compile Include="Queries\SpatialArgsParser.cs" />
+ <Compile Include="Queries\SpatialOperation.cs" />
+ <Compile Include="Queries\UnsupportedSpatialOperation.cs" />
+ <Compile Include="SpatialStrategy.cs" />
+ <Compile Include="Util\Bits.cs" />
+ <Compile Include="Util\ReciprocalFloatFunction.cs" />
+ <Compile Include="Util\ShapeFieldCacheDistanceValueSource.cs" />
+ <Compile Include="Util\CachingDoubleValueSource.cs" />
+ <Compile Include="Util\CompatibilityExtensions.cs" />
+ <Compile Include="Util\FixedBitSet.cs" />
+ <Compile Include="Util\FunctionQuery.cs" />
+ <Compile Include="Util\ShapeFieldCache.cs" />
+ <Compile Include="Util\ShapeFieldCacheProvider.cs" />
+ <Compile Include="Util\TermsEnumCompatibility.cs" />
+ <Compile Include="Util\TermsFilter.cs" />
+ <Compile Include="Util\ValueSourceFilter.cs" />
+ <Compile Include="Vector\DistanceValueSource.cs" />
+ <Compile Include="Vector\PointVectorStrategy.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\core\Lucene.Net.csproj">
+ <Project>{5D4AD9BE-1FFB-41AB-9943-25737971BF57}</Project>
+ <Name>Lucene.Net</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include=".NETFramework,Version=v4.0">
+ <Visible>False</Visible>
+ <ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Lucene.Net.snk" />
+ </ItemGroup>
+ <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
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c9f901b2/src/Lucene.Net.Spatial/Overview.html
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/Overview.html b/src/Lucene.Net.Spatial/Overview.html
new file mode 100644
index 0000000..536c2f2
--- /dev/null
+++ b/src/Lucene.Net.Spatial/Overview.html
@@ -0,0 +1,41 @@
+<!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>
+ <head>
+ <title>Geographical filtering & sorting with Lucene</title>
+ </head>
+ <body>
+ <p>
+ This package makes it possible to filter and sort according to
+ geographical constraints. For example, filter to include only
+ restaurants within 2 miles of a specified latitude/longitude, sorting
+ by distance ascending.
+ </p>
+ <p>
+ See <a href="http://www.nsshutdown.com/projects/lucene/whitepaper/locallucene_v2.html">here</a>
+ for details on the technical approach.
+ </p>
+ <p>
+ Unfortunately, this package is still very new, and has little to no
+ documentation. It's best to look at the unit tests included in
+ the source distribution.
+ </p>
+ </body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c9f901b2/src/Lucene.Net.Spatial/Prefix/PointPrefixTreeFieldCacheProvider.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/Prefix/PointPrefixTreeFieldCacheProvider.cs b/src/Lucene.Net.Spatial/Prefix/PointPrefixTreeFieldCacheProvider.cs
new file mode 100644
index 0000000..5a7c554
--- /dev/null
+++ b/src/Lucene.Net.Spatial/Prefix/PointPrefixTreeFieldCacheProvider.cs
@@ -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 System;
+using Lucene.Net.Index;
+using Lucene.Net.Spatial.Prefix.Tree;
+using Lucene.Net.Spatial.Util;
+using Spatial4n.Core.Shapes;
+
+namespace Lucene.Net.Spatial.Prefix
+{
+ /// <summary>
+ /// Implementation of {@link ShapeFieldCacheProvider} designed for {@link PrefixTreeStrategy}s.
+ ///
+ /// Note, due to the fragmented representation of Shapes in these Strategies, this implementation
+ /// can only retrieve the central {@link Point} of the original Shapes.
+ /// </summary>
+ public class PointPrefixTreeFieldCacheProvider : ShapeFieldCacheProvider<Point>
+ {
+ readonly SpatialPrefixTree grid; //
+
+ public PointPrefixTreeFieldCacheProvider(SpatialPrefixTree grid, String shapeField, int defaultSize)
+ : base(shapeField, defaultSize)
+ {
+ this.grid = grid;
+ }
+
+ //A kluge that this is a field
+ private Node scanCell = null;
+
+ protected override Point ReadShape(Term term)
+ {
+ scanCell = grid.GetNode(term.Text, scanCell);
+ return scanCell.IsLeaf() ? scanCell.GetShape().GetCenter() : null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c9f901b2/src/Lucene.Net.Spatial/Prefix/PrefixTreeStrategy.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/Prefix/PrefixTreeStrategy.cs b/src/Lucene.Net.Spatial/Prefix/PrefixTreeStrategy.cs
new file mode 100644
index 0000000..e15f6cd
--- /dev/null
+++ b/src/Lucene.Net.Spatial/Prefix/PrefixTreeStrategy.cs
@@ -0,0 +1,176 @@
+/*
+ * 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;
+#if !NET35
+using System.Collections.Concurrent;
+#else
+using Lucene.Net.Support.Compatibility;
+#endif
+using System.Collections.Generic;
+using Lucene.Net.Analysis;
+using Lucene.Net.Analysis.Tokenattributes;
+using Lucene.Net.Documents;
+using Lucene.Net.Search.Function;
+using Lucene.Net.Spatial.Prefix.Tree;
+using Lucene.Net.Spatial.Queries;
+using Lucene.Net.Spatial.Util;
+using Spatial4n.Core.Shapes;
+
+namespace Lucene.Net.Spatial.Prefix
+{
+ /// <summary>
+ /// Abstract SpatialStrategy which provides common functionality for those
+ /// Strategys which use {@link SpatialPrefixTree}s
+ /// </summary>
+ public abstract class PrefixTreeStrategy : SpatialStrategy
+ {
+ protected readonly SpatialPrefixTree grid;
+
+ private readonly IDictionary<String, PointPrefixTreeFieldCacheProvider> provider =
+ new ConcurrentDictionary<string, PointPrefixTreeFieldCacheProvider>();
+
+ protected int defaultFieldValuesArrayLen = 2;
+ protected double distErrPct = SpatialArgs.DEFAULT_DISTERRPCT; // [ 0 TO 0.5 ]
+
+ protected PrefixTreeStrategy(SpatialPrefixTree grid, String fieldName)
+ : base(grid.GetSpatialContext(), fieldName)
+ {
+ this.grid = grid;
+ }
+
+ /* Used in the in-memory ValueSource as a default ArrayList length for this field's array of values, per doc. */
+
+ public void SetDefaultFieldValuesArrayLen(int defaultFieldValuesArrayLen)
+ {
+ this.defaultFieldValuesArrayLen = defaultFieldValuesArrayLen;
+ }
+
+ /// <summary>
+ /// The default measure of shape precision affecting indexed and query shapes.
+ /// Specific shapes at index and query time can use something different.
+ /// @see org.apache.lucene.spatial.query.SpatialArgs#getDistErrPct()
+ /// </summary>
+ public double DistErrPct { get; set; }
+
+ public override AbstractField[] CreateIndexableFields(Shape shape)
+ {
+ double distErr = SpatialArgs.CalcDistanceFromErrPct(shape, distErrPct, ctx);
+ return CreateIndexableFields(shape, distErr);
+ }
+
+ public AbstractField[] CreateIndexableFields(Shape shape, double distErr)
+ {
+ int detailLevel = grid.GetLevelForDistance(distErr);
+ var cells = grid.GetNodes(shape, detailLevel, true);//true=intermediates cells
+ //If shape isn't a point, add a full-resolution center-point so that
+ // PointPrefixTreeFieldCacheProvider has the center-points.
+ // TODO index each center of a multi-point? Yes/no?
+ if (!(shape is Point))
+ {
+ Point ctr = shape.GetCenter();
+ //TODO should be smarter; don't index 2 tokens for this in CellTokenStream. Harmless though.
+ cells.Add(grid.GetNodes(ctr, grid.GetMaxLevels(), false)[0]);
+ }
+
+ //TODO is CellTokenStream supposed to be re-used somehow? see Uwe's comments:
+ // http://code.google.com/p/lucene-spatial-playground/issues/detail?id=4
+
+ return new AbstractField[]
+ {
+ new Field(GetFieldName(), new CellTokenStream(cells.GetEnumerator()))
+ {OmitNorms = true, OmitTermFreqAndPositions = true}
+ };
+ }
+
+ /// <summary>
+ /// Outputs the tokenString of a cell, and if its a leaf, outputs it again with the leaf byte.
+ /// </summary>
+ protected class CellTokenStream : TokenStream
+ {
+ private ITermAttribute termAtt;
+ private readonly IEnumerator<Node> iter;
+
+ public CellTokenStream(IEnumerator<Node> tokens)
+ {
+ this.iter = tokens;
+ Init();
+ }
+
+ private void Init()
+ {
+ termAtt = AddAttribute<ITermAttribute>();
+ }
+
+ private string nextTokenStringNeedingLeaf;
+
+ public override bool IncrementToken()
+ {
+ ClearAttributes();
+ if (nextTokenStringNeedingLeaf != null)
+ {
+ termAtt.Append(nextTokenStringNeedingLeaf);
+ termAtt.Append((char)Node.LEAF_BYTE);
+ nextTokenStringNeedingLeaf = null;
+ return true;
+ }
+ if (iter.MoveNext())
+ {
+ Node cell = iter.Current;
+ var token = cell.GetTokenString();
+ termAtt.Append(token);
+ if (cell.IsLeaf())
+ nextTokenStringNeedingLeaf = token;
+ return true;
+ }
+ return false;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ }
+ }
+
+ public ShapeFieldCacheProvider<Point> GetCacheProvider()
+ {
+ PointPrefixTreeFieldCacheProvider p;
+ if (!provider.TryGetValue(GetFieldName(), out p) || p == null)
+ {
+ lock (this)
+ {//double checked locking idiom is okay since provider is threadsafe
+ if (!provider.ContainsKey(GetFieldName()))
+ {
+ p = new PointPrefixTreeFieldCacheProvider(grid, GetFieldName(), defaultFieldValuesArrayLen);
+ provider[GetFieldName()] = p;
+ }
+ }
+ }
+ return p;
+ }
+
+ public override ValueSource MakeDistanceValueSource(Point queryPoint)
+ {
+ var p = (PointPrefixTreeFieldCacheProvider)GetCacheProvider();
+ return new ShapeFieldCacheDistanceValueSource(ctx, p, queryPoint);
+ }
+
+ public SpatialPrefixTree GetGrid()
+ {
+ return grid;
+ }
+ }
+}