2017-02-24 7 views
5

現在、特定の都市のすべてのジオタグ付きツリーを表示するアプリケーションを構築しています。 次のように私はテーブルからデータをフェッチするために使用しています主な列があり、MySQLの北東および南西座標のバウンディングボックス内のデータベースからすべてのポイントを取得します。

+-----------------+-------------+------+-----+---------+-------+ 
| Field   | Type  | Null | Key | Default | Extra | 
+-----------------+-------------+------+-----+---------+-------+ 
| tree_geotags_id | int(11)  | NO | PRI | None |  | 
| lattitude_dl | double(9,7) | YES |  | NULL |  | 
| longitude_dl | double(9,7) | YES |  | NULL |  | 
+-----------------+-------------+------+-----+---------+-------+ 

表は158000以上の行があります。

現在、私はこれは、それは0.4の半径ですべてのレコードをフェッチん

SELECT gt.tree_geotags_id, gt.latitude_dl, gt.longitude_dl, 
    SQRT(
     POW(69.1 * (gt.latitude_dl - [ center_lat ]), 2) + 
     POW(69.1 * ([ center_lon ] - gt.longitude_dl) * COS(gt.latitude_dl/57.3), 2) 
    ) AS distance 
    FROM tree_geotags_t gt 
    HAVING distance < 0.4 ORDER BY distance 

何を、私の出力を取得するには、次のクエリを使用しています。 地図の中心座標が変更されるたびに(マップパンまたはズームで)、ajax呼び出しを使用してデータを取得し、フェッチされたデータをgeojson形式に変換してマップとしてレイヤーとしてロードします。私がこれを持っている問題は、木が非常に高密度である場所では、マップがすべての点を配置​​するのに時間がかかり、半径上にそれをフェッチするので、マップの外側にある点もロードされますビューポート。

北東と南西の座標を境界として使用して、ビューポート内の座標のデータのみを読み込むクエリが必要です。私はここでかなり長い間検索しましたが、私の要件に適したものは見つかりませんでした。私を助けてください。前もって感謝します..!!

+0

緯度/経度が下限/目標値よりも大きい項目を除外するWHERE句を追加します。 – CBroe

答えて

0

あなたは非常に近いです。あなたの(それ以外の場合は大雑把に間違っている)距離式には、バウンディングボックスチェックの種が含まれています。

この

SET @distance_unit := 69.0; /* for miles, use 111.045 for km. */ 
SET @radius := 1.0;   /* for radius */ 
SET @center_lat := target_latitude_in_degrees; 
SET @center_lon := target_longitude_in_degrees; 

SELECT gt.tree_geotags_id, gt.latitude_dl, gt.longitude_dl 
    FROM tree_geotags_t gt 
WHERE gt.latitude_dl 
    BETWEEN @center_lat - (@radius/@distance_unit) /*east boundary*/ 
     AND @center_lat + (@radius/@distance_unit) /*west*/ 
    AND gt.longitude_dl 
    BETWEEN @center_lon - (@radius/(@distance_unit * COS(RADIANS(@center_lat)))) /*south*/ 
     AND @center_lon + (@radius/(@distance_unit * COS(RADIANS(@center_lat)))) /*north*/ 

はあなたのバウンディングボックスの代わりに、その中心の東、西、北、南の境界を知っていると仮定してみます。それは上記のコードの簡単な適応です。

SELECT gt.tree_geotags_id, gt.latitude_dl, gt.longitude_dl 
    FROM tree_geotags_t gt 
WHERE gt.latitude_dl BETWEEN @east AND @west 
    AND gt.longitude_dl BETWEEN @south AND @north 

バウンディングボックスの座標が度である限り、境界ボックスの辺を隅から派生させる方法は簡単です。それらが何らかの投射単位(例えばtransverse UTM coordinateのような)で与えられている場合、答えがStack Overflow投稿に収まる方法はありません。

このクエリは、化合物インデックス(latitude_dl, longitude_dl, tree_geotags_id)で高速に実行できます。緯度の検索ではインデックス範囲のスキャンが使用され、経度とIDはインデックスから直接取得できます。

距離計算式に問題がありますか?デカルトですが、球面座標を扱っているため、球面余弦法則が必要です。

これは北極または南極の近くでは機能しません(cos(緯度)がゼロに近づく傾向があるため)が、これは問題ありません。あなたは木を扱っていますが、そこではまだ成長しません。

ここでは、トピックに関する包括的な執筆をしています。 http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/

+0

訂正していただきありがとうございますが、私は実際にビューポート内のすべての点を取得するのに役立つクエリを探しています。北東、北西、南東、南西の4つのコーナーの座標を取得しています。しかし、これらの値を使ってクエリを作成して、これらの座標間のすべてのツリーを取得することはできません。 –

+0

これは、ズームインすると、ビューポートの外にポイントが読み込まれるためです。これらが回避できれば、パフォーマンスははるかに速くなる可能性があります。 –

+0

私はあまりにもあなたがこの問題を思慮深く考えています。 –

関連する問題