php mysql long karşılaştırmak ve lat, 10 kilometre altında olanları iade

6 Cevap php

Hay ben enlem ve uzun değerlerini kullanarak 2 konum arasında (mil olarak) mesafeyi bulmak ve birbirlerine bir 10 kilometre yarıçapı içinde olup olmadığını kontrol etmek istiyorum.

Bir kullanıcı oturum açtığında, enlem / boylam değerleri oturumda kaydedilir

$_SESSION['lat']
$_SESSION['long']

Ben 2 işlevleri

Bu bir km mesafeyi dışarı çalışır ve bir yuvarlak değeri döndürür

function distance($lat1, $lng1, $lat2, $lng2){
    $pi80 = M_PI / 180;
    $lat1 *= $pi80;
    $lng1 *= $pi80;
    $lat2 *= $pi80;
    $lng2 *= $pi80;
    $r = 6372.797; // mean radius of Earth in km
    $dlat = $lat2 - $lat1;
    $dlng = $lng2 - $lng1;
    $a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlng / 2) * sin($dlng / 2);
    $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
    $km = $r * $c;
    return floor($km * 0.621371192);
}

Lat ve uzun yılların 2 takım arasındaki mesafe 10 altında ise bu bir bool döndürür.

function is_within_10_miles($lat1, $lng1, $lat2, $lng2){
    $d = distance($lat1, $lng1, $lat2, $lng2);
    if( $d <= 10 ){
        return True;
    }else{
        return False;
    }
}

Beklendiği gibi i lat / uzun ürün 2 set vermek ve aralarındaki mesafe benim is_within_10_miles () fonksiyonu false döndürürse, 20 mil demek ise her iki işlevi çalışır.

Şimdi, 'yerleri' (- kimliği, adı, enlem, uzun 4 alanlar) bir veritabanı var.

Ben bir 10 kilometre yarıçapı içindeki tüm yerleri bulmak istiyorum.

Herhangi bir fikir?

EDIT: I can loop through ALL the and perform the is_within_10_miles() on them like this

$query = "SELECT * FROM `locations`";
$result = mysql_query($query);

while($location = mysql_fetch_assoc($result)){
echo $location['name']." is ";
echo distance($lat2, $lon2, $location['lat'], $location['lon']);
echo " miles form your house, is it with a 10 mile radius? ";
if( is_within_10_miles($lat2, $lon2, $location['lat'], $location['lon']) ){
    echo "yeah";
}else{
    echo "no";
}
echo "<br>";

}

Örnek bir sonuç olurdu

goodison park is 7 miles form your house, is it with a 10 mile radius? yeah

Ben nasılsa benim sorgu içinde is_within_10_miles işlevi gerçekleştirmek gerekir.

EDIT EDIT

Bu efsane http://www.zcentric.com/blog/2007/03/calculate_distance_in_mysql_wi.html bu ile geldi ...

SELECT ((ACOS(SIN($lat * PI() / 180) * SIN(lat * PI() / 180) + COS($lat * PI() / 180) * COS(lat * PI() / 180) * COS(($lon - lon) * PI() / 180)) * 180 / PI()) * 60 * 1.1515) AS distance FROM members HAVING distance<='10' ORDER BY distance ASC

Bu aslında çalışır. Sorun i * satırları yerine, bunları tek tek seçerek seçmek istiyor. Ben bunu nasıl yapacağız?

6 Cevap

Muhtemelen kodda bunu yapmak gerekmez, muhtemelen tüm DB yapabilirsiniz. Eğer kullanırsanız spatial index. MySQL docuemtnation for spatial index

EDIT to reflect your edit:

Ben böyle bir şey istiyorum düşünüyorum:

SELECT *, ((ACOS(SIN($lat * PI() / 180) * SIN(lat * PI() / 180) + COS($lat * PI() / 180) * COS(lat * PI() / 180) * COS(($lon - lon) * PI() / 180)) * 180 / PI()) * 60 * 1.1515) AS distance FROM locations HAVING distance<='10' ORDER BY distance ASC

VIA: http://www.zcentric.com/blog/2007/03/calculate_distance_in_mysql_wi.html :

I don't know of any efficient way to do this using SQL, the way I've done it is to build a kd-tree of all the points, then conduct radius or nearest-neighbour searches around your desired point: http://en.wikipedia.org/wiki/Kd-tree There are various examples of implementing kd-trees around the net, though I've not seen one in PHP.

İpucu: sadece her şeyi kare alma ve oldukça gerçek mesafelerden daha kare mesafeleri karşılaştırarak sqrt () önlemek için deneyin.

Sorgunuz önce, on kilometre dairenin maksimum ve minimum enlem ve boylam hesaplayabilirsiniz. Lütfen nerede fıkra ilk bölümü yaklaşık 10 mil-her şekilde kutunun dışında kalan tüm satırları dışarıda olacak bu yüzden size dört numaralar verecek.

Bu dairenin içinde de eğer Sonra fıkra kare içinde sadece olanları denetler karmaşık gerçek mesafe, görmek için.

Eğer gibi düzenlemek gerekir tembel değerlendirme geçerli olup olmadığını veya görmek için DBMS dokümanlar okumak

SELECT *
FROM (SELECT *
      FROM table
      WHERE (simple rough box clause)
     )
WHERE (complex clause)

yerine olağan

SELECT * FROM table WHERE (simple clause) AND (complex clause)

Ben sadece burada terk gidiyorum:

https://gist.github.com/899413

Bu tamsayılar (ARASINDA) bir kare içinde sorgulamak ve çıkış sonuçları yuvarlak yarıçapı döndürmek için KAREKÖK () ile sonuçları azaltmak için nasıl bir örnek. (Ayrıca kilometre mesafeyi verir)

Bunu yapmak için size takarken düz bir harita üzerinde onları bırakmaya kilometre, tüm noktaları dönüştürmek gerekir. (Php fonksiyonlarına bakınız)

Burada her bir cevap devletler gibi sorgu içindeki tüm hesaplamaları yaparak çok daha hızlı - sonuç inanılmaz hızlı bir tamsayı araması olduğunu.

(Ben tam 10 yıl önce bu inşa ... hala mysql ile akıllı bir çözüm gibi görünüyor)

Bu doğru yönde bir işaret olmalıdır - hayır cinas.

Enlem / boylam kullanarak iki yer arasındaki mesafeyi bulmak için mysql fonksiyonu

Sometimes we need to find out list of places that are within a certain radius from a center place where coordinates of the places are saved in the database. Now we have 2 solutions for this – either loop through all the places find the distance from the center point and keep the places that have distance less or equal to the radius, or make an sql function to find the distance of two places, and select the places having distance less or equal to the radius. Obviously the second option is better than the first one. So I have written a Mysql function that does the work for you. In my case, the coordinates were saved in the database as a string of the form "10.1357002, 49.9225563, 0". This is the standard format of coordinates that is used by many (for example Google map). The first element is the longitude, second one is latitude and we can ignore the third (always 0). So here is the Mysql function that returns the distance between 2 coordinates in Miles.

DELIMITER $$

DROP FUNCTION IF EXISTS `GetDistance`$$

CREATE FUNCTION `GetDistance`(coordinate1 VARCHAR(120), coordinate2 VARCHAR(120))
    RETURNS VARCHAR(120)
BEGIN
    DECLARE pos_comma1, pos_comma2 INT;
    DECLARE lon1, lon2, lat1, lat2, distance DECIMAL(12,8);

    select locate(',', coordinate1) into pos_comma1;
    select locate(',', coordinate1, pos_comma1+1) into pos_comma2;
    select CAST(substring(coordinate1, 1, pos_comma1-1) as DECIMAL(12,8)) into lon1;
    select CAST(substring(coordinate1, pos_comma1+1, pos_comma2-pos_comma1-1) as DECIMAL(12,8)) into lat1;

    select locate(',', coordinate2) into pos_comma1;
    select locate(',', coordinate2, pos_comma1+1) into pos_comma2;
    select CAST(substring(coordinate2, 1, pos_comma1-1) as DECIMAL(12,8)) into lon2;
    select CAST(substring(coordinate2, pos_comma1+1, pos_comma2-pos_comma1-1) as DECIMAL(12,8)) into lat2;

        select ((ACOS(SIN(lat1 * PI() / 180) * SIN(lat2 * PI() / 180) + COS(lat1 * PI() / 180) * COS(lat2 * PI() / 180) * COS((lon1 - lon2) * PI() / 180)) * 180 / PI()) * 60 * 1.1515) into distance;
    RETURN distance;

END$$

DELIMITER ;

Örnek:

Eğer "10.1357002, 49.9225563, 0" koordine olan bir yerden 40 kilometre yarıçapı tüm posta kodlarını bulmak için var diyelim. Sen alanlar id, posta kodu, koordinatları olan bir tablo Posta kodları var. Yani sql bu gibi görünmelidir:

  select id, postcode from POSTCODES where GetDistance("10.1357002, 49.9225563, 0", coordinates) <= 40;

Enlem ve boylam orijin noktası

$orig_lat=23.04988655049843;
$orig_lon= 72.51734018325806;
$dist=10;  // Radius;

//Latitude = database field name;
//Longitude = database field name;

$query = SELECT *, 3956 * 2 * ASIN(SQRT( POWER(SIN(($orig_lat -abs(dest.Latitude)) * pi()/180 / 2),2) + COS($orig_lat * pi()/180 ) * COS( abs(dest.Latitude) *  pi()/180) * POWER(SIN(($orig_lon - dest.Longitude) *  pi()/180 / 2), 2) )) as distance FROM tbl_name dest having distance &lt; $dist ORDER BY distance limit 10

Find all location those are in Radius 10 miles.
Working fine!