You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by cc...@apache.org on 2013/04/03 19:40:16 UTC
[33/51] [partial] Mass convert mixed tabs to spaces
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/62f018ab/src/contrib/Spatial/BBox/BBoxStrategy.cs
----------------------------------------------------------------------
diff --git a/src/contrib/Spatial/BBox/BBoxStrategy.cs b/src/contrib/Spatial/BBox/BBoxStrategy.cs
index b97bb17..f14af08 100644
--- a/src/contrib/Spatial/BBox/BBoxStrategy.cs
+++ b/src/contrib/Spatial/BBox/BBoxStrategy.cs
@@ -1,4 +1,4 @@
-/*
+/*
* 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.
@@ -36,9 +36,9 @@ namespace Lucene.Net.Spatial.BBox
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).
- */
+ * 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;
@@ -130,356 +130,356 @@ namespace Lucene.Net.Spatial.BBox
}
public override Filter MakeFilter(SpatialArgs args)
- {
+ {
return new QueryWrapperFilter(MakeSpatialQuery(args));
- }
+ }
- private Query MakeSpatialQuery(SpatialArgs 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;
- }
- }
+ 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/62f018ab/src/contrib/Spatial/BBox/DistanceSimilarity.cs
----------------------------------------------------------------------
diff --git a/src/contrib/Spatial/BBox/DistanceSimilarity.cs b/src/contrib/Spatial/BBox/DistanceSimilarity.cs
index 98273f4..9b7c88b 100644
--- a/src/contrib/Spatial/BBox/DistanceSimilarity.cs
+++ b/src/contrib/Spatial/BBox/DistanceSimilarity.cs
@@ -1,4 +1,4 @@
-/*
+/*
* 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.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/62f018ab/src/contrib/Spatial/Prefix/PointPrefixTreeFieldCacheProvider.cs
----------------------------------------------------------------------
diff --git a/src/contrib/Spatial/Prefix/PointPrefixTreeFieldCacheProvider.cs b/src/contrib/Spatial/Prefix/PointPrefixTreeFieldCacheProvider.cs
index 614226c..5a7c554 100644
--- a/src/contrib/Spatial/Prefix/PointPrefixTreeFieldCacheProvider.cs
+++ b/src/contrib/Spatial/Prefix/PointPrefixTreeFieldCacheProvider.cs
@@ -1,4 +1,4 @@
-/*
+/*
* 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.
@@ -29,23 +29,23 @@ namespace Lucene.Net.Spatial.Prefix
/// 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 class PointPrefixTreeFieldCacheProvider : ShapeFieldCacheProvider<Point>
+ {
+ readonly SpatialPrefixTree grid; //
- public PointPrefixTreeFieldCacheProvider(SpatialPrefixTree grid, String shapeField, int defaultSize)
- : base(shapeField, defaultSize)
- {
- this.grid = 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;
+ //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;
- }
- }
+ 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/62f018ab/src/contrib/Spatial/Prefix/PrefixTreeStrategy.cs
----------------------------------------------------------------------
diff --git a/src/contrib/Spatial/Prefix/PrefixTreeStrategy.cs b/src/contrib/Spatial/Prefix/PrefixTreeStrategy.cs
index e300b4d..e15f6cd 100644
--- a/src/contrib/Spatial/Prefix/PrefixTreeStrategy.cs
+++ b/src/contrib/Spatial/Prefix/PrefixTreeStrategy.cs
@@ -1,4 +1,4 @@
-/*
+/*
* 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.
@@ -67,110 +67,110 @@ namespace Lucene.Net.Spatial.Prefix
/// </summary>
public double DistErrPct { get; set; }
- public override AbstractField[] CreateIndexableFields(Shape shape)
- {
- double distErr = SpatialArgs.CalcDistanceFromErrPct(shape, distErrPct, ctx);
- return CreateIndexableFields(shape, distErr);
- }
+ 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
+ //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 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;
- }
+ 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();
+ {
+ var p = (PointPrefixTreeFieldCacheProvider)GetCacheProvider();
return new ShapeFieldCacheDistanceValueSource(ctx, p, queryPoint);
- }
+ }
- public SpatialPrefixTree GetGrid()
- {
- return grid;
- }
- }
+ public SpatialPrefixTree GetGrid()
+ {
+ return grid;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/62f018ab/src/contrib/Spatial/Prefix/RecursivePrefixTreeFilter.cs
----------------------------------------------------------------------
diff --git a/src/contrib/Spatial/Prefix/RecursivePrefixTreeFilter.cs b/src/contrib/Spatial/Prefix/RecursivePrefixTreeFilter.cs
index bb12704..ce0d0d9 100644
--- a/src/contrib/Spatial/Prefix/RecursivePrefixTreeFilter.cs
+++ b/src/contrib/Spatial/Prefix/RecursivePrefixTreeFilter.cs
@@ -1,4 +1,4 @@
-/*
+/*
* 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.
@@ -26,16 +26,16 @@ using Spatial4n.Core.Shapes;
namespace Lucene.Net.Spatial.Prefix
{
- /// <summary>
- /// Performs a spatial intersection filter against a field indexed with {@link SpatialPrefixTree}, a Trie.
- /// SPT yields terms (grids) at length 1 and at greater lengths corresponding to greater precisions.
- /// This filter recursively traverses each grid length and uses methods on {@link Shape} to efficiently know
- /// that all points at a prefix fit in the shape or not to either short-circuit unnecessary traversals or to efficiently
- /// load all enclosed points.
- /// </summary>
- public class RecursivePrefixTreeFilter : Filter
- {
- /* TODOs for future:
+ /// <summary>
+ /// Performs a spatial intersection filter against a field indexed with {@link SpatialPrefixTree}, a Trie.
+ /// SPT yields terms (grids) at length 1 and at greater lengths corresponding to greater precisions.
+ /// This filter recursively traverses each grid length and uses methods on {@link Shape} to efficiently know
+ /// that all points at a prefix fit in the shape or not to either short-circuit unnecessary traversals or to efficiently
+ /// load all enclosed points.
+ /// </summary>
+ public class RecursivePrefixTreeFilter : Filter
+ {
+ /* TODOs for future:
Can a polygon query shape be optimized / made-simpler at recursive depths (e.g. intersection of shape + cell box)
@@ -48,142 +48,142 @@ if (!scan) {
long termsThreshold = (long) estimateNumberIndexedTerms(cell.length(),queryShape.getDocFreqExpenseThreshold(cell));
long thisOrd = termsEnum.ord();
scan = (termsEnum.seek(thisOrd+termsThreshold+1) == TermsEnum.SeekStatus.END
- || !cell.contains(termsEnum.term()));
+ || !cell.contains(termsEnum.term()));
termsEnum.seek(thisOrd);//return to last position
}
*/
- private readonly String fieldName;
- private readonly SpatialPrefixTree grid;
- private readonly Shape queryShape;
- private readonly int prefixGridScanLevel;//at least one less than grid.getMaxLevels()
- private readonly int detailLevel;
-
- public RecursivePrefixTreeFilter(String fieldName, SpatialPrefixTree grid, Shape queryShape, int prefixGridScanLevel,
- int detailLevel)
- {
- this.fieldName = fieldName;
- this.grid = grid;
- this.queryShape = queryShape;
- this.prefixGridScanLevel = Math.Max(1, Math.Min(prefixGridScanLevel, grid.GetMaxLevels() - 1));
- this.detailLevel = detailLevel;
- Debug.Assert(detailLevel <= grid.GetMaxLevels());
- }
-
- public override DocIdSet GetDocIdSet(Index.IndexReader reader /*, Bits acceptDocs*/)
- {
- var bits = new OpenBitSet(reader.MaxDoc);
- var terms = new TermsEnumCompatibility(reader, fieldName);
- var term = terms.Next();
- if (term == null)
- return null;
- Node scanCell = null;
-
- //cells is treated like a stack. LinkedList conveniently has bulk add to beginning. It's in sorted order so that we
- // always advance forward through the termsEnum index.
- var cells = new LinkedList<Node>(
- grid.GetWorldNode().GetSubCells(queryShape));
-
- //This is a recursive algorithm that starts with one or more "big" cells, and then recursively dives down into the
- // first such cell that intersects with the query shape. It's a depth first traversal because we don't move onto
- // the next big cell (breadth) until we're completely done considering all smaller cells beneath it. For a given
- // cell, if it's *within* the query shape then we can conveniently short-circuit the depth traversal and
- // grab all documents assigned to this cell/term. For an intersection of the cell and query shape, we either
- // recursively step down another grid level or we decide heuristically (via prefixGridScanLevel) that there aren't
- // that many points, and so we scan through all terms within this cell (i.e. the term starts with the cell's term),
- // seeing which ones are within the query shape.
- while (cells.Count > 0)
- {
- Node cell = cells.First.Value; cells.RemoveFirst();
- var cellTerm = cell.GetTokenString();
- var seekStat = terms.Seek(cellTerm);
- if (seekStat == TermsEnumCompatibility.SeekStatus.END)
- break;
- if (seekStat == TermsEnumCompatibility.SeekStatus.NOT_FOUND)
- continue;
- if (cell.GetLevel() == detailLevel || cell.IsLeaf())
- {
- terms.Docs(bits);
- }
- else
- {//any other intersection
- //If the next indexed term is the leaf marker, then add all of them
- var nextCellTerm = terms.Next();
- Debug.Assert(nextCellTerm.Text.StartsWith(cellTerm));
- scanCell = grid.GetNode(nextCellTerm.Text, scanCell);
- if (scanCell.IsLeaf())
- {
- terms.Docs(bits);
- term = terms.Next();//move pointer to avoid potential redundant addDocs() below
- }
-
- //Decide whether to continue to divide & conquer, or whether it's time to scan through terms beneath this cell.
- // Scanning is a performance optimization trade-off.
- bool scan = cell.GetLevel() >= prefixGridScanLevel;//simple heuristic
-
- if (!scan)
- {
- //Divide & conquer
- var lst = cell.GetSubCells(queryShape);
- for (var i = lst.Count - 1; i >= 0; i--) //add to beginning
- {
- cells.AddFirst(lst[i]);
- }
- }
- else
- {
- //Scan through all terms within this cell to see if they are within the queryShape. No seek()s.
- for (var t = terms.Term(); t != null && t.Text.StartsWith(cellTerm); t = terms.Next())
- {
- scanCell = grid.GetNode(t.Text, scanCell);
- int termLevel = scanCell.GetLevel();
- if (termLevel > detailLevel)
- continue;
- if (termLevel == detailLevel || scanCell.IsLeaf())
- {
- //TODO should put more thought into implications of box vs point
- Shape cShape = termLevel == grid.GetMaxLevels() ? scanCell.GetCenter() : scanCell.GetShape();
+ private readonly String fieldName;
+ private readonly SpatialPrefixTree grid;
+ private readonly Shape queryShape;
+ private readonly int prefixGridScanLevel;//at least one less than grid.getMaxLevels()
+ private readonly int detailLevel;
+
+ public RecursivePrefixTreeFilter(String fieldName, SpatialPrefixTree grid, Shape queryShape, int prefixGridScanLevel,
+ int detailLevel)
+ {
+ this.fieldName = fieldName;
+ this.grid = grid;
+ this.queryShape = queryShape;
+ this.prefixGridScanLevel = Math.Max(1, Math.Min(prefixGridScanLevel, grid.GetMaxLevels() - 1));
+ this.detailLevel = detailLevel;
+ Debug.Assert(detailLevel <= grid.GetMaxLevels());
+ }
+
+ public override DocIdSet GetDocIdSet(Index.IndexReader reader /*, Bits acceptDocs*/)
+ {
+ var bits = new OpenBitSet(reader.MaxDoc);
+ var terms = new TermsEnumCompatibility(reader, fieldName);
+ var term = terms.Next();
+ if (term == null)
+ return null;
+ Node scanCell = null;
+
+ //cells is treated like a stack. LinkedList conveniently has bulk add to beginning. It's in sorted order so that we
+ // always advance forward through the termsEnum index.
+ var cells = new LinkedList<Node>(
+ grid.GetWorldNode().GetSubCells(queryShape));
+
+ //This is a recursive algorithm that starts with one or more "big" cells, and then recursively dives down into the
+ // first such cell that intersects with the query shape. It's a depth first traversal because we don't move onto
+ // the next big cell (breadth) until we're completely done considering all smaller cells beneath it. For a given
+ // cell, if it's *within* the query shape then we can conveniently short-circuit the depth traversal and
+ // grab all documents assigned to this cell/term. For an intersection of the cell and query shape, we either
+ // recursively step down another grid level or we decide heuristically (via prefixGridScanLevel) that there aren't
+ // that many points, and so we scan through all terms within this cell (i.e. the term starts with the cell's term),
+ // seeing which ones are within the query shape.
+ while (cells.Count > 0)
+ {
+ Node cell = cells.First.Value; cells.RemoveFirst();
+ var cellTerm = cell.GetTokenString();
+ var seekStat = terms.Seek(cellTerm);
+ if (seekStat == TermsEnumCompatibility.SeekStatus.END)
+ break;
+ if (seekStat == TermsEnumCompatibility.SeekStatus.NOT_FOUND)
+ continue;
+ if (cell.GetLevel() == detailLevel || cell.IsLeaf())
+ {
+ terms.Docs(bits);
+ }
+ else
+ {//any other intersection
+ //If the next indexed term is the leaf marker, then add all of them
+ var nextCellTerm = terms.Next();
+ Debug.Assert(nextCellTerm.Text.StartsWith(cellTerm));
+ scanCell = grid.GetNode(nextCellTerm.Text, scanCell);
+ if (scanCell.IsLeaf())
+ {
+ terms.Docs(bits);
+ term = terms.Next();//move pointer to avoid potential redundant addDocs() below
+ }
+
+ //Decide whether to continue to divide & conquer, or whether it's time to scan through terms beneath this cell.
+ // Scanning is a performance optimization trade-off.
+ bool scan = cell.GetLevel() >= prefixGridScanLevel;//simple heuristic
+
+ if (!scan)
+ {
+ //Divide & conquer
+ var lst = cell.GetSubCells(queryShape);
+ for (var i = lst.Count - 1; i >= 0; i--) //add to beginning
+ {
+ cells.AddFirst(lst[i]);
+ }
+ }
+ else
+ {
+ //Scan through all terms within this cell to see if they are within the queryShape. No seek()s.
+ for (var t = terms.Term(); t != null && t.Text.StartsWith(cellTerm); t = terms.Next())
+ {
+ scanCell = grid.GetNode(t.Text, scanCell);
+ int termLevel = scanCell.GetLevel();
+ if (termLevel > detailLevel)
+ continue;
+ if (termLevel == detailLevel || scanCell.IsLeaf())
+ {
+ //TODO should put more thought into implications of box vs point
+ Shape cShape = termLevel == grid.GetMaxLevels() ? scanCell.GetCenter() : scanCell.GetShape();
if (queryShape.Relate(cShape) == SpatialRelation.DISJOINT)
- continue;
-
- terms.Docs(bits);
- }
- }//term loop
- }
- }
- }//cell loop
-
- return bits;
- }
-
- public override string ToString()
- {
- return "GeoFilter{fieldName='" + fieldName + '\'' + ", shape=" + queryShape + '}';
- }
-
- public override bool Equals(object o)
- {
- if (this == o) return true;
- var that = o as RecursivePrefixTreeFilter;
-
- if (that == null) return false;
-
- if (!fieldName.Equals(that.fieldName)) return false;
- //note that we don't need to look at grid since for the same field it should be the same
- if (prefixGridScanLevel != that.prefixGridScanLevel) return false;
- if (detailLevel != that.detailLevel) return false;
- if (!queryShape.Equals(that.queryShape)) return false;
-
- return true;
- }
-
- public override int GetHashCode()
- {
- int result = fieldName.GetHashCode();
- result = 31 * result + queryShape.GetHashCode();
- result = 31 * result + detailLevel;
- return result;
- }
- }
+ continue;
+
+ terms.Docs(bits);
+ }
+ }//term loop
+ }
+ }
+ }//cell loop
+
+ return bits;
+ }
+
+ public override string ToString()
+ {
+ return "GeoFilter{fieldName='" + fieldName + '\'' + ", shape=" + queryShape + '}';
+ }
+
+ public override bool Equals(object o)
+ {
+ if (this == o) return true;
+ var that = o as RecursivePrefixTreeFilter;
+
+ if (that == null) return false;
+
+ if (!fieldName.Equals(that.fieldName)) return false;
+ //note that we don't need to look at grid since for the same field it should be the same
+ if (prefixGridScanLevel != that.prefixGridScanLevel) return false;
+ if (detailLevel != that.detailLevel) return false;
+ if (!queryShape.Equals(that.queryShape)) return false;
+
+ return true;
+ }
+
+ public override int GetHashCode()
+ {
+ int result = fieldName.GetHashCode();
+ result = 31 * result + queryShape.GetHashCode();
+ result = 31 * result + detailLevel;
+ return result;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/62f018ab/src/contrib/Spatial/Prefix/RecursivePrefixTreeStrategy.cs
----------------------------------------------------------------------
diff --git a/src/contrib/Spatial/Prefix/RecursivePrefixTreeStrategy.cs b/src/contrib/Spatial/Prefix/RecursivePrefixTreeStrategy.cs
index e1f5718..d6fa681 100644
--- a/src/contrib/Spatial/Prefix/RecursivePrefixTreeStrategy.cs
+++ b/src/contrib/Spatial/Prefix/RecursivePrefixTreeStrategy.cs
@@ -1,4 +1,4 @@
-/*
+/*
* 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.
@@ -22,41 +22,41 @@ using Spatial4n.Core.Shapes;
namespace Lucene.Net.Spatial.Prefix
{
- /// <summary>
- /// Based on {@link RecursivePrefixTreeFilter}.
- /// </summary>
- public class RecursivePrefixTreeStrategy : PrefixTreeStrategy
- {
- private int prefixGridScanLevel;
-
- public RecursivePrefixTreeStrategy(SpatialPrefixTree grid, string fieldName)
- : base(grid, fieldName)
- {
- prefixGridScanLevel = grid.GetMaxLevels() - 4;//TODO this default constant is dependent on the prefix grid size
- }
-
- public void SetPrefixGridScanLevel(int prefixGridScanLevel)
- {
- //TODO if negative then subtract from maxlevels
- this.prefixGridScanLevel = prefixGridScanLevel;
- }
-
- public override Filter MakeFilter(SpatialArgs args)
- {
- var op = args.Operation;
+ /// <summary>
+ /// Based on {@link RecursivePrefixTreeFilter}.
+ /// </summary>
+ public class RecursivePrefixTreeStrategy : PrefixTreeStrategy
+ {
+ private int prefixGridScanLevel;
+
+ public RecursivePrefixTreeStrategy(SpatialPrefixTree grid, string fieldName)
+ : base(grid, fieldName)
+ {
+ prefixGridScanLevel = grid.GetMaxLevels() - 4;//TODO this default constant is dependent on the prefix grid size
+ }
+
+ public void SetPrefixGridScanLevel(int prefixGridScanLevel)
+ {
+ //TODO if negative then subtract from maxlevels
+ this.prefixGridScanLevel = prefixGridScanLevel;
+ }
+
+ public override Filter MakeFilter(SpatialArgs args)
+ {
+ var op = args.Operation;
if (op != SpatialOperation.Intersects)
- throw new UnsupportedSpatialOperation(op);
+ throw new UnsupportedSpatialOperation(op);
- Shape shape = args.Shape;
+ Shape shape = args.Shape;
int detailLevel = grid.GetLevelForDistance(args.ResolveDistErr(ctx, distErrPct));
- return new RecursivePrefixTreeFilter(GetFieldName(), grid, shape, prefixGridScanLevel, detailLevel);
- }
+ return new RecursivePrefixTreeFilter(GetFieldName(), grid, shape, prefixGridScanLevel, detailLevel);
+ }
- public override string ToString()
- {
- return GetType().Name + "(prefixGridScanLevel:" + prefixGridScanLevel + ",SPG:(" + grid + "))";
- }
- }
+ public override string ToString()
+ {
+ return GetType().Name + "(prefixGridScanLevel:" + prefixGridScanLevel + ",SPG:(" + grid + "))";
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/62f018ab/src/contrib/Spatial/Prefix/TermQueryPrefixTreeStrategy.cs
----------------------------------------------------------------------
diff --git a/src/contrib/Spatial/Prefix/TermQueryPrefixTreeStrategy.cs b/src/contrib/Spatial/Prefix/TermQueryPrefixTreeStrategy.cs
index a658a0b..84a074a 100644
--- a/src/contrib/Spatial/Prefix/TermQueryPrefixTreeStrategy.cs
+++ b/src/contrib/Spatial/Prefix/TermQueryPrefixTreeStrategy.cs
@@ -1,4 +1,4 @@
-/*
+/*
* 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.
@@ -25,32 +25,32 @@ using Spatial4n.Core.Shapes;
namespace Lucene.Net.Spatial.Prefix
{
- /// <summary>
- /// A basic implementation using a large {@link TermsFilter} of all the nodes from
- /// {@link SpatialPrefixTree#getNodes(com.spatial4j.core.shape.Shape, int, boolean)}.
- /// </summary>
- public class TermQueryPrefixTreeStrategy : PrefixTreeStrategy
- {
- public TermQueryPrefixTreeStrategy(SpatialPrefixTree grid, string fieldName)
- : base(grid, fieldName)
- {
- }
+ /// <summary>
+ /// A basic implementation using a large {@link TermsFilter} of all the nodes from
+ /// {@link SpatialPrefixTree#getNodes(com.spatial4j.core.shape.Shape, int, boolean)}.
+ /// </summary>
+ public class TermQueryPrefixTreeStrategy : PrefixTreeStrategy
+ {
+ public TermQueryPrefixTreeStrategy(SpatialPrefixTree grid, string fieldName)
+ : base(grid, fieldName)
+ {
+ }
- public override Filter MakeFilter(SpatialArgs args)
- {
- SpatialOperation op = args.Operation;
+ public override Filter MakeFilter(SpatialArgs args)
+ {
+ SpatialOperation op = args.Operation;
if (op != SpatialOperation.Intersects)
- throw new UnsupportedSpatialOperation(op);
+ throw new UnsupportedSpatialOperation(op);
- Shape shape = args.Shape;
+ Shape shape = args.Shape;
int detailLevel = grid.GetLevelForDistance(args.ResolveDistErr(ctx, distErrPct));
- var cells = grid.GetNodes(shape, detailLevel, false);
- var filter = new TermsFilter();
- foreach (Node cell in cells)
- {
- filter.AddTerm(new Term(GetFieldName(), cell.GetTokenString()));
- }
- return filter;
- }
- }
+ var cells = grid.GetNodes(shape, detailLevel, false);
+ var filter = new TermsFilter();
+ foreach (Node cell in cells)
+ {
+ filter.AddTerm(new Term(GetFieldName(), cell.GetTokenString()));
+ }
+ return filter;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/62f018ab/src/contrib/Spatial/Prefix/Tree/GeohashPrefixTree.cs
----------------------------------------------------------------------
diff --git a/src/contrib/Spatial/Prefix/Tree/GeohashPrefixTree.cs b/src/contrib/Spatial/Prefix/Tree/GeohashPrefixTree.cs
index 27676e4..b05d7d2 100644
--- a/src/contrib/Spatial/Prefix/Tree/GeohashPrefixTree.cs
+++ b/src/contrib/Spatial/Prefix/Tree/GeohashPrefixTree.cs
@@ -1,4 +1,4 @@
-/*
+/*
* 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.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/62f018ab/src/contrib/Spatial/Prefix/Tree/Node.cs
----------------------------------------------------------------------
diff --git a/src/contrib/Spatial/Prefix/Tree/Node.cs b/src/contrib/Spatial/Prefix/Tree/Node.cs
index 033bbb8..ce403b0 100644
--- a/src/contrib/Spatial/Prefix/Tree/Node.cs
+++ b/src/contrib/Spatial/Prefix/Tree/Node.cs
@@ -1,4 +1,4 @@
-/*
+/*
* 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.
@@ -24,199 +24,199 @@ using Spatial4n.Core.Shapes;
namespace Lucene.Net.Spatial.Prefix.Tree
{
- public abstract class Node : IComparable<Node>
- {
- public static byte LEAF_BYTE = (byte)'+';//NOTE: must sort before letters & numbers
-
- // /*
- //Holds a byte[] and/or String representation of the cell. Both are lazy constructed from the other.
- //Neither contains the trailing leaf byte.
- // */
- //private byte[] bytes;
- //private int b_off;
- //private int b_len;
-
- private String token;//this is the only part of equality
-
- protected SpatialRelation shapeRel;//set in getSubCells(filter), and via setLeaf().
- protected readonly SpatialPrefixTree spatialPrefixTree;
-
- protected Node(SpatialPrefixTree spatialPrefixTree, String token)
- {
- this.spatialPrefixTree = spatialPrefixTree;
- this.token = token;
- if (token.Length > 0 && token[token.Length - 1] == (char)LEAF_BYTE)
- {
- this.token = token.Substring(0, token.Length - 1);
- SetLeaf();
- }
-
- if (GetLevel() == 0)
- GetShape();//ensure any lazy instantiation completes to make this threadsafe
- }
-
- public virtual void Reset(string newToken)
- {
- Debug.Assert(GetLevel() != 0);
- this.token = newToken;
- shapeRel = SpatialRelation.NULL_VALUE;
- b_fixLeaf();
- }
-
- private void b_fixLeaf()
- {
- if (GetLevel() == spatialPrefixTree.GetMaxLevels())
- {
- SetLeaf();
- }
- }
-
- public SpatialRelation GetShapeRel()
- {
- return shapeRel;
- }
-
- public bool IsLeaf()
- {
- return shapeRel == SpatialRelation.WITHIN;
- }
-
- public void SetLeaf()
- {
- Debug.Assert(GetLevel() != 0);
- shapeRel = SpatialRelation.WITHIN;
- }
-
- /*
- * Note: doesn't contain a trailing leaf byte.
- */
- public String GetTokenString()
- {
- if (token == null)
- throw new InvalidOperationException("Somehow we got a null token");
- return token;
- }
-
- ///// <summary>
- ///// Note: doesn't contain a trailing leaf byte.
- ///// </summary>
- ///// <returns></returns>
- //public byte[] GetTokenBytes()
- //{
- // if (bytes != null)
- // {
- // if (b_off != 0 || b_len != bytes.Length)
- // {
- // throw new IllegalStateException("Not supported if byte[] needs to be recreated.");
- // }
- // }
- // else
- // {
- // bytes = token.GetBytes(SpatialPrefixTree.UTF8);
- // b_off = 0;
- // b_len = bytes.Length;
- // }
- // return bytes;
- //}
-
- public int GetLevel()
- {
- return token.Length;
- //return token != null ? token.Length : b_len;
- }
-
- //TODO add getParent() and update some algorithms to use this?
- //public Cell getParent();
-
- /*
- * Like {@link #getSubCells()} but with the results filtered by a shape. If that shape is a {@link com.spatial4j.core.shape.Point} then it
- * must call {@link #getSubCell(com.spatial4j.core.shape.Point)};
- * Precondition: Never called when getLevel() == maxLevel.
- *
- * @param shapeFilter an optional filter for the returned cells.
- * @return A set of cells (no dups), sorted. Not Modifiable.
- */
- public IList<Node> GetSubCells(Shape shapeFilter)
- {
- //Note: Higher-performing subclasses might override to consider the shape filter to generate fewer cells.
- var point = shapeFilter as Point;
- if (point != null)
- {
+ public abstract class Node : IComparable<Node>
+ {
+ public static byte LEAF_BYTE = (byte)'+';//NOTE: must sort before letters & numbers
+
+ // /*
+ //Holds a byte[] and/or String representation of the cell. Both are lazy constructed from the other.
+ //Neither contains the trailing leaf byte.
+ // */
+ //private byte[] bytes;
+ //private int b_off;
+ //private int b_len;
+
+ private String token;//this is the only part of equality
+
+ protected SpatialRelation shapeRel;//set in getSubCells(filter), and via setLeaf().
+ protected readonly SpatialPrefixTree spatialPrefixTree;
+
+ protected Node(SpatialPrefixTree spatialPrefixTree, String token)
+ {
+ this.spatialPrefixTree = spatialPrefixTree;
+ this.token = token;
+ if (token.Length > 0 && token[token.Length - 1] == (char)LEAF_BYTE)
+ {
+ this.token = token.Substring(0, token.Length - 1);
+ SetLeaf();
+ }
+
+ if (GetLevel() == 0)
+ GetShape();//ensure any lazy instantiation completes to make this threadsafe
+ }
+
+ public virtual void Reset(string newToken)
+ {
+ Debug.Assert(GetLevel() != 0);
+ this.token = newToken;
+ shapeRel = SpatialRelation.NULL_VALUE;
+ b_fixLeaf();
+ }
+
+ private void b_fixLeaf()
+ {
+ if (GetLevel() == spatialPrefixTree.GetMaxLevels())
+ {
+ SetLeaf();
+ }
+ }
+
+ public SpatialRelation GetShapeRel()
+ {
+ return shapeRel;
+ }
+
+ public bool IsLeaf()
+ {
+ return shapeRel == SpatialRelation.WITHIN;
+ }
+
+ public void SetLeaf()
+ {
+ Debug.Assert(GetLevel() != 0);
+ shapeRel = SpatialRelation.WITHIN;
+ }
+
+ /*
+ * Note: doesn't contain a trailing leaf byte.
+ */
+ public String GetTokenString()
+ {
+ if (token == null)
+ throw new InvalidOperationException("Somehow we got a null token");
+ return token;
+ }
+
+ ///// <summary>
+ ///// Note: doesn't contain a trailing leaf byte.
+ ///// </summary>
+ ///// <returns></returns>
+ //public byte[] GetTokenBytes()
+ //{
+ // if (bytes != null)
+ // {
+ // if (b_off != 0 || b_len != bytes.Length)
+ // {
+ // throw new IllegalStateException("Not supported if byte[] needs to be recreated.");
+ // }
+ // }
+ // else
+ // {
+ // bytes = token.GetBytes(SpatialPrefixTree.UTF8);
+ // b_off = 0;
+ // b_len = bytes.Length;
+ // }
+ // return bytes;
+ //}
+
+ public int GetLevel()
+ {
+ return token.Length;
+ //return token != null ? token.Length : b_len;
+ }
+
+ //TODO add getParent() and update some algorithms to use this?
+ //public Cell getParent();
+
+ /*
+ * Like {@link #getSubCells()} but with the results filtered by a shape. If that shape is a {@link com.spatial4j.core.shape.Point} then it
+ * must call {@link #getSubCell(com.spatial4j.core.shape.Point)};
+ * Precondition: Never called when getLevel() == maxLevel.
+ *
+ * @param shapeFilter an optional filter for the returned cells.
+ * @return A set of cells (no dups), sorted. Not Modifiable.
+ */
+ public IList<Node> GetSubCells(Shape shapeFilter)
+ {
+ //Note: Higher-performing subclasses might override to consider the shape filter to generate fewer cells.
+ var point = shapeFilter as Point;
+ if (point != null)
+ {
#if !NET35
- return new ReadOnlyCollectionBuilder<Node>(new[] {GetSubCell(point)}).ToReadOnlyCollection();
+ return new ReadOnlyCollectionBuilder<Node>(new[] {GetSubCell(point)}).ToReadOnlyCollection();
#else
return new List<Node>(new[]{GetSubCell(point)}).AsReadOnly();
#endif
- }
+ }
- var cells = GetSubCells();
- if (shapeFilter == null)
- {
- return cells;
- }
- var copy = new List<Node>(cells.Count);//copy since cells contractually isn't modifiable
- foreach (var cell in cells)
- {
+ var cells = GetSubCells();
+ if (shapeFilter == null)
+ {
+ return cells;
+ }
+ var copy = new List<Node>(cells.Count);//copy since cells contractually isn't modifiable
+ foreach (var cell in cells)
+ {
SpatialRelation rel = cell.GetShape().Relate(shapeFilter);
- if (rel == SpatialRelation.DISJOINT)
- continue;
- cell.shapeRel = rel;
- copy.Add(cell);
- }
- cells = copy;
- return cells;
- }
-
- /*
- * Performant implementations are expected to implement this efficiently by considering the current
- * cell's boundary.
- * Precondition: Never called when getLevel() == maxLevel.
- * Precondition: this.getShape().relate(p) != DISJOINT.
- */
- public abstract Node GetSubCell(Point p);
-
- //TODO Cell getSubCell(byte b)
-
- /*
- * Gets the cells at the next grid cell level that cover this cell.
- * Precondition: Never called when getLevel() == maxLevel.
- *
- * @return A set of cells (no dups), sorted. Not Modifiable.
- */
- public abstract IList<Node> GetSubCells();
-
- /*
- * {@link #getSubCells()}.size() -- usually a constant. Should be >=2
- */
- public abstract int GetSubCellsSize();
-
- public abstract Shape GetShape();
-
- public virtual Point GetCenter()
- {
- return GetShape().GetCenter();
- }
-
-
- public int CompareTo(Node o)
- {
- return System.String.CompareOrdinal(GetTokenString(), o.GetTokenString());
- }
-
- public override bool Equals(object obj)
- {
- return !(obj == null || !(obj is Node)) && GetTokenString().Equals(((Node) obj).GetTokenString());
- }
-
- public override int GetHashCode()
- {
- return GetTokenString().GetHashCode();
- }
-
- public override string ToString()
- {
- return GetTokenString() + (IsLeaf() ? new string(new[] {(char) LEAF_BYTE}) : string.Empty);
- }
- }
+ if (rel == SpatialRelation.DISJOINT)
+ continue;
+ cell.shapeRel = rel;
+ copy.Add(cell);
+ }
+ cells = copy;
+ return cells;
+ }
+
+ /*
+ * Performant implementations are expected to implement this efficiently by considering the current
+ * cell's boundary.
+ * Precondition: Never called when getLevel() == maxLevel.
+ * Precondition: this.getShape().relate(p) != DISJOINT.
+ */
+ public abstract Node GetSubCell(Point p);
+
+ //TODO Cell getSubCell(byte b)
+
+ /*
+ * Gets the cells at the next grid cell level that cover this cell.
+ * Precondition: Never called when getLevel() == maxLevel.
+ *
+ * @return A set of cells (no dups), sorted. Not Modifiable.
+ */
+ public abstract IList<Node> GetSubCells();
+
+ /*
+ * {@link #getSubCells()}.size() -- usually a constant. Should be >=2
+ */
+ public abstract int GetSubCellsSize();
+
+ public abstract Shape GetShape();
+
+ public virtual Point GetCenter()
+ {
+ return GetShape().GetCenter();
+ }
+
+
+ public int CompareTo(Node o)
+ {
+ return System.String.CompareOrdinal(GetTokenString(), o.GetTokenString());
+ }
+
+ public override bool Equals(object obj)
+ {
+ return !(obj == null || !(obj is Node)) && GetTokenString().Equals(((Node) obj).GetTokenString());
+ }
+
+ public override int GetHashCode()
+ {
+ return GetTokenString().GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return GetTokenString() + (IsLeaf() ? new string(new[] {(char) LEAF_BYTE}) : string.Empty);
+ }
+ }
}