8

我有代表纬度和经度的双打。
我可以使用以下函数轻松地将经度限制为(-180.0, 180.0] 。

double limitLon(double lon)
{
  return fmod(lon - 180.0, 360.0) + 180.0;
}

这是有效的,因为一端是排他的,另一端是包容的。fmod 包括 0 但不包括 -360.0。

谁能想到一个优雅的纬度方法?
所需的间隔是[-90.0, 90.0]。封闭形式的解决方案将是最好的,即没有循环。我认为 fmod() 可能不是首发,因为现在两端都包含在内。

编辑:正如所指出的,一个人无论如何都不能去纬度 91 度。从技术上讲,91 应该映射到 89.0。哦,男孩,这改变了事情。

4

4 回答 4

5

有一种比使用 sin 和 arcsin 更有效的方法。最昂贵的操作是单个部门。观察到所需的间隔是闭合的是关键。

  • 除以 360 并取余数。这会在区间 中产生一个数字[0, 360),如观察到的那样,它是半开的。

  • 将间隔对折。如果余数 >=180,则从 360 中减去它。这会将区间映射[180, 360)到区间(0, 180]。这个区间与下半部分的并集就是闭区间[0, 180]

  • 从结果中减去 90。根据需要,此间隔为[-90, 90]

实际上,这与 完全相同的功能arcsin(sin(x)),但没有费用或数值稳定性的任何问题。

于 2012-11-20T13:57:56.330 回答
5

使用三角函数sin()/cos()在时间上很昂贵,并且会导致精度损失。remainder()使用该功能要好得多。请注意,如果可以的话,结果与 的大小相同x且大小小于 的大小。y

OP是在正确的轨道上!下面的解决方案很容易根据 -180 和 + 180.0 的边缘值进行调整。

#include <math.h>

// Reduce to (-180.0, 180.0]
double Limit_Longitude(double longitude_degrees) {
  // A good implementation of `fmod()` will introduce _no_ loss of precision.
  // -360.0 <= longitude_reduced <=- 360.0
  double longitude_reduced = fmod(longitude_degrees, 360.0);

  if (longitude_reduced > 180.0) {
    longitude_reduced -= 360.0;
  } else if (longitude_reduced <= -180.0) {
    longitude_reduced += 360.0;
  }
  return longitude_reduced;
}

将纬度限制为 [-90 到 +90] 比较棘手,因为 +91 度的纬度会越过北极,但会切换经度 +/- 180 度。要保持经度精度,请向 0 度方向调整 180。

void Limit_Latitude_Longitude(double *latitude_degrees, double *longitude_degrees) {
  *latitude_degrees = Limit_Longitude(*latitude_degrees);
  int flip = 0;
  if (*latitude_degrees > 90.0) {
    *latitude_degrees = 180.0 - *latitude_degrees;
    flip = 1;
  } else if (*latitude_degrees < -90.0) {
    *latitude_degrees = -180.0 - *latitude_degrees;
    flip = 1;
  }
  if (flip) {
    *longitude_degrees += *longitude_degrees > 0 ? -180.0 : 180.0;
  }
  *longitude_degrees = Limit_Longitude(*longitude_degrees);
}

次要:虽然目标是“将经度限制为 (-180.0, 180.0]”,但我希望更普遍需要 [-180.0, 180.0)、[-180.0, 180.0] 的范围。

于 2015-06-29T21:35:45.367 回答
2

如何使用sin和反函数?

asin(sin((lat/180.0)*3.14159265)) * (180.0/3.14159265);
于 2012-11-13T20:56:14.067 回答
1

提供的答案(D Stanley,eh9)都不起作用……尽管对于 eh9,我可能会误解某些东西。尝试使用多个值。

不幸的是,正确的答案很昂贵。请参阅 Microsoft Research 的以下内容:https ://web.archive.org/web/20150109080324/http://research.microsoft.com/en-us/projects/wraplatitudelongitude/ 。

从那里,答案是:
latitude_new = atan(sin(latitude)/fabs(cos(latitude)))- 注意 cos(latitude) 周围的绝对值

longitude_new = atan2(sin(latitude),cos(latitude))

请注意,在 C 中您可能想要使用atan2f(float vs double)。此外,所有三角函数都采用弧度。

于 2015-06-29T15:19:23.980 回答