| /* |
| * 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; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| |
| /** |
| * Fast implementation of a polygon representing S2 geometry cell. There are no checks validating that |
| * points are convex therefore users must be provide four points in CCW or the logic will fail. |
| * |
| * @lucene.internal |
| */ |
| class GeoS2Shape extends GeoBasePolygon { |
| |
| /** The first point */ |
| protected final GeoPoint point1; |
| /** The second point */ |
| protected final GeoPoint point2; |
| /** The third point */ |
| protected final GeoPoint point3; |
| /** The fourth point */ |
| protected final GeoPoint point4; |
| |
| /** The first plane */ |
| protected final SidedPlane plane1; |
| /** The second plane */ |
| protected final SidedPlane plane2; |
| /** The third plane */ |
| protected final SidedPlane plane3; |
| /** The fourth plane */ |
| protected final SidedPlane plane4; |
| |
| /** Notable points for the first plane */ |
| protected final GeoPoint[] plane1Points; |
| /** Notable points for second plane */ |
| protected final GeoPoint[] plane2Points; |
| /** Notable points for third plane */ |
| protected final GeoPoint[] plane3Points; |
| /** Notable points for fourth plane */ |
| protected final GeoPoint[] plane4Points; |
| |
| /** Edge point for this S2 cell */ |
| protected final GeoPoint[] edgePoints; |
| |
| /** |
| * It builds from 4 points given in CCW. It must be convex or logic will fail. |
| * |
| *@param planetModel is the planet model. |
| *@param point1 the first point. |
| *@param point2 the second point. |
| *@param point3 the third point. |
| *@param point4 the four point. |
| */ |
| public GeoS2Shape(final PlanetModel planetModel, GeoPoint point1, GeoPoint point2, GeoPoint point3, GeoPoint point4) { |
| super(planetModel); |
| this.point1 = point1; |
| this.point2 = point2; |
| this.point3 = point3; |
| this.point4 = point4; |
| |
| // Now build the four planes |
| this.plane1 = new SidedPlane(point4, point1, point2); |
| this.plane2 = new SidedPlane(point1, point2, point3); |
| this.plane3 = new SidedPlane(point2, point3, point4); |
| this.plane4 = new SidedPlane(point3, point4, point1); |
| |
| //collect the notable points for the planes |
| this.plane1Points = new GeoPoint[]{point1, point2}; |
| this.plane2Points = new GeoPoint[]{point2, point3}; |
| this.plane3Points = new GeoPoint[]{point3, point4}; |
| this.plane4Points = new GeoPoint[]{point4, point1}; |
| |
| this.edgePoints = new GeoPoint[]{point1}; |
| } |
| |
| /** |
| * Constructor for deserialization. |
| * @param planetModel is the planet model. |
| * @param inputStream is the input stream. |
| */ |
| public GeoS2Shape(final PlanetModel planetModel, final InputStream inputStream) throws IOException { |
| this(planetModel, |
| (GeoPoint) SerializableObject.readObject(inputStream), |
| (GeoPoint) SerializableObject.readObject(inputStream), |
| (GeoPoint) SerializableObject.readObject(inputStream), |
| (GeoPoint) SerializableObject.readObject(inputStream)); |
| } |
| |
| @Override |
| public void write(final OutputStream outputStream) throws IOException { |
| SerializableObject.writeObject(outputStream, point1); |
| SerializableObject.writeObject(outputStream, point2); |
| SerializableObject.writeObject(outputStream, point3); |
| SerializableObject.writeObject(outputStream, point4); |
| } |
| |
| |
| @Override |
| public boolean isWithin(final double x, final double y, final double z) { |
| return plane1.isWithin(x, y, z) && |
| plane2.isWithin(x, y, z) && |
| plane3.isWithin(x, y, z) && |
| plane4.isWithin(x, y, z); |
| } |
| |
| |
| @Override |
| public GeoPoint[] getEdgePoints() { |
| return edgePoints; |
| } |
| |
| @Override |
| public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) { |
| return p.intersects(planetModel, plane1, notablePoints, plane1Points, bounds, plane2, plane4) || |
| p.intersects(planetModel, plane2, notablePoints, plane2Points, bounds, plane3, plane1) || |
| p.intersects(planetModel, plane3, notablePoints, plane3Points, bounds, plane4, plane2) || |
| p.intersects(planetModel, plane4, notablePoints, plane4Points, bounds, plane1, plane3); |
| } |
| |
| @Override |
| public boolean intersects(GeoShape geoShape) { |
| return geoShape.intersects(plane1, plane1Points, plane2, plane4) || |
| geoShape.intersects(plane2, plane2Points, plane3, plane1) || |
| geoShape.intersects(plane3, plane3Points, plane4, plane2) || |
| geoShape.intersects(plane4, plane4Points, plane1, plane3); |
| } |
| |
| @Override |
| public void getBounds(Bounds bounds) { |
| super.getBounds(bounds); |
| bounds.addPlane(planetModel, plane1, plane2, plane4) |
| .addPlane(planetModel, plane2, plane3, plane1) |
| .addPlane(planetModel, plane3, plane4, plane2) |
| .addPlane(planetModel, plane4, plane1, plane3) |
| .addPoint(point1).addPoint(point2).addPoint(point3).addPoint(point4); |
| } |
| |
| @Override |
| public double outsideDistance(DistanceStyle distanceStyle, double x, double y, double z) { |
| final double planeDistance1 = distanceStyle.computeDistance(planetModel, plane1, x,y,z, plane2, plane4); |
| final double planeDistance2 = distanceStyle.computeDistance(planetModel, plane2, x,y,z, plane3, plane1); |
| final double planeDistance3 = distanceStyle.computeDistance(planetModel, plane3, x,y,z, plane4, plane2); |
| final double planeDistance4 = distanceStyle.computeDistance(planetModel, plane4, x,y,z, plane1, plane3); |
| |
| final double pointDistance1 = distanceStyle.computeDistance(point1, x,y,z); |
| final double pointDistance2 = distanceStyle.computeDistance(point2, x,y,z); |
| final double pointDistance3 = distanceStyle.computeDistance(point3, x,y,z); |
| final double pointDistance4 = distanceStyle.computeDistance(point4, x,y,z); |
| |
| return Math.min( |
| Math.min( |
| Math.min(planeDistance1, planeDistance2), |
| Math.min(planeDistance3, planeDistance4)), |
| Math.min( |
| Math.min(pointDistance1, pointDistance2), |
| Math.min(pointDistance3, pointDistance4))); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (!(o instanceof GeoS2Shape)) |
| return false; |
| GeoS2Shape other = (GeoS2Shape) o; |
| return super.equals(other) && other.point1.equals(point1) |
| && other.point2.equals(point2) && other.point3.equals(point3) |
| && other.point4.equals(point4); |
| } |
| |
| @Override |
| public int hashCode() { |
| int result = super.hashCode(); |
| result = 31 * result + point1.hashCode(); |
| result = 31 * result + point2.hashCode(); |
| result = 31 * result + point3.hashCode(); |
| result = 31 * result + point4.hashCode(); |
| return result; |
| } |
| |
| @Override |
| public String toString() { |
| return "GeoS2Shape: {planetmodel="+planetModel+", point1=" + point1 +", point2=" + point2 +", point3=" + point3 +", point4=" + point4+ "}"; |
| } |
| |
| } |
| |