序文
今日のモバイルインターネットの広範な開発により、アプリ開発は多くの企業がモバイルインターネットに参入するための最初の選択肢となっています。著者は多くのアプリを開発しており、多くのアプリにはそのような機能があること、つまり近くの人々を取得することを発見しました。近くの人を取得する方法は?実際、それは非常に簡単です。ユーザーの座標(緯度と経度)情報を常にデータベースに記録し、データベース内のすべてのユーザーと現在のユーザーの座標に基づいて特定の範囲内の現在の座標位置を検索することです。
実際、地理的位置が変わらない2つの被験者間の距離については、結果を直接静的にすることが最善です。つまり、構成に直接書き込みます。
たとえば、あなたの家の近くに地下鉄の駅を見つけてください。
この場合、一般的に言えば、「家」の主題は簡単に「走り回る」ことはありません。クエリごとに距離を計算することは意味がありません。距離を維持し、直接照会することが最善です。
別のケース:
アプリユーザーの場所の近くに地下鉄駅を取得します
この場合、ユーザーの地理的位置が変わります。したがって、実際の距離は毎回リアルタイムで計算する必要があります。
実装のアイデア
地球を標準的な球体として扱い、球状距離式を使用して、球面上の2つの点の間の大きな円のアーク長を計算します。
球状距離
public static double getDistance2(double long1、double lat1、double long2、double lat2){lat1 = rad(lat1); lat2 = rad(lat2); double a = lat1 -lat2; double b = rad(long1 -long2); double sa2 = math.sin(a / 2.0); double sb2 = math.sin(b / 2.0); 2 * Earth_mean_radius_km * math.asin(math.sqrt(sa2 * sa2 + math.cos(lat1) * math.cos(lat2) * sb2 * sb2));}2つのポイント間の緯度と経度を知ってください。
もちろん、この計算はデータベースに配置し、距離に応じて並べ替える必要があります。上記の式をSQLに持ち込むだけです。
近くの地下鉄駅の例
地下鉄駅を建設するための例
テーブルステーションの作成(ID int auto_incrementプライマリキー、名前Varchar(20)nullコメント「MRTステーション名」、lng double nullコメント「経度」、lat二重ヌルコメント「ディメンション」);
SQLの例
@targetlat = 31.175702; set @targetlng = 121.519095; select s.id、s.name、s.lng、s.lat、round(6378.138 * 2 * asin(sqrt(pow((@teargetlat * pi() / 180 -s.lat * pi(2) + 180) / 180) / 180() @targetlat * pi() / 180) * cos(s.lat * pi() / 180) * pow((@targetlng * pi() / 180 -s.lng * pi() / 180) / 2)、2)) * 1000)
その中で、TargetLatとTargetlngはユーザーの地理的な場所です。
これは確かに目標を達成できます。ただし、これはすべてのデータとユーザー間の距離を最初に計算し、次にソートすることです。
地下鉄の駅の数が大きすぎると、この操作はエレガントになりません。エレガントではないだけでなく、非常に効率的です。
最適化
実際、距離を計算する前に、多くのデータをフィルタリングできます。
上海の地下鉄駅間の距離を計算するときに、米国地下鉄駅間の距離を計算する必要はありません。
これは、ほとんどのアプリケーションで最初にいくつかの不要なデータをフィルタリングできます。
たとえば、データが都市を区別する場合、SQLを次のように変更できます。
@targetlat = 31.175702; set @targetlng = 121.519095; set @cityid = 605; select s.id、s.name、s.lng、s.lat、round(6378.138 * 2 * asin(sqrt(pow(@tergetlat * pi() / 180- * pi() / 180-) 2) + cos(@targetlat * pi() / 180) * cos(s.lat * pi() / 180) * pow((@targetlng * pi() / 180 -s.lng * pi() / 180) / 2)、2)、2)) * 1000) 20;
上記の改善は、計算する前に計算するデータのほとんどを削除することです。チャンシャ地下鉄駅を探しているとき、最初に上海で検索する必要はありません。
もちろん、ユーザーが事前にある都市を知ることができるので、この状況は少し特別です。
別の改善は次のとおりです。
ユーザーの位置を中心にして、半径rの円を描き、円の外側四辺形の緯度と経度範囲を逆に排出します。距離を計算する前に、外側四辺形の経度と経度の外側にデータを除外します。
理想的な半径Rを指定し、最初に基準を満たすことができないデータを除外します。
逆プッシュアウト外部四辺形の範囲
/***指定された緯度と経度のポイントの4つの頂点の緯度と経度を取得します{@code radius} kmの外部四辺形(厳密に言えば、それは外部キューブである必要があります)** @param lng lng lng lng lungitude* @param lat latitude* @param radius:cm* @return <ng1、lng2、lng1、lng1、lng1、lat2。 tuple4 <double> calcboxbydistfrompt(double lng、double lat、double radius){spatialContext context = spatialContext.geo; rectangle rectangle = context.getDistcalc()// .calcboxbydistfrompt(// context.makepoint(lng、lat)、// radius * com.spatial4j.core.distance.distanceutils.km_to_deg、context、null //);新しいtuple4 <>(rectangle.getMinx()、rectangle.getmaxx()、rectangle.getminy()、rectangle.getmaxy();}を返します。ここで使用されるMaven座標は次のとおりです。
<依存関係> <groupId> com.spatial4j </groupId> <artifactid> spatial4j </artifactid> <バージョン> 0.5 </version> </dependency>
この時点で、SQLはこれに変更できます。
@targetlat = 31.175702; set @targetlng = 121.519095; select s.id、s.name、s.lng、s.lat、round(6378.138 * 2 * asin(sqrt(pow((@teargetlat * pi() / 180 -s.lat * pi(2) + 180) / 180) / 180() @targetlat * pi() / 180) * cos(s.lat * pi() / 180) * pow((@targetlng * pi() / 180 -s.lng * pi() / 180) / 2)、2)) * 1000) $ {lat1}および$ {lat2})distance asc、s.idlimit 20;上記のLNG1、LNG2、LAT1、LAT2は、外部四辺形の範囲です。
引用情報:http://blog.csdn.net/a364572/article/details/50483568
サンプルソースコード
サービス:https://github.com/hylexus/bl ...
データの初期化:https://github.com/hylexus/bl ...
要約します
上記は、この記事のコンテンツ全体です。この記事の内容には、すべての人の研究や仕事に特定の参照値があることを願っています。ご質問がある場合は、メッセージを残してコミュニケーションをとることができます。 wulin.comへのご支援ありがとうございます。