判斷GPS座標是否在中國

  由於某些原因,國內地圖總會有些偏移。雖說這是個相對偏移,但總會對需要座標定位的應用造成幾百米的漂移。若定位座標在國外,則不會存在此問題。因此我們需要判別當前座標是否在國內,然後決定是否進行座標修正。

      判定座標是否在國內,有下列幾種方法可選:

  1. 通過網絡地圖接口查詢
  2. 根據國家行政邊界判定
  3. 根據國家行政邊界近似判定

 

方法1,通過網絡地圖接口查詢

      網絡接口:http://maps.google.com/maps/api/geocode/xml?latlng=xxx,xxx&sensor=false,其中latlng參數填寫的是座標的經緯度參數。

      例如進行如下調用:http://maps.google.com/maps/api/geocode/xml?latlng=39.829632,117.059326&sensor=false

      返回結果如下:

<?xml version="1.0" encoding="UTF-8"?>
<GeocodeResponse>
 <status>OK</status>
 <result>
  <type>route</type>
  <formatted_address>274 Provincial Rd, Sanhe, Langfang, Hebei, China</formatted_address>
  <address_component>
   <long_name>274 Provincial Rd</long_name>
   <short_name>S274</short_name>
   <type>route</type>
  </address_component>
  <address_component>
   <long_name>Sanhe</long_name>
   <short_name>Sanhe</short_name>
   <type>sublocality</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Langfang</long_name>
   <short_name>Langfang</short_name>
   <type>locality</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Hebei</long_name>
   <short_name>Hebei</short_name>
   <type>administrative_area_level_1</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>China</long_name>
   <short_name>CN</short_name>
   <type>country</type>
   <type>political</type>
  </address_component>
  <geometry>
   <location>
    <lat>39.8483120</lat>
    <lng>117.0741900</lng>
   </location>
   <location_type>APPROXIMATE</location_type>
   <viewport>
    <southwest>
     <lat>39.8292258</lat>
     <lng>117.0728091</lng>
    </southwest>
    <northeast>
     <lat>39.8674069</lat>
     <lng>117.0757736</lng>
    </northeast>
   </viewport>
   <bounds>
    <southwest>
     <lat>39.8292258</lat>
     <lng>117.0728091</lng>
    </southwest>
    <northeast>
     <lat>39.8674069</lat>
     <lng>117.0757736</lng>
    </northeast>
   </bounds>
  </geometry>
 </result>
 <result>
  <type>sublocality</type>
  <type>political</type>
  <formatted_address>Sanhe, Langfang, Hebei, China</formatted_address>
  <address_component>
   <long_name>Sanhe</long_name>
   <short_name>Sanhe</short_name>
   <type>sublocality</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Langfang</long_name>
   <short_name>Langfang</short_name>
   <type>locality</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Hebei</long_name>
   <short_name>Hebei</short_name>
   <type>administrative_area_level_1</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>China</long_name>
   <short_name>CN</short_name>
   <type>country</type>
   <type>political</type>
  </address_component>
  <geometry>
   <location>
    <lat>39.9827180</lat>
    <lng>117.0782950</lng>
   </location>
   <location_type>APPROXIMATE</location_type>
   <viewport>
    <southwest>
     <lat>39.8081545</lat>
     <lng>116.7572022</lng>
    </southwest>
    <northeast>
     <lat>40.0850111</lat>
     <lng>117.2599867</lng>
    </northeast>
   </viewport>
   <bounds>
    <southwest>
     <lat>39.8081545</lat>
     <lng>116.7572022</lng>
    </southwest>
    <northeast>
     <lat>40.0850111</lat>
     <lng>117.2599867</lng>
    </northeast>
   </bounds>
  </geometry>
 </result>
 <result>
  <type>locality</type>
  <type>political</type>
  <formatted_address>Langfang, Hebei, China</formatted_address>
  <address_component>
   <long_name>Langfang</long_name>
   <short_name>Langfang</short_name>
   <type>locality</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Hebei</long_name>
   <short_name>Hebei</short_name>
   <type>administrative_area_level_1</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>China</long_name>
   <short_name>CN</short_name>
   <type>country</type>
   <type>political</type>
  </address_component>
  <geometry>
   <location>
    <lat>39.5380470</lat>
    <lng>116.6837520</lng>
   </location>
   <location_type>APPROXIMATE</location_type>
   <viewport>
    <southwest>
     <lat>39.4355307</lat>
     <lng>116.5841675</lng>
    </southwest>
    <northeast>
     <lat>39.6029123</lat>
     <lng>116.8444061</lng>
    </northeast>
   </viewport>
   <bounds>
    <southwest>
     <lat>38.4703170</lat>
     <lng>116.1166769</lng>
    </southwest>
    <northeast>
     <lat>40.0850111</lat>
     <lng>117.2599867</lng>
    </northeast>
   </bounds>
  </geometry>
 </result>
 <result>
  <type>administrative_area_level_1</type>
  <type>political</type>
  <formatted_address>Hebei, China</formatted_address>
  <address_component>
   <long_name>Hebei</long_name>
   <short_name>Hebei</short_name>
   <type>administrative_area_level_1</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>China</long_name>
   <short_name>CN</short_name>
   <type>country</type>
   <type>political</type>
  </address_component>
  <geometry>
   <location>
    <lat>38.0370570</lat>
    <lng>114.4686650</lng>
   </location>
   <location_type>APPROXIMATE</location_type>
   <viewport>
    <southwest>
     <lat>36.0482067</lat>
     <lng>113.4653687</lng>
    </southwest>
    <northeast>
     <lat>42.6197178</lat>
     <lng>119.8542560</lng>
    </northeast>
   </viewport>
   <bounds>
    <southwest>
     <lat>36.0482067</lat>
     <lng>113.4653687</lng>
    </southwest>
    <northeast>
     <lat>42.6197178</lat>
     <lng>119.8542560</lng>
    </northeast>
   </bounds>
  </geometry>
 </result>
 <result>
  <type>country</type>
  <type>political</type>
  <formatted_address>China</formatted_address>
  <address_component>
   <long_name>China</long_name>
   <short_name>CN</short_name>
   <type>country</type>
   <type>political</type>
  </address_component>
  <geometry>
   <location>
    <lat>35.8616600</lat>
    <lng>104.1953970</lng>
   </location>
   <location_type>APPROXIMATE</location_type>
   <viewport>
    <southwest>
     <lat>18.1535216</lat>
     <lng>73.4994137</lng>
    </southwest>
    <northeast>
     <lat>53.5609740</lat>
     <lng>134.7728100</lng>
    </northeast>
   </viewport>
   <bounds>
    <southwest>
     <lat>18.1535216</lat>
     <lng>73.4994137</lng>
    </southwest>
    <northeast>
     <lat>53.5609740</lat>
     <lng>134.7728100</lng>
    </northeast>
   </bounds>
  </geometry>
 </result>
</GeocodeResponse>


      查詢結果各字段的含義可以參考Google Map API的Reverse Geocoding (Address Lookup)章節。簡化後可以直接判斷返回的字符串中是否存在“<short_name>CN</short_name>”作爲判定所查詢座標是否在中國的依據。

 

方法2,根據國家行政邊界判定

      由於國家行政邊界是由多個簡單多邊形組成的。對多個多邊形進行命中測試 (Hit Testing),只要其中一個多邊形測試成功,則表示整個命中測試成功。但多邊形的命中測試有些麻煩,更簡單的方法是判別點是否在多邊形內(Point in polygon(PIP))。這些算法中簡單高效的莫過於是光線投射算法 (Ray casting algorithm)

      光線投射算法的要義是:在二維空間的任意一點射出一條射線,射線穿過多邊形邊界奇數次則這個點在多邊形內,否則在多邊形外。此方法適用於複雜多邊形。實現此算法往往會限制射線的方向是向右的,這樣的好處是簡化了許多計算。此算法的一個實現參考1987年Paul Bourke教授所寫“Determining if a point lies on the interior of a polygon”的Solution 1。

      在 Windows Phone 7 中的實現,首先需要獲取到國家行政邊界的WGS84座標數據。Alexey Strakh(鏈接有惡意軟件警告)所開發的gMaps應用中包含了此邊界數據。因此,自己可以把數據摳出來。摳出的數據由四部分組成我國的行政邊界:大陸、臺灣省、海南省、崇明島。此數據相對來說比較準確,但是邊界附近誤差較大。每次判別座標是否在此區域內的計算次數較多,大約需要幾百次的幾何計算。

      此方法的實現代碼如下:

方法3,根據國家行政邊界近似判定

      有時候需要一種快速的方法判定,這種快速判定的方法是從Nokia Maps中挖掘出來的。基本思路是:把整個行政區域劃分爲幾個小的矩形,然後再排除掉一些矩形區域。只要一個點在限定的區域內,並且不在排除的區域內,則判定成功,否則失敗。下圖中藍色區域爲限定區域,紅色區域爲排除區域。

此方法的實現代碼如下:

      這幾種方法的比較

  備註
方法1 
通過網絡地圖接口查詢
簡單、準確 
信息量大
速度慢 
依賴網絡
可用Google、Baidu地圖接口
方法2 
根據國家行政邊界判定
準確 代碼相對較多 
判別計算次數較多 
陸地邊界數據誤差較大
方法和數據從gMaps中挖掘
方法3 
根據國家行政邊界近似判定
快速 
相對準確
邊界誤差較大 方法和數據從Nokia Maps中挖掘

 

PS:你可能會問,在方法3中爲什麼把臺灣給排除掉了,這是因爲所謂的座標偏移對臺灣地區不適用。對於香港澳門地區,視情況需要單獨判定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章