pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / contrib / spatial / src / java / org / apache / lucene / spatial / geometry / LatLng.java
diff --git a/lucene-java-3.5.0/lucene/contrib/spatial/src/java/org/apache/lucene/spatial/geometry/LatLng.java b/lucene-java-3.5.0/lucene/contrib/spatial/src/java/org/apache/lucene/spatial/geometry/LatLng.java
new file mode 100644 (file)
index 0000000..b2128ab
--- /dev/null
@@ -0,0 +1,160 @@
+/**
+ * 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.spatial.geometry;
+
+
+/**
+ * Abstract base lat-lng class which can manipulate fixed point or floating
+ * point based coordinates. Instances are immutable.
+ * 
+ * @see FloatLatLng
+ *
+ * <p><font color="red"><b>NOTE:</b> This API is still in
+ * flux and might change in incompatible ways in the next
+ * release.</font>
+ */
+public abstract class LatLng {
+
+  public abstract boolean isNormalized();
+
+  public abstract boolean isFixedPoint();
+
+  public abstract LatLng normalize();
+
+  public abstract int getFixedLat();
+
+  public abstract int getFixedLng();
+
+  public abstract double getLat();
+
+  public abstract double getLng();
+
+  public abstract LatLng copy();
+
+  public abstract FixedLatLng toFixed();
+
+  public abstract FloatLatLng toFloat();
+  
+  /**
+   * Convert the lat/lng into the cartesian coordinate plane such that all
+   * world coordinates are represented in the first quadrant.
+   * The x dimension corresponds to latitude and y corresponds to longitude.
+   * The translation starts with the normalized latlng and adds 180 to the latitude and 
+   * 90 to the longitude (subject to fixed point scaling).
+   */
+  public CartesianPoint toCartesian() {
+    LatLng ll=normalize();
+    
+    int lat=ll.getFixedLat();
+    int lng=ll.getFixedLng();
+    
+    return new CartesianPoint(
+        lng+180*FixedLatLng.SCALE_FACTOR_INT,
+        lat+90*FixedLatLng.SCALE_FACTOR_INT
+    );
+  }
+  
+  /**
+   * The inverse of toCartesian().  Always returns a FixedLatLng.
+   * @param pt
+   */
+  public static LatLng fromCartesian(CartesianPoint pt) {
+    int lat=pt.getY() - 90 * FixedLatLng.SCALE_FACTOR_INT;
+    int lng=pt.getX() - 180 * FixedLatLng.SCALE_FACTOR_INT;
+    
+    return new FixedLatLng(lat, lng);
+  }
+  
+  /**
+   * Calculates the distance between two lat/lng's in miles.
+   * Imported from mq java client.
+   * 
+   * @param ll2
+   *            Second lat,lng position to calculate distance to.
+   * 
+   * @return Returns the distance in miles.
+   */
+  public double arcDistance(LatLng ll2) {
+    return arcDistance(ll2, DistanceUnits.MILES);
+  }
+
+  /**
+   * Calculates the distance between two lat/lng's in miles or meters.
+   * Imported from mq java client.  Variable references changed to match.
+   * 
+   * @param ll2
+   *            Second lat,lng position to calculate distance to.
+   * @param lUnits
+   *            Units to calculate distance, defaults to miles
+   * 
+   * @return Returns the distance in meters or miles.
+   */
+  public double arcDistance(LatLng ll2, DistanceUnits lUnits) {
+    LatLng ll1 = normalize();
+    ll2 = ll2.normalize();
+
+    double lat1 = ll1.getLat(), lng1 = ll1.getLng();
+    double lat2 = ll2.getLat(), lng2 = ll2.getLng();
+
+    // Check for same position
+    if (lat1 == lat2 && lng1 == lng2)
+      return 0.0;
+
+    // Get the m_dLongitude difference. Don't need to worry about
+    // crossing 180 since cos(x) = cos(-x)
+    double dLon = lng2 - lng1;
+
+    double a = radians(90.0 - lat1);
+    double c = radians(90.0 - lat2);
+    double cosB = (Math.cos(a) * Math.cos(c))
+        + (Math.sin(a) * Math.sin(c) * Math.cos(radians(dLon)));
+
+    double radius = (lUnits == DistanceUnits.MILES) ? 3963.205/* MILERADIUSOFEARTH */
+    : 6378.160187/* KMRADIUSOFEARTH */;
+
+    // Find angle subtended (with some bounds checking) in radians and
+    // multiply by earth radius to find the arc distance
+    if (cosB < -1.0)
+      return 3.14159265358979323846/* PI */* radius;
+    else if (cosB >= 1.0)
+      return 0;
+    else
+      return Math.acos(cosB) * radius;
+  }
+
+  private double radians(double a) {
+    return a * 0.01745329251994;
+  }
+
+  @Override
+  public String toString() {
+    return "[" + getLat() + "," + getLng() + "]";
+  }
+
+  /**
+   * Calculate the midpoint between this point an another.  Respects fixed vs floating point
+   * @param other
+   */
+  public abstract LatLng calculateMidpoint(LatLng other);
+  
+  @Override
+  public abstract int hashCode();
+
+  @Override
+  public abstract boolean equals(Object obj);
+}