mirror of https://github.com/apache/lucene.git
LUCENE-6800: use factory to create XYZSolid
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1702454 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ba44c41918
commit
1be2bf1dfd
|
@ -155,6 +155,9 @@ Other
|
|||
it, to eventually handle degenerate cases (Karl Wright via Mike
|
||||
McCandless)
|
||||
|
||||
* LUCENE-6800: Use XYZSolidFactory to create XYZSolids (Karl Wright
|
||||
via Mike McCandless)
|
||||
|
||||
Build
|
||||
|
||||
* LUCENE-6732: Improve checker for invalid source patterns to also
|
||||
|
|
|
@ -22,7 +22,7 @@ package org.apache.lucene.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public abstract class BaseXYZSolid extends BasePlanetObject implements GeoArea {
|
||||
public abstract class BaseXYZSolid extends BasePlanetObject implements XYZSolid {
|
||||
|
||||
/** Unit vector in x */
|
||||
protected static final Vector xUnitVector = new Vector(1.0, 0.0, 0.0);
|
||||
|
|
|
@ -50,32 +50,7 @@ public class GeoAreaFactory {
|
|||
* @param maxZ is the max Z boundary
|
||||
*/
|
||||
public static GeoArea makeGeoArea(final PlanetModel planetModel, final double minX, final double maxX, final double minY, final double maxY, final double minZ, final double maxZ) {
|
||||
if (Math.abs(maxX - minX) < Vector.MINIMUM_RESOLUTION) {
|
||||
if (Math.abs(maxY - minY) < Vector.MINIMUM_RESOLUTION) {
|
||||
if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
|
||||
return new dXdYdZSolid(planetModel, (minX+maxX) * 0.5, (minY+maxY) * 0.5, minZ);
|
||||
} else {
|
||||
return new dXdYZSolid(planetModel, (minX+maxX) * 0.5, (minY+maxY) * 0.5, minZ, maxZ);
|
||||
}
|
||||
} else {
|
||||
if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
|
||||
return new dXYdZSolid(planetModel, (minX+maxX) * 0.5, minY, maxY, (minZ+maxZ) * 0.5);
|
||||
} else {
|
||||
return new dXYZSolid(planetModel, (minX+maxX) * 0.5, minY, maxY, minZ, maxZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Math.abs(maxY - minY) < Vector.MINIMUM_RESOLUTION) {
|
||||
if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
|
||||
return new XdYdZSolid(planetModel, minX, maxX, (minY+maxY) * 0.5, (minZ+maxZ) * 0.5);
|
||||
} else {
|
||||
return new XdYZSolid(planetModel, minX, maxX, (minY+maxY) * 0.5, minZ, maxZ);
|
||||
}
|
||||
}
|
||||
if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
|
||||
return new XYdZSolid(planetModel, minX, maxX, minY, maxY, (minZ+maxZ) * 0.5);
|
||||
}
|
||||
return new XYZSolid(planetModel, minX, maxX, minY, maxY, minZ, maxZ);
|
||||
return XYZSolidFactory.makeXYZSolid(planetModel, minX, maxX, minY, maxY, minZ, maxZ);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,418 @@
|
|||
package org.apache.lucene.geo3d;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 3D rectangle, bounded on six sides by X,Y,Z limits
|
||||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class StandardXYZSolid extends BaseXYZSolid {
|
||||
|
||||
/** Whole world? */
|
||||
protected final boolean isWholeWorld;
|
||||
/** Min-X plane */
|
||||
protected final SidedPlane minXPlane;
|
||||
/** Max-X plane */
|
||||
protected final SidedPlane maxXPlane;
|
||||
/** Min-Y plane */
|
||||
protected final SidedPlane minYPlane;
|
||||
/** Max-Y plane */
|
||||
protected final SidedPlane maxYPlane;
|
||||
/** Min-Z plane */
|
||||
protected final SidedPlane minZPlane;
|
||||
/** Max-Z plane */
|
||||
protected final SidedPlane maxZPlane;
|
||||
|
||||
/** These are the edge points of the shape, which are defined to be at least one point on
|
||||
* each surface area boundary. In the case of a solid, this includes points which represent
|
||||
* the intersection of XYZ bounding planes and the planet, as well as points representing
|
||||
* the intersection of single bounding planes with the planet itself.
|
||||
*/
|
||||
protected final GeoPoint[] edgePoints;
|
||||
|
||||
/** Notable points for minXPlane */
|
||||
protected final GeoPoint[] notableMinXPoints;
|
||||
/** Notable points for maxXPlane */
|
||||
protected final GeoPoint[] notableMaxXPoints;
|
||||
/** Notable points for minYPlane */
|
||||
protected final GeoPoint[] notableMinYPoints;
|
||||
/** Notable points for maxYPlane */
|
||||
protected final GeoPoint[] notableMaxYPoints;
|
||||
/** Notable points for minZPlane */
|
||||
protected final GeoPoint[] notableMinZPoints;
|
||||
/** Notable points for maxZPlane */
|
||||
protected final GeoPoint[] notableMaxZPoints;
|
||||
|
||||
/**
|
||||
* Sole constructor
|
||||
*
|
||||
*@param planetModel is the planet model.
|
||||
*@param minX is the minimum X value.
|
||||
*@param maxX is the maximum X value.
|
||||
*@param minY is the minimum Y value.
|
||||
*@param maxY is the maximum Y value.
|
||||
*@param minZ is the minimum Z value.
|
||||
*@param maxZ is the maximum Z value.
|
||||
*/
|
||||
public StandardXYZSolid(final PlanetModel planetModel,
|
||||
final double minX,
|
||||
final double maxX,
|
||||
final double minY,
|
||||
final double maxY,
|
||||
final double minZ,
|
||||
final double maxZ) {
|
||||
super(planetModel);
|
||||
// Argument checking
|
||||
if (maxX - minX < Vector.MINIMUM_RESOLUTION)
|
||||
throw new IllegalArgumentException("X values in wrong order or identical");
|
||||
if (maxY - minY < Vector.MINIMUM_RESOLUTION)
|
||||
throw new IllegalArgumentException("Y values in wrong order or identical");
|
||||
if (maxZ - minZ < Vector.MINIMUM_RESOLUTION)
|
||||
throw new IllegalArgumentException("Z values in wrong order or identical");
|
||||
|
||||
final double worldMinX = planetModel.getMinimumXValue();
|
||||
final double worldMaxX = planetModel.getMaximumXValue();
|
||||
final double worldMinY = planetModel.getMinimumYValue();
|
||||
final double worldMaxY = planetModel.getMaximumYValue();
|
||||
final double worldMinZ = planetModel.getMinimumZValue();
|
||||
final double worldMaxZ = planetModel.getMaximumZValue();
|
||||
|
||||
// We must distinguish between the case where the solid represents the entire world,
|
||||
// and when the solid has no overlap with any part of the surface. In both cases,
|
||||
// there will be no edgepoints.
|
||||
isWholeWorld =
|
||||
(minX - worldMinX < -Vector.MINIMUM_RESOLUTION) &&
|
||||
(maxX - worldMaxX > Vector.MINIMUM_RESOLUTION) &&
|
||||
(minY - worldMinY < -Vector.MINIMUM_RESOLUTION) &&
|
||||
(maxY - worldMaxY > Vector.MINIMUM_RESOLUTION) &&
|
||||
(minZ - worldMinZ < -Vector.MINIMUM_RESOLUTION) &&
|
||||
(maxZ - worldMaxZ > Vector.MINIMUM_RESOLUTION);
|
||||
|
||||
if (isWholeWorld) {
|
||||
minXPlane = null;
|
||||
maxXPlane = null;
|
||||
minYPlane = null;
|
||||
maxYPlane = null;
|
||||
minZPlane = null;
|
||||
maxZPlane = null;
|
||||
notableMinXPoints = null;
|
||||
notableMaxXPoints = null;
|
||||
notableMinYPoints = null;
|
||||
notableMaxYPoints = null;
|
||||
notableMinZPoints = null;
|
||||
notableMaxZPoints = null;
|
||||
edgePoints = null;
|
||||
} else {
|
||||
// Construct the planes
|
||||
minXPlane = new SidedPlane(maxX,0.0,0.0,xUnitVector,-minX);
|
||||
maxXPlane = new SidedPlane(minX,0.0,0.0,xUnitVector,-maxX);
|
||||
minYPlane = new SidedPlane(0.0,maxY,0.0,yUnitVector,-minY);
|
||||
maxYPlane = new SidedPlane(0.0,minY,0.0,yUnitVector,-maxY);
|
||||
minZPlane = new SidedPlane(0.0,0.0,maxZ,zUnitVector,-minZ);
|
||||
maxZPlane = new SidedPlane(0.0,0.0,minZ,zUnitVector,-maxZ);
|
||||
|
||||
// We need at least one point on the planet surface for each manifestation of the shape.
|
||||
// There can be up to 2 (on opposite sides of the world). But we have to go through
|
||||
// 12 combinations of adjacent planes in order to find out if any have 2 intersection solution.
|
||||
// Typically, this requires 12 square root operations.
|
||||
final GeoPoint[] minXminY = minXPlane.findIntersections(planetModel,minYPlane,maxXPlane,maxYPlane,minZPlane,maxZPlane);
|
||||
final GeoPoint[] minXmaxY = minXPlane.findIntersections(planetModel,maxYPlane,maxXPlane,minYPlane,minZPlane,maxZPlane);
|
||||
final GeoPoint[] minXminZ = minXPlane.findIntersections(planetModel,minZPlane,maxXPlane,maxZPlane,minYPlane,maxYPlane);
|
||||
final GeoPoint[] minXmaxZ = minXPlane.findIntersections(planetModel,maxZPlane,maxXPlane,minZPlane,minYPlane,maxYPlane);
|
||||
|
||||
final GeoPoint[] maxXminY = maxXPlane.findIntersections(planetModel,minYPlane,minXPlane,maxYPlane,minZPlane,maxZPlane);
|
||||
final GeoPoint[] maxXmaxY = maxXPlane.findIntersections(planetModel,maxYPlane,minXPlane,minYPlane,minZPlane,maxZPlane);
|
||||
final GeoPoint[] maxXminZ = maxXPlane.findIntersections(planetModel,minZPlane,minXPlane,maxZPlane,minYPlane,maxYPlane);
|
||||
final GeoPoint[] maxXmaxZ = maxXPlane.findIntersections(planetModel,maxZPlane,minXPlane,minZPlane,minYPlane,maxYPlane);
|
||||
|
||||
final GeoPoint[] minYminZ = minYPlane.findIntersections(planetModel,minZPlane,maxYPlane,maxZPlane,minXPlane,maxXPlane);
|
||||
final GeoPoint[] minYmaxZ = minYPlane.findIntersections(planetModel,maxZPlane,maxYPlane,minZPlane,minXPlane,maxXPlane);
|
||||
final GeoPoint[] maxYminZ = maxYPlane.findIntersections(planetModel,minZPlane,minYPlane,maxZPlane,minXPlane,maxXPlane);
|
||||
final GeoPoint[] maxYmaxZ = maxYPlane.findIntersections(planetModel,maxZPlane,minYPlane,minZPlane,minXPlane,maxXPlane);
|
||||
|
||||
notableMinXPoints = glueTogether(minXminY, minXmaxY, minXminZ, minXmaxZ);
|
||||
notableMaxXPoints = glueTogether(maxXminY, maxXmaxY, maxXminZ, maxXmaxZ);
|
||||
notableMinYPoints = glueTogether(minXminY, maxXminY, minYminZ, minYmaxZ);
|
||||
notableMaxYPoints = glueTogether(minXmaxY, maxXmaxY, maxYminZ, maxYmaxZ);
|
||||
notableMinZPoints = glueTogether(minXminZ, maxXminZ, minYminZ, maxYminZ);
|
||||
notableMaxZPoints = glueTogether(minXmaxZ, maxXmaxZ, minYmaxZ, maxYmaxZ);
|
||||
|
||||
// Now, compute the edge points.
|
||||
// This is the trickiest part of setting up an XYZSolid. We've computed intersections already, so
|
||||
// we'll start there.
|
||||
// There can be a number of shapes, each of which needs an edgepoint. Each side by itself might contribute
|
||||
// an edgepoint, for instance, if the plane describing that side intercepts the planet in such a way that the ellipse
|
||||
// of interception does not meet any other planes. Plane intersections can each contribute 0, 1, or 2 edgepoints.
|
||||
//
|
||||
// All of this makes for a lot of potential edgepoints, but I believe these can be pruned back with careful analysis.
|
||||
// I haven't yet done that analysis, however, so I will treat them all as individual edgepoints.
|
||||
|
||||
// The cases we are looking for are when the four corner points for any given
|
||||
// plane are all outside of the world, AND that plane intersects the world.
|
||||
// There are eight corner points all told; we must evaluate these WRT the planet surface.
|
||||
final boolean minXminYminZ = planetModel.pointOutside(minX, minY, minZ);
|
||||
final boolean minXminYmaxZ = planetModel.pointOutside(minX, minY, maxZ);
|
||||
final boolean minXmaxYminZ = planetModel.pointOutside(minX, maxY, minZ);
|
||||
final boolean minXmaxYmaxZ = planetModel.pointOutside(minX, maxY, maxZ);
|
||||
final boolean maxXminYminZ = planetModel.pointOutside(maxX, minY, minZ);
|
||||
final boolean maxXminYmaxZ = planetModel.pointOutside(maxX, minY, maxZ);
|
||||
final boolean maxXmaxYminZ = planetModel.pointOutside(maxX, maxY, minZ);
|
||||
final boolean maxXmaxYmaxZ = planetModel.pointOutside(maxX, maxY, maxZ);
|
||||
|
||||
// Look at single-plane/world intersections.
|
||||
// We detect these by looking at the world model and noting its x, y, and z bounds.
|
||||
|
||||
final GeoPoint[] minXEdges;
|
||||
if (minX - worldMinX >= -Vector.MINIMUM_RESOLUTION && minX - worldMaxX <= Vector.MINIMUM_RESOLUTION &&
|
||||
minY < 0.0 && maxY > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
|
||||
minXminYminZ && minXminYmaxZ && minXmaxYminZ && minXmaxYmaxZ) {
|
||||
// Find any point on the minX plane that intersects the world
|
||||
// First construct a perpendicular plane that will allow us to find a sample point.
|
||||
// This plane is vertical and goes through the points (0,0,0) and (1,0,0)
|
||||
// Then use it to compute a sample point.
|
||||
final GeoPoint intPoint = minXPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
|
||||
if (intPoint != null) {
|
||||
minXEdges = new GeoPoint[]{intPoint};
|
||||
} else {
|
||||
// No intersection found?
|
||||
minXEdges = EMPTY_POINTS;
|
||||
}
|
||||
} else {
|
||||
minXEdges = EMPTY_POINTS;
|
||||
}
|
||||
|
||||
final GeoPoint[] maxXEdges;
|
||||
if (maxX - worldMinX >= -Vector.MINIMUM_RESOLUTION && maxX - worldMaxX <= Vector.MINIMUM_RESOLUTION &&
|
||||
minY < 0.0 && maxY > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
|
||||
maxXminYminZ && maxXminYmaxZ && maxXmaxYminZ && maxXmaxYmaxZ) {
|
||||
// Find any point on the maxX plane that intersects the world
|
||||
// First construct a perpendicular plane that will allow us to find a sample point.
|
||||
// This plane is vertical and goes through the points (0,0,0) and (1,0,0)
|
||||
// Then use it to compute a sample point.
|
||||
final GeoPoint intPoint = maxXPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
|
||||
if (intPoint != null) {
|
||||
maxXEdges = new GeoPoint[]{intPoint};
|
||||
} else {
|
||||
maxXEdges = EMPTY_POINTS;
|
||||
}
|
||||
} else {
|
||||
maxXEdges = EMPTY_POINTS;
|
||||
}
|
||||
|
||||
final GeoPoint[] minYEdges;
|
||||
if (minY - worldMinY >= -Vector.MINIMUM_RESOLUTION && minY - worldMaxY <= Vector.MINIMUM_RESOLUTION &&
|
||||
minX < 0.0 && maxX > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
|
||||
minXminYminZ && minXminYmaxZ && maxXminYminZ && maxXminYmaxZ) {
|
||||
// Find any point on the minY plane that intersects the world
|
||||
// First construct a perpendicular plane that will allow us to find a sample point.
|
||||
// This plane is vertical and goes through the points (0,0,0) and (0,1,0)
|
||||
// Then use it to compute a sample point.
|
||||
final GeoPoint intPoint = minYPlane.getSampleIntersectionPoint(planetModel, yVerticalPlane);
|
||||
if (intPoint != null) {
|
||||
minYEdges = new GeoPoint[]{intPoint};
|
||||
} else {
|
||||
minYEdges = EMPTY_POINTS;
|
||||
}
|
||||
} else {
|
||||
minYEdges = EMPTY_POINTS;
|
||||
}
|
||||
|
||||
final GeoPoint[] maxYEdges;
|
||||
if (maxY - worldMinY >= -Vector.MINIMUM_RESOLUTION && maxY - worldMaxY <= Vector.MINIMUM_RESOLUTION &&
|
||||
minX < 0.0 && maxX > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
|
||||
minXmaxYminZ && minXmaxYmaxZ && maxXmaxYminZ && maxXmaxYmaxZ) {
|
||||
// Find any point on the maxY plane that intersects the world
|
||||
// First construct a perpendicular plane that will allow us to find a sample point.
|
||||
// This plane is vertical and goes through the points (0,0,0) and (0,1,0)
|
||||
// Then use it to compute a sample point.
|
||||
final GeoPoint intPoint = maxYPlane.getSampleIntersectionPoint(planetModel, yVerticalPlane);
|
||||
if (intPoint != null) {
|
||||
maxYEdges = new GeoPoint[]{intPoint};
|
||||
} else {
|
||||
maxYEdges = EMPTY_POINTS;
|
||||
}
|
||||
} else {
|
||||
maxYEdges = EMPTY_POINTS;
|
||||
}
|
||||
|
||||
final GeoPoint[] minZEdges;
|
||||
if (minZ - worldMinZ >= -Vector.MINIMUM_RESOLUTION && minZ - worldMaxZ <= Vector.MINIMUM_RESOLUTION &&
|
||||
minX < 0.0 && maxX > 0.0 && minY < 0.0 && maxY > 0.0 &&
|
||||
minXminYminZ && minXmaxYminZ && maxXminYminZ && maxXmaxYminZ) {
|
||||
// Find any point on the minZ plane that intersects the world
|
||||
// First construct a perpendicular plane that will allow us to find a sample point.
|
||||
// This plane is vertical and goes through the points (0,0,0) and (1,0,0)
|
||||
// Then use it to compute a sample point.
|
||||
final GeoPoint intPoint = minZPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
|
||||
if (intPoint != null) {
|
||||
minZEdges = new GeoPoint[]{intPoint};
|
||||
} else {
|
||||
minZEdges = EMPTY_POINTS;
|
||||
}
|
||||
} else {
|
||||
minZEdges = EMPTY_POINTS;
|
||||
}
|
||||
|
||||
final GeoPoint[] maxZEdges;
|
||||
if (maxZ - worldMinZ >= -Vector.MINIMUM_RESOLUTION && maxZ - worldMaxZ <= Vector.MINIMUM_RESOLUTION &&
|
||||
minX < 0.0 && maxX > 0.0 && minY < 0.0 && maxY > 0.0 &&
|
||||
minXminYmaxZ && minXmaxYmaxZ && maxXminYmaxZ && maxXmaxYmaxZ) {
|
||||
// Find any point on the maxZ plane that intersects the world
|
||||
// First construct a perpendicular plane that will allow us to find a sample point.
|
||||
// This plane is vertical and goes through the points (0,0,0) and (1,0,0) (that is, its orientation doesn't matter)
|
||||
// Then use it to compute a sample point.
|
||||
final GeoPoint intPoint = maxZPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
|
||||
if (intPoint != null) {
|
||||
maxZEdges = new GeoPoint[]{intPoint};
|
||||
} else {
|
||||
maxZEdges = EMPTY_POINTS;
|
||||
}
|
||||
} else {
|
||||
maxZEdges = EMPTY_POINTS;
|
||||
}
|
||||
|
||||
// Glue everything together. This is not a minimal set of edgepoints, as of now, but it does completely describe all shapes on the
|
||||
// planet.
|
||||
this.edgePoints = glueTogether(minXminY, minXmaxY, minXminZ, minXmaxZ,
|
||||
maxXminY, maxXmaxY, maxXminZ, maxXmaxZ,
|
||||
minYminZ, minYmaxZ, maxYminZ, maxYmaxZ,
|
||||
minXEdges, maxXEdges, minYEdges, maxYEdges, minZEdges, maxZEdges);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GeoPoint[] getEdgePoints() {
|
||||
return edgePoints;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWithin(final double x, final double y, final double z) {
|
||||
if (isWholeWorld) {
|
||||
return true;
|
||||
}
|
||||
return minXPlane.isWithin(x, y, z) &&
|
||||
maxXPlane.isWithin(x, y, z) &&
|
||||
minYPlane.isWithin(x, y, z) &&
|
||||
maxYPlane.isWithin(x, y, z) &&
|
||||
minZPlane.isWithin(x, y, z) &&
|
||||
maxZPlane.isWithin(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRelationship(final GeoShape path) {
|
||||
if (isWholeWorld) {
|
||||
if (path.getEdgePoints().length > 0)
|
||||
return WITHIN;
|
||||
return OVERLAPS;
|
||||
}
|
||||
|
||||
/*
|
||||
for (GeoPoint p : getEdgePoints()) {
|
||||
System.err.println(" Edge point "+p+" path.isWithin()? "+path.isWithin(p));
|
||||
}
|
||||
|
||||
for (GeoPoint p : path.getEdgePoints()) {
|
||||
System.err.println(" path edge point "+p+" isWithin()? "+isWithin(p)+" minx="+minXPlane.evaluate(p)+" maxx="+maxXPlane.evaluate(p)+" miny="+minYPlane.evaluate(p)+" maxy="+maxYPlane.evaluate(p)+" minz="+minZPlane.evaluate(p)+" maxz="+maxZPlane.evaluate(p));
|
||||
}
|
||||
*/
|
||||
|
||||
//System.err.println(this+" getrelationship with "+path);
|
||||
final int insideRectangle = isShapeInsideArea(path);
|
||||
if (insideRectangle == SOME_INSIDE) {
|
||||
//System.err.println(" some shape points inside area");
|
||||
return OVERLAPS;
|
||||
}
|
||||
|
||||
// Figure out if the entire XYZArea is contained by the shape.
|
||||
final int insideShape = isAreaInsideShape(path);
|
||||
if (insideShape == SOME_INSIDE) {
|
||||
//System.err.println(" some area points inside shape");
|
||||
return OVERLAPS;
|
||||
}
|
||||
|
||||
if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
|
||||
//System.err.println(" inside of each other");
|
||||
return OVERLAPS;
|
||||
}
|
||||
|
||||
if (path.intersects(minXPlane, notableMinXPoints, maxXPlane, minYPlane, maxYPlane, minZPlane, maxZPlane) ||
|
||||
path.intersects(maxXPlane, notableMaxXPoints, minXPlane, minYPlane, maxYPlane, minZPlane, maxZPlane) ||
|
||||
path.intersects(minYPlane, notableMinYPoints, maxYPlane, minXPlane, maxXPlane, minZPlane, maxZPlane) ||
|
||||
path.intersects(maxYPlane, notableMaxYPoints, minYPlane, minXPlane, maxXPlane, minZPlane, maxZPlane) ||
|
||||
path.intersects(minZPlane, notableMinZPoints, maxZPlane, minXPlane, maxXPlane, minYPlane, maxYPlane) ||
|
||||
path.intersects(maxZPlane, notableMaxZPoints, minZPlane, minXPlane, maxXPlane, minYPlane, maxYPlane)) {
|
||||
//System.err.println(" edges intersect");
|
||||
return OVERLAPS;
|
||||
}
|
||||
|
||||
if (insideRectangle == ALL_INSIDE) {
|
||||
//System.err.println(" all shape points inside area");
|
||||
return WITHIN;
|
||||
}
|
||||
|
||||
if (insideShape == ALL_INSIDE) {
|
||||
//System.err.println(" all area points inside shape");
|
||||
return CONTAINS;
|
||||
}
|
||||
//System.err.println(" disjoint");
|
||||
return DISJOINT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof StandardXYZSolid))
|
||||
return false;
|
||||
StandardXYZSolid other = (StandardXYZSolid) o;
|
||||
if (!super.equals(other) ||
|
||||
other.isWholeWorld != isWholeWorld) {
|
||||
return false;
|
||||
}
|
||||
if (!isWholeWorld) {
|
||||
return other.minXPlane.equals(minXPlane) &&
|
||||
other.maxXPlane.equals(maxXPlane) &&
|
||||
other.minYPlane.equals(minYPlane) &&
|
||||
other.maxYPlane.equals(maxYPlane) &&
|
||||
other.minZPlane.equals(minZPlane) &&
|
||||
other.maxZPlane.equals(maxZPlane);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + (isWholeWorld?1:0);
|
||||
if (!isWholeWorld) {
|
||||
result = 31 * result + minXPlane.hashCode();
|
||||
result = 31 * result + maxXPlane.hashCode();
|
||||
result = 31 * result + minYPlane.hashCode();
|
||||
result = 31 * result + maxYPlane.hashCode();
|
||||
result = 31 * result + minZPlane.hashCode();
|
||||
result = 31 * result + maxZPlane.hashCode();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StandardXYZSolid: {planetmodel="+planetModel+", isWholeWorld="+isWholeWorld+", minXplane="+minXPlane+", maxXplane="+maxXPlane+", minYplane="+minYPlane+", maxYplane="+maxYPlane+", minZplane="+minZPlane+", maxZplane="+maxZPlane+"}";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -18,401 +18,10 @@ package org.apache.lucene.geo3d;
|
|||
*/
|
||||
|
||||
/**
|
||||
* 3D rectangle, bounded on six sides by X,Y,Z limits
|
||||
* Interface for a family of 3D rectangles, bounded on six sides by X,Y,Z limits
|
||||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class XYZSolid extends BaseXYZSolid {
|
||||
|
||||
/** Whole world? */
|
||||
protected final boolean isWholeWorld;
|
||||
/** Min-X plane */
|
||||
protected final SidedPlane minXPlane;
|
||||
/** Max-X plane */
|
||||
protected final SidedPlane maxXPlane;
|
||||
/** Min-Y plane */
|
||||
protected final SidedPlane minYPlane;
|
||||
/** Max-Y plane */
|
||||
protected final SidedPlane maxYPlane;
|
||||
/** Min-Z plane */
|
||||
protected final SidedPlane minZPlane;
|
||||
/** Max-Z plane */
|
||||
protected final SidedPlane maxZPlane;
|
||||
|
||||
/** These are the edge points of the shape, which are defined to be at least one point on
|
||||
* each surface area boundary. In the case of a solid, this includes points which represent
|
||||
* the intersection of XYZ bounding planes and the planet, as well as points representing
|
||||
* the intersection of single bounding planes with the planet itself.
|
||||
*/
|
||||
protected final GeoPoint[] edgePoints;
|
||||
|
||||
/** Notable points for minXPlane */
|
||||
protected final GeoPoint[] notableMinXPoints;
|
||||
/** Notable points for maxXPlane */
|
||||
protected final GeoPoint[] notableMaxXPoints;
|
||||
/** Notable points for minYPlane */
|
||||
protected final GeoPoint[] notableMinYPoints;
|
||||
/** Notable points for maxYPlane */
|
||||
protected final GeoPoint[] notableMaxYPoints;
|
||||
/** Notable points for minZPlane */
|
||||
protected final GeoPoint[] notableMinZPoints;
|
||||
/** Notable points for maxZPlane */
|
||||
protected final GeoPoint[] notableMaxZPoints;
|
||||
|
||||
/**
|
||||
* Sole constructor
|
||||
*
|
||||
*@param planetModel is the planet model.
|
||||
*@param minX is the minimum X value.
|
||||
*@param maxX is the maximum X value.
|
||||
*@param minY is the minimum Y value.
|
||||
*@param maxY is the maximum Y value.
|
||||
*@param minZ is the minimum Z value.
|
||||
*@param maxZ is the maximum Z value.
|
||||
*/
|
||||
public XYZSolid(final PlanetModel planetModel,
|
||||
final double minX,
|
||||
final double maxX,
|
||||
final double minY,
|
||||
final double maxY,
|
||||
final double minZ,
|
||||
final double maxZ) {
|
||||
super(planetModel);
|
||||
// Argument checking
|
||||
if (maxX - minX < Vector.MINIMUM_RESOLUTION)
|
||||
throw new IllegalArgumentException("X values in wrong order or identical");
|
||||
if (maxY - minY < Vector.MINIMUM_RESOLUTION)
|
||||
throw new IllegalArgumentException("Y values in wrong order or identical");
|
||||
if (maxZ - minZ < Vector.MINIMUM_RESOLUTION)
|
||||
throw new IllegalArgumentException("Z values in wrong order or identical");
|
||||
|
||||
final double worldMinX = planetModel.getMinimumXValue();
|
||||
final double worldMaxX = planetModel.getMaximumXValue();
|
||||
final double worldMinY = planetModel.getMinimumYValue();
|
||||
final double worldMaxY = planetModel.getMaximumYValue();
|
||||
final double worldMinZ = planetModel.getMinimumZValue();
|
||||
final double worldMaxZ = planetModel.getMaximumZValue();
|
||||
|
||||
// We must distinguish between the case where the solid represents the entire world,
|
||||
// and when the solid has no overlap with any part of the surface. In both cases,
|
||||
// there will be no edgepoints.
|
||||
isWholeWorld =
|
||||
(minX - worldMinX < -Vector.MINIMUM_RESOLUTION) &&
|
||||
(maxX - worldMaxX > Vector.MINIMUM_RESOLUTION) &&
|
||||
(minY - worldMinY < -Vector.MINIMUM_RESOLUTION) &&
|
||||
(maxY - worldMaxY > Vector.MINIMUM_RESOLUTION) &&
|
||||
(minZ - worldMinZ < -Vector.MINIMUM_RESOLUTION) &&
|
||||
(maxZ - worldMaxZ > Vector.MINIMUM_RESOLUTION);
|
||||
|
||||
if (isWholeWorld) {
|
||||
minXPlane = null;
|
||||
maxXPlane = null;
|
||||
minYPlane = null;
|
||||
maxYPlane = null;
|
||||
minZPlane = null;
|
||||
maxZPlane = null;
|
||||
notableMinXPoints = null;
|
||||
notableMaxXPoints = null;
|
||||
notableMinYPoints = null;
|
||||
notableMaxYPoints = null;
|
||||
notableMinZPoints = null;
|
||||
notableMaxZPoints = null;
|
||||
edgePoints = null;
|
||||
} else {
|
||||
// Construct the planes
|
||||
minXPlane = new SidedPlane(maxX,0.0,0.0,xUnitVector,-minX);
|
||||
maxXPlane = new SidedPlane(minX,0.0,0.0,xUnitVector,-maxX);
|
||||
minYPlane = new SidedPlane(0.0,maxY,0.0,yUnitVector,-minY);
|
||||
maxYPlane = new SidedPlane(0.0,minY,0.0,yUnitVector,-maxY);
|
||||
minZPlane = new SidedPlane(0.0,0.0,maxZ,zUnitVector,-minZ);
|
||||
maxZPlane = new SidedPlane(0.0,0.0,minZ,zUnitVector,-maxZ);
|
||||
|
||||
// We need at least one point on the planet surface for each manifestation of the shape.
|
||||
// There can be up to 2 (on opposite sides of the world). But we have to go through
|
||||
// 12 combinations of adjacent planes in order to find out if any have 2 intersection solution.
|
||||
// Typically, this requires 12 square root operations.
|
||||
final GeoPoint[] minXminY = minXPlane.findIntersections(planetModel,minYPlane,maxXPlane,maxYPlane,minZPlane,maxZPlane);
|
||||
final GeoPoint[] minXmaxY = minXPlane.findIntersections(planetModel,maxYPlane,maxXPlane,minYPlane,minZPlane,maxZPlane);
|
||||
final GeoPoint[] minXminZ = minXPlane.findIntersections(planetModel,minZPlane,maxXPlane,maxZPlane,minYPlane,maxYPlane);
|
||||
final GeoPoint[] minXmaxZ = minXPlane.findIntersections(planetModel,maxZPlane,maxXPlane,minZPlane,minYPlane,maxYPlane);
|
||||
|
||||
final GeoPoint[] maxXminY = maxXPlane.findIntersections(planetModel,minYPlane,minXPlane,maxYPlane,minZPlane,maxZPlane);
|
||||
final GeoPoint[] maxXmaxY = maxXPlane.findIntersections(planetModel,maxYPlane,minXPlane,minYPlane,minZPlane,maxZPlane);
|
||||
final GeoPoint[] maxXminZ = maxXPlane.findIntersections(planetModel,minZPlane,minXPlane,maxZPlane,minYPlane,maxYPlane);
|
||||
final GeoPoint[] maxXmaxZ = maxXPlane.findIntersections(planetModel,maxZPlane,minXPlane,minZPlane,minYPlane,maxYPlane);
|
||||
|
||||
final GeoPoint[] minYminZ = minYPlane.findIntersections(planetModel,minZPlane,maxYPlane,maxZPlane,minXPlane,maxXPlane);
|
||||
final GeoPoint[] minYmaxZ = minYPlane.findIntersections(planetModel,maxZPlane,maxYPlane,minZPlane,minXPlane,maxXPlane);
|
||||
final GeoPoint[] maxYminZ = maxYPlane.findIntersections(planetModel,minZPlane,minYPlane,maxZPlane,minXPlane,maxXPlane);
|
||||
final GeoPoint[] maxYmaxZ = maxYPlane.findIntersections(planetModel,maxZPlane,minYPlane,minZPlane,minXPlane,maxXPlane);
|
||||
|
||||
notableMinXPoints = glueTogether(minXminY, minXmaxY, minXminZ, minXmaxZ);
|
||||
notableMaxXPoints = glueTogether(maxXminY, maxXmaxY, maxXminZ, maxXmaxZ);
|
||||
notableMinYPoints = glueTogether(minXminY, maxXminY, minYminZ, minYmaxZ);
|
||||
notableMaxYPoints = glueTogether(minXmaxY, maxXmaxY, maxYminZ, maxYmaxZ);
|
||||
notableMinZPoints = glueTogether(minXminZ, maxXminZ, minYminZ, maxYminZ);
|
||||
notableMaxZPoints = glueTogether(minXmaxZ, maxXmaxZ, minYmaxZ, maxYmaxZ);
|
||||
|
||||
// Now, compute the edge points.
|
||||
// This is the trickiest part of setting up an XYZSolid. We've computed intersections already, so
|
||||
// we'll start there.
|
||||
// There can be a number of shapes, each of which needs an edgepoint. Each side by itself might contribute
|
||||
// an edgepoint, for instance, if the plane describing that side intercepts the planet in such a way that the ellipse
|
||||
// of interception does not meet any other planes. Plane intersections can each contribute 0, 1, or 2 edgepoints.
|
||||
//
|
||||
// All of this makes for a lot of potential edgepoints, but I believe these can be pruned back with careful analysis.
|
||||
// I haven't yet done that analysis, however, so I will treat them all as individual edgepoints.
|
||||
|
||||
// The cases we are looking for are when the four corner points for any given
|
||||
// plane are all outside of the world, AND that plane intersects the world.
|
||||
// There are eight corner points all told; we must evaluate these WRT the planet surface.
|
||||
final boolean minXminYminZ = planetModel.pointOutside(minX, minY, minZ);
|
||||
final boolean minXminYmaxZ = planetModel.pointOutside(minX, minY, maxZ);
|
||||
final boolean minXmaxYminZ = planetModel.pointOutside(minX, maxY, minZ);
|
||||
final boolean minXmaxYmaxZ = planetModel.pointOutside(minX, maxY, maxZ);
|
||||
final boolean maxXminYminZ = planetModel.pointOutside(maxX, minY, minZ);
|
||||
final boolean maxXminYmaxZ = planetModel.pointOutside(maxX, minY, maxZ);
|
||||
final boolean maxXmaxYminZ = planetModel.pointOutside(maxX, maxY, minZ);
|
||||
final boolean maxXmaxYmaxZ = planetModel.pointOutside(maxX, maxY, maxZ);
|
||||
|
||||
// Look at single-plane/world intersections.
|
||||
// We detect these by looking at the world model and noting its x, y, and z bounds.
|
||||
|
||||
final GeoPoint[] minXEdges;
|
||||
if (minX - worldMinX >= -Vector.MINIMUM_RESOLUTION && minX - worldMaxX <= Vector.MINIMUM_RESOLUTION &&
|
||||
minY < 0.0 && maxY > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
|
||||
minXminYminZ && minXminYmaxZ && minXmaxYminZ && minXmaxYmaxZ) {
|
||||
// Find any point on the minX plane that intersects the world
|
||||
// First construct a perpendicular plane that will allow us to find a sample point.
|
||||
// This plane is vertical and goes through the points (0,0,0) and (1,0,0)
|
||||
// Then use it to compute a sample point.
|
||||
final GeoPoint intPoint = minXPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
|
||||
if (intPoint != null) {
|
||||
minXEdges = new GeoPoint[]{intPoint};
|
||||
} else {
|
||||
// No intersection found?
|
||||
minXEdges = EMPTY_POINTS;
|
||||
}
|
||||
} else {
|
||||
minXEdges = EMPTY_POINTS;
|
||||
}
|
||||
|
||||
final GeoPoint[] maxXEdges;
|
||||
if (maxX - worldMinX >= -Vector.MINIMUM_RESOLUTION && maxX - worldMaxX <= Vector.MINIMUM_RESOLUTION &&
|
||||
minY < 0.0 && maxY > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
|
||||
maxXminYminZ && maxXminYmaxZ && maxXmaxYminZ && maxXmaxYmaxZ) {
|
||||
// Find any point on the maxX plane that intersects the world
|
||||
// First construct a perpendicular plane that will allow us to find a sample point.
|
||||
// This plane is vertical and goes through the points (0,0,0) and (1,0,0)
|
||||
// Then use it to compute a sample point.
|
||||
final GeoPoint intPoint = maxXPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
|
||||
if (intPoint != null) {
|
||||
maxXEdges = new GeoPoint[]{intPoint};
|
||||
} else {
|
||||
maxXEdges = EMPTY_POINTS;
|
||||
}
|
||||
} else {
|
||||
maxXEdges = EMPTY_POINTS;
|
||||
}
|
||||
|
||||
final GeoPoint[] minYEdges;
|
||||
if (minY - worldMinY >= -Vector.MINIMUM_RESOLUTION && minY - worldMaxY <= Vector.MINIMUM_RESOLUTION &&
|
||||
minX < 0.0 && maxX > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
|
||||
minXminYminZ && minXminYmaxZ && maxXminYminZ && maxXminYmaxZ) {
|
||||
// Find any point on the minY plane that intersects the world
|
||||
// First construct a perpendicular plane that will allow us to find a sample point.
|
||||
// This plane is vertical and goes through the points (0,0,0) and (0,1,0)
|
||||
// Then use it to compute a sample point.
|
||||
final GeoPoint intPoint = minYPlane.getSampleIntersectionPoint(planetModel, yVerticalPlane);
|
||||
if (intPoint != null) {
|
||||
minYEdges = new GeoPoint[]{intPoint};
|
||||
} else {
|
||||
minYEdges = EMPTY_POINTS;
|
||||
}
|
||||
} else {
|
||||
minYEdges = EMPTY_POINTS;
|
||||
}
|
||||
|
||||
final GeoPoint[] maxYEdges;
|
||||
if (maxY - worldMinY >= -Vector.MINIMUM_RESOLUTION && maxY - worldMaxY <= Vector.MINIMUM_RESOLUTION &&
|
||||
minX < 0.0 && maxX > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
|
||||
minXmaxYminZ && minXmaxYmaxZ && maxXmaxYminZ && maxXmaxYmaxZ) {
|
||||
// Find any point on the maxY plane that intersects the world
|
||||
// First construct a perpendicular plane that will allow us to find a sample point.
|
||||
// This plane is vertical and goes through the points (0,0,0) and (0,1,0)
|
||||
// Then use it to compute a sample point.
|
||||
final GeoPoint intPoint = maxYPlane.getSampleIntersectionPoint(planetModel, yVerticalPlane);
|
||||
if (intPoint != null) {
|
||||
maxYEdges = new GeoPoint[]{intPoint};
|
||||
} else {
|
||||
maxYEdges = EMPTY_POINTS;
|
||||
}
|
||||
} else {
|
||||
maxYEdges = EMPTY_POINTS;
|
||||
}
|
||||
|
||||
final GeoPoint[] minZEdges;
|
||||
if (minZ - worldMinZ >= -Vector.MINIMUM_RESOLUTION && minZ - worldMaxZ <= Vector.MINIMUM_RESOLUTION &&
|
||||
minX < 0.0 && maxX > 0.0 && minY < 0.0 && maxY > 0.0 &&
|
||||
minXminYminZ && minXmaxYminZ && maxXminYminZ && maxXmaxYminZ) {
|
||||
// Find any point on the minZ plane that intersects the world
|
||||
// First construct a perpendicular plane that will allow us to find a sample point.
|
||||
// This plane is vertical and goes through the points (0,0,0) and (1,0,0)
|
||||
// Then use it to compute a sample point.
|
||||
final GeoPoint intPoint = minZPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
|
||||
if (intPoint != null) {
|
||||
minZEdges = new GeoPoint[]{intPoint};
|
||||
} else {
|
||||
minZEdges = EMPTY_POINTS;
|
||||
}
|
||||
} else {
|
||||
minZEdges = EMPTY_POINTS;
|
||||
}
|
||||
|
||||
final GeoPoint[] maxZEdges;
|
||||
if (maxZ - worldMinZ >= -Vector.MINIMUM_RESOLUTION && maxZ - worldMaxZ <= Vector.MINIMUM_RESOLUTION &&
|
||||
minX < 0.0 && maxX > 0.0 && minY < 0.0 && maxY > 0.0 &&
|
||||
minXminYmaxZ && minXmaxYmaxZ && maxXminYmaxZ && maxXmaxYmaxZ) {
|
||||
// Find any point on the maxZ plane that intersects the world
|
||||
// First construct a perpendicular plane that will allow us to find a sample point.
|
||||
// This plane is vertical and goes through the points (0,0,0) and (1,0,0) (that is, its orientation doesn't matter)
|
||||
// Then use it to compute a sample point.
|
||||
final GeoPoint intPoint = maxZPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
|
||||
if (intPoint != null) {
|
||||
maxZEdges = new GeoPoint[]{intPoint};
|
||||
} else {
|
||||
maxZEdges = EMPTY_POINTS;
|
||||
}
|
||||
} else {
|
||||
maxZEdges = EMPTY_POINTS;
|
||||
}
|
||||
|
||||
// Glue everything together. This is not a minimal set of edgepoints, as of now, but it does completely describe all shapes on the
|
||||
// planet.
|
||||
this.edgePoints = glueTogether(minXminY, minXmaxY, minXminZ, minXmaxZ,
|
||||
maxXminY, maxXmaxY, maxXminZ, maxXmaxZ,
|
||||
minYminZ, minYmaxZ, maxYminZ, maxYmaxZ,
|
||||
minXEdges, maxXEdges, minYEdges, maxYEdges, minZEdges, maxZEdges);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GeoPoint[] getEdgePoints() {
|
||||
return edgePoints;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWithin(final double x, final double y, final double z) {
|
||||
if (isWholeWorld) {
|
||||
return true;
|
||||
}
|
||||
return minXPlane.isWithin(x, y, z) &&
|
||||
maxXPlane.isWithin(x, y, z) &&
|
||||
minYPlane.isWithin(x, y, z) &&
|
||||
maxYPlane.isWithin(x, y, z) &&
|
||||
minZPlane.isWithin(x, y, z) &&
|
||||
maxZPlane.isWithin(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRelationship(final GeoShape path) {
|
||||
if (isWholeWorld) {
|
||||
if (path.getEdgePoints().length > 0)
|
||||
return WITHIN;
|
||||
return OVERLAPS;
|
||||
}
|
||||
|
||||
/*
|
||||
for (GeoPoint p : getEdgePoints()) {
|
||||
System.err.println(" Edge point "+p+" path.isWithin()? "+path.isWithin(p));
|
||||
}
|
||||
|
||||
for (GeoPoint p : path.getEdgePoints()) {
|
||||
System.err.println(" path edge point "+p+" isWithin()? "+isWithin(p)+" minx="+minXPlane.evaluate(p)+" maxx="+maxXPlane.evaluate(p)+" miny="+minYPlane.evaluate(p)+" maxy="+maxYPlane.evaluate(p)+" minz="+minZPlane.evaluate(p)+" maxz="+maxZPlane.evaluate(p));
|
||||
}
|
||||
*/
|
||||
|
||||
//System.err.println(this+" getrelationship with "+path);
|
||||
final int insideRectangle = isShapeInsideArea(path);
|
||||
if (insideRectangle == SOME_INSIDE) {
|
||||
//System.err.println(" some shape points inside area");
|
||||
return OVERLAPS;
|
||||
}
|
||||
|
||||
// Figure out if the entire XYZArea is contained by the shape.
|
||||
final int insideShape = isAreaInsideShape(path);
|
||||
if (insideShape == SOME_INSIDE) {
|
||||
//System.err.println(" some area points inside shape");
|
||||
return OVERLAPS;
|
||||
}
|
||||
|
||||
if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
|
||||
//System.err.println(" inside of each other");
|
||||
return OVERLAPS;
|
||||
}
|
||||
|
||||
if (path.intersects(minXPlane, notableMinXPoints, maxXPlane, minYPlane, maxYPlane, minZPlane, maxZPlane) ||
|
||||
path.intersects(maxXPlane, notableMaxXPoints, minXPlane, minYPlane, maxYPlane, minZPlane, maxZPlane) ||
|
||||
path.intersects(minYPlane, notableMinYPoints, maxYPlane, minXPlane, maxXPlane, minZPlane, maxZPlane) ||
|
||||
path.intersects(maxYPlane, notableMaxYPoints, minYPlane, minXPlane, maxXPlane, minZPlane, maxZPlane) ||
|
||||
path.intersects(minZPlane, notableMinZPoints, maxZPlane, minXPlane, maxXPlane, minYPlane, maxYPlane) ||
|
||||
path.intersects(maxZPlane, notableMaxZPoints, minZPlane, minXPlane, maxXPlane, minYPlane, maxYPlane)) {
|
||||
//System.err.println(" edges intersect");
|
||||
return OVERLAPS;
|
||||
}
|
||||
|
||||
if (insideRectangle == ALL_INSIDE) {
|
||||
//System.err.println(" all shape points inside area");
|
||||
return WITHIN;
|
||||
}
|
||||
|
||||
if (insideShape == ALL_INSIDE) {
|
||||
//System.err.println(" all area points inside shape");
|
||||
return CONTAINS;
|
||||
}
|
||||
//System.err.println(" disjoint");
|
||||
return DISJOINT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof XYZSolid))
|
||||
return false;
|
||||
XYZSolid other = (XYZSolid) o;
|
||||
if (!super.equals(other) ||
|
||||
other.isWholeWorld != isWholeWorld) {
|
||||
return false;
|
||||
}
|
||||
if (!isWholeWorld) {
|
||||
return other.minXPlane.equals(minXPlane) &&
|
||||
other.maxXPlane.equals(maxXPlane) &&
|
||||
other.minYPlane.equals(minYPlane) &&
|
||||
other.maxYPlane.equals(maxYPlane) &&
|
||||
other.minZPlane.equals(minZPlane) &&
|
||||
other.maxZPlane.equals(maxZPlane);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + (isWholeWorld?1:0);
|
||||
if (!isWholeWorld) {
|
||||
result = 31 * result + minXPlane.hashCode();
|
||||
result = 31 * result + maxXPlane.hashCode();
|
||||
result = 31 * result + minYPlane.hashCode();
|
||||
result = 31 * result + maxYPlane.hashCode();
|
||||
result = 31 * result + minZPlane.hashCode();
|
||||
result = 31 * result + maxZPlane.hashCode();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "XYZSolid: {planetmodel="+planetModel+", isWholeWorld="+isWholeWorld+", minXplane="+minXPlane+", maxXplane="+maxXPlane+", minYplane="+minYPlane+", maxYplane="+maxYPlane+", minZplane="+minZPlane+", maxZplane="+maxZPlane+"}";
|
||||
}
|
||||
|
||||
public interface XYZSolid extends GeoArea {
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package org.apache.lucene.geo3d;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Factory for {@link org.apache.lucene.geo3d.XYZSolid}.
|
||||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public class XYZSolidFactory {
|
||||
private XYZSolidFactory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a XYZSolid of the right kind given (x,y,z) bounds.
|
||||
* @param planetModel is the planet model
|
||||
* @param minX is the min X boundary
|
||||
* @param maxX is the max X boundary
|
||||
* @param minY is the min Y boundary
|
||||
* @param maxY is the max Y boundary
|
||||
* @param minZ is the min Z boundary
|
||||
* @param maxZ is the max Z boundary
|
||||
*/
|
||||
public static XYZSolid makeXYZSolid(final PlanetModel planetModel, final double minX, final double maxX, final double minY, final double maxY, final double minZ, final double maxZ) {
|
||||
if (Math.abs(maxX - minX) < Vector.MINIMUM_RESOLUTION) {
|
||||
if (Math.abs(maxY - minY) < Vector.MINIMUM_RESOLUTION) {
|
||||
if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
|
||||
return new dXdYdZSolid(planetModel, (minX+maxX) * 0.5, (minY+maxY) * 0.5, minZ);
|
||||
} else {
|
||||
return new dXdYZSolid(planetModel, (minX+maxX) * 0.5, (minY+maxY) * 0.5, minZ, maxZ);
|
||||
}
|
||||
} else {
|
||||
if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
|
||||
return new dXYdZSolid(planetModel, (minX+maxX) * 0.5, minY, maxY, (minZ+maxZ) * 0.5);
|
||||
} else {
|
||||
return new dXYZSolid(planetModel, (minX+maxX) * 0.5, minY, maxY, minZ, maxZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Math.abs(maxY - minY) < Vector.MINIMUM_RESOLUTION) {
|
||||
if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
|
||||
return new XdYdZSolid(planetModel, minX, maxX, (minY+maxY) * 0.5, (minZ+maxZ) * 0.5);
|
||||
} else {
|
||||
return new XdYZSolid(planetModel, minX, maxX, (minY+maxY) * 0.5, minZ, maxZ);
|
||||
}
|
||||
}
|
||||
if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
|
||||
return new XYdZSolid(planetModel, minX, maxX, minY, maxY, (minZ+maxZ) * 0.5);
|
||||
}
|
||||
return new StandardXYZSolid(planetModel, minX, maxX, minY, maxY, minZ, maxZ);
|
||||
}
|
||||
|
||||
}
|
|
@ -27,7 +27,7 @@ public class XYZSolidTest extends LuceneTestCase {
|
|||
XYZSolid s;
|
||||
GeoShape shape;
|
||||
// Something bigger than the world
|
||||
s = new XYZSolid(PlanetModel.SPHERE, -2.0, 2.0, -2.0, 2.0, -2.0, 2.0);
|
||||
s = new StandardXYZSolid(PlanetModel.SPHERE, -2.0, 2.0, -2.0, 2.0, -2.0, 2.0);
|
||||
// Any shape, except whole world, should be within.
|
||||
shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
|
||||
assertEquals(GeoArea.WITHIN, s.getRelationship(shape));
|
||||
|
@ -37,7 +37,7 @@ public class XYZSolidTest extends LuceneTestCase {
|
|||
assertEquals(GeoArea.OVERLAPS, s.getRelationship(shape));
|
||||
|
||||
// Something overlapping the world on only one side
|
||||
s = new XYZSolid(PlanetModel.SPHERE, -2.0, 0.0, -2.0, 2.0, -2.0, 2.0);
|
||||
s = new StandardXYZSolid(PlanetModel.SPHERE, -2.0, 0.0, -2.0, 2.0, -2.0, 2.0);
|
||||
// Some things should be disjoint...
|
||||
shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
|
||||
assertEquals(GeoArea.DISJOINT, s.getRelationship(shape));
|
||||
|
@ -53,7 +53,7 @@ public class XYZSolidTest extends LuceneTestCase {
|
|||
assertEquals(GeoArea.CONTAINS, s.getRelationship(shape));
|
||||
|
||||
// Something inside the world
|
||||
s = new XYZSolid(PlanetModel.SPHERE, -0.1, 0.1, -0.1, 0.1, -0.1, 0.1);
|
||||
s = new StandardXYZSolid(PlanetModel.SPHERE, -0.1, 0.1, -0.1, 0.1, -0.1, 0.1);
|
||||
// All shapes should be disjoint
|
||||
shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
|
||||
assertEquals(GeoArea.DISJOINT, s.getRelationship(shape));
|
||||
|
|
Loading…
Reference in New Issue