3

私は、できればPHPを使用して、最新のプロジェクトで機能を作成することを目指しています。各ユーザーがサインアップするときに、郵便番号を入力します。次に、OpenStreetMapを使用してこれを緯度/経度に変換することを願っています。

とにかく、現在のユーザーの近くにいる他のユーザーを見つけられるようにしたいと思います。多くの人がHaversineの公式を使用しているのを見てきましたが、これは、ユーザーが他のすべてのユーザーの詳細を照会して距離を計算することを意味します。これをキャッシュすることはできますが、新しいユーザーがサインアップするとすぐに古くなります。

次のクエリを実行すると、システムにどのような影響がありますか?

sql = "SELECT zipcode, ( 3959 * acos( cos( radians( {$coords['latitude']} ) ) 
    * cos( radians( latitude ) ) * cos( radians( longitude ) 
    - radians( {$coords['longitude']} ) ) 
    + sin( radians( {$coords['latitude']} ) ) * sin( radians( latitude ) ) ) ) 
    AS distance FROM zipcodes HAVING distance <= {$radius} ORDER BY distance";

それは誰かのブログから引き出されたものです。

まだ開発中なので、登録率や利用者数はわかりません。

特定の半径内で一致するユーザーを見つけるために使用できるフィードバックやその他の方法をいただければ幸いです。

4

3 に答える 3

2

バージョン 4.1 には、mySql に対する GIS および空間拡張機能があります。こちらを参照してください。説明から、ここにあるような問題に使用されることがわかります。

GIS (地理情報システム) は、サイズや位置などの 1 つ以上の空間属性を持つオブジェクトを格納および検索し、そのようなオブジェクトの処理に使用されます。簡単な例は、地理座標を使用して町の住所を保存するシステムです。このかなり静的なデータを、タクシーの場所などの他の情報と組み合わせると、このデータを使用して、特定の場所に最も近いタクシーを見つけることができます。

次のようにMySqlにいくつかのものを追加します。

  • 空間キーと POINT タイプ:

    CREATE TABLE アドレス ( address CHAR(80) NOT NULL, address_loc POINT NOT NULL, PRIMARY KEY(address), SPATIAL KEY(address_loc) );

  • 変換ルーチン

    INSERT INTO address VALUES('Foobar street 12', GeomFromText('POINT(2671 2500)') );

  • GIS計算機能

    SELECT c.cabdriver, ROUND( GLength(LineStringFromWKB(LineString(AsBinary(c.cab_loc), AsBinary(a.address_loc)))) ) AS distance from cab c, address a ORDER BY distance ASC LIMIT 1;

(上のリンクからの例)

于 2009-07-28T13:28:06.657 に答える
1

「特定の半径内」の定義を緩めて、具体的には円ではない場合は、問題を大幅に簡略化できます。「正方形」に単純化すると、2つの単純な「between」句(1つはlat用、もう1つはlong)を使用して、「radius」内のすべての場所を見つけることができます。例えば:

SELECT * FROM location WHERE
  lat BETWEEN (my_lat - radius) AND (my_lat + radius)
  AND long BETWEEN (my_long - radius) AND (my_long + radius);

もちろん、これを使用して、より正確な方法を使用して実際の距離を計算する前に、場所のサブセットを選択することもできます。

于 2009-07-28T13:35:58.397 に答える
0

確かにこれはPHPではなくJavascriptですが、私が想像するように変換するのは簡単です。

地球の曲率を考慮して、2点間の距離を計算します。適切な道路ルートを使用してそれを行うコードに置き換える前に、しばらく前にロジスティクスアプリで使用されます。

それはあなたに役立つかもしれません....

<script type="text/javascript">
function getDistance(lat1,lng1,lat2,lng2)
 {
  p1 = new VELatLong(lat1,lng1);
  p2 = new VELatLong(lat2,lng2);
  miles = true;
  p1.Latitude= latLonToRadians(p1.Latitude);
  p1.Longitude= latLonToRadians(p1.Longitude);
  p2.Latitude= latLonToRadians(p2.Latitude);
  p2.Longitude= latLonToRadians(p2.Longitude);
  var R = 6371; // earth's mean radius in km
  var dLat  = p2.Latitude- p1.Latitude;
  var dLong = p2.Longitude- p1.Longitude;
  var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
  Math.cos(p1.Latitude) * Math.cos(p2.Latitude) * Math.sin(dLong/2) * 
Math.sin(dLong/2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  var disKm = R * c;
  var disMiles = disKm * 0.6214;
  alert (miles ? disMiles : disKm);
 }
 //  convert lat/long in degrees to radians
 function latLonToRadians( point )
 {
  return point * Math.PI / 180;
 }
</script>

ああ、VELatLongオブジェクトはVirtual Earth API(http://msdn.microsoft.com/en-us/library/bb412519.aspx)から来ていますが、基本的には栄光の構造体なので、適切な代替品を見つけることができるはずです。

于 2009-07-28T13:34:19.723 に答える