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;
27 namespace Lucene.Net.Spatial.Vector
41 public static String SUFFIX_X =
"__x";
42 public static String SUFFIX_Y =
"__y";
44 private readonly String fieldNameX;
45 private readonly String fieldNameY;
47 public int precisionStep = 8;
50 : base(ctx, fieldNamePrefix)
52 this.fieldNameX = fieldNamePrefix + SUFFIX_X;
53 this.fieldNameY = fieldNamePrefix + SUFFIX_Y;
56 public void SetPrecisionStep(
int p)
59 if (precisionStep <= 0 || precisionStep >= 64)
60 precisionStep =
int.MaxValue;
63 public string GetFieldNameX()
68 public string GetFieldNameY()
75 var point = shape as Point;
77 return CreateIndexableFields(point);
79 throw new InvalidOperationException(
"Can only index Point, not " + shape);
87 {OmitNorms =
true, OmitTermFreqAndPositions =
true};
92 {OmitNorms =
true, OmitTermFreqAndPositions =
true};
99 public override ValueSource MakeDistanceValueSource(Point queryPoint)
111 Shape shape = args.Shape;
112 var bbox = shape as Rectangle;
116 var circle = shape as Circle;
119 bbox = circle.GetBoundingBox();
122 MakeDistanceValueSource(circle.GetCenter()),
128 throw new InvalidOperationException(
"Only Rectangles and Circles are currently supported, " +
129 "found [" + shape.GetType().Name +
"]");
133 public Query MakeQueryDistanceScore(SpatialArgs args)
136 var shape = args.Shape;
137 if (!(shape is Rectangle || shape is Circle))
138 throw new InvalidOperationException(
"Only Rectangles and Circles are currently supported, found ["
139 + shape.GetType().Name +
"]");
141 Rectangle bbox = shape.GetBoundingBox();
142 if (bbox.GetCrossesDateLine())
144 throw new InvalidOperationException(
"Crossing dateline not yet supported");
149 Query spatial = null;
156 spatial = MakeWithin(bbox);
162 spatial = MakeWithin(bbox);
163 var circle = args.Shape as Circle;
167 valueSource = MakeDistanceValueSource(shape.GetCenter());
177 spatial = MakeDisjoint(bbox);
185 if (valueSource != null)
191 valueSource = MakeDistanceValueSource(shape.GetCenter());
195 bq.Add(spatial,
Occur.MUST);
196 bq.Add(spatialRankingQuery,
Occur.MUST);
201 public override Filter MakeFilter(SpatialArgs args)
216 private Query MakeWithin(Rectangle bbox)
220 if (bbox.GetCrossesDateLine())
223 bq.Add(RangeQuery(fieldNameX, null , bbox.GetMaxX()),
Occur.SHOULD);
224 bq.Add(RangeQuery(fieldNameX, bbox.GetMinX(), null ),
Occur.SHOULD);
225 bq.MinimumNumberShouldMatch = 1;
229 bq.Add(RangeQuery(fieldNameX, bbox.GetMinX(), bbox.GetMaxX()), MUST);
231 bq.Add(RangeQuery(fieldNameY, bbox.GetMinY(), bbox.GetMaxY()), MUST);
235 private NumericRangeQuery<Double> RangeQuery(String fieldName,
double? min,
double? max)
237 return NumericRangeQuery.NewDoubleRange(
250 private Query MakeDisjoint(Rectangle bbox)
252 if (bbox.GetCrossesDateLine())
253 throw new InvalidOperationException(
"MakeDisjoint doesn't handle dateline cross");
254 Query qX = RangeQuery(fieldNameX, bbox.GetMinX(), bbox.GetMaxX());
255 Query qY = RangeQuery(fieldNameY, bbox.GetMinY(), bbox.GetMaxY());