8

緯度と経度を表す double があります。次の関数を使用して、経度を(-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 を使用するよりもはるかに効率的な方法があります。最もコストのかかる操作は、1 つの分割です。必要な間隔が閉じているという観察が重要です。

  • 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)。複数の値で試してみてください。

残念ながら、適切な答えは高価です。Microsoft Research の以下を参照してください: https://web.archive.org/web/20150109080324/http://research.microsoft.com/en-us/projects/wraplattitudelongitude/

そこから、答えは次のとおりです。
latitude_new = atan(sin(latitude)/fabs(cos(latitude)))-- cos(latitude) 付近の絶対値に注意してください。

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

atan2fC では(float と double)を使用する場合があることに注意してください。また、すべての三角関数はラジアンを取ります。

于 2015-06-29T15:19:23.980 に答える