in lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/StandardXYZSolid.java [124:458]
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");
this.minX = minX;
this.maxX = maxX;
this.minY = minY;
this.maxY = maxY;
this.minZ = minZ;
this.maxZ = maxZ;
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;
minXPlaneIntersects = false;
maxXPlaneIntersects = false;
minYPlaneIntersects = false;
maxYPlaneIntersects = false;
minZPlaneIntersects = false;
maxZPlaneIntersects = false;
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);
// System.err.println(
// " notableMinXPoints="+Arrays.asList(notableMinXPoints)+"
// notableMaxXPoints="+Arrays.asList(notableMaxXPoints)+
// " notableMinYPoints="+Arrays.asList(notableMinYPoints)+"
// notableMaxYPoints="+Arrays.asList(notableMaxYPoints)+
// " notableMinZPoints="+Arrays.asList(notableMinZPoints)+"
// notableMaxZPoints="+Arrays.asList(notableMaxZPoints));
// 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);
// System.err.println("Outside world: minXminYminZ="+minXminYminZ+"
// minXminYmaxZ="+minXminYmaxZ+" minXmaxYminZ="+minXmaxYminZ+
// " minXmaxYmaxZ="+minXmaxYmaxZ+" maxXminYminZ="+maxXminYminZ+"
// maxXminYmaxZ="+maxXminYmaxZ+" maxXmaxYminZ="+maxXmaxYminZ+
// " maxXmaxYmaxZ="+maxXmaxYmaxZ);
// 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;
}
// System.err.println(
// " minXEdges="+Arrays.asList(minXEdges)+" maxXEdges="+Arrays.asList(maxXEdges)+
// " minYEdges="+Arrays.asList(minYEdges)+" maxYEdges="+Arrays.asList(maxYEdges)+
// " minZEdges="+Arrays.asList(minZEdges)+" maxZEdges="+Arrays.asList(maxZEdges));
minXPlaneIntersects = notableMinXPoints.length + minXEdges.length > 0;
maxXPlaneIntersects = notableMaxXPoints.length + maxXEdges.length > 0;
minYPlaneIntersects = notableMinYPoints.length + minYEdges.length > 0;
maxYPlaneIntersects = notableMaxYPoints.length + maxYEdges.length > 0;
minZPlaneIntersects = notableMinZPoints.length + minZEdges.length > 0;
maxZPlaneIntersects = notableMaxZPoints.length + maxZEdges.length > 0;
// 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);
}
}