/* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (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.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is the Kowari Metadata Store. * * The Initial Developer of the Original Code is Plugged In Software Pty * Ltd (http://www.pisoftware.com, mailto:info@pisoftware.com). Portions * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002 * Plugged In Software Pty Ltd. All Rights Reserved. * * Contributor(s): N/A. * * [NOTE: The text of this Exhibit A may differ slightly from the text * of the notices in the Source Code files of the Original Code. You * should use the text of this Exhibit A rather than the text found in the * Original Code Source Code for Your Modifications.] * */ package org.mulgara.resolver.gis.tools; // Log4J import org.apache.log4j.Logger; /** * Estimates the distance between two co-ordinates on the surface of a Sphere * with a specific radius. * * @created 2004-11-17 * * @author <a href="mailto:robert.turner@tucanatech.com">Robert Turner</a> * * @version $Revision: 1.6 $ * * @modified $Date: 2005/01/05 04:58:29 $ * * @maintenanceAuthor $Author: newmana $ * * @company <A href="mailto:info@PIsoftware.com">Plugged In Software</A> * * @copyright ©2001 <a href="http://www.pisoftware.com/">Plugged In * Software Pty Ltd</a> * * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a> */ public class SphericalDistanceEstimator implements DistanceCalculator { /** * Logger. This is named after the class. */ @SuppressWarnings("unused") private final static Logger log = Logger.getLogger(SphericalDistanceEstimator.class.getName()); /** Size of the sphere (in metres). */ private int radius = 0; /** * Constructor. Sets the size of the Sphere. * * @param radius int */ public SphericalDistanceEstimator(int radius) { super(); //validate if (radius <= 0) { throw new IllegalArgumentException("Sphere radius cannot be negative " + "or zero."); } this.radius = radius; } /** * Returns the "Great Circle" distance (in metres) between the two points. * * <p> * algorithm derived from: http://www.ga.gov.au/nmd/geodesy/datums/distance.jsp * * D = RADIUS * ARCOS ( SIN(L1) * SIN(L2) + COS(L1) * COS(L2) * COS(DG)) * L1 = latitude at the first point (radians) * L2 = latitude at the second point (radians) * G1 = longitude at the first point (radians) * G2 = longitude at the second point (radians) * DG = longitude of the second point minus longitude of the first point (radians) * DL = latitude of the second point minus latitude of the first point (radians) * D = computed distance (m) * * @param pointA GISCoordinate * @param pointB GISCoordinate * @return double */ public double distanceBetween(GISCoordinate pointA, GISCoordinate pointB) { //validate if (pointA == null) { throw new IllegalArgumentException("'pointA' parameter is null."); } if (pointB == null) { throw new IllegalArgumentException("'pointB' parameter is null."); } //short circuit if they are equal (same place/coordinate) if (pointA.equals(pointB)) { return 0.0; } //get the latitude and longitude of each point in radians double latA = pointA.getLatitide().asRadians(); double longA = pointA.getLongitude().asRadians(); double latB = pointB.getLatitide().asRadians(); double longB = pointB.getLongitude().asRadians(); return radius * (Math.acos(Math.sin(latA) * Math.sin(latB) + Math.cos(latA) * Math.cos(latB) * Math.cos(longB - longA))); } /** * Returns the "Great Circle" distance (in metres) between the two points. * * @param pointA GISCoordinate * @param pointB GISCoordinate * @return double */ // public double distanceBetween(GISCoordinate pointA, GISCoordinate pointB) { // // //validate // if (pointA == null) { // throw new IllegalArgumentException("'pointA' parameter is null."); // } // if (pointB == null) { // throw new IllegalArgumentException("'pointB' parameter is null."); // } // // //short circuit if they are equal (same place/coordinate) // if (pointA.equals(pointB)) { // return 0.0; // } // // //get the latitude and longitude of each point in radians // double latA = pointA.getLatitide().asRadians(); // double longA = pointA.getLongitude().asRadians(); // double latB = pointB.getLatitide().asRadians(); // double longB = pointB.getLongitude().asRadians(); // // //convert co-ordinates to 3D vectors (x,y,z) // double xA = Math.cos(latA) * Math.cos(longA); // double yA = Math.cos(latA) * Math.sin(longA); // double zA = Math.sin(latA); // // double xB = Math.cos(latB) * Math.cos(longB); // double yB = Math.cos(latB) * Math.sin(longB); // double zB = Math.sin(latB); // // //find their dot product // double x = xA * xB; // double y = yA * yB; // double z = zA * zB; // // //determine the great circle distance of their dot-product // return (Math.acos(x+y+z) * radius); // } }