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

Wil*_*iam 8 c math floating-point modulo intervals

我有代表纬度和经度的双打.
我可以使用以下功能轻松地将经度限制在(-180.0,180.0).

double limitLon(double lon)
{
  return fmod(lon - 180.0, 360.0) + 180.0;
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为一端是独占的,另一端是包容性的.fmod包括0但不包括-360.0.

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

编辑:正如所指出的那样,无论如何都不能进入91度纬度.技术上91应该映射到89.0.哦,男孩,这会改变一切.

eh9*_*eh9 5

除了使用sin和arcsin之外,还有一种更有效的方法.最昂贵的操作是单一部门.关闭所需间隔的观察结果是关键.

  • 除以360并取余数.[0, 360)如所观察到的,这产生了间隔中的数字,其是半开的.

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

  • 从结果中减去90.[-90, 90]根据需要,该间隔是.

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


chu*_*ica 5

使用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;
}
Run Code Online (Sandbox Code Playgroud)

将纬度限制为[-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);
}
Run Code Online (Sandbox Code Playgroud)

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


D S*_*ley 2

使用 和 反函数怎么样sin

asin(sin((lat/180.0)*3.14159265)) * (180.0/3.14159265);
Run Code Online (Sandbox Code Playgroud)