【问题标题】:"Get 100 meters out from" Haversin Formula“走出 100 米”Haversine 公式
【发布时间】:2013-12-29 18:11:11
【问题描述】:

我对使用坐标很感兴趣,我想知道,如何以米为单位获得两点(坐标)之间的距离。经过长时间的搜索,我找到了 Haversine 公式,以及它的 Objective-C 实现here

如下(我自己稍微修改了一下):

- (CGFloat)directMetersFromCoordinate:(CLLocation *)from toCoordinate:(CLLocation *)to {

static const double DEG_TO_RAD = 0.017453292519943295769236907684886;
static const double EARTH_RADIUS_IN_METERS = 6372797.560856;

double latitudeArc  = (from.coordinate.latitude - to.coordinate.latitude) * DEG_TO_RAD;
double longitudeArc = (from.coordinate.longitude - to.coordinate.longitude) * DEG_TO_RAD;
double latitudeH = sin(latitudeArc * 0.5);
latitudeH *= latitudeH;
double lontitudeH = sin(longitudeArc * 0.5);
lontitudeH *= lontitudeH;
double tmp = cos(from.coordinate.latitude*DEG_TO_RAD) * cos(to.coordinate.latitude*DEG_TO_RAD);
return EARTH_RADIUS_IN_METERS * 2.0 * asin(sqrt(latitudeH + tmp*lontitudeH)); }

我的问题是: 如何获得当前位置的 100 米距离(纬度和经度)? 这个公式对我来说太复杂了,我看不懂,所以我不能“把它编码回来”得到我想要的结果。

我只需要实际位置(巴黎、东京、伦敦、纽约等)和一个 (float) 数字表示纬度,一个 (float) 数字表示经度,其中 (float) 数字表示距城市 100 米的距离实际位置。

如果您打开this 页面,您可以在此处“计算”两点之间的 100 米距离(“实际”和一个 100 米距离)。

例如:

Point1: 47.0, 19.0 点2:47.0、19.0013190 --- 那是 0.1000 公里(100 米)的距离。

Point1: 47.0, 19.0 点 2:47.0008995, 19.0 --- 也是 0.1000 km (100 m) 的距离。

在这里你可以看到,在那个坐标(纬度 47.0 和经度 19.0)100 米的距离是 0.0008995(纬度)和 0.0013190(经度)。

我想借助 Haversine 公式获取这些数据,只是不知道如何。

你能帮我弄清楚吗?

谢谢!

更新: 感谢您的回答,现在我没有时间尝试它们,但据我所知,我没有准确解释我想要什么。 也许这是一个更好的例子,我想如何使用这些“100米”:

所以,现在我在坐标“lat x”和“lon y”。在另一个给定坐标“lat a”和“lon b”处还有另一个点(假设是一家酒店)。 我的问题是:如果这家酒店距离我(小于)100 米,我该如何计算?所以没关系,如果只是5米还是99米,两者距离我都小于(或等于)100米。

使用我提供的代码,我可以计算出来,这就是那个公式的用途。

但是,假设我有一百万个其他坐标(酒店位置)要使用。我只需要一份清单,离我(不到)100 米的地方。所以是的,这是一个半径为 100 米的圆圈,我需要其中的结果。

将这些“百万”酒店的所有坐标一一计算距离会花费更多的时间和资源,这就是为什么我认为计算出来会容易得多,纬度有多少100米和经度(改变我们在不同位置的值,这就是为什么我不能简单地使用我在上面的例子中计算出来的那些)。 因此,如果我知道纬度和经度有多少 100 米,例如在伦敦的坐标(如果我在那里),我可以简单地获取距离我(小于)100 米的酒店列表,通过简单划分:

if 
((hotelLocation.coordinate.latitude <= (myLocation.coordinate.latitude + "100metersInLatitude")) || (hotelLocation.coordinate.latitude >= (myLocation.coordinate.latitude - "100metersInLatitude")))
&&
((hotelLocation.coordinate.longitude <= (myLocation.coordinate.longitude + "100metersInLongitude")) || (hotelLocation.coordinate.longitude >= (myLocation.coordinate.longitude - "100metersInLongitude")))
{
   NSLog(@"Be Happy :-) !");
}

我只需要这些“100metersInLatitude”和“100metersInLongitude”,总是从“myLocation”计算而来。

哇哦,我希望有人能理解我刚刚写下的内容,因为这对我来说并不容易,也... :-)))

【问题讨论】:

  • 你需要距离和方位(方向),否则你会得到一个圆(圆上的所有点到中心的距离都相同)

标签: objective-c haversine


【解决方案1】:

假设您有一个经纬度的点,并且您想在方位b上找到另一个距离为d的点,当距离很小时(您说“100米”在表面上非常小)地球)然后你可以做一个简单的近似 - 将地球表面局部视为“平坦”。这是一个实现此功能的简单 C 程序(使用上面的数字)。我更新了它以包含“准确”的公式 - 它只是更多的计算,但它在所有距离上都是准确的(而不仅仅是短距离)。我使用的等式来自您引用的链接 - 副标题“目的地点给定距离和距起点的方位”

更新 - 我将精确计算移到一个单独的函数中,并添加了一个循环来计算从 0 到 359 的所有整数方位的新点,每 30 次打印一次。这给了你我在最初评论中谈到的“圈子”。

#include <stdio.h>
#include <math.h>

double radians(double x) {
  return acos(0.0) * x / 90.0;
}

void calcNewPosition(double lat, double lon, double bearing, double d, double *newLat, double *newLon) {
  double lat1, lon1, br, pi;
  double Re = 6371000;
// convert everything to radians first:
  lat1 = radians(lat);
  lon1 = radians(lon);
  br = radians(bearing);

  pi = 2 * acos(0.0);

  double lat2, lon2;
  lat2 = asin( sin(lat1) * cos(d/Re) +
              cos( lat1 ) * sin( d / Re ) * cos(br ) );
  lon2 = lon1 + atan2(sin(br) * sin( d / Re ) * cos( lat1 ), \
    cos( d / Re ) - sin(lat1 ) * sin( lat2 ) );
  *newLat = 180. * lat2 / pi;
  *newLon = 180. * lon2 / pi;
}


int main(void) {
  double lon = 47., lat=19.;
  double newLongitude, newLatitude;
  double dx, dy, dLong, dLat;
  double Re = 6371000, d = 100, bearing = 0.0;
  double pi;
  double lat1, lon1, br;

  // convert everything to radians first:
  lat1 = radians(lat);
  lon1 = radians(lon);
  br = radians(bearing);

  pi = 2 * acos(0.0);

  // approximate calculation - using equirectangular approximation
  // and noting that distance between meridians (lines of longitude)
  // get closer at higher latitudes, with cos(latitude).
  dx = d * sin(br);                                // distance in E-W direction
  dy = d * cos(br);                                // distance in N-S direction
  dLat = 360 * dy / (2.0 * pi * Re);               // convert N-S to degrees latitude
  dLong = 360 * dx / (2.0 * pi * Re * cos(lat1));  // convert E-W to degrees longitude

  newLatitude = lat + dLat;
  newLongitude = lon + dLong;
  printf("simple forumula: the new position is %.8lf lon, %.8lf lat\n", newLongitude, newLatitude);

  // more accurate formula: based on http://www.movable-type.co.uk/scripts/latlong.html

  double lat2, lon2;
  calcNewPosition(lat, lon, bearing, d, &lat2, &lon2);
  printf("more accurate:   the new position is %.8lf lon, %.8lf lat\n", lon2, lat2);

  // now loop over all bearings and compute the "circle of points":
  int iBearing;
  double lonArray[360], latArray[360];
  for(iBearing = 0; iBearing < 360; iBearing++) {
    calcNewPosition(lat, lon, (double)iBearing, d, &latArray[iBearing], &lonArray[iBearing]);
    if (iBearing % 30 == 0) printf("bearing %03d: new lat = %.8lf, new lon = %.8lf\n", iBearing, latArray[iBearing], lonArray[iBearing]);
  }

return 0;
}

这个的输出是

simple forumula: the new position is 47.00000000 lon, 19.00089932 lat
more accurate:   the new position is 47.00000000 lon, 19.00089932 lat
bearing 000: new lat = 19.00089932, new lon = 47.00000000
bearing 030: new lat = 19.00077883, new lon = 47.00047557
bearing 060: new lat = 19.00044966, new lon = 47.00082371
bearing 090: new lat = 19.00000000, new lon = 47.00095114
bearing 120: new lat = 18.99955034, new lon = 47.00082371
bearing 150: new lat = 18.99922116, new lon = 47.00047557
bearing 180: new lat = 18.99910068, new lon = 47.00000000
bearing 210: new lat = 18.99922116, new lon = 46.99952443
bearing 240: new lat = 18.99955034, new lon = 46.99917629
bearing 270: new lat = 19.00000000, new lon = 46.99904886
bearing 300: new lat = 19.00044966, new lon = 46.99917629
bearing 330: new lat = 19.00077883, new lon = 46.99952443

如您所见,精确到几分之一米(您的代码给出 19.0008995 - 实际上您的结果可能在最后一位数字中“错误”,因为这两种方法同意 8 个有效数字,即使他们使用不同的方程式)。

【讨论】:

    【解决方案2】:

    如果 OP 想要一个与当前位置相距一定距离(100 米)的位置,而没有提供所需的方位,那么这个问题实际上是无法回答的,在该点周围的圆圈中有无限数量的点。

    所以,这个答案可能是也可能不是 OP 想要的,这是CLLocation 计算两点之间距离的一种方式。

    创建两个CLLocation点并使用方法Have you looked at theCLLocationmethod- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location`。

    CLLocation *location1 = [[CLLocation alloc] initWithLatitude:)latitude1 longitude:longitude1];
    CLLocation *location2 = [[CLLocation alloc] initWithLatitude:)latitude2 longitude:longitude2];
    double distance = [location1 distanceFromLocation:location2];
    

    【讨论】:

      【解决方案3】:

      赤道处的地球半径 = 6,371 公里。赤道被划分为360度的经度,所以赤道的每一度代表大约111.32公里。从赤道向极点移动,此距离在极点处减小到零。要计算不同纬度的距离,请将其乘以纬度的余弦

      3 位小数,0.001 度近似于 赤道111.32米
      北纬 30 度时 96.41 米
      北纬 45 度时 78.71 米
      北纬 60 度时 55.66 米
      28.82 米,北纬 75 度

      对于小距离(100 米),毕达哥拉斯定理可用于equirectangular projection 来计算距离。这比Haversine 或Spherical Law of Cosines 简单。

      变量 R = 6371; // 公里
      以弧度表示的纬度/经度

      在我不知道 Objective-C 的伪代码中

      var x = (lng2-lng1) * cos((lat1+lat2)/2);
      var y = (lat2-lat1);
      var d = sqrt(x*x + y*y) * R;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-06
        • 2013-01-22
        • 2011-09-12
        • 2012-06-10
        • 1970-01-01
        • 2015-02-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多