add --shared
[pylucene.git] / lucene-java-3.4.0 / lucene / contrib / spatial / src / java / org / apache / lucene / spatial / geometry / LatLng.java
1 /**
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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 package org.apache.lucene.spatial.geometry;
19
20
21 /**
22  * Abstract base lat-lng class which can manipulate fixed point or floating
23  * point based coordinates. Instances are immutable.
24  * 
25  * @see FloatLatLng
26  *
27  * <p><font color="red"><b>NOTE:</b> This API is still in
28  * flux and might change in incompatible ways in the next
29  * release.</font>
30  */
31 public abstract class LatLng {
32
33   public abstract boolean isNormalized();
34
35   public abstract boolean isFixedPoint();
36
37   public abstract LatLng normalize();
38
39   public abstract int getFixedLat();
40
41   public abstract int getFixedLng();
42
43   public abstract double getLat();
44
45   public abstract double getLng();
46
47   public abstract LatLng copy();
48
49   public abstract FixedLatLng toFixed();
50
51   public abstract FloatLatLng toFloat();
52   
53   /**
54    * Convert the lat/lng into the cartesian coordinate plane such that all
55    * world coordinates are represented in the first quadrant.
56    * The x dimension corresponds to latitude and y corresponds to longitude.
57    * The translation starts with the normalized latlng and adds 180 to the latitude and 
58    * 90 to the longitude (subject to fixed point scaling).
59    */
60   public CartesianPoint toCartesian() {
61     LatLng ll=normalize();
62     
63     int lat=ll.getFixedLat();
64     int lng=ll.getFixedLng();
65     
66     return new CartesianPoint(
67         lng+180*FixedLatLng.SCALE_FACTOR_INT,
68         lat+90*FixedLatLng.SCALE_FACTOR_INT
69     );
70   }
71   
72   /**
73    * The inverse of toCartesian().  Always returns a FixedLatLng.
74    * @param pt
75    */
76   public static LatLng fromCartesian(CartesianPoint pt) {
77     int lat=pt.getY() - 90 * FixedLatLng.SCALE_FACTOR_INT;
78     int lng=pt.getX() - 180 * FixedLatLng.SCALE_FACTOR_INT;
79     
80     return new FixedLatLng(lat, lng);
81   }
82   
83   /**
84    * Calculates the distance between two lat/lng's in miles.
85    * Imported from mq java client.
86    * 
87    * @param ll2
88    *            Second lat,lng position to calculate distance to.
89    * 
90    * @return Returns the distance in miles.
91    */
92   public double arcDistance(LatLng ll2) {
93     return arcDistance(ll2, DistanceUnits.MILES);
94   }
95
96   /**
97    * Calculates the distance between two lat/lng's in miles or meters.
98    * Imported from mq java client.  Variable references changed to match.
99    * 
100    * @param ll2
101    *            Second lat,lng position to calculate distance to.
102    * @param lUnits
103    *            Units to calculate distance, defaults to miles
104    * 
105    * @return Returns the distance in meters or miles.
106    */
107   public double arcDistance(LatLng ll2, DistanceUnits lUnits) {
108     LatLng ll1 = normalize();
109     ll2 = ll2.normalize();
110
111     double lat1 = ll1.getLat(), lng1 = ll1.getLng();
112     double lat2 = ll2.getLat(), lng2 = ll2.getLng();
113
114     // Check for same position
115     if (lat1 == lat2 && lng1 == lng2)
116       return 0.0;
117
118     // Get the m_dLongitude difference. Don't need to worry about
119     // crossing 180 since cos(x) = cos(-x)
120     double dLon = lng2 - lng1;
121
122     double a = radians(90.0 - lat1);
123     double c = radians(90.0 - lat2);
124     double cosB = (Math.cos(a) * Math.cos(c))
125         + (Math.sin(a) * Math.sin(c) * Math.cos(radians(dLon)));
126
127     double radius = (lUnits == DistanceUnits.MILES) ? 3963.205/* MILERADIUSOFEARTH */
128     : 6378.160187/* KMRADIUSOFEARTH */;
129
130     // Find angle subtended (with some bounds checking) in radians and
131     // multiply by earth radius to find the arc distance
132     if (cosB < -1.0)
133       return 3.14159265358979323846/* PI */* radius;
134     else if (cosB >= 1.0)
135       return 0;
136     else
137       return Math.acos(cosB) * radius;
138   }
139
140   private double radians(double a) {
141     return a * 0.01745329251994;
142   }
143
144   @Override
145   public String toString() {
146     return "[" + getLat() + "," + getLng() + "]";
147   }
148
149   /**
150    * Calculate the midpoint between this point an another.  Respects fixed vs floating point
151    * @param other
152    */
153   public abstract LatLng calculateMidpoint(LatLng other);
154   
155   @Override
156   public abstract int hashCode();
157
158   @Override
159   public abstract boolean equals(Object obj);
160 }