19 using Lucene.Net.Documents;
20 using Lucene.Net.Index;
21 using Lucene.Net.Search;
22 using Lucene.Net.Search.Function;
23 using Lucene.Net.Spatial.Queries;
24 using Lucene.Net.Spatial.Util;
25 using Spatial4n.Core.Context;
26 using Spatial4n.Core.Shapes;
28 namespace Lucene.Net.Spatial.BBox
32 public static String SUFFIX_MINX =
"__minX";
33 public static String SUFFIX_MAXX =
"__maxX";
34 public static String SUFFIX_MINY =
"__minY";
35 public static String SUFFIX_MAXY =
"__maxY";
36 public static String SUFFIX_XDL =
"__xdl";
49 public readonly
double queryPower = 1.0;
50 public readonly
double targetPower = 1.0f;
51 public int precisionStep = 8;
54 : base(ctx, fieldNamePrefix)
56 field_bbox = fieldNamePrefix;
57 field_minX = fieldNamePrefix + SUFFIX_MINX;
58 field_maxX = fieldNamePrefix + SUFFIX_MAXX;
59 field_minY = fieldNamePrefix + SUFFIX_MINY;
60 field_maxY = fieldNamePrefix + SUFFIX_MAXY;
61 field_xdl = fieldNamePrefix + SUFFIX_XDL;
64 public void SetPrecisionStep(
int p)
67 if (precisionStep <= 0 || precisionStep >= 64)
68 precisionStep =
int.MaxValue;
77 var rect = shape as Rectangle;
79 return CreateIndexableFields(rect);
80 throw new InvalidOperationException(
"Can only index Rectangle, not " + shape);
86 fields[0] = DoubleField(field_minX, bbox.GetMinX());
87 fields[1] = DoubleField(field_maxX, bbox.GetMaxX());
88 fields[2] = DoubleField(field_minY, bbox.GetMinY());
89 fields[3] = DoubleField(field_maxY, bbox.GetMaxY());
90 fields[4] =
new Field(field_xdl, bbox.GetCrossesDateLine() ?
"T" :
"F",
Field.
Store.NO,
91 Field.
Index.NOT_ANALYZED_NO_NORMS) {OmitNorms =
true, OmitTermFreqAndPositions =
true};
98 {OmitNorms =
true, OmitTermFreqAndPositions =
true};
103 public override ValueSource MakeDistanceValueSource(Point queryPoint)
108 public ValueSource MakeBBoxAreaSimilarityValueSource(Rectangle queryBox)
123 var spatial = MakeFilter(args);
128 bq.Add(spatialRankingQuery,
Occur.MUST);
132 public override Filter MakeFilter(SpatialArgs args)
137 private Query MakeSpatialQuery(SpatialArgs args)
139 var bbox = args.Shape as Rectangle;
141 throw new InvalidOperationException(
"Can only query by Rectangle, not " + args.Shape);
143 Query spatial = null;
172 protected Query MakeContains(Rectangle bbox)
180 Query qMinY = NumericRangeQuery.NewDoubleRange(field_minY, precisionStep, null, bbox.GetMinY(),
false,
true);
181 Query qMaxY = NumericRangeQuery.NewDoubleRange(field_maxY, precisionStep, bbox.GetMaxY(), null,
true,
false);
182 Query yConditions = this.MakeQuery(
new Query[] { qMinY, qMaxY },
Occur.MUST);
185 Query xConditions = null;
188 if (!bbox.GetCrossesDateLine())
194 Query qMinX = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, null, bbox.GetMinX(),
false,
true);
195 Query qMaxX = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, bbox.GetMaxX(), null,
true,
false);
196 Query qMinMax = this.MakeQuery(
new Query[] { qMinX, qMaxX },
Occur.MUST);
197 Query qNonXDL = this.MakeXDL(
false, qMinMax);
203 Query qXDLLeft = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, null, bbox.GetMinX(),
false,
true);
204 Query qXDLRight = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, bbox.GetMaxX(), null,
true,
false);
205 Query qXDLLeftRight = this.MakeQuery(
new Query[] { qXDLLeft, qXDLRight },
Occur.SHOULD);
206 Query qXDL = this.MakeXDL(
true, qXDLLeftRight);
209 xConditions = this.MakeQuery(
new Query[] { qNonXDL, qXDL },
Occur.SHOULD);
222 Query qXDLLeft = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, null, bbox.GetMinX(),
false,
true);
223 Query qXDLRight = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, bbox.GetMaxX(), null,
true,
false);
224 Query qXDLLeftRight = this.MakeQuery(
new Query[] { qXDLLeft, qXDLRight },
Occur.MUST);
226 xConditions = this.MakeXDL(
true, qXDLLeftRight);
230 return this.MakeQuery(
new Query[] { xConditions, yConditions },
Occur.MUST);
238 Query MakeDisjoint(Rectangle bbox)
246 Query qMinY = NumericRangeQuery.NewDoubleRange(field_minY, precisionStep, bbox.GetMaxY(), null,
false,
false);
247 Query qMaxY = NumericRangeQuery.NewDoubleRange(field_maxY, precisionStep, null, bbox.GetMinY(),
false,
false);
248 Query yConditions = this.MakeQuery(
new Query[] { qMinY, qMaxY },
Occur.SHOULD);
251 Query xConditions = null;
254 if (!bbox.GetCrossesDateLine())
259 Query qMinX = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, bbox.GetMaxX(), null,
false,
false);
260 Query qMaxX = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, null, bbox.GetMinX(),
false,
false);
261 Query qMinMax = this.MakeQuery(
new Query[] { qMinX, qMaxX },
Occur.SHOULD);
262 Query qNonXDL = this.MakeXDL(
false, qMinMax);
271 Query qMinXLeft = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, bbox.GetMaxX(), null,
false,
false);
272 Query qMaxXRight = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, null, bbox.GetMinX(),
false,
false);
273 Query qLeftRight = this.MakeQuery(
new Query[] { qMinXLeft, qMaxXRight },
Occur.MUST);
274 Query qXDL = this.MakeXDL(
true, qLeftRight);
277 xConditions = this.MakeQuery(
new Query[] { qNonXDL, qXDL },
Occur.SHOULD);
288 Query qMinXLeft = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, 180.0, null,
false,
false);
289 Query qMaxXLeft = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, null, bbox.GetMinX(),
false,
false);
290 Query qMinXRight = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, bbox.GetMaxX(), null,
false,
false);
291 Query qMaxXRight = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, null, -180.0,
false,
false);
292 Query qLeft = this.MakeQuery(
new Query[] { qMinXLeft, qMaxXLeft },
Occur.SHOULD);
293 Query qRight = this.MakeQuery(
new Query[] { qMinXRight, qMaxXRight },
Occur.SHOULD);
294 Query qLeftRight = this.MakeQuery(
new Query[] { qLeft, qRight },
Occur.MUST);
298 xConditions = this.MakeXDL(
false, qLeftRight);
302 return this.MakeQuery(
new Query[] { xConditions, yConditions },
Occur.SHOULD);
310 public Query MakeEquals(Rectangle bbox)
314 Query qMinX = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, bbox.GetMinX(), bbox.GetMinX(),
true,
true);
315 Query qMinY = NumericRangeQuery.NewDoubleRange(field_minY, precisionStep, bbox.GetMinY(), bbox.GetMinY(),
true,
true);
316 Query qMaxX = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, bbox.GetMaxX(), bbox.GetMaxX(),
true,
true);
317 Query qMaxY = NumericRangeQuery.NewDoubleRange(field_maxY, precisionStep, bbox.GetMaxY(), bbox.GetMaxY(),
true,
true);
334 Query MakeIntersects(Rectangle bbox)
344 Query qDisjoint = MakeDisjoint(bbox);
345 Query qIsNonXDL = this.MakeXDL(
false);
346 Query qIsXDL = this.MakeXDL(
true);
347 Query qHasEnv = this.MakeQuery(
new Query[] { qIsNonXDL, qIsXDL },
Occur.SHOULD);
367 foreach (
Query query
in queries)
369 bq.Add(query, occur);
379 Query MakeWithin(Rectangle bbox)
387 Query qMinY = NumericRangeQuery.NewDoubleRange(field_minY, precisionStep, bbox.GetMinY(), null,
true,
false);
388 Query qMaxY = NumericRangeQuery.NewDoubleRange(field_maxY, precisionStep, null, bbox.GetMaxY(),
false,
true);
389 Query yConditions = this.MakeQuery(
new Query[] { qMinY, qMaxY },
Occur.MUST);
392 Query xConditions = null;
399 Query qXDLLeft = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, bbox.GetMinX(), null,
true,
false);
400 Query qXDLRight = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, null, bbox.GetMaxX(),
false,
true);
401 Query qXDLLeftRight = this.MakeQuery(
new Query[] { qXDLLeft, qXDLRight },
Occur.MUST);
402 Query qXDL = this.MakeXDL(
true, qXDLLeftRight);
405 if (!bbox.GetCrossesDateLine())
410 Query qMinX = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, bbox.GetMinX(), null,
true,
false);
411 Query qMaxX = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, null, bbox.GetMaxX(),
false,
true);
412 Query qMinMax = this.MakeQuery(
new Query[] { qMinX, qMaxX },
Occur.MUST);
413 Query qNonXDL = this.MakeXDL(
false, qMinMax);
416 if ((bbox.GetMinX() <= -180.0) && bbox.GetMaxX() >= 180.0)
418 xConditions = this.MakeQuery(
new Query[] { qNonXDL, qXDL },
Occur.SHOULD);
422 xConditions = qNonXDL;
434 Query qMinXLeft = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, bbox.GetMinX(), null,
true,
false);
435 Query qMaxXLeft = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, null, 180.0,
false,
true);
436 Query qLeft = this.MakeQuery(
new Query[] { qMinXLeft, qMaxXLeft },
Occur.MUST);
440 Query qMinXRight = NumericRangeQuery.NewDoubleRange(field_minX, precisionStep, -180.0, null,
true,
false);
441 Query qMaxXRight = NumericRangeQuery.NewDoubleRange(field_maxX, precisionStep, null, bbox.GetMaxX(),
false,
true);
442 Query qRight = this.MakeQuery(
new Query[] { qMinXRight, qMaxXRight },
Occur.MUST);
446 Query qLeftRight = this.MakeQuery(
new Query[] { qLeft, qRight },
Occur.SHOULD);
447 Query qNonXDL = this.MakeXDL(
false, qLeftRight);
450 xConditions = this.MakeQuery(
new Query[] { qNonXDL, qXDL },
Occur.SHOULD);
454 return this.MakeQuery(
new Query[] { xConditions, yConditions },
Occur.MUST);
464 public Query MakeXDL(
bool crossedDateLine)
467 return new TermQuery(
new Term(field_xdl, crossedDateLine ?
"T" :
"F"));
481 {{this.MakeXDL(crossedDateLine),
Occur.MUST}, {query,
Occur.MUST}};