2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package org.apache.lucene.spatial.geometry.shape;
20 import org.apache.lucene.spatial.geometry.FloatLatLng;
21 import org.apache.lucene.spatial.geometry.LatLng;
26 * Lat-long rect. Instances are mutable.
28 * <p><font color="red"><b>NOTE:</b> This API is still in
29 * flux and might change in incompatible ways in the next
33 private LatLng ll, ur;
35 public LLRect(LatLng ll, LatLng ur) {
40 public LLRect(LLRect other) {
46 * Return the area in units of lat-lng squared. This is a contrived unit
47 * that only has value when comparing to something else.
49 public double area() {
50 return Math.abs((ll.getLat()-ur.getLat()) * (ll.getLng()-ur.getLng()));
53 public LatLng getLowerLeft() {
57 public LatLng getUpperRight() {
62 public String toString() {
63 return "{" + ll + ", " + ur + "}";
66 public LatLng getMidpoint() {
67 return ll.calculateMidpoint(ur);
71 * Approximates a box centered at the given point with the given width and height in miles.
76 public static LLRect createBox(LatLng center, double widthMi, double heightMi) {
78 LatLng ur = boxCorners(center, d, 45.0); // assume right angles
79 LatLng ll = boxCorners(center, d, 225.0);
81 //System.err.println("boxCorners: ur " + ur.getLat() + ',' + ur.getLng());
82 //System.err.println("boxCorners: cnt " + center.getLat() + ',' + center.getLng());
83 //System.err.println("boxCorners: ll " + ll.getLat() + ',' + ll.getLng());
84 return new LLRect(ll, ur);
88 * Returns a rectangle shape for the bounding box
90 public Rectangle toRectangle() {
91 return new Rectangle(ll.getLng(), ll.getLat(), ur.getLng(), ur.getLat());
94 private static LatLng boxCorners(LatLng center, double d, double brngdeg) {
95 double a = center.getLat();
96 double b = center.getLng();
97 double R = 3963.0; // radius of earth in miles
98 double brng = (Math.PI*brngdeg/180);
99 double lat1 = (Math.PI*a/180);
100 double lon1 = (Math.PI*b/180);
103 double lat2 = Math.asin( Math.sin(lat1)*Math.cos(d/R) +
104 Math.cos(lat1)*Math.sin(d/R)*Math.cos(brng) );
105 double lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos(lat1),
106 Math.cos(d/R)-Math.sin(lat1)*Math.sin(lat2));
108 lat2 = (lat2*180)/Math.PI;
109 lon2 = (lon2*180)/Math.PI;
111 // normalize long first
112 LatLng ll = normLng(lat2,lon2);
114 // normalize lat - could flip poles
115 ll = normLat(ll.getLat(),ll.getLng());
121 * Returns a normalized Lat rectangle shape for the bounding box
122 * If you go over the poles, you need to flip the lng value too
124 private static LatLng normLat(double lat, double lng) {
126 lat = 90.0 - (lat - 90.0);
133 else if (lat < -90.0) {
134 lat = -90.0 - (lat + 90.0);
141 LatLng ll=new FloatLatLng(lat, lng);
146 * Returns a normalized Lng rectangle shape for the bounding box
148 private static LatLng normLng(double lat,double lng) {
150 lng = -1.0*(180.0 - (lng - 180.0));
152 else if (lng < -180.0) {
153 lng = (lng + 180.0)+180.0;
155 LatLng ll=new FloatLatLng(lat, lng);
160 public int hashCode() {
161 final int prime = 31;
163 result = prime * result + ((ll == null) ? 0 : ll.hashCode());
164 result = prime * result + ((ur == null) ? 0 : ur.hashCode());
169 public boolean equals(Object obj) {
174 if (getClass() != obj.getClass())
176 LLRect other = (LLRect) obj;
178 if (other.ll != null)
180 } else if (!ll.equals(other.ll))
183 if (other.ur != null)
185 } else if (!ur.equals(other.ur))