blob: 0b0b701ce6f246d8ae4fc90382579e129a24f371 [file] [log] [blame]
/*
* 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.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lucene.spatial3d.geom;
/**
* An object for accumulating XYZ bounds information.
*
* @lucene.experimental
*/
public class XYZBounds implements Bounds {
/** A 'fudge factor', which is added to maximums and subtracted from minimums,
* in order to compensate for potential error deltas. This would not be necessary
* except that our 'bounds' is defined as always equaling or exceeding the boundary
* of the shape, and we cannot guarantee that without making MINIMUM_RESOLUTION
* unacceptably large.
* Also, see LUCENE-7290 for a description of how geometry can magnify the bounds delta.
*/
private static final double FUDGE_FACTOR = Vector.MINIMUM_RESOLUTION * 1e3;
/** Minimum x */
private Double minX = null;
/** Maximum x */
private Double maxX = null;
/** Minimum y */
private Double minY = null;
/** Maximum y */
private Double maxY = null;
/** Minimum z */
private Double minZ = null;
/** Maximum z */
private Double maxZ = null;
/** Set to true if no longitude bounds can be stated */
private boolean noLongitudeBound = false;
/** Set to true if no top latitude bound can be stated */
private boolean noTopLatitudeBound = false;
/** Set to true if no bottom latitude bound can be stated */
private boolean noBottomLatitudeBound = false;
/** Construct an empty bounds object */
public XYZBounds() {
}
// Accessor methods
/** Return the minimum X value.
*@return minimum X value.
*/
public Double getMinimumX() {
return minX;
}
/** Return the maximum X value.
*@return maximum X value.
*/
public Double getMaximumX() {
return maxX;
}
/** Return the minimum Y value.
*@return minimum Y value.
*/
public Double getMinimumY() {
return minY;
}
/** Return the maximum Y value.
*@return maximum Y value.
*/
public Double getMaximumY() {
return maxY;
}
/** Return the minimum Z value.
*@return minimum Z value.
*/
public Double getMinimumZ() {
return minZ;
}
/** Return the maximum Z value.
*@return maximum Z value.
*/
public Double getMaximumZ() {
return maxZ;
}
/** Return true if minX is as small as the planet model allows.
*@return true if minX has reached its bound.
*/
public boolean isSmallestMinX(final PlanetModel planetModel) {
if (minX == null)
return false;
return minX - planetModel.getMinimumXValue() < Vector.MINIMUM_RESOLUTION;
}
/** Return true if maxX is as large as the planet model allows.
*@return true if maxX has reached its bound.
*/
public boolean isLargestMaxX(final PlanetModel planetModel) {
if (maxX == null)
return false;
return planetModel.getMaximumXValue() - maxX < Vector.MINIMUM_RESOLUTION;
}
/** Return true if minY is as small as the planet model allows.
*@return true if minY has reached its bound.
*/
public boolean isSmallestMinY(final PlanetModel planetModel) {
if (minY == null)
return false;
return minY - planetModel.getMinimumYValue() < Vector.MINIMUM_RESOLUTION;
}
/** Return true if maxY is as large as the planet model allows.
*@return true if maxY has reached its bound.
*/
public boolean isLargestMaxY(final PlanetModel planetModel) {
if (maxY == null)
return false;
return planetModel.getMaximumYValue() - maxY < Vector.MINIMUM_RESOLUTION;
}
/** Return true if minZ is as small as the planet model allows.
*@return true if minZ has reached its bound.
*/
public boolean isSmallestMinZ(final PlanetModel planetModel) {
if (minZ == null)
return false;
return minZ - planetModel.getMinimumZValue() < Vector.MINIMUM_RESOLUTION;
}
/** Return true if maxZ is as large as the planet model allows.
*@return true if maxZ has reached its bound.
*/
public boolean isLargestMaxZ(final PlanetModel planetModel) {
if (maxZ == null)
return false;
return planetModel.getMaximumZValue() - maxZ < Vector.MINIMUM_RESOLUTION;
}
// Modification methods
@Override
public Bounds addPlane(final PlanetModel planetModel, final Plane plane, final Membership... bounds) {
plane.recordBounds(planetModel, this, bounds);
return this;
}
/** Add a horizontal plane to the bounds description.
* This method should EITHER use the supplied latitude, OR use the supplied
* plane, depending on what is most efficient.
*@param planetModel is the planet model.
*@param latitude is the latitude.
*@param horizontalPlane is the plane.
*@param bounds are the constraints on the plane.
*@return updated Bounds object.
*/
public Bounds addHorizontalPlane(final PlanetModel planetModel,
final double latitude,
final Plane horizontalPlane,
final Membership... bounds) {
return addPlane(planetModel, horizontalPlane, bounds);
}
/** Add a vertical plane to the bounds description.
* This method should EITHER use the supplied longitude, OR use the supplied
* plane, depending on what is most efficient.
*@param planetModel is the planet model.
*@param longitude is the longitude.
*@param verticalPlane is the plane.
*@param bounds are the constraints on the plane.
*@return updated Bounds object.
*/
public Bounds addVerticalPlane(final PlanetModel planetModel,
final double longitude,
final Plane verticalPlane,
final Membership... bounds) {
return addPlane(planetModel, verticalPlane, bounds);
}
@Override
public Bounds addXValue(final GeoPoint point) {
return addXValue(point.x);
}
/** Add a specific X value.
* @param x is the value to add.
* @return the bounds object.
*/
public Bounds addXValue(final double x) {
final double small = x - FUDGE_FACTOR;
if (minX == null || minX > small) {
minX = small;
}
final double large = x + FUDGE_FACTOR;
if (maxX == null || maxX < large) {
maxX = large;
}
return this;
}
@Override
public Bounds addYValue(final GeoPoint point) {
return addYValue(point.y);
}
/** Add a specific Y value.
* @param y is the value to add.
* @return the bounds object.
*/
public Bounds addYValue(final double y) {
final double small = y - FUDGE_FACTOR;
if (minY == null || minY > small) {
minY = small;
}
final double large = y + FUDGE_FACTOR;
if (maxY == null || maxY < large) {
maxY = large;
}
return this;
}
@Override
public Bounds addZValue(final GeoPoint point) {
return addZValue(point.z);
}
/** Add a specific Z value.
* @param z is the value to add.
* @return the bounds object.
*/
public Bounds addZValue(final double z) {
final double small = z - FUDGE_FACTOR;
if (minZ == null || minZ > small) {
minZ = small;
}
final double large = z + FUDGE_FACTOR;
if (maxZ == null || maxZ < large) {
maxZ = large;
}
return this;
}
@Override
public Bounds addIntersection(final PlanetModel planetModel, final Plane plane1, final Plane plane2, final Membership... bounds) {
plane1.recordBounds(planetModel, this, plane2, bounds);
return this;
}
@Override
public Bounds addPoint(final GeoPoint point) {
return addXValue(point).addYValue(point).addZValue(point);
}
@Override
public Bounds isWide() {
// No specific thing we need to do.
return this;
}
@Override
public Bounds noLongitudeBound() {
// No specific thing we need to do.
return this;
}
@Override
public Bounds noTopLatitudeBound() {
// No specific thing we need to do.
return this;
}
@Override
public Bounds noBottomLatitudeBound() {
// No specific thing we need to do.
return this;
}
@Override
public Bounds noBound(final PlanetModel planetModel) {
minX = planetModel.getMinimumXValue();
maxX = planetModel.getMaximumXValue();
minY = planetModel.getMinimumYValue();
maxY = planetModel.getMaximumYValue();
minZ = planetModel.getMinimumZValue();
maxZ = planetModel.getMaximumZValue();
return this;
}
@Override
public String toString() {
return "XYZBounds: [xmin="+minX+" xmax="+maxX+" ymin="+minY+" ymax="+maxY+" zmin="+minZ+" zmax="+maxZ+"]";
}
}