Lucene.Net  3.0.3
Lucene.Net is a port of the Lucene search engine library, written in C# and targeted at .NET runtime users.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
SpatialStrategy.cs
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 using System;
19 using Lucene.Net.Documents;
20 using Lucene.Net.Search;
21 using Lucene.Net.Search.Function;
22 using Lucene.Net.Spatial.Queries;
23 using Lucene.Net.Spatial.Util;
24 using Spatial4n.Core.Context;
25 using Spatial4n.Core.Shapes;
26 
27 namespace Lucene.Net.Spatial
28 {
29  /// <summary>
30  /// The SpatialStrategy encapsulates an approach to indexing and searching based on shapes.
31  /// <p/>
32  /// Note that a SpatialStrategy is not involved with the Lucene stored field values of shapes, which is
33  /// immaterial to indexing and search.
34  /// <p/>
35  /// Thread-safe.
36  /// </summary>
37  public abstract class SpatialStrategy
38  {
39  protected readonly SpatialContext ctx;
40  protected readonly string fieldName;
41 
42  /// <summary>
43  /// Constructs the spatial strategy with its mandatory arguments.
44  /// </summary>
45  /// <param name="ctx"></param>
46  /// <param name="fieldName"> </param>
47  protected SpatialStrategy(SpatialContext ctx, string fieldName)
48  {
49  if (ctx == null)
50  throw new ArgumentException("ctx is required", "ctx");
51  this.ctx = ctx;
52  if (string.IsNullOrEmpty(fieldName))
53  throw new ArgumentException("fieldName is required", "fieldName");
54  this.fieldName = fieldName;
55  }
56 
57  public SpatialContext GetSpatialContext()
58  {
59  return ctx;
60  }
61 
62  /// <summary>
63  /// The name of the field or the prefix of them if there are multiple
64  /// fields needed internally.
65  /// </summary>
66  /// <returns></returns>
67  public String GetFieldName()
68  {
69  return fieldName;
70  }
71 
72  /// <summary>
73  /// Returns the IndexableField(s) from the <c>shape</c> that are to be
74  /// added to the {@link org.apache.lucene.document.Document}. These fields
75  /// are expected to be marked as indexed and not stored.
76  /// <p/>
77  /// Note: If you want to <i>store</i> the shape as a string for retrieval in search
78  /// results, you could add it like this:
79  /// <pre>document.add(new StoredField(fieldName,ctx.toString(shape)));</pre>
80  /// The particular string representation used doesn't matter to the Strategy since it
81  /// doesn't use it.
82  /// </summary>
83  /// <param name="shape"></param>
84  /// <returns>Not null nor will it have null elements.</returns>
85  public abstract AbstractField[] CreateIndexableFields(Shape shape);
86 
87  public AbstractField CreateStoredField(Shape shape)
88  {
89  return new Field(GetFieldName(), ctx.ToString(shape), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO);
90  }
91 
92  /// <summary>
93  /// Make a ValueSource returning the distance between the center of the
94  /// indexed shape and {@code queryPoint}. If there are multiple indexed shapes
95  /// then the closest one is chosen.
96  /// </summary>
97  public abstract ValueSource MakeDistanceValueSource(Point queryPoint);
98 
99  /// <summary>
100  /// Make a (ConstantScore) Query based principally on {@link org.apache.lucene.spatial.query.SpatialOperation}
101  /// and {@link Shape} from the supplied {@code args}.
102  /// The default implementation is
103  /// <pre>return new ConstantScoreQuery(makeFilter(args));</pre>
104  /// </summary>
105  /// <param name="args"></param>
106  /// <returns></returns>
107  public virtual ConstantScoreQuery MakeQuery(SpatialArgs args)
108  {
109  return new ConstantScoreQuery(MakeFilter(args));
110  }
111 
112  /// <summary>
113  /// Make a Filter based principally on {@link org.apache.lucene.spatial.query.SpatialOperation}
114  /// and {@link Shape} from the supplied {@code args}.
115  /// <p />
116  /// If a subclasses implements
117  /// {@link #makeQuery(org.apache.lucene.spatial.query.SpatialArgs)}
118  /// then this method could be simply:
119  /// <pre>return new QueryWrapperFilter(makeQuery(args).getQuery());</pre>
120  /// </summary>
121  /// <param name="args"></param>
122  /// <returns></returns>
123  public abstract Filter MakeFilter(SpatialArgs args);
124 
125  /// <summary>
126  /// Returns a ValueSource with values ranging from 1 to 0, depending inversely
127  /// on the distance from {@link #makeDistanceValueSource(com.spatial4j.core.shape.Point)}.
128  /// The formula is <c>c/(d + c)</c> where 'd' is the distance and 'c' is
129  /// one tenth the distance to the farthest edge from the center. Thus the
130  /// scores will be 1 for indexed points at the center of the query shape and as
131  /// low as ~0.1 at its furthest edges.
132  /// </summary>
133  /// <param name="queryShape"></param>
134  /// <returns></returns>
135  public ValueSource MakeRecipDistanceValueSource(Shape queryShape)
136  {
137  Rectangle bbox = queryShape.GetBoundingBox();
138  double diagonalDist = ctx.GetDistCalc().Distance(
139  ctx.MakePoint(bbox.GetMinX(), bbox.GetMinY()), bbox.GetMaxX(), bbox.GetMaxY());
140  double distToEdge = diagonalDist*0.5;
141  float c = (float) distToEdge*0.1f; //one tenth
142  return new ReciprocalFloatFunction(MakeDistanceValueSource(queryShape.GetCenter()), 1f, c, c);
143  }
144 
145  public override string ToString()
146  {
147  return GetType().Name + " field:" + fieldName + " ctx=" + ctx;
148  }
149  }
150 }