11

私のWeb/MySQLアプリケーションでは、2つのポイント間の距離を取得するために次のようなものがあります。

6371 * acos(cos(radians(-19.83996)) * cos(radians(lat)) * cos(radians(-43.94910) - radians(lng)) + sin(radians(-19.83996)) * sin(radians(lat)))

しかし、私はSQLiteでテストしましたが、これらの数学関数(acos、cos、radians、sin)は存在しません。データベースで直接距離を計算するのに相当するものはありますか?

ただし、この方法を使用して計算するiPhoneアプリケーションがあります。完全に機能しますが、Androidアプリケーションのデータベースでこれと同じ検索を実行する必要があります。

前もって感謝します。

アップデート

距離を計算し、特定のポイントの5つの近くの場所を取得するために9000ポイントがあります。

4

5 に答える 5

7

これが私がすることです:

あなたの与えられたポイントを取りなさい。a(これは洗練される任意の値)を測定し、その周囲の幅が約2 kmの正方形を測定し、東/西/北/南の境界の値を取得します。

この正方形内の要素をクエリします。これは簡単です、あなたはただする必要があります

select * from points where lat between ? and ? and lon between ? and ?

結果を数えます。結果が十分ではありません(明らかに5未満ですが、確かに2倍と言います)。より大きな半径で再試行してください。多すぎる(たとえば、100を超える)場合は、半径を小さくして再試行してください。

十分な数になったら、それらをロードし、必要な5つの要素すべてがXkm幅の正方形だけでなく、Xkm半径の円にもあることを確認します(前の近似で検出されない潜在的なより近い要素がないようにするため)。

別のアプローチ

指定されたポイントが検索しているポイントに比較的近い場合にのみ有効です。

平らな地球の局所近似を測定します。ポイントの近くで、緯度、経度、距離の間の線形関係を考慮することができます。これにより、単純な計算でソートされたリクエストを作成できます。(乗算と加算)。ここでも、SQLiteリクエストの後で適切な計算を行うために、もう少しポイントを選択します。

于 2012-04-12T15:47:38.013 に答える
5

cos_lat_rad、sin_lat_rad、cos_lon_rad、sin_lon_radをテーブルに挿入します

contentValues.put("cos_lat_rad", Math.cos(deg2rad(latitude)));
contentValues.put("sin_lat_rad", Math.sin(deg2rad(latitude)));
contentValues.put("cos_lon_rad", Math.cos(deg2rad(longitude)));
contentValues.put("sin_lon_rad", Math.sin(deg2rad(longitude)));

ラジアン度

public static double deg2rad(double deg) {
    return (deg * Math.PI / 180.0);
}

クエリ、距離(km)

 Cursor c=database.dis(String.valueOf(Math.cos((double) distance / (double) 6380)), Math.cos(deg2rad(latitude)), Math.sin(deg2rad(latitude)), Math.cos(deg2rad(longitude)), Math.sin(deg2rad(longitude)));

クエリ

public Cursor dis(String dis, double cos_lat_rad, double sin_lat_rad, double cos_lon_rad, double sin_lon_rad) {

    Cursor cursor = sqLiteDatabase.rawQuery("SELECT * ,(" + sin_lat_rad + "*\"sin_lat_rad\"+" + cos_lat_rad + "*\"cos_lat_rad\"*(" + sin_lon_rad + "*\"sin_lon_rad\"+" + cos_lon_rad + "*\"cos_lon_rad\")) AS \"distance_acos\" FROM parish WHERE ("+sin_lat_rad+" * \"sin_lat_rad\" +"+ cos_lat_rad +"* \"cos_lat_rad\" * (+"+sin_lon_rad +"* \"sin_lon_rad\" + "+cos_lon_rad +"* \"cos_lon_rad\")) >"+dis+ " ORDER BY \"distance_acos\" DESC ", null);
    return cursor;

}

distance_acosをkmに変換します

 if(c.moveToFirst())
        do {
            double distance_acos= c.getDouble(c.getColumnIndex("distance_acos"));
                     String Distance=String.valueOf(Math.acos(distance_acos) * 6380); 
        }while (c.moveToNext());
于 2016-01-07T10:03:23.760 に答える
0

エンジェルの返信は、SQLiteには存在しないACOS関数がまだ含まれているため、SQLiteの問題を解決しません

徹底的な調査の結果、私が結論付けたのは、SQLiteで使用する大まかな見積もりを次の式で選択する必要があるということです。

kmの距離推定:

SQRT(SQUARE((TO_LAT-FROM_LAT)*110)+
     SQUARE((TO_LONG-FROM_LONG)*COS(TO_LAT)*111)) 
于 2018-05-31T11:44:35.247 に答える
0
For windows:

Install minGw full options. modify environment variable: system variable path, including

c:\mingw\bin


test functionality command:

g++ --version

copy files: extension-functions.c, sqlite3.h, sqlite3ext.h in sqlite3 program directory. Go to sqlite3 directory and compile:

gcc -shared -I "path" -o libsqlitefunctions.so extension-functions.c

   (path = path of sqlite3ext.h; i.e. C:\sqlite3)

If the program is built so that loading extensions is permitted, the following will work:

   sqlite> SELECT load_extension('./libsqlitefunctions.so');

   sqlite> select cos(radians(45));

   0.707106781186548

SQLite Distance implementation:

From:  https://www.movable-type.co.uk/scripts/latlong.html https://en.wikipedia.org/wiki/Haversine_formula

Distance
This uses the ‘haversine’ formula to calculate the great-circle distance between two points – that is, the shortest distance over the earth’s surface – giving an ‘as-the-crow-flies’ distance between the points (ignoring any hills they fly over, of course!).

Haversine
formula:    a = sin²(Δφ/2) + cos φ1 * cos φ2 * sin²(Δλ/2)
c = 2 * atan2( √a, √(1−a) )
c = 2 * 
d = R * c
where   φ is latitude, λ is longitude, R is earth’s radius (mean radius = 6,371km);
note that angles need to be in radians to pass to trig functions!
JavaScript: 
const R = 6378136.6 ; // meters equatorial radius
const φ1 = lat1 * Math.PI/180; // φ, λ in radians
const φ2 = lat2 * Math.PI/180;
const Δφ = (lat2-lat1) * Math.PI/180;
const Δλ = (lon2-lon1) * Math.PI/180;

const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
          Math.cos(φ1) * Math.cos(φ2) *
          Math.sin(Δλ/2) * Math.sin(Δλ/2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

const c = 2 * Math.asen(MIN (1, Math.sqrt(a))); //sqlite implementation

const d = R * c; // in metres

Distance = 2 * R * ASIN( MIN (1, SQRT( SIN( (RADIANS(lat1)-RADIANS(lat2))/2 )^2 + COS( RADIANS(lat1) )*COS( RADIANS(lat2) )*SIN( (RADIANS(long1)-RADIANS(long2))/2 )^2 )))

Physical Properties of Earth https://en.wikipedia.org/wiki/Earth_ellipsoid :Ecuatorial radius: 6378.1366 Kms. Average radius: 6367 Kms


Constant = 2 * 6378136.6 = 12756273.2

SQLite query command with coordinates taken from table PAR: 

ROUND (
      12756273.2 * ASIN(
                        MIN (1 , 
                                SQRT(
                                    POWER( SIN(RADIANS(PAR.Lat1 - PAR.Lat2)/2) , 2) + 
                                    COS(RADIANS(PAR.Lat1)) * COS(RADIANS(PAR.Lat2)) * POWER ( SIN(RADIANS(PAR.Long1 - PAR.Long2)/2) , 2)
                                      )
                            )
                        )
         , 0) AS Distance
于 2020-06-08T14:09:55.060 に答える
-3

androidにはLocationクラスがあり、locationクラスを初期化する必要があり、その中に2つのジオポイント間の距離を与えるdistanceBetween()というメソッドがあります。

このリンクを参照してください

于 2012-04-12T15:16:03.390 に答える