3

我正在使用 Google Maps API V3 和 jQuery 创建一个 Phonegap 应用程序。

当检测到坑洞时,应用程序将经度和纬度值分别存储在 MySQL 数据库中。我需要做的是选择任何相对接近并且很可能是同一个坑洼的值。

jQuery/PHP/SQL 中是否有任何方法可以获取相对接近的值,找到它们的均值,然后使用该值继续处理其他一些事情?

基本上我需要的是,一旦一个特定的坑洞被检测到 5 次,它就会在谷歌地图上绘制出来。但是,只有在满足此阈值时。困难在于,在经度和纬度值略有不同的情况下,可能会报告相同的坑洼,具体取决于报告它的设备的准确性。

4

2 回答 2

2

您需要的是Haversine 公式来计算两个给定地点的经纬度坐标之间的距离。基于此,您可以编写一个方法来检查所有接近/接近给定坐标的值,使用以公里为单位的范围。

Haversine公式计算距离

$('some_element').click(function(){
    var location1 = [lat, lon] // Specify Longitude and latitude
    var location2 = [lat, lon] // Specify Longitude and latitude

    var lat1 = location1[0], lon1 = location1[1];
    var lat2 = location2[0], lon2 = location2[1];
    var earth = 6371 // Earth's Radius in Kms

    var dLat = (lat2-lat1) * Math.PI / 180;
    var dLon = (lon2-lon1) * Math.PI / 180;
    var nlat1 = (lat1) * Math.PI / 180;
    var nlat2 = (lat2) * Math.PI / 180;
    // Calculation
    var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(nlat1) * Math.cos(nlat2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    var d = earth * c;
    var distance = Math.round(d*Math.pow(10,2)) / Math.pow(10,2); //Round off to 2 decimal places
    alert(distance);
});
于 2012-12-21T21:46:10.160 回答
1

由于您需要识别新坑附近的坑洼,因此以下代码可以以米为单位执行此操作。它使用带有错误检查的 POD 在 MySQL 查询中使用Haversine 公式。

$lat & $lng 是新坑洞的坐标 & $radius 是以米为单位的搜索半径。6378160 是地球在赤道处的半径,以米为单位。

为确保此级别的准确性,数据库中的坐标必须至少有 4 位小数参见 Wiki

编辑

    try {
    // Prepare search statement
    $stmt1 = $dbh->prepare("SELECT id, lat, lng, cnt, ( 6378160 * acos( cos( radians(?) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(?) ) + sin( radians(?) ) * sin( radians( lat ) ) ) ) AS  distance FROM potholes  HAVING distance <  ? ORDER BY distance LIMIT 0,10");
    // Assign parameters
    $stmt1->bindParam(1,$lat);
    $stmt1->bindParam(2,$lng);
    $stmt1->bindParam(3,$lat);
    $stmt1->bindParam(4,$radius);
    //Execute query
    $stmt1->setFetchMode(PDO::FETCH_ASSOC);
    $stmt1->execute();
    if ($stmt1->rowCount()>0) {//Existing pothole 
        // fetch row
        $row = $stmt1->fetch();
        $id = $row['id'];
        $lat1 = $row['lat'];
        $lng1 = $row['lng'];
        $cnt = $row['cnt'];
        $meanLat = (($lat1*$cnt)+$lat)/($cnt+1);
        $meanLng = (($lng1*$cnt)+$lng)/($cnt+1);
        ++$cnt;
        // Prepare UPDATE statement existing pothole
        $stmt2 = $dbh->prepare("UPDATE  `potholes` SET  `lat` = ?,`cnt` =  ? WHERE  `potholes`.`id` = ? LIMIT 1");
        // Assign parameters
        $stmt2->bindParam(1,$meanLat);
        $stmt2->bindParam(2,$cnt);
        $stmt2->bindParam(3,$id);
        $stmt2->execute();
    //  }
    }else{//New pothole
        // Prepare INSERT statement new pothole
        $stmt3 = $dbh->prepare("INSERT INTO `potholes` (`id`, `lat`, `lng`, `cnt`) VALUES (NULL, ?, ?, '1')");
        // Assign parameters
        $stmt3->bindParam(1,$lat);
        $stmt3->bindParam(2,$lng);
        $stmt3->execute();

    }
echo json_encode($data);//Echo to calling page if required
}



catch(PDOException $e) {
    echo "Error Message.". $e->getMessage() ;// Remove or modify after testing 
    file_put_contents('PDOErrors.txt',date('[Y-m-d H:i:s]').", data2c.php, ". $e->getMessage()."\r\n", FILE_APPEND);  
 }
//Close the connection
$dbh = null; 
于 2012-12-22T08:41:01.127 回答