我正在尝试使用GPS在固定点周围以随机距离生成一些点。
如何向GPS坐标添加以米为单位的距离? 我已经看过UTM到GPS转换,但是否有更简单的方法实现这一目标?
我是在Android平台上工作的,如果需要的话。
谢谢, fgs
您可以使用近似值计算随机位置的位置:
lat = lat0 + (180/pi)*(dy/6378137)
lon = lon0 + (180/pi)*(dx/6378137)/cos(lat0)
如果随机距离偏移量在10-100公里以下,这就相当精确。
编辑:当然,在Java中,Math.cos()期望弧度值,所以如果lat0是以度为单位的(如上所述),请使用Math.cos(Math.PI/180.0*lat0)
。
为了取得一个正方形,我正在使用这个:
private double[] getBoundingBox(final double pLatitude, final double pLongitude, final int pDistanceInMeters) {
final double[] boundingBox = new double[4];
final double latRadian = Math.toRadians(pLatitude);
final double degLatKm = 110.574235;
final double degLongKm = 110.572833 * Math.cos(latRadian);
final double deltaLat = pDistanceInMeters / 1000.0 / degLatKm;
final double deltaLong = pDistanceInMeters / 1000.0 / degLongKm;
final double minLat = pLatitude - deltaLat;
final double minLong = pLongitude - deltaLong;
final double maxLat = pLatitude + deltaLat;
final double maxLong = pLongitude + deltaLong;
boundingBox[0] = minLat;
boundingBox[1] = minLong;
boundingBox[2] = maxLat;
boundingBox[3] = maxLong;
return boundingBox;
}
这会返回一个包含4个坐标的数组,使用它们你可以使得一个正方形以你原来的点为中心。
pDistanceInMeters
在这里是“半径”。 - Pavel Vlasov@SuppressLint("DefaultLocale")
public static double go_mock_loc(double xx_lat,double xx_long,double xx_dinstance,String Direction)
{
// double xx_lat= 45.815005;
// double xx_long= 15.978501;
// int xx_dinstance=500;
int equator_circumference=6371000;
int polar_circumference=6356800;
double m_per_deg_long = 360 / polar_circumference;
double rad_lat=(xx_lat* (Math.PI) / 180);
double m_per_deg_lat = 360 / ( Math.cos(rad_lat) * equator_circumference);
double deg_diff_long = xx_dinstance * m_per_deg_long;
double deg_diff_lat = xx_dinstance * m_per_deg_lat;
double xx_north_lat = xx_lat + deg_diff_long;
//double xx_north_long= xx_long;
double xx_south_lat = xx_lat - deg_diff_long;
//double xx_south_long= xx_long;
//double xx_east_lat = xx_lat;
double xx_east_long= xx_long + deg_diff_lat;
//double xx_west_lat = xx_lat;
double xx_west_long= xx_long - deg_diff_lat;
if (Direction.toUpperCase().contains("NORTH")) {
return xx_north_lat;
} else if (Direction.toUpperCase().contains("SOUTH"))
{
return xx_south_lat;
} else if (Direction.toUpperCase().contains("EAST"))
{
return xx_east_long;
} else if (Direction.toUpperCase().contains("WEST"))
{
return xx_west_long;
}
else
return 0;
}
详细的大纲请参考http://www.movable-type.co.uk/scripts/latlong.html。
如果您需要在某个地方将经度/纬度转换为UTM坐标(GPS中使用的坐标),您可能需要查看http://www.uwgb.edu/dutchs/UsefulData/UTMFormulas.htm
我发现@Bogdan Khrystov提供的解决方案非常好。
这是他方案的C#版本。
public enum GeoDirection
{
NORTH = 1, SOUTH = 2, EAST = 3, WEST = 4
}
public static Tuple<double, double> AddDistanceInMeters(double latitude, double longitude, int distanceInMeters, GeoDirection direction)
{
var equatorCircumference = 6371000;
var polarCircumference = 6356800;
var mPerDegLong = 360 / (double)polarCircumference;
var radLat = latitude * Math.PI / 180;
var mPerDegLat = 360 / (Math.Cos(radLat) * equatorCircumference);
var degDiffLong = distanceInMeters * mPerDegLong;
var degDiffLat = distanceInMeters * mPerDegLat;
var xxNorthLat = latitude + degDiffLong;
var xxSouthLat = latitude - degDiffLong;
var xxEastLong = longitude + degDiffLat;
var xxWestLong = longitude - degDiffLat;
switch (direction)
{
case GeoDirection.NORTH:
return new Tuple<double, double>(xxNorthLat, longitude);
case GeoDirection.SOUTH:
return new Tuple<double, double>(xxSouthLat, longitude);
case GeoDirection.EAST:
return new Tuple<double, double>(latitude, xxEastLong);
case GeoDirection.WEST:
return new Tuple<double, double>(latitude, xxWestLong);
default:
return null;
}
}
object LocationUtil {
enum class Direction {
NORTH, SOUTH, EAST, WEST
}
fun addDistanceInMeters(
latitude: Double,
longitude: Double,
distanceInMeters: Int,
direction: Direction
): Pair<Double, Double> {
val equatorCircumference = 6371000
val polarCircumference = 6356800
val mPerDegLong = (360 / polarCircumference.toDouble())
val radLat = latitude * Math.PI / 180
val mPerDegLat = 360 / (Math.cos(radLat) * equatorCircumference)
val degDiffLong = distanceInMeters * mPerDegLong
val degDiffLat = distanceInMeters * mPerDegLat
val xxNorthLat = latitude + degDiffLong
val xxSouthLat = latitude - degDiffLong
val xxEastLong = longitude + degDiffLat
val xxWestLong = longitude - degDiffLat
return when (direction) {
Direction.NORTH -> Pair(xxNorthLat, longitude)
Direction.SOUTH -> Pair(xxSouthLat, longitude)
Direction.EAST -> Pair(latitude, xxEastLong)
Direction.WEST -> Pair(latitude, xxWestLong)
}
}
}
这个代码可行,已经测试过了。虽然是C#语言编写的,但你可以轻松地将其改为其他语言。
private PointLatLng NewPositionBasedOnDistanceAngle(PointLatLng org, double distance, double bearing)
{
double rad = bearing * Math.PI / 180; //to radians
double lat1 = org.Lat * Math.PI / 180; //to radians
double lng1 = org.Lng * Math.PI / 180; //to radians
double lat = Math.Asin(Math.Sin(lat1) * Math.Cos(distance / 6378137) + Math.Cos(lat1) * Math.Sin(distance / 6378137) * Math.Cos(rad));
double lng = lng1 + Math.Atan2(Math.Sin(rad) * Math.Sin(distance / 6378137) * Math.Cos(lat1), Math.Cos(distance / 6378137) - Math.Sin(lat1) * Math.Sin(lat));
return new PointLatLng(lat * 180 / Math.PI, lng * 180 / Math.PI); // to degrees
}
结合@Ersin Gülbahar和@Stéphane的答案,我在Flutter/Dart中得出了以下解决方案:
import 'dart:math' as math;
enum Direction { north, south, east, west }
double moveCoordinate(
double latitude, double longitude, double distanceToMoveInMeters, Direction directionToMove) {
const earthEquatorRadius = 6378137;
final latitudeOffset = (180 / math.pi) * (distanceToMoveInMeters / earthEquatorRadius);
final longitudeOffset = (180 / math.pi) *
(distanceToMoveInMeters / earthEquatorRadius) /
math.cos(math.pi / 180 * latitude);
switch (directionToMove) {
case Direction.north:
return latitude + latitudeOffset;
case Direction.south:
return latitude - latitudeOffset;
case Direction.east:
return longitude + longitudeOffset;
case Direction.west:
return longitude - longitudeOffset;
}
return 0;
}
@Override
public void split(Coordinates p1, Coordinates p2, int segments) {
double φ1 = Math.toRadians(p1.getLat());
double λ1 = Math.toRadians(p1.getLon());
double φ2 = Math.toRadians(p2.getLat());
double λ2 = Math.toRadians(p2.getLon());
double xDelta = (φ2 - φ1) / segments;
double yDelta = (λ2 - λ1) / segments;
for (int i = 0; i < segments; i++){
double x = φ1 + i * xDelta;
double y = λ1 + i * yDelta;
double xc = Math.toDegrees(x);
double yc = Math.toDegrees(y);
System.out.println(xc+","+yc);
}
}