将度、分、秒(DMS)转换为十进制的PHP代码。

10
目前,我正在学习使用Google Maps API。根据我所了解的,该API要求使用十进制度(DD)表示纬度和经度。
在我的数据库中,数据以度分秒(DMS)的形式存储。
例如,110° 29' 01.1"
我想问一下,您是否有任何可以将DMS转换为PHP中的DD的方法。而且,这个转换器必须能够接受像上面示例中的单个字符串作为输入。

可能是[将Android中的纬度/经度值(DMS +指南针方向格式)转换为相应的十进制点值]的重复问题(https://dev59.com/ylnUa4cB1Zd3GeqPfO-U)。 - Mike
上面的链接是关于Android的,但原理完全相同。 - Mike
7个回答

21

你可以尝试看看这是否适用于你。

<?php

function DMStoDD($deg,$min,$sec)
{

    // Converting DMS ( Degrees / minutes / seconds ) to decimal format
    return $deg+((($min*60)+($sec))/3600);
}    

function DDtoDMS($dec)
{
    // Converts decimal format to DMS ( Degrees / minutes / seconds ) 
    $vars = explode(".",$dec);
    $deg = $vars[0];
    $tempma = "0.".$vars[1];

    $tempma = $tempma * 3600;
    $min = floor($tempma / 60);
    $sec = $tempma - ($min*60);

    return array("deg"=>$deg,"min"=>$min,"sec"=>$sec);
}    

?>

但我不知道如何将输入分离。 例如:110° 29' 01.1" --> 度数 110,分钟 29,秒数 01.1 - Azlan Nohara
请参考以下链接:https://dev59.com/9XM_5IYBdhLWcg3w-4jw。 - Romi
那篇文章使用了JavaScript函数。我更喜欢使用PHP函数,因为我在phpmyadmin中检索数据。 - Azlan Nohara
在 PHP 中,使用以下代码: $vars=preg_split("/[^\d\w]+/",$longitude); 然后使用 $vars[0]、$vars[1] 和 $vars[2]。 - Alessandro Battistini
1
如果使用此解决方案,请注意,如果使用“-”表示西经,则无法正常工作。 - user2395126

5

这里有一个可以传入经纬度的DMS值并返回转换后的DMS字符串的函数。简单易用。

function DECtoDMS($latitude, $longitude)
{
    $latitudeDirection = $latitude < 0 ? 'S': 'N';
    $longitudeDirection = $longitude < 0 ? 'W': 'E';

    $latitudeNotation = $latitude < 0 ? '-': '';
    $longitudeNotation = $longitude < 0 ? '-': '';

    $latitudeInDegrees = floor(abs($latitude));
    $longitudeInDegrees = floor(abs($longitude));

    $latitudeDecimal = abs($latitude)-$latitudeInDegrees;
    $longitudeDecimal = abs($longitude)-$longitudeInDegrees;

    $_precision = 3;
    $latitudeMinutes = round($latitudeDecimal*60,$_precision);
    $longitudeMinutes = round($longitudeDecimal*60,$_precision);

    return sprintf('%s%s° %s %s %s%s° %s %s',
        $latitudeNotation,
        $latitudeInDegrees,
        $latitudeMinutes,
        $latitudeDirection,
        $longitudeNotation,
        $longitudeInDegrees,
        $longitudeMinutes,
        $longitudeDirection
    );

}

5
我写了一个PHP函数来实现问题所需的功能:将度/分/秒格式的字符串转换为十进制度数。它可以接受多种字符串格式,并支持方向(北/南/东/西)。
以下是代码:

<?php
function convertDMSToDecimal($latlng) {
    $valid = false;
    $decimal_degrees = 0;
    $degrees = 0; $minutes = 0; $seconds = 0; $direction = 1;
    // Determine if there are extra periods in the input string
    $num_periods = substr_count($latlng, '.');
    if ($num_periods > 1) {
        $temp = preg_replace('/\./', ' ', $latlng, $num_periods - 1); // replace all but last period with delimiter
        $temp = trim(preg_replace('/[a-zA-Z]/','',$temp)); // when counting chunks we only want numbers
        $chunk_count = count(explode(" ",$temp));
        if ($chunk_count > 2) {
            $latlng = $temp; // remove last period
        } else {
            $latlng = str_replace("."," ",$latlng); // remove all periods, not enough chunks left by keeping last one
        }
    }

    // Remove unneeded characters
    $latlng = trim($latlng);
    $latlng = str_replace("º","",$latlng);
    $latlng = str_replace("'","",$latlng);
    $latlng = str_replace("\"","",$latlng);
    $latlng = substr($latlng,0,1) . str_replace('-', ' ', substr($latlng,1)); // remove all but first dash

    if ($latlng != "") {
        // DMS with the direction at the start of the string
        if (preg_match("/^([nsewNSEW]?)\s*(\d{1,3})\s+(\d{1,3})\s+(\d+\.?\d*)$/",$latlng,$matches)) {
            $valid = true;
            $degrees = intval($matches[2]);
            $minutes = intval($matches[3]);
            $seconds = floatval($matches[4]);
            if (strtoupper($matches[1]) == "S" || strtoupper($matches[1]) == "W")
                $direction = -1;
        }
        // DMS with the direction at the end of the string
        if (preg_match("/^(-?\d{1,3})\s+(\d{1,3})\s+(\d+(?:\.\d+)?)\s*([nsewNSEW]?)$/",$latlng,$matches)) {
            $valid = true;
            $degrees = intval($matches[1]);
            $minutes = intval($matches[2]);
            $seconds = floatval($matches[3]);
            if (strtoupper($matches[4]) == "S" || strtoupper($matches[4]) == "W" || $degrees < 0) {
                $direction = -1;
                $degrees = abs($degrees);
            }
        }
        if ($valid) {
            // A match was found, do the calculation
            $decimal_degrees = ($degrees + ($minutes / 60) + ($seconds / 3600)) * $direction;
        } else {
            // Decimal degrees with a direction at the start of the string
            if (preg_match("/^(-?\d+(?:\.\d+)?)\s*([nsewNSEW]?)$/",$latlng,$matches)) {
                $valid = true;
                if (strtoupper($matches[2]) == "S" || strtoupper($matches[2]) == "W" || $degrees < 0) {
                    $direction = -1;
                    $degrees = abs($degrees);
                }
                $decimal_degrees = $matches[1] * $direction;
            }
            // Decimal degrees with a direction at the end of the string
            if (preg_match("/^([nsewNSEW]?)\s*(\d+(?:\.\d+)?)$/",$latlng,$matches)) {
                $valid = true;
                if (strtoupper($matches[1]) == "S" || strtoupper($matches[1]) == "W")
                    $direction = -1;
                $decimal_degrees = $matches[2] * $direction;
            }
        }
    }
    if ($valid) {
        return $decimal_degrees;
    } else {
        return false;
    }
}
?>

以下是在Github上附带测试案例的IT技术相关内容翻译: https://github.com/prairiewest/PHPconvertDMSToDecimal


我更新了@Todd的库,以支持DM->DD和法语西方字母o | O。请访问https://github.com/bcag2/PHPconvertDMSToDecimal/tree/dm2dd。 - bcag2

2
解决了。
 <?php

 function DMStoDD($input)
{
    $deg = " " ;
    $min = " " ;
    $sec = " " ;  
    $inputM = " " ;        


    print "<br> Input is ".$input." <br>";

    for ($i=0; $i < strlen($input); $i++) 
    {                     
        $tempD = $input[$i];
         //print "<br> TempD [$i] is : $tempD"; 

        if ($tempD == iconv("UTF-8", "ISO-8859-1//TRANSLIT", '°') ) 
        { 
            $newI = $i + 1 ;
            //print "<br> newI is : $newI"; 
            $inputM =  substr($input, $newI, -1) ;
            break; 
        }//close if degree

        $deg .= $tempD ;                    
    }//close for degree

     //print "InputM is ".$inputM." <br>";

    for ($j=0; $j < strlen($inputM); $j++) 
    { 
        $tempM = $inputM[$j];
         //print "<br> TempM [$j] is : $tempM"; 

        if ($tempM == "'")  
         {                     
            $newI = $j + 1 ;
             //print "<br> newI is : $newI"; 
            $sec =  substr($inputM, $newI, -1) ;
            break; 
         }//close if minute
         $min .= $tempM ;                    
    }//close for min

        $result =  $deg+( (( $min*60)+($sec) ) /3600 );


        print "<br> Degree is ". $deg*1 ;
        print "<br> Minutes is ". $min ;
        print "<br> Seconds is ". $sec ;
        print "<br> Result is ". $result ;


return $deg + ($min / 60) + ($sec / 3600);

   }
?>

0
如果你也想包含参考资料,你可以使用这个函数:
function DMStoDD($ref, $deg, $min, $sec)
{
    $n = $deg + (($min * 60 + $sec) / 3600);
    if (($ref == "S") or ($ref == "W")) {
        return -$n;
    } else {
        return $n;
    }
}

0
进一步构建在DDtoDMS($dec)函数的基础上,如果您想要获得一个在Google地图上看到的表示字符串,您可以使用下面的函数作为扩展:
function DDtoDMS_string($latitude=false, $longitude=false)
{
    $result = array();
    
    # latitude (N or S)
    if($latitude)
    {
        $degrees = DDtoDMS($latitude);
        
        # data manipulation (2 digits, round, ...)
        $degrees['min'] = sprintf('%02d',$degrees['min']);
        $degrees['sec'] = sprintf('%04.1f',number_format($degrees['sec'], 1));
        
        # N or S
        $north_south = ($degrees['deg'] < 0) ? 'S' : 'N';
        
        array_push($result, abs($degrees['deg']).'°'.$degrees['min'].'\''.$degrees['sec'].'"'.$north_south);
    }
    
    # longitude (E or W)
    if($longitude)
    {
        $degrees = DDtoDMS($longitude);
        
        # data manipulation (2 digits, round, ...)
        $degrees['min'] = sprintf('%02d',$degrees['min']);
        $degrees['sec'] = sprintf('%04.1f',number_format($degrees['sec'], 1));
        
        # E or W
        $east_west = ($degrees['deg'] < 0) ? 'W' : 'E';
        
        array_push($result, abs($degrees['deg']).'°'.$degrees['min'].'\''.$degrees['sec'].'"'.$east_west); 
    }
    
    return implode(' ', $result);
}

例子:

# North West
echo DDtoDMS_string(38.686290, -47.464092);
# Result: 38°41'10.6"N 47°27'50.7"W

# North East
echo DDtoDMS_string(34.505935, 134.732914);
# Result: 34°30'21.4"N 134°43'58.5"E

# South West
echo DDtoDMS_string(-51.102776, -68.786031);
# Result: 51°06'10.0"S 68°47'09.7"W

# South East
echo DDtoDMS_string(-23.724127, 110.561906);
# Result: 23°43'26.9"S 110°33'42.9"E

或者单独使用它:
$latitude = 51.120578;
$longitude = 4.276586;

echo '<p>latitude: '.$latitude.' == '.DDtoDMS_string($latitude).'</p>';
echo '<p>longitude: '.$longitude.' == '.DDtoDMS_string(false, $longitude).'</p>';

给你:

纬度:51.120578 == 51°07'14.1"北
经度:4.276586 == 4°16'35.7"东

希望这有所帮助。


-4

这个非常好用:

<?php echo "<td> $deg&#176 $min' $sec&#8243 </td>";  ?> 

其中deg、min和sec是角度坐标。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接