5

rgeo-activerecord 0.4.5 gemを使用してPostGIS 1.5データベースに接続するproj4サポート付きのrgeo 0.3.19を使用しているレールアプリがあります。

私のアプリには、地理的なポイント、半径、および多角形を含む Region というモデルがあります。新しいリージョンを保存しようとすると、リージョンのジオファクトリのバッファ関数を使用して、半径と地理的ポイントを使用してポリゴンを作成します。

これは、地域モデルに使用されているジオファクトリーです

GEOFACTORY = RGeo::Geographic.projected_factory(:buffer_resolution => 8, :projection_proj4 => '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs', :projection_srid => 3857)

私が使用している Projection_srid は、Apple および Google マップのメルカトル図法 3857 のものです。問題は、作成されているバッファーが、Apple マップまたは Google マップで描画しているものと同じサイズではないことです。たとえば、組み込みの MapKit 関数 MKCircle を使用すると、

[MKCircle circleWithCenterCoordinate:self.coordinate radius:50];

このように円を描いて重ねていきます。 iOS 描画半径

しかし、データベース内のポリゴン形状を構成するバッファ関数から作成された座標を取得し、それらを Google マップにプロットすると、これが得られます。

GoogleMaps 半径

ご覧のとおり、同じ投影システムを使用して作成されたポリゴンは、実際よりも小さくなっています。この問題は、定義された半径のサイズに基づいて指数関数的に制御不能になります。また、同じ結果が得られた RGeo で定義されている simple_mercator ファクトリを使用しようとしました。

経度、緯度の投影されたポイントがバッファリングされると、間違ったサイズのポリゴンが作成される理由について、誰かが洞察を持っていることを願っています。

4

1 に答える 1

10

ここで観察しているのは、メルカトルの歪みです。メルカトル図法での「50」の距離は、赤道にいる場合を除き、実際の惑星表面の 50 メートルには対応しません。

iOS マップで描かれた円は正しいです。半径 50 メートルです。2番目の画像を作成するためにあなたがしたと思われるのは、ポイントをメルカトル図法に投影することでした(提供したProj4による)。次に、投影座標系で半径 50 のバッファーを作成しました。ただし、緯度 40.61 での 50 メルカトル単位は、地表面の距離で約 37.96 メートルにしか相当しません。そのポリゴンを緯度と経度に投影してプロットすると、38 メートルの円が表示されます。

これを視覚化する 1 つの方法は、Google マップで世界全体の地図を見ることです。赤道上に半径 50 ピクセルの円を描きます。そして、グリーンランドの上に半径 50 ピクセルの別の円を描きます。マップ上 (メルカトル座標) では、これらの円は同じサイズです。しかし、メルカトル図法を知っていれば、グリーンランドが赤道から遠く離れているため、グリーンランドが歪んでいることがわかります。そのため、実際のグリーンランド上の円は、赤道上の円よりも実際にははるかに小さくなります。緯度 40 度では、歪みはそれほど深刻ではありませんが、それでも存在します。

これを修正したい場合は、非常に簡単です。メルカトル図法によるサイズの歪みは、緯度の正割に比例します。つまり、赤道上の 50 メルカトル単位は 50 メートルに相当しますが、緯度 x (ラジアン) での 50 メルカトル単位は 50 / 秒 (x) メートルに相当します。したがって、半径 50 メートルが必要な場合は、50 に秒 (緯度) を掛けて、その数値をメルカトル座標の半径として使用します。RGeo で言えば:

p_lonlat = GEOFACTORY.point(40.610355377197266, -75.38220214843749)
p_proj = p_lonlat.projection
buf_proj = p_proj.buffer(50.0 * (1 / Math.cos(p_lonlat.y / 180.0 * Math::PI)))
buf_lonlat = GEOFACTORY.unproject(buf_proj)
于 2012-12-06T06:54:04.120 に答える