Java Code Examples for org.locationtech.spatial4j.shape.Rectangle#getCrossesDateLine()

The following examples show how to use org.locationtech.spatial4j.shape.Rectangle#getCrossesDateLine() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: RandomSpatialOpFuzzyPrefixTreeTest.java    From lucene-solr with Apache License 2.0 6 votes vote down vote up
private Shape toNonGeo(Shape shape) {
  if (!ctx.isGeo())
    return shape;//already non-geo
  if (shape instanceof Rectangle) {
    Rectangle rect = (Rectangle) shape;
    if (rect.getCrossesDateLine()) {
      return new ShapePair(
          ctx2D.makeRectangle(rect.getMinX(), 180, rect.getMinY(), rect.getMaxY()),
          ctx2D.makeRectangle(-180, rect.getMaxX(), rect.getMinY(), rect.getMaxY()),
          biasContainsThenWithin);
    } else {
      return ctx2D.makeRectangle(rect.getMinX(), rect.getMaxX(), rect.getMinY(), rect.getMaxY());
    }
  }
  //no need to do others; this addresses the -180/+180 ambiguity corner test problem
  return shape;
}
 
Example 2
Source File: PointVectorStrategy.java    From lucene-solr with Apache License 2.0 5 votes vote down vote up
/**
 * Constructs a query to retrieve documents that fully contain the input envelope.
 */
private Query makeWithin(Rectangle bbox) {
  BooleanQuery.Builder bq = new BooleanQuery.Builder();
  BooleanClause.Occur MUST = BooleanClause.Occur.MUST;
  if (bbox.getCrossesDateLine()) {
    //use null as performance trick since no data will be beyond the world bounds
    bq.add(rangeQuery(fieldNameX, null/*-180*/, bbox.getMaxX()), BooleanClause.Occur.SHOULD );
    bq.add(rangeQuery(fieldNameX, bbox.getMinX(), null/*+180*/), BooleanClause.Occur.SHOULD );
    bq.setMinimumNumberShouldMatch(1);//must match at least one of the SHOULD
  } else {
    bq.add(rangeQuery(fieldNameX, bbox.getMinX(), bbox.getMaxX()), MUST);
  }
  bq.add(rangeQuery(fieldNameY, bbox.getMinY(), bbox.getMaxY()), MUST);
  return bq.build();
}
 
Example 3
Source File: SpatialTestCase.java    From lucene-solr with Apache License 2.0 5 votes vote down vote up
protected Rectangle randomRectangle(Rectangle bounds) {
  double[] xNewStartAndWidth = randomSubRange(bounds.getMinX(), bounds.getWidth());
  double xMin = xNewStartAndWidth[0];
  double xMax = xMin + xNewStartAndWidth[1];
  if (bounds.getCrossesDateLine()) {
    xMin = DistanceUtils.normLonDEG(xMin);
    xMax = DistanceUtils.normLonDEG(xMax);
  }

  double[] yNewStartAndHeight = randomSubRange(bounds.getMinY(), bounds.getHeight());
  double yMin = yNewStartAndHeight[0];
  double yMax = yMin + yNewStartAndHeight[1];

  return ctx.getShapeFactory().rect(xMin, xMax, yMin, yMax);
}
 
Example 4
Source File: PointVectorStrategy.java    From lucene-solr with Apache License 2.0 5 votes vote down vote up
/**
 * Constructs a query to retrieve documents that fully contain the input envelope.
 */
private Query makeWithin(Rectangle bbox) {
  BooleanQuery.Builder bq = new BooleanQuery.Builder();
  BooleanClause.Occur MUST = BooleanClause.Occur.MUST;
  if (bbox.getCrossesDateLine()) {
    //use null as performance trick since no data will be beyond the world bounds
    bq.add(rangeQuery(fieldNameX, null/*-180*/, bbox.getMaxX()), BooleanClause.Occur.SHOULD );
    bq.add(rangeQuery(fieldNameX, bbox.getMinX(), null/*+180*/), BooleanClause.Occur.SHOULD );
    bq.setMinimumNumberShouldMatch(1);//must match at least one of the SHOULD
  } else {
    bq.add(rangeQuery(fieldNameX, bbox.getMinX(), bbox.getMaxX()), MUST);
  }
  bq.add(rangeQuery(fieldNameY, bbox.getMinY(), bbox.getMaxY()), MUST);
  return bq.build();
}
 
Example 5
Source File: BBoxStrategy.java    From lucene-solr with Apache License 2.0 4 votes vote down vote up
/**
 * 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 = this.makeNumericRangeQuery(field_minY, bbox.getMinY(), null, true, false);
  Query qMaxY = this.makeNumericRangeQuery(field_maxY, null, bbox.getMaxY(), false, true);
  Query yConditions = this.makeQuery(BooleanClause.Occur.MUST, qMinY, qMaxY);

  // X conditions
  Query xConditions;

  if (ctx.isGeo() && bbox.getMinX() == -180.0 && bbox.getMaxX() == 180.0) {
    //if query world-wraps, only the y condition matters
    return yConditions;

  } else if (!bbox.getCrossesDateLine()) {
    // queries that do not cross the date line

    // docMinX >= queryExtent.getMinX() AND docMaxX <= queryExtent.getMaxX()
    Query qMinX = this.makeNumericRangeQuery(field_minX, bbox.getMinX(), null, true, false);
    Query qMaxX = this.makeNumericRangeQuery(field_maxX, null, bbox.getMaxX(), false, true);
    Query qMinMax = this.makeQuery(BooleanClause.Occur.MUST, qMinX, qMaxX);

    double edge = 0;//none, otherwise opposite dateline of query
    if (bbox.getMinX() == -180.0)
      edge = 180;
    else if (bbox.getMaxX() == 180.0)
      edge = -180;
    if (edge != 0 && ctx.isGeo()) {
      Query edgeQ = makeQuery(BooleanClause.Occur.MUST,
          makeNumberTermQuery(field_minX, edge), makeNumberTermQuery(field_maxX, edge));
      qMinMax = makeQuery(BooleanClause.Occur.SHOULD, qMinMax, edgeQ);
    }

    xConditions = this.makeXDL(false, qMinMax);

    // 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 = this.makeNumericRangeQuery(field_minX, bbox.getMinX(), null, true, false);
    Query qMaxXLeft = this.makeNumericRangeQuery(field_maxX, null, 180.0, false, true);
    Query qLeft = this.makeQuery(BooleanClause.Occur.MUST, qMinXLeft, qMaxXLeft);

    // the document should be within the right portion of the query
    // docMinX >= -180.0 AND docMaxX <= queryExtent.getMaxX()
    Query qMinXRight = this.makeNumericRangeQuery(field_minX, -180.0, null, true, false);
    Query qMaxXRight = this.makeNumericRangeQuery(field_maxX, null, bbox.getMaxX(), false, true);
    Query qRight = this.makeQuery(BooleanClause.Occur.MUST, qMinXRight, qMaxXRight);

    // 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(BooleanClause.Occur.SHOULD, qLeft, qRight);
    Query qNonXDL = this.makeXDL(false, qLeftRight);

    // 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 = this.makeNumericRangeQuery(field_minX, bbox.getMinX(), null, true, false);
    Query qXDLRight = this.makeNumericRangeQuery(field_maxX, null, bbox.getMaxX(), false, true);
    Query qXDLLeftRight = this.makeQuery(BooleanClause.Occur.MUST, qXDLLeft, qXDLRight);
    Query qXDL = this.makeXDL(true, qXDLLeftRight);

    // apply the non-XDL and XDL conditions
    xConditions = this.makeQuery(BooleanClause.Occur.SHOULD, qNonXDL, qXDL);
  }

  // both X and Y conditions must occur
  return this.makeQuery(BooleanClause.Occur.MUST, xConditions, yConditions);
}
 
Example 6
Source File: BBoxStrategy.java    From lucene-solr with Apache License 2.0 4 votes vote down vote up
/**
 * 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 = this.makeNumericRangeQuery(field_minY, bbox.getMinY(), null, true, false);
  Query qMaxY = this.makeNumericRangeQuery(field_maxY, null, bbox.getMaxY(), false, true);
  Query yConditions = this.makeQuery(BooleanClause.Occur.MUST, qMinY, qMaxY);

  // X conditions
  Query xConditions;

  if (ctx.isGeo() && bbox.getMinX() == -180.0 && bbox.getMaxX() == 180.0) {
    //if query world-wraps, only the y condition matters
    return yConditions;

  } else if (!bbox.getCrossesDateLine()) {
    // queries that do not cross the date line

    // docMinX >= queryExtent.getMinX() AND docMaxX <= queryExtent.getMaxX()
    Query qMinX = this.makeNumericRangeQuery(field_minX, bbox.getMinX(), null, true, false);
    Query qMaxX = this.makeNumericRangeQuery(field_maxX, null, bbox.getMaxX(), false, true);
    Query qMinMax = this.makeQuery(BooleanClause.Occur.MUST, qMinX, qMaxX);

    double edge = 0;//none, otherwise opposite dateline of query
    if (bbox.getMinX() == -180.0)
      edge = 180;
    else if (bbox.getMaxX() == 180.0)
      edge = -180;
    if (edge != 0 && ctx.isGeo()) {
      Query edgeQ = makeQuery(BooleanClause.Occur.MUST,
          makeNumberTermQuery(field_minX, edge), makeNumberTermQuery(field_maxX, edge));
      qMinMax = makeQuery(BooleanClause.Occur.SHOULD, qMinMax, edgeQ);
    }

    xConditions = this.makeXDL(false, qMinMax);

    // 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 = this.makeNumericRangeQuery(field_minX, bbox.getMinX(), null, true, false);
    Query qMaxXLeft = this.makeNumericRangeQuery(field_maxX, null, 180.0, false, true);
    Query qLeft = this.makeQuery(BooleanClause.Occur.MUST, qMinXLeft, qMaxXLeft);

    // the document should be within the right portion of the query
    // docMinX >= -180.0 AND docMaxX <= queryExtent.getMaxX()
    Query qMinXRight = this.makeNumericRangeQuery(field_minX, -180.0, null, true, false);
    Query qMaxXRight = this.makeNumericRangeQuery(field_maxX, null, bbox.getMaxX(), false, true);
    Query qRight = this.makeQuery(BooleanClause.Occur.MUST, qMinXRight, qMaxXRight);

    // 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(BooleanClause.Occur.SHOULD, qLeft, qRight);
    Query qNonXDL = this.makeXDL(false, qLeftRight);

    // 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 = this.makeNumericRangeQuery(field_minX, bbox.getMinX(), null, true, false);
    Query qXDLRight = this.makeNumericRangeQuery(field_maxX, null, bbox.getMaxX(), false, true);
    Query qXDLLeftRight = this.makeQuery(BooleanClause.Occur.MUST, qXDLLeft, qXDLRight);
    Query qXDL = this.makeXDL(true, qXDLLeftRight);

    // apply the non-XDL and XDL conditions
    xConditions = this.makeQuery(BooleanClause.Occur.SHOULD, qNonXDL, qXDL);
  }

  // both X and Y conditions must occur
  return this.makeQuery(BooleanClause.Occur.MUST, xConditions, yConditions);
}
 
Example 7
Source File: LatLonType.java    From lucene-solr with Apache License 2.0 4 votes vote down vote up
@Override
public Query createSpatialQuery(QParser parser, SpatialOptions options) {
  Point point = SpatialUtils.parsePointSolrException(options.pointStr, SpatialContext.GEO);

  // lat & lon in degrees
  double latCenter = point.getY();
  double lonCenter = point.getX();
  
  double distDeg = DistanceUtils.dist2Degrees(options.distance, options.radius);
  Rectangle bbox = DistanceUtils.calcBoxByDistFromPtDEG(latCenter, lonCenter, distDeg, SpatialContext.GEO, null);
  double latMin = bbox.getMinY();
  double latMax = bbox.getMaxY();
  double lonMin, lonMax, lon2Min, lon2Max;
  if (bbox.getCrossesDateLine()) {
     lonMin = -180;
     lonMax = bbox.getMaxX();
     lon2Min = bbox.getMinX();
     lon2Max = 180;
  } else {
     lonMin = bbox.getMinX();
     lonMax = bbox.getMaxX();
     lon2Min = -180;
     lon2Max = 180;
  }
  
  IndexSchema schema = parser.getReq().getSchema();
  
  // Now that we've figured out the ranges, build them!
  SchemaField latSF = subField(options.field, LAT, schema);
  SchemaField lonSF = subField(options.field, LON, schema);

  SpatialDistanceQuery spatial = new SpatialDistanceQuery();


  if (options.bbox) {
    BooleanQuery.Builder result = new BooleanQuery.Builder();

    Query latRange = latSF.getType().getRangeQuery(parser, latSF,
              String.valueOf(latMin),
              String.valueOf(latMax),
              true, true);
    result.add(latRange, BooleanClause.Occur.MUST);

    if (lonMin != -180 || lonMax != 180) {
      Query lonRange = lonSF.getType().getRangeQuery(parser, lonSF,
              String.valueOf(lonMin),
              String.valueOf(lonMax),
              true, true);
      if (lon2Min != -180 || lon2Max != 180) {
        // another valid longitude range
        BooleanQuery.Builder bothLons = new BooleanQuery.Builder();
        bothLons.add(lonRange, BooleanClause.Occur.SHOULD);

        lonRange = lonSF.getType().getRangeQuery(parser, lonSF,
              String.valueOf(lon2Min),
              String.valueOf(lon2Max),
              true, true);
        bothLons.add(lonRange, BooleanClause.Occur.SHOULD);

        lonRange = bothLons.build();
      }

      result.add(lonRange, BooleanClause.Occur.MUST);
    }

    spatial.bboxQuery = result.build();
  }


  spatial.origField = options.field.getName();
  spatial.latSource = latSF.getType().getValueSource(latSF, parser);
  spatial.lonSource = lonSF.getType().getValueSource(lonSF, parser);
  spatial.latMin = latMin;
  spatial.latMax = latMax;
  spatial.lonMin = lonMin;
  spatial.lonMax = lonMax;
  spatial.lon2Min = lon2Min;
  spatial.lon2Max = lon2Max;
  spatial.lon2 = lon2Min != -180 || lon2Max != 180;

  spatial.latCenter = latCenter;
  spatial.lonCenter = lonCenter;
  spatial.dist = options.distance;
  spatial.planetRadius = options.radius;

  spatial.calcDist = !options.bbox;

  return spatial;
}