📄 lonlattrig.java
字号:
/*
LonLatTrig.java
Copyright (C) 2004 Traverse Technologies Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.traversetechnologies.fulcrum.math;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
/**
* <p>This class provides common calculations involving the use of longitude and
* latitude world coordinates. Since longitude and latitude representations of
* spatial data are not planar, the calculations for distances and paths become
* significantly more complex than the flat equivalents. The methods in this
* class have not yet been tested outside the northern hemisphere and may
* require sign changes in places. Likewise, for special applications, the
* radius of the earth may need to be adjusted. Earth is treated as a sphere
* for the purpose of these calculations unless otherwise noted.</p>
*
* <p>It's possible to use the <code>CoordSpaceTransform</code> class to
* extrapolate longitude and latitude positions from screen coordinates.
* Keep in mind, however, that the extrapolation process has inherent errors
* that are magnified when the number of pixels are small and the geographic
* area being displayed is large. All this is a disclaimer that the calculations
* derived from the workings of this class, with or without the <code>
* CoordSpaceTransform</code> class, should not be used with applications
* requiring high accuracy and precision (but probably good enough for what
* Fulcrum was initially designed for - web based mapping applications). </p>
*
* @author Carleton Tsui
*/
public abstract class LonLatTrig {
/**
* The earth radius according to the FAI sphere in kilometers is 6371 km.
*/
public static final double EARTH_RADIUS = 6371;
/**
* Get the Great Circle distance in kilometers between two points given the
* longitude and latitude positions of two points. Adapted from <em>
* Trigonometry DeMystified</em> by Stan Gibilisco. Not suited for precise
* measurements, but probably good enough for web based applications where
* getting the longitude/latitude positions interpolated from pixel locations
* are spotty in the first place.
*
* @param lon1 The longitude degree of the first point.
* @param lat1 The latitude degree of the first point.
* @param lon2 The longitude degree of the second point.
* @param lat2 The latitude degree of the second point.
* @return The distance in kilometers.
*/
public static final double getDistanceKm(double lon1, double lat1,
double lon2, double lat2) {
double latO = 90; // north pole
double sphAngle = Math.toRadians(Math.abs(lon1-lon2));
double s1 = Math.toRadians(Math.abs(latO-lat1));
double s2 = Math.toRadians(Math.abs(latO-lat2));
double radDist = Math.acos( (Math.cos(s1)*Math.cos(s2))+
(Math.sin(s1)*Math.sin(s2)*Math.cos(sphAngle)));
return radDist*EARTH_RADIUS;
}
/**
* Get the Great Circle distance in miles between two points given the
* longitude and latitude positions of two points. This method calls the
* getDistanceKm method and converts the results to miles. See notes for that
* method.
*
* @param lon1 The longitude degree of the first point.
* @param lat1 The latitude degree of the first point.
* @param lon2 The longitude degree of the second point.
* @param lat2 The latitude degree of the second point.
* @return The distance in miles.
*/
public static final double getDistanceMi(double lon1, double lat1,
double lon2, double lat2) {
return getDistanceKm(lon1,lat1,lon2,lat2)*0.621371; //km to miles
}
/**
* Determine the end longitude/latitude point given a start point, distance
* and bearing. The calculations in this method were adapted from the
* <a href="http://williams.best.vwh.net/avform.htm">Aviation Formulary
* v1.30</a> by Ed Williams and proofed against the working examples
* found there. There appear to be slight deviations between the proofs and
* the results returned here due to differences in Java's Math.toRadians
* method returns and calculating it directly. The Java method was used in
* order to preserve consistency in conversions between methods in this
* class.
*
* @param lon The starting longitude point.
* @param lat The starting latitude point.
* @param km The distance in kilometers.
* @param radial The bearing in degrees (e.g. 0=north, 90=east, etc.)
* @return A <code>Point2D</code> with the longitude and latitude coordinate
* of the spot along the distance 'km' on course 'radial'.
*/
public static final Point2D getPointOnRadialKm(double lon, double lat,
double km, double radial) {
/* Convert km to nautical miles to arc radians; 1 nm = 1.852km */
double dRadArc = ((km/1.852)*Math.PI)/10800;
double tc = Math.toRadians(radial);
double lat1 = Math.toRadians(lat);
double lon1 = Math.toRadians(lon);
double pLat = Math.asin((Math.sin(lat1)*Math.cos(dRadArc))+
(Math.cos(lat1)*Math.sin(dRadArc)*Math.cos(tc)));
double dLon = Math.atan2(Math.sin(tc)*Math.sin(dRadArc)*Math.cos(lat1),
Math.cos(dRadArc)-Math.sin(lat1)*Math.sin(lat1));
double pLon = (lon1+dLon+Math.PI % (2*Math.PI))-Math.PI;
/* Convert radians back into decimal degrees */
pLat = (pLat*180)/Math.PI;
pLon = (pLon*180)/Math.PI;
return new Point2D.Double(pLon,pLat);
}
/**
* Determine the end longitude/latitude point given a start point, distance
* and bearing. See the notes for getPointOnRadialKm for more information.
*
* @param lon The starting longitude point.
* @param lat The starting latitude point.
* @param mi The distance in miles.
* @param radial The bearing in degrees (e.g. 0=north, 90=east, etc.)
* @return A <code>Point2D</code> with the longitude and latitude coordinate
* of the spot along the distance 'km' on course 'radial'.
*/
public static final Point2D getPointOnRadialMi(double lon, double lat,
double mi, double radial) {
return getPointOnRadialKm(lon,lat,mi*1.6093,radial);
}
/**
* Given a center point and a distance this method produces a bounding box.
* @param lon The center point longitude.
* @param lat The center point latitutde.
* @param km The distance in kilometers.
* @return The bounding box of +/- km distance from the center point on the
* x and y axes.
*/
public static final Rectangle2D getRadiusBoundsKm(double lon, double lat,
double km) {
/* Get the east point for maximum x */
double maxX= getPointOnRadialKm(lon,lat,km,90).getX();
/* Get the north point for maximum y*/
double maxY= getPointOnRadialKm(lon,lat,km,0).getY();
/* Get the point west for minimum x */
double minX = getPointOnRadialKm(lon,lat,km,270).getX();
/* Get the point south for minimum y */
double minY= getPointOnRadialKm(lon,lat,km,180).getY();
return new Rectangle2D.Double(minX, minY, Math.abs(maxX-minX),
Math.abs(maxY-minY));
}
/**
* Given a center point and a distance this method produces a bounding box.
* This method calls the getRadiusBoundsKm method with distances converted
* from the miles distance.
*
* @param lon The center point longitude.
* @param lat The center point latitutde.
* @param mi The distance in miles.
* @return The bounding box of +/- mi distance from the center point on the
* x and y axes.
*/
public static final Rectangle2D getRadiusBoundsMi(double lon, double lat,
double mi) {
return getRadiusBoundsKm(lon,lat,mi*1.6093);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -