GeoUtils.java :  » Science » Cougaar12_4 » org » cougaar » glm » util » Java Open Source

Java Open Source » Science » Cougaar12_4 
Cougaar12_4 » org » cougaar » glm » util » GeoUtils.java
/*
 * <copyright>
 *  
 *  Copyright 1997-2004 BBNT Solutions, LLC
 *  under sponsorship of the Defense Advanced Research Projects
 *  Agency (DARPA).
 * 
 *  You can redistribute this software and/or modify it under the
 *  terms of the Cougaar Open Source License as published on the
 *  Cougaar Open Source Website (www.cougaar.org).
 * 
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *  
 * </copyright>
 */

package org.cougaar.glm.util;

import org.cougaar.glm.ldm.plan.Position;
import org.cougaar.planning.ldm.measure.Distance;
import org.cougaar.planning.ldm.measure.Latitude;
import org.cougaar.planning.ldm.measure.Longitude;
import org.cougaar.util.log.Logger;
import org.cougaar.util.log.LoggerFactory;

/**
 * A class containing static methods for geographic computations, 
 * particularly those related to great-circle distance calculations
 */
public class GeoUtils {

  // Circumference of earth in KM (around equator)
  public static final double EARTH_CIRCUMFERENCE = 40075.16;

  // Radius of earth in KM
  public static final double EARTH_RADIUS = 
      EARTH_CIRCUMFERENCE / (Math.PI * 2.0);


  /**
   * Compute great-circle distance (expressed as COUGAAR Distance measure)
   * between two points on globe (expressed as COUGAAR Position)
   * @param position1 of first point
   * @param position2 of second point
   * @return Distance of great-circle distance between points
   */
  public static Distance DistanceBetweenPositions(Position position1,
              Position position2)
  {
    // Get distance as KM
    double distance = 
      DistanceBetweenPositions(position1.getLatitude().getDegrees(),
             position1.getLongitude().getDegrees(),
             position2.getLatitude().getDegrees(),
             position2.getLongitude().getDegrees());

    // Return as Distance
    return Distance.newKilometers(distance);
  }

  /**
   * Compute great-circle distance in KM between two points on globe
   * expressed as latitude and longitude.
   * @param latitude1 of first point (degrees)
   * @param longitude1 of first point (degrees)
   * @param latitude2 of second point (degrees)
   * @param longitude2 of second point (degrees)
   * @return double great-circle distance between two points
   */
  public static double DistanceBetweenPositions(double latitude1,
            double longitude1, 
            double latitude2,
            double longitude2)
  {
    // Convert arguments to Radians
    double lon1_rad = Math.toRadians(longitude1);
    double lat1_rad = Math.toRadians(latitude1);
    double lon2_rad = Math.toRadians(longitude2);
    double lat2_rad = Math.toRadians(latitude2);

    // Convert to 3-D Cartesian coordinates (X,Y,Z with earth center at 0,0,0)
    double node_1_x = Math.cos(lat1_rad)*Math.cos(lon1_rad);
    double node_1_y = Math.cos(lat1_rad)*Math.sin(lon1_rad);
    double node_1_z = Math.sin(lat1_rad);

    double node_2_x = Math.cos(lat2_rad)*Math.cos(lon2_rad);
    double node_2_y = Math.cos(lat2_rad)*Math.sin(lon2_rad);
    double node_2_z = Math.sin(lat2_rad);

    // Calculate Cross-Product
    double cross_x = (node_1_y * node_2_z) - (node_1_z * node_2_y);
    double cross_y = (node_1_z * node_2_x) - (node_1_x * node_2_z);
    double cross_z = (node_1_x * node_2_y) - (node_1_y * node_2_x);

    // Calculate the length of the Cross-Product
    double norm_cross = 
      Math.sqrt((cross_x * cross_x) + 
    (cross_y * cross_y) + 
    (cross_z * cross_z));
    
    // Calculate the Dot-Product
    double dot_product = 
      (node_1_x * node_2_x) + (node_1_y * node_2_y) + (node_1_z * node_2_z); 

    // Calculate the central angle
    double angle = Math.atan2(norm_cross, dot_product);

    // Calculate the great-circle distance
    double distance = EARTH_RADIUS * angle;

    return distance;
  } 

  /* only used for isolated main ()-style testing */
  private static Logger logger=LoggerFactory.getInstance().createLogger("GeoUtils");
  // Test procedure on great-circle calculations
  public static void main(String []args) 
  {
    logger.debug("GeoUtils...");

    // One degree longitude at equator should be ~111 KM.
    double one_degree_longitude_at_equator = 
      DistanceBetweenPositions(0.0, 0.0, 0.0, 1.0);
    logger.debug("One degree longitude at equator = " +
           one_degree_longitude_at_equator);

    // One degree latitude at equator should be ~111 KM.
    double one_degree_latitude_at_equator = 
      DistanceBetweenPositions(0.0, 0.0, 1.0, 0.0);
    logger.debug("One degree latitude at equator = " +
           one_degree_latitude_at_equator);

    // Distance between Boston and New York should be 183.9 mi (296 km)
    // Distance between NYC and LA should be 2464 mi (3943 km) 
    // (as the crow flies...).
    // Boston is 42-15'N, 71-07'W
    // NYC is 40.40'N, 73-58'W
    // LA is 34.03'N, 118.14'W
    double BOS_LAT = 42.0 +  (15.0/60.0);
    double BOS_LON = -(71.0 + (7.0/60.0));
    double NY_LAT = 40.0 + (40.0/60.0);
    double NY_LON = -(73.0 + (58.0/60.0));
    double LA_LAT = 34.0 + (3.0/60.0);
    double LA_LON = -(118.0 + (14.0/60.0));
    logger.debug("Distance between NYC and LA (km) = " + 
           DistanceBetweenPositions(NY_LAT, NY_LON,
            LA_LAT, LA_LON));
    logger.debug("Distance between LA and NEW YORK (km) = " + 
           DistanceBetweenPositions(LA_LAT, LA_LON, 
            NY_LAT, NY_LON));
    logger.debug("Distance between BOSTON and NEW YORK (km) = " + 
           DistanceBetweenPositions(BOS_LAT, BOS_LON, 
            NY_LAT, NY_LON));
    Position BOSTON = 
      new org.cougaar.glm.ldm.plan.PositionImpl
      (Latitude.newLatitude(BOS_LAT), Longitude.newLongitude(BOS_LON));
    Position NEW_YORK = 
      new org.cougaar.glm.ldm.plan.PositionImpl
      (Latitude.newLatitude(NY_LAT), Longitude.newLongitude(NY_LON));
    Distance distance_between_BOS_and_NY = 
      DistanceBetweenPositions(BOSTON, NEW_YORK);
    logger.debug("Distance between BOSTON and NEW YORK (miles) = " + 
     distance_between_BOS_and_NY.getMiles());
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.