Формула Haversine, PHP, добавить в 2-й таблице, если применяются условия - PullRequest
0 голосов
/ 06 января 2020

Я пытаюсь реализовать Haversine Formula для проверки широты / долготы таблицы. Мое приложение android сохраняет все входящие местоположения в базе данных, в определенной таблице, inregistrari. Моя цель - получить формулу для проверки новых входящих местоположений на основе долготы и широты, и, если расстояние между новыми значениями и значениями, существующими в alerte (2-я таблица), превышает 50 м, до insert местоположений в обе таблицы (alerte, inregistrari), иначе, только в inregistrari. Новые значения должны быть проверены со всеми местоположениями, сохраненными в alerte. Таким образом, в конце я бы получил таблицу со всеми местоположениями (inregistrari), а второй - только с местоположениями, у которых нет другого местоположения в пределах 50 м (alerte). Я пытался реализовать ( 6371 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) ), но не смог заставить его работать так, как я хочу. Я ищу руководства из-за PHP, на самом деле я еще не очень знаком с этим. В качестве первого шага мне удалось создать PHP для автоматического insert непосредственно в обеих таблицах, теперь мне нужно только реализовать Haversine. Заранее спасибо!

php попробуйте реализовать haversine:

case 'alerta':

            if(isTheseParametersAvailable(array('latitudine', 'longitudine', 'id_alerta_tip', 'ID_user'))){

                $problema = $_POST['id_alerta_tip'];
                $latitudine = $_POST['latitudine'];
                $longitudine = $_POST['longitudine'];
                $id = $_POST['ID_user'];

                $stmt = $conn->prepare("SELECT latitudine, longitudine FROM inregistrari WHERE latitudine = ? AND longitudine = ?");
                $stmt->bind_param("ss", $latitudine, $longitudine);
                $stmt->execute();
                $stmt->store_result();

                if($stmt->num_rows < 1){
                $stmt = $conn->prepare("INSERT INTO inregistrari (ID_user, id_alerta_tip, latitudine, longitudine) VALUES (?, ?, ?, ?)");
                $stmt->bind_param("ssss", $id, $problema, $latitudine, $longitudine);
                $stmt->execute();
                $stmt->store_result();
                $stmt = $conn->prepare("SELECT * FROM alerte WHERE id_alerta_tip = ?");
                $stmt->bind_param("s",$problema);
                $stmt->execute();
                $stmt->store_result();
                while($row = mysqli_fetch_array($stmt))
                {
                    $latitudine1=$row[latitudine];
                    $longitudine1=$row[longitudine];
                    function getDistance($latitude1, $longitude1, $latitude2, $longitude2) {  
                    $earth_radius = 6371;  
                    $dLat = deg2rad($latitude2 - $latitude1);  
                    $dLon = deg2rad($longitude2 - $longitude1);  
                    $a = sin($dLat/2) * sin($dLat/2) + cos(deg2rad($latitude1)) * cos(deg2rad($latitude2)) * sin($dLon/2) * sin($dLon/2);  
                    $c = 2 * asin(sqrt($a));  
                    $d = $earth_radius * $c;  
                    return $d;  
                    }  
                    if(getDistance($latitudine,$longitudine,$latitudine1,$longitudine1)<0.05)
                    {
                        $stmt = $conn->prepare("INSERT INTO alerte(id_utilizator, latitudine, longitudine, tip_problema) VALUES ('$id','$latitudine', '$longitudine', '$problema')");
                        $stmt->execute();
                    }

                }

                $stmt = $conn->prepare("SELECT id_alerta FROM alerte WHERE latitudine = ? AND longitudine = ?");
                $stmt->bind_param("ss", $latitudine, $longitudine);
                $stmt->execute();
                $stmt->store_result();
                if($stmt->num_rows > 0){
                $stmt->bind_result($id_alerta);
                $stmt->fetch();
                $stmt= $conn->prepare("UPDATE inregistrari SET ID_Alerta_Primarie = ? WHERE latitudine = ? AND longitudine = ?");
                $stmt->bind_param("iss",$id_alerta ,$latitudine, $longitudine);
                $stmt->execute();   
                $stmt->close();
                }else{
                    $response['error'] = false; 
                    $response['message'] = 'Alerta nu a putut fi inregistrata';
                }
                    $response['error'] = false; 
                    $response['message'] = 'Alerta raportata';                      
                }else{
                    $response['error'] = false; 
                    $response['message'] = 'Alerta nu a putut fi inregistrata';
                }
            }else{
                    $response['error'] = false; 
                    $response['message'] = 'Alerta nu a putut fi inregistrata';
                }
            break;

Я попытался реализовать while, чтобы получить все строки сразу, но это не работает. Код перестает выполняться перед оператором while. Спасибо!

1 Ответ

0 голосов
/ 06 января 2020

Вот фактическая формула Хаверсайна:

R = earth’s radius (mean radius = 6,371km)
Δlat = lat2− lat1
Δlong = long2− long1
a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
c = 2.atan2(√a, √(1−a))
d = R.c
Angles need to be in radians to pass to Trigonometric functions

А вот эквивалент MySQL:

SELECT *, 
 ( 3959 * acos( cos( radians(55.864237) ) * cos( radians( latitude ) ) 
 * cos( radians( longitude ) - radians(-4.251806) ) + sin( radians(55.864237) ) 
 * sin( radians( latitude ) ) ) ) AS distance 
FROM postcodes HAVING distance < 20 
ORDER BY distance LIMIT 1;

Здесь я проверяю любой район в пределах 20 миль, но вы можете сделать это так коротко или долго, как вы хотите. Число 3959 в начале запроса - это число, используемое для миль. Если вы используете километры, вы должны изменить это число на 6371. Я ограничил его одной строкой, поскольку я хочу только самое близкое совпадение, однако вы можете захотеть измените это в других ситуациях!

Вот вики для Haversine http://en.wikipedia.org/wiki/Haversine_formula

Удачи!

...