将GPS纬度/经度从不同格式转换为一种格式(在PHP中)

时间:2010-06-16 10:38:25

标签: php geolocation gps

我正在尝试建立对我的应用程序中的位置的支持,并且我期望用户以各种方式输入gps坐标。我需要将以下所有内容转换为:纬度 - 方向(N / s),degres,分钟,秒;经度(E / W) - 度,小时,秒。

注意,每个用户输入都在一行中。我希望我的用户只能以一种方式输入,但是ppl肯定会以下列其中一种方式输入...:

例如: 9.182,-39.140625
9.182 / -39.140625
9.182,-39.140625
9.182 -39.140625
21°16'672S [some_separator] 27°30'318E
21 16 674S [some_separator] 27 30 318E

[some_separator]也可能是一个单独的空间......

最终格式需要是:
latitude.direction = south
latitude.degrees = 21
latitude.minutes = 16
latitude.seconds = 674
longitude.direction =东
longitude.degrees = 27
longitude.minutes = 30
longitude.seconds = 318

(a)要求普通非科技用户输入GPS坐标的最简单方法是什么? (b)我如何将上述内容转换为最终格式?任何处理数据输入变化的内置函数?

我见过GPS format in PHP - 但我需要处理更多变化的输入。

4 个答案:

答案 0 :(得分:11)

我一直在努力解决这个问题(我注意到你编辑了你的问题)。

A)要求普通非科技用户输入GPS坐标的最简单方法是什么?

让非技术用户输入详细信息的最简单,最友好的方式是使用谷歌地图。这将允许您使用Google Geocoder解析其输入(并提供更标准化和格式化的输出)。此外,如果用户输入的位置是他们当前的位置,您可以查看使用某些现代浏览器提供的地理位置功能。<​​/ p>

B)如何将上述内容转换为最终格式?是否有任何内置函数可以处理数据输入中的这些变化?

根据您的测试数据,我已经制定了一个PHP正则表达式来解析它并返回一个可预测的标准化输出。

$rexp = '/^(\-?\d+(?:\.\d+)?)(?:\D+(\d+)\D+(\d+)([NS]?))?[^\d\-]+(\-?\d+(?:\.\d+)?)(?:\D+(\d+)\D+(\d+)([EW]?))?$/i';

$data = array(
  "21° 16' 674S, 27° 30' 318E" ,
  '21 16 674S, 27 30 318E' ,
  '9.182, -39.140625' ,
  '9.182 / -39.140625' ,
  '9.182,-39.140625' ,
  '9.182 -39.140625'
);

foreach( $data as $test ) {
  if( !preg_match( $rexp , $test , $matches ) ) {
    echo '<b>Failed</b>';
  } else {
    // Match Found
  }
}

输出:

array(
  [0] => Matched Text ,
  [1] => Full Degrees ,
  [2] => Minutes ,
  [3] => Seconds ,
  [4] => Hemisphere (N or S) ,
  [5] => Full Degrees ,
  [6] => Minutes ,
  [7] => Seconds ,
  [8] => Hemisphere (E or W)
)

示例:

// Matching 21° 16' 674S, 27° 30' 318E
array(
  [0] => "21° 16' 674S, 27° 30' 318E" ,
  [1] => "21" , [2] => "16" , [3] => "674" , [4] => "S" ,
  [5] => "27" , [6] => "30" , [7] => "318" , [8] => "E"
)

// Matching 21 16 674S, 27 30 318E
array(
  [0]=> "21 16 674S, 27 30 318E" ,
  [1]=> "21" , [2]=> "16" , [3]=> "674" , [4]=> "S" ,
  [5]=> "27" , [6]=> "30" , [7]=> "318" , [8]=> "E"
)

// Matching 9.182, -39.140625
array(
  [0]=> "9.182, -39.140625" ,
  [1]=>   "9.182" ,    [2]=> "" , [3]=> "" , [4]=> "" ,
  [5]=> "-39.140625" , [6]=> "" , [7]=> "" , [8]=> ""
)

// Matching 9.182 / -39.140625
array(
  [0]=> "9.182 / -39.140625" ,
  [1]=>   "9.182" ,    [2]=> "" , [3]=> "" , [4]=> "" ,
  [5]=> "-39.140625" , [6]=> "" , [7]=> "" , [8]=> ""
)

// Matching 9.182,-39.140625
array(
  [0]=> "9.182,-39.140625" ,
  [1]=>   "9.182" ,    [2]=> "" , [3]=> "" , [4]=> "" ,
  [5]=> "-39.140625" , [6]=> "" , [7]=> "" , [8]=> ""
)

// Matching 9.182 -39.140625
array(
  [0]=> "9.182 -39.140625" ,
  [1]=>   "9.182" ,    [2]=> "" , [3]=> "" , [4]=> "" ,
  [5]=> "-39.140625" , [6]=> "" , [7]=> "" , [8]=> ""
)

然后,您可以随后处理正则表达式的结果,以生成Lat / Long链接的浮点数,以便:

// (Replacing the "Match Found" comment)
  $latitude  = $matches[1]+((int)$matches[2]/60)+((int)$matches[3]/3600)*(strtolower($matches[4])=='s'?-1:1);
  $longitude = $matches[5]+((int)$matches[6]/60)+((int)$matches[7]/3600)*(strtolower($matches[8])=='w'?-1:1);

产生:

// Matching 21° 16' 674S, 27° 30' 318E
$latitude  = -21.4538888889
$longitude =  27.5883333333

// Matching 21 16 674S, 27 30 318E
$latitude  = -21.4538888889
$longitude =  27.5883333333

// Matching 9.182, -39.140625
$latitude  =   9.182
$longitude = -39.140625

// Matching 9.182 / -39.140625
$latitude  =   9.182
$longitude = -39.140625

// Matching 9.182,-39.140625
$latitude  =   9.182
$longitude = -39.140625

// Matching 9.182 -39.140625
$latitude  =   9.182
$longitude = -39.140625

答案 1 :(得分:1)

我认为最好的方法是尽可能限制用户输入,以便他们只输入有效数据。让用户为您分隔令牌中的数据,而不是您试图考虑每一种可能性。根据需要使用尽可能多的文本框/下拉/等,以强制用户正确填充数据。我认为最好尽量减少金额和数量。你将要做的文本解析的变化。

用户以何种格式获取数据?如果它只是一个十进制纬度/长度,例如(50.32,123.55),那么只需要填写两个数字输入,并且可能在框中包含一个示例值。如果用户以度/分/秒格式获取数据,则确切地说明他们需要为每个纬度和经度填写这些字段。如果你同时允许十进制和&amp;它应涵盖所有用户的学位表示。

根据需要提供尽可能多的输入来分解足够的令牌数据,以确保在程序中解释数据时的一致性!

编辑: 如果您发现自己的网站可以接受,那么这个简单的想法就是拥有一个Google地图,用户可以将标记拖动到所需的位置。然后,您可以从该标记以一致的方式获取GPS坐标,并将其用于您需要做的任何进一步工作!

答案 2 :(得分:0)

  1. 使用explode()或preg_split()分割纬度和经度。
  2. 对于纬度和经度,确定它是以浮动还是以分钟形式给出。
  3. 将值转换为度数(浮点数)

答案 3 :(得分:0)

您最好的(但无可否认,保证最少)方法是推动用户行为尝试让他们以标准化且易于解析的格式格式化数据。即使只有一两种简单的主要格式来尝试并鼓励它们转换为一个很好的步骤,也可以减少纠错/格式化所需的数量。

除此之外,我建议创建正则表达式,以及这些RegExps背后的函数来标准化您将要使用的数据将是一个解决方案。

我针对您提供的测试数据运行了几个RegExps,但是在创建这方面的防弹解决方案时遇到了问题(可能需要使用几种不同的模式来获取每个组合)。 / p>

我甚至尝试解析通过Google Geocoding API提供的一些测试数据(通常是一个非常有弹性的系统,允许纯文本寻址,以及多种Lat / Long格式),但是,没有快乐。

数据越标准,就越容易创建准确的信息。也许将地图(谷歌地图或其他)集成到输入阶段可以让您更准确地验证输入。