| /* |
| * 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; |
| |
| /** |
| * Factory for {@link GeoBBox}. |
| * |
| * @lucene.experimental |
| */ |
| public class GeoBBoxFactory { |
| private GeoBBoxFactory() { |
| } |
| |
| /** |
| * Create a geobbox of the right kind given the specified bounds. |
| * |
| * @param planetModel is the planet model |
| * @param topLat is the top latitude |
| * @param bottomLat is the bottom latitude |
| * @param leftLon is the left longitude |
| * @param rightLon is the right longitude |
| * @return a GeoBBox corresponding to what was specified. |
| */ |
| public static GeoBBox makeGeoBBox(final PlanetModel planetModel, double topLat, double bottomLat, double leftLon, double rightLon) { |
| //System.err.println("Making rectangle for topLat="+topLat*180.0/Math.PI+", bottomLat="+bottomLat*180.0/Math.PI+", leftLon="+leftLon*180.0/Math.PI+", rightlon="+rightLon*180.0/Math.PI); |
| if (topLat > Math.PI * 0.5) |
| topLat = Math.PI * 0.5; |
| if (bottomLat < -Math.PI * 0.5) |
| bottomLat = -Math.PI * 0.5; |
| if (leftLon < -Math.PI) |
| leftLon = -Math.PI; |
| if (rightLon > Math.PI) |
| rightLon = Math.PI; |
| if ((Math.abs(leftLon + Math.PI) < Vector.MINIMUM_ANGULAR_RESOLUTION && Math.abs(rightLon - Math.PI) < Vector.MINIMUM_ANGULAR_RESOLUTION) || |
| (Math.abs(rightLon + Math.PI) < Vector.MINIMUM_ANGULAR_RESOLUTION && Math.abs(leftLon - Math.PI) < Vector.MINIMUM_ANGULAR_RESOLUTION)) { |
| if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_ANGULAR_RESOLUTION && Math.abs(bottomLat + Math.PI * 0.5) < Vector.MINIMUM_ANGULAR_RESOLUTION) |
| return new GeoWorld(planetModel); |
| if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_ANGULAR_RESOLUTION) { |
| if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_ANGULAR_RESOLUTION || Math.abs(topLat + Math.PI * 0.5) < Vector.MINIMUM_ANGULAR_RESOLUTION) |
| return new GeoDegeneratePoint(planetModel, topLat, 0.0); |
| return new GeoDegenerateLatitudeZone(planetModel, topLat); |
| } |
| if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_ANGULAR_RESOLUTION) |
| return new GeoNorthLatitudeZone(planetModel, bottomLat); |
| else if (Math.abs(bottomLat + Math.PI * 0.5) < Vector.MINIMUM_ANGULAR_RESOLUTION) |
| return new GeoSouthLatitudeZone(planetModel, topLat); |
| return new GeoLatitudeZone(planetModel, topLat, bottomLat); |
| } |
| //System.err.println(" not latitude zone"); |
| double extent = rightLon - leftLon; |
| if (extent < 0.0) |
| extent += Math.PI * 2.0; |
| if (topLat == Math.PI * 0.5 && bottomLat == -Math.PI * 0.5) { |
| if (Math.abs(leftLon - rightLon) < Vector.MINIMUM_ANGULAR_RESOLUTION) |
| return new GeoDegenerateLongitudeSlice(planetModel, leftLon); |
| |
| if (extent >= Math.PI) |
| return new GeoWideLongitudeSlice(planetModel, leftLon, rightLon); |
| |
| return new GeoLongitudeSlice(planetModel, leftLon, rightLon); |
| } |
| //System.err.println(" not longitude slice"); |
| if (Math.abs(leftLon - rightLon) < Vector.MINIMUM_ANGULAR_RESOLUTION) { |
| if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_ANGULAR_RESOLUTION) |
| return new GeoDegeneratePoint(planetModel, topLat, leftLon); |
| return new GeoDegenerateVerticalLine(planetModel, topLat, bottomLat, leftLon); |
| } |
| //System.err.println(" not vertical line"); |
| if (extent >= Math.PI) { |
| if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_ANGULAR_RESOLUTION) { |
| if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_ANGULAR_RESOLUTION) { |
| return new GeoDegeneratePoint(planetModel, topLat, 0.0); |
| } else if (Math.abs(bottomLat + Math.PI * 0.5) < Vector.MINIMUM_ANGULAR_RESOLUTION) { |
| return new GeoDegeneratePoint(planetModel, bottomLat, 0.0); |
| } |
| //System.err.println(" wide degenerate line"); |
| return new GeoWideDegenerateHorizontalLine(planetModel, topLat, leftLon, rightLon); |
| } |
| if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_ANGULAR_RESOLUTION) { |
| return new GeoWideNorthRectangle(planetModel, bottomLat, leftLon, rightLon); |
| } else if (Math.abs(bottomLat + Math.PI * 0.5) < Vector.MINIMUM_ANGULAR_RESOLUTION) { |
| return new GeoWideSouthRectangle(planetModel, topLat, leftLon, rightLon); |
| } |
| //System.err.println(" wide rect"); |
| return new GeoWideRectangle(planetModel, topLat, bottomLat, leftLon, rightLon); |
| } |
| if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_ANGULAR_RESOLUTION) { |
| if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_ANGULAR_RESOLUTION) { |
| return new GeoDegeneratePoint(planetModel, topLat, 0.0); |
| } else if (Math.abs(bottomLat + Math.PI * 0.5) < Vector.MINIMUM_ANGULAR_RESOLUTION) { |
| return new GeoDegeneratePoint(planetModel, bottomLat, 0.0); |
| } |
| //System.err.println(" horizontal line"); |
| return new GeoDegenerateHorizontalLine(planetModel, topLat, leftLon, rightLon); |
| } |
| if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_ANGULAR_RESOLUTION) { |
| return new GeoNorthRectangle(planetModel, bottomLat, leftLon, rightLon); |
| } else if (Math.abs(bottomLat + Math.PI * 0.5) < Vector.MINIMUM_ANGULAR_RESOLUTION) { |
| return new GeoSouthRectangle(planetModel, topLat, leftLon, rightLon); |
| } |
| //System.err.println(" rectangle"); |
| return new GeoRectangle(planetModel, topLat, bottomLat, leftLon, rightLon); |
| } |
| |
| /** |
| * Create a geobbox of the right kind given the specified {@link LatLonBounds}. |
| * |
| * @param planetModel is the planet model |
| * @param bounds are the bounds |
| * @return a GeoBBox corresponding to what was specified. |
| */ |
| public static GeoBBox makeGeoBBox(final PlanetModel planetModel, LatLonBounds bounds) { |
| final double topLat = (bounds.checkNoTopLatitudeBound()) ? Math.PI * 0.5 : bounds.getMaxLatitude(); |
| final double bottomLat = (bounds.checkNoBottomLatitudeBound()) ? -Math.PI * 0.5 : bounds.getMinLatitude(); |
| final double leftLon = (bounds.checkNoLongitudeBound()) ? -Math.PI : bounds.getLeftLongitude(); |
| final double rightLon = (bounds.checkNoLongitudeBound()) ? Math.PI : bounds.getRightLongitude(); |
| return makeGeoBBox(planetModel, topLat, bottomLat, leftLon, rightLon); |
| } |
| |
| } |