2012-01-02 9 views
-1

私は2つのGPS座標間の距離を計算する関数を持っています。私はデータベースからすべての座標を取得し、現在のものと前のものとの間の距離を得るためにそれらをすべてループし、それを特定のGPSデバイス用の配列に追加します。なんらかの理由でそれは返されたNaNです。私は倍精度浮動小数点型(int)としてキャストしようとしました。ここでNaNを返すPHP

は私のPHPコードです:

function distance($lat1, $lon1, $lat2, $lon2) { 
     $lat1 = round($lat1, 3); 
     $lon1 = round($lon1, 3); 
     $lat2 = round($lat2, 3); 
     $lon2 = round($lon2, 3); 
     $theta = $lon1 - $lon2; 
     $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta)); 
     $dist = acos($dist); 
     $dist = rad2deg($dist); 
     $miles = $dist * 60 * 1.1515; 
     if($miles < 0) $miles = $miles * -1; 
     return ($miles * 1.609344); 
} 
$this->db->query("SELECT * FROM `gps_loc` WHERE `imeiN`='" . $sql . "' AND `updatetime`>=$timeLimit ORDER BY `_id` DESC"); 
    $dist = array(); 
    $dist2 = array(); 
    while($row = $this->db->getResults()) { 
     $dist2[$row['imeiN']] = 0; 
     $dist[$row['imeiN']][]["lat"] = $row['lat']; 
     $dist[$row['imeiN']][count($dist[$row['imeiN']]) - 1]["lng"] = $row['lon']; 
    } 

    foreach($dist as $key=>$d) { 
     $a = 0; 
     $b = 0; 
     foreach($dist[$key] as $n) { 
      if($a > 0) { 
       $dist2[$key] += $this->distance($n['lat'], $n['lng'], $dist[$key][$a - 1]['lat'], $dist[$key][$a - 1]['lng']); 
      } 
      $a++; 
     } 

    } 
    echo json_encode($dist2); 
+2

正確に何がうまくいかないのかを詳細に表示できますか? –

+0

あなたはデータベースから取得する値が文字列ではないことを確認していますか? – Chad

+0

私はdistance()式の各段階でデバッグ出力を入れて、nanが生成された場所を正確に把握することをお勧めします。 –

答えて

2

データベースから取得している値が文字列の場合、この問題が発生する可能性があります。

また、Kolinkが投稿した問題を確認することもできます。

4

sin()cos()の範囲の間-1と$distのあなたの最初の計算によって1.結果の範囲は-2 2にあなたは、このを渡しますacos()に、その引数は-1と1の間でなければなりません。したがって、acos(2)はNaNを与えます。それ以外のものはNaNにもなります。

私は数式が正確であるはずですが、あなたのNaNがどこから来ているのか分かりません。三角法を再確認してください。

0

これは、使用している余弦の球法ですか?

function distance($lat1, $lon1, $lat2, $lon2) 
{ 
    $radius = 3959; //approximate mean radius of the earth in miles, can change to any unit of measurement, will get results back in that unit 

    $delta_Rad_Lat = deg2rad($lat2 - $lat1); //Latitude delta in radians 
    $delta_Rad_Lon = deg2rad($lon2 - $lon1); //Longitude delta in radians 
    $rad_Lat1 = deg2rad($lat1); //Latitude 1 in radians 
    $rad_Lat2 = deg2rad($lat2); //Latitude 2 in radians 

    $sq_Half_Chord = sin($delta_Rad_Lat/2) * sin($delta_Rad_Lat/2) + cos($rad_Lat1) * cos($rad_Lat2) * sin($delta_Rad_Lon/2) * sin($delta_Rad_Lon/2); //Square of half the chord length 
    $ang_Dist_Rad = 2 * asin(sqrt($sq_Half_Chord)); //Angular distance in radians 
    $distance = $radius * $ang_Dist_Rad; 

    return $distance; 
} 

はあなたが使用する単位のために戻って適切な数をナノメートルに半径に光年に半径からの測定のいずれかの形式に地球の半径を変更して得ることができる必要があります:私は半正矢式に切り替えたいです。

4

ポイントが近すぎると、アルゴはNaNを生成します。その場合、$ distは値1をとります。acos(1)はNaNです。その後の計算でもNaNが生成されます。 最初のステップとして座標を丸めるので、丸め後に値が等しくなる可能性が高くなります。NaN

+0

はacos(1)が0を返してはいけませんか? http://www.rapidtables.com/math/trigonometry/arccos.htm#table –

0

すべての回答をありがとう - その結果、私は計算とテストを組み合わせた関数を作成しましたそれぞれがNaNでない場合は、NaNでない場合は計算を平均し、NaNであれば計算を平均し、もう一方はNaNでない場合は、有効なものを使用して計算の1つに失敗した座標のエラーレポートを返します。

function distance_slc($lat1, $lon1, $lat2, $lon2) { 
     $earth_radius = 3960.00; # in miles 
     $distance = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($lon2-$lon1)) ; 
     $distance = acos($distance); 
     $distance = rad2deg($distance); 
     $distance = $distance * 60 * 1.1515; 
     $distance1 = round($distance, 4); 

     // use a second method as well and average   
     $radius = 3959; //approximate mean radius of the earth in miles, can change to any unit of measurement, will get results back in that unit 
    $delta_Rad_Lat = deg2rad($lat2 - $lat1); //Latitude delta in radians 
    $delta_Rad_Lon = deg2rad($lon2 - $lon1); //Longitude delta in radians 
    $rad_Lat1 = deg2rad($lat1); //Latitude 1 in radians 
    $rad_Lat2 = deg2rad($lat2); //Latitude 2 in radians 

    $sq_Half_Chord = sin($delta_Rad_Lat/2) * sin($delta_Rad_Lat/2) + cos($rad_Lat1) * cos($rad_Lat2) * sin($delta_Rad_Lon/2) * sin($delta_Rad_Lon/2); //Square of half the chord length 
    $ang_Dist_Rad = 2 * asin(sqrt($sq_Half_Chord)); //Angular distance in radians 
    $distance2 = $radius * $ang_Dist_Rad; 
     //echo "distance=$distance and distance2=$distance2\n"; 
    $avg_distance=-1; 
    $distance1=acos(2); 
     if((!is_nan($distance1)) && (!is_nan($distance2))){ 
      $avg_distance=($distance1+$distance2)/2; 
     } else { 
      if(!is_nan($distance1)){ 
       $avg_distance=$distance1; 
       try{ 
        throw new Exception("distance1=NAN with lat1=$lat1 lat2=$lat2 lon1=$lon1 lon2=$lon2"); 
       } catch(Exception $e){ 
        trigger_error($e->getMessage()); 
        trigger_error($e->getTraceAsString()); 
       } 
      } 
      if(!is_nan($distance2)){ 
       $avg_distance=$distance2; 
       try{ 
        throw new Exception("distance1=NAN with lat1=$lat1 lat2=$lat2 lon1=$lon1 lon2=$lon2"); 
       } catch(Exception $e){ 
        trigger_error($e->getMessage()); 
        trigger_error($e->getTraceAsString()); 
       } 
      } 
     } 
     return $avg_distance; 
} 

将来的に誰かがHTHになります。

関連する問題