用于限制纬度和经度值的模数

时间:2012-11-13 20:47:42

标签: c math floating-point intervals modulo

我有代表纬度和经度的双打 我可以使用以下功能轻松地将经度限制为( - 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 个答案:

答案 0 :(得分:5)

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

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

  • 将间隔折成两半。如果余数>≥180,则将其从360减去。这将间隔[180, 360)映射到区间(0, 180]。此间隔与下半部分的并集是闭合间隔[0, 180]

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

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

答案 1 :(得分:4)

使用trig函数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度。要保持经度精度,请将180度调整为0度。

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);
}

答案 2 :(得分:2)

如何使用sin和反函数?

asin(sin((lat/180.0)*3.14159265)) * (180.0/3.14159265);

答案 3 :(得分:1)

两个答案都没有(D Stanley,eh9)有效......但是对于eh9来说,我可能会误解一些东西。尝试使用多个值。

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

从那里,答案是:
longitude_new = atan2(sin(latitude),cos(latitude)) - 请注意cos(纬度)

附近的绝对值
atan2f

请注意,在C中,您可能希望使用def find_template_paths(query) Dir[query].reject { |filename| File.directory?(filename) || # deals with case-insensitive file systems. !File.fnmatch(query, filename, File::FNM_EXTGLOB) } end (float vs double)。此外,所有trig函数都需要弧度。