11

緯度/経度がクローゼットの都市/州または郵便番号を返すことができる無料の(オープンソース)ソリューションが必要です。mysql はオプションではありません。可能であれば、小規模で軽量なデータベースが最適です。

更新: Web サービスはありません。1 日に 5000 万回のインプレッションがあるため、最小のアドオンでも問題があるため、サービス リクエストを追加すると応答時間が長くなります。リクエストに 200 ミリ秒以上追加したくありません。

私はデータベース、lat/lon/zip/city/state を csv で持っています。これは、保存方法だけでなく、さらに重要なことに、それを最も迅速に取得する方法です。

4

10 に答える 10

10

ブルートフォース:すべてのデータをアレイにプリロードします。現在のポイントと配列内の各ポイントの間の距離を計算し(三角関数の代わりに線形代数を使用するこの計算を行う方法がありますが、それが何であるかは思い出せません)、最も近いポイントを見つけます。

反対票を投じる前にこれを読んでください。このようなブルー​​トフォース検索を高速化する方法はいくつかありますが、通常は問題を起こす価値がないことがわかりました。以前にこのアプローチを使用して緯度/経度から最も近いzipを見つけただけでなく、Windows Mobileアプリケーション(処理能力が正確に圧倒的ではない)で使用し、1秒未満の検索時間を達成しました。三角関数の使用を避ける限り、これは費用のかかるプロセスではありません。

更新:zipデータをサブリージョン(たとえば、北西、南東などの象限)に割り当て、各データポイントでリージョンIDを保存することにより、検索時間を短縮できます。次に、検索では、最初に現在の場所がどの地域にあるかを判断し、それらのデータポイントのみと比較します。

境界エラー(現在の場所がその領域の端に近いが、実際には隣接する領域のzipに最も近い場合など)を回避するには、領域をある程度オーバーラップさせる必要があります。これは、一部のzipレコードが複製されるため、データセット全体が少し大きくなることを意味します。

于 2009-08-11T14:35:00.853 に答える
10

これは複雑な答えを持つ非常に興味深い質問です。

緯度/経度を含む都市のデータベースについて言及していますが、都市は単一のポイントではないため、都市 A の大部分が都市 B の中心よりも都市 B の「中心」に近い人口密度の高い地域では、これが大きな違いを生む可能性があります。都市 A. 小さな郊外に囲まれた大都市を取り上げます。大都市の郊外は、大都市自体の中心よりも郊外の中心に近いかもしれません。最も近い市の中心にスナップすることは、市の中心点のボロノイ図であるマップを意味します。このようなマップは、都市部の実際のマップのようには見えません。

特定の緯度/経度の都市と州を知りたい場合は、適切なマップをクエリし、ポリゴン テストでポイントを実行して、それがどのマップにあるかを調べる必要があります。これは計算コストがかかるように思えますが、適切な空間インデックスを使用し、コーディングに注意してください。私は、この地理的クエリへの API アクセスを販売する Web サイトを運営しています。基盤となるエンジン (Java で記述) は、平均クエリ時間 3e-4 秒 (3,000 クエリ以上) で、米国内の都市または最寄りの都市を返すことができます。毎秒)。

私たちはそれを販売していますが、私はそれがどのように機能するかを喜んで説明します. だからここにある:

  • 必要なマップを見つけます。米国の場所については、米国国勢調査がhttp://www.census.gov/geo/www/tiger/tgrshp2010/tgrshp2010.htmlで非常に正確な地図を提供しています。米国の国勢調査マップほど優れたグローバル マップは見つかりませんでしたが、存在する可能性があります。
  • ESRI シェープファイル形式のパーサーを検索または記述します。言語に大きく依存するため、これに関する特定のリンクはありませんが、Web 上には無料および商用のパーサーが多数あります。プログラミング言語とともに「シェープファイル パーサー」を検索してください。
  • マップをメモリにロードします。デジタル マップは、緯度と経度のペアのリストで表されるポリゴンのリストで構成され、通常は反時計回りに並べられます。ほとんどの地図では、緯度/経度のペアが時計回りにリストされているポリゴンとしてリストされているカットアウト (たとえば、南アフリカのレソト) が許可されています。パフォーマンスとメモリ消費の理由から、生の float 配列を使用することをお勧めします (倍精度はメモリを浪費するため避け、可能な場合はネイティブ配列を使用してボックス化を回避します)。
  • 次に、特定のクエリ ポイントが特定のポリゴンに含まれているかどうかを回答するコードが必要です。これは、ポリゴン内のポイントの問題に関する優れた議論です: 2D ポイントがポリゴン内にあるかどうかを判断するにはどうすればよいですか?
  • 私の経験では、別の回答で提案されているブルート フォース手法 (すべてのエンティティをチェックする) は、国内または世界の地図ではうまく機能しません。代わりに、指定された緯度/経度の候補ポリゴンのリストを返す高速空間インデックスを強くお勧めします。ここには多くのオプションがあります。多くの人がツリー ベースのインデックスを提案しますが、私はグリッド インデックスを好む傾向があります。グリッド インデックスの方が高速であり、最近のサーバーは大量のメモリを搭載する傾向があるためです。私が使用した唯一のそのようなインデックスを作成しました。それらが GIS ライブラリに存在することは知っていますが、ほとんどの GIS コードは非常に複雑で、遅く、使いにくいことがわかりました。そのため、緯度/経度のクエリが与えられた場合、空間インデックスから候補ポリゴンのリストを取得し、point-in-polygon 関数を使用して、どの候補にクエリ ポイントが含まれているかを見つけます。
  • クエリ ポイントがどのポリゴンにも含まれていない場合を処理することも重要です。このような場合、おそらく、指定された最大距離までの最も近いそのようなポリゴンを見つけたいと思うでしょう。これを行うには、空間インデックスがポリゴンを含む候補のリストだけでなく、近くのポリゴンのリストを返すことができることを確認する必要があります。また、クエリ ポイントと緯度/経度線分の間の距離を計算するコードも必要です (緯度/経度はユークリッド空間ではないため、これは困難です)。これを行う方法についての良い議論がオンラインで見つからなかったので、独自の方法を考案しました。これは、クエリ ポイント (新しい空間では (0, 0) になる) の周りに線形化された空間を作成することによって機能します経度は、変更された経度が緯度と同じ距離になるように再スケーリングされます (相対経度に緯度のコサインを乗算する必要があります)。この線形化された空間で、標準的な方法を使用して線分上の最も近い点を見つけ (「点と線分の間の最短距離」を参照)、その点を緯度/経度に変換し直して、Haversine 式を使用して線分間の距離を計算します。 2 点 ( 2 つの緯度経度点間の距離を計算しますか? (Haversine 式) を参照)。

以上です。そんなシステムをオンオフで約半年かけて構築しました。私の見積もりでは、少なくとも 3 人月の本格的なコーディングが必要であり、それは主題に詳しい人です (購入するか構築するかを決定する場合は注意してください)。

于 2012-05-07T22:50:47.233 に答える
3

kd ツリーを使用して最近傍検索を高速化します。プラットフォームが何であれ、利用可能な無料の実装がたくさんあるはずです。

于 2009-08-11T15:26:05.167 に答える
1

オープンソースではありませんが、GoogleMapsAPIを使用できるかもしれません。

逆ジオコーディング

于 2009-08-11T14:04:46.767 に答える
1

geonamesをチェックしてください。XML や JSON を返す API があります。また、データベースをダウンロードすることもできます。

于 2009-08-11T14:38:37.010 に答える
0

zipの長さと緯度の両方、および現在の場所がある場合は、半径を計算して、その円内のポイントを見つけることができます。各郵便番号範囲の想定境界を作成すると、検索を高速化できます。

SQL 2008(標準またはエクスプレス)を使用できる場合は、空間データ型を使用できます。

于 2009-08-11T14:28:26.637 に答える
0

別のスレッドは、MaxMindを介してmod_geoipを推奨しています。PHP / .NET / Javaに到達する前に、Apacheレベルで実行されます。 MaxmindジオロケーションAPI:ApacheとPHP

于 2009-08-11T14:23:29.080 に答える
0

Yahoo! _ Placemakerは、これを実行できる無料のWebサービスです。地名(「ニューヨーク市」、「バッキンガム宮殿」)を検索できますが、Geomicroformatを使用して緯度と経度を検索することもできます。

このサービスを使用するには、POSTリクエストを送信すると、XMLが返されます。

小さなコマンドラインの例(Yahoo!アプリIDを隠しました。自分で登録する必要があります):

$ curl -X POST -ddocumentContent='<div class="geo">GEO: <span class="latitude">37.386013</span>, <span class="longitude">-122.082932</span></div>' -ddocumentType='text/html' -dappid='your_yahoo_app_id' http://wherein.yahooapis.com/v1/document

これにより、非常に詳細なXMLドキュメントが返されます。その一部は次のとおりです。

<type>Town</type>
<name><![CDATA[Los Altos, CA, US]]></name>

次のデータも含まれています。

<type>Zip</type>
<name><![CDATA[94024, Los Altos, CA, US]]></name>

Placemakerはあまり使用していませんが、Geocoding APIを使用しており、非常に高速です。これをローカルmemcachedと組み合わせると、ユーザーはデータがローカルではないことを知りません。

于 2009-08-11T14:35:27.967 に答える
0

あなたのソースの場所から最も近い都市はどれくらい離れていると思いますか? 50マイル?200マイル?500マイル?2 つの都市がほぼ等距離にある場合、アルゴリズムが正確に近い方を選択するかどうかは重要ですか? この情報を使用して、検索を高速化できます。

距離の差が小さい (~250 マイル程度はおそらく「小さい」と見なすのに十分近い) と合理的に推測でき、距離の計算が少し「曖昧」である可能性がある場合は、「ブルート フォース」を最適化できます。検索スペースをソースから +/- 5 lat (緯度あたり約 70 マイル、つまり南北に 350 マイル程度)、および +/- 5 の長さ (検索していないと仮定) に制限して確認してください。両極にある都市の場合、これは赤道の約 350 マイルからカナダ北部の約 100 マイルまでの範囲です)。これらの範囲を、問題領域に適していると思われる範囲に調整してください。

三角関数は距離を正確に示すのに役立ちますが、これらのような短い距離の場合、ピタゴラス数は通常、x = 69.1 * (sourcelat - citylat) および y = 53.0 * (sourcelong -市内)。

于 2009-08-11T15:31:08.697 に答える
0

ソース データについては geonames.org データベースを参照してください。

軽いデータベースの場合は、sqlite が適しています。

geonames も Web サービスを実行しますが、Web 呼び出しを使用せずに自分で実行したい場合 (実際に実行しているように聞こえます)、ローカル データベースが必要になります。次に、緯度/経度ポイントのペア間の大圏距離 (Google で検索) を計算し、結果を距離順に並べ替えるために、適切な三角計算を実行するだけです。計算を行う前に検索半径を制限したい場合は、境界ボックスまたは半径を使用することもできます。

ローカル データベースが SQL ベース (これは sqllite3 です) である場合、すべてが SQL クエリになり、'distance' 列を計算するための一連の三角計算が追加されます。半径または境界ボックス。クエリで距離列を計算したら、距離で並べ替えたり、その他の条件を追加したりするのは簡単です。Ruby/Rails を知っていて、これがどのように行われるかの良い例を見たい場合は、GeoKit rails プラグイン ソースを見てください。

于 2009-08-11T14:41:41.717 に答える