2013-04-10 73 views
20

我正在繪製地圖中兩點之間的路線。我收到的點是這樣的:使用新的Google Maps API解碼多段線

StringBuilder urlString = new StringBuilder(); 
    urlString.append("http://maps.googleapis.com/maps/api/directions/json"); 
    urlString.append("?origin=");// from 
    urlString.append(Double.toString(src.latitude)); 
    urlString.append(","); 
    urlString.append(Double.toString(src.longitude)); 
    urlString.append("&destination=");// to 
    urlString.append(Double.toString(dest.latitude)); 
    urlString.append(","); 
    urlString.append(Double.toString(dest.longitude)); 
    urlString.append("&sensor=false&mode="); 
    if (tipo != null) { 
     urlString.append(tipo); 
    } 
return urlString.toString; 

我收到來自谷歌的響應,並獲得JSON:

resp = new JSONObject(builder.toString()); 
       Log.i("Location", "Contenido del kml: "+resp); 
       JSONArray routeObject = resp.getJSONArray("routes"); 
       JSONObject routes = routeObject.getJSONObject(0); 
       JSONObject overviewPolylines = routes 
         .getJSONObject("overview_polyline"); 
       String encodedString = overviewPolylines.getString("points"); 
       ArrayList<LatLng> puntos=decodePoly(encodedString); 

我從谷歌獲得的響應:(JSON格式):

Response: {"status":"OK","routes":[{"waypoint_order":[],"summary":"R-3 and A-3","bounds":{"southwest":{"lng":-3.676540000000001,"lat":40.00040000000001},"northeast":{"lng":-2.99933,"lat":40.43357}},"legs":[{"duration":{"value":3267,"text":"54 mins"},"distance":{"value":85039,"text":"85.0 km"},"end_location":{"lng":-2.99933,"lat":40.00040000000001},"start_address":"Calle del General Díaz Porlier, 91, 28006 Madrid, Spain","end_address":"Camino Veinticuatro, 2, 16400 Tarancón, Cuenca, Spain","start_location":{"lng":-3.676540000000001,"lat":40.43331000000001},"via_waypoint":[],"steps":[{"html_instructions":"Head <b>north<\/b> on <b>Calle del Gral Díaz Porlier<\/b> toward <b>Calle de Maldonado<\/b>","duration":{"value":6,"text":"1 min"},"distance":{"value":29,"text":"29 m"},"end_location":{"lng":-3.676520000000001,"lat":40.43357},"polyline":{"points":"[email protected]"},"travel_mode":"DRIVING","start_location":{"lng":-3.676540000000001,"lat":40.43331000000001}},{"html_instructions":"Take the 1st <b>right<\/b> onto <b>Calle de Maldonado<\/b>","duration":{"value":62,"text":"1 min"},"distance":{"value":266,"text":"0.3 km"},"end_location":{"lng":-3.6734,"lat":40.43345},"polyline":{"points":"[email protected]@[email protected]"},"travel_mode":"DRIVING","start_location":{"lng":-3.676520000000001,"lat":40.43357}},{"html_instructions":"Take the 2nd <b>right<\/b> onto <b>Calle de Fco. Silvela<\/b>","duration":{"value":57,"text":"1 min"},"distance":{"value":245,"text":"0.2 km"},"end_location":{"lng":-3.671830000000001,"lat":40.4316},"polyline":{"points":"[email protected]@[email protected]]pBeBLK"},"travel_mode":"DRIVING","start_location":{"lng":-3.6734,"lat":40.43345}},{"html_instructions":"Slight <b>right<\/b> onto <b>Calle de Francisco Silvela<\/b>","duration":{"value":51,"text":"1 min"},"distance":{"value":437,"text":"0.4 km"},"end_location":{"lng":-3.66913,"lat":40.42827},"polyline":{"points":"oxwuF|clUJADAFCbBkAjAeA`BoA^[XUPMLMFEnAeALIdBuAZUPMXS"},"travel_mode":"DRIVING","start_location":{"lng":-3.671830000000001,"lat":40.4316}},{"html_instructions":"Turn <b>right<\/b> onto <b>Pl. de Manuel Becerra<\/b>","duration":{"value":32,"text":"1 min"},"distance":{"value":154,"text":"0.2 km"},"end_location":{"lng":-3.668380000000001,"lat":40.42827},"polyline":{"points":"ucwuF`[email protected][email protected]@@@@[email protected]@@[email protected]@[email protected]@[email protected]"},"travel_mode":"DRIVING","start_location":{"lng":-3.66913,"lat":40.42827}},{"html_instructions":"Turn <b>right<\/b> onto <b>Calle Alcala<\/b>","duration":{"value":61,"text":"1 min"},"distance":{"value":709,"text":"0.7 km"},"end_location":{"lng":-3.66107,"lat":40.43126000000001},"polyline":{"points":"[email protected]}[email protected]@[[email protected]@kB?KAQ]aAI[[email protected]@[email protected]"},"travel_mode":"DRIVING","start_location":{"lng":-3.668380000000001,"lat":40.42827}},{"html_instructions":"Turn <b>right<\/b> onto the ramp to <b>M-30\/A-3\/A-4<\/b>","duration":{"value":44,"text":"1 min"},"distance":{"value":453,"text":"0.5 km"},"end_location":{"lng":-3.660580000000001,"lat":40.42720000000001},"polyline":{"points":"kvwuFt`jU\\[email protected]?rCOvDY"},"travel_mode":"DRIVING","start_location":{"lng":-3.66107,"lat":40.43126000000001}},{"html_instructions":"Continue straight","duration":{"value":45,"text":"1 min"},"distance":{"value":1009,"text":"1.0 km"},"end_location":{"lng":-3.659120000000001,"lat":40.41822000000001},"polyline":{"points":"_}vuFr}[email protected]@[email protected]|[email protected]^[email protected]@[email protected]"},"travel_mode":"DRIVING","start_location":{"lng":-3.660580000000001,"lat":40.42720000000001}},{"html_instructions":"Take exit <b>7B<\/b> to merge onto <b>M-23<\/b> toward <b>Vicálvaro\/R-3\/Valencia<\/b>","duration":{"value":117,"text":"2 mins"},"distance":{"value":2552,"text":"2.6 km"},"end_location":{"lng":-3.63392,"lat":40.41499},"polyline":{"points":"{[email protected]^[email protected]@[email protected][email protected][email protected]@[email protected][email protected]@[email protected]@[email protected][email protected]{[email protected][@[email protected]@@G?A^{BjA}HF[[email protected]][email protected][email protected]@[email protected]@iGXmHDgFCgGG{DM 

最後,我解碼收到的字符串這種方式,我發現在這裏在Stackoverflow大量的答案:

private ArrayList<LatLng> decodePoly(String encoded) { 

    Log.i("Location", "String received: "+encoded); 
    ArrayList<LatLng> poly = new ArrayList<LatLng>(); 
    int index = 0, len = encoded.length(); 
    int lat = 0, lng = 0; 

    while (index < len) { 
     int b, shift = 0, result = 0; 
     do { 
      b = encoded.charAt(index++) - 63; 
      result |= (b & 0x1f) << shift; 
      shift += 5; 
     } while (b >= 0x20); 
     int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); 
     lat += dlat; 

     shift = 0; 
     result = 0; 
     do { 
      b = encoded.charAt(index++) - 63; 
      result |= (b & 0x1f) << shift; 
      shift += 5; 
     } while (b >= 0x20); 
     int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); 
     lng += dlng; 

     LatLng p = new LatLng((int) (((double) lat /1E5)* 1E6), (int) (((double) lng/1E5 * 1E6))); 
     poly.add(p); 
    } 

    for(int i=0;i<poly.size();i++){ 
     Log.i("Location", "Point sent: Latitude: "+poly.get(i).latitude+" Longitude: "+poly.get(i).longitude); 
    } 
    return poly; 
} 

這是我認爲是錯誤的,因爲我設置了地看到,被解碼的點,得到的回答是這樣的:

04-10 13:33:54.578: I/Location(25065): Point sent: Latitude: 90.0 Longitude: -110.0 
04-10 13:33:54.578: I/Location(25065): Point sent: Latitude: 90.0 Longitude: -120.0 
04-10 13:33:54.578: I/Location(25065): Point sent: Latitude: 90.0 Longitude: 100.0 
04-10 13:33:54.578: I/Location(25065): Point sent: Latitude: 90.0 Longitude: 120.0 
04-10 13:33:54.578: I/Location(25065): Point sent: Latitude: 90.0 Longitude: 40.0 

Obviosly,這些點都是很重要解析。結果是,任何地方都沒有畫線。

我的問題是......任何人都知道如何解析來自Google的答案,並將其轉換爲LatLng對象(非GeoPoints對象)?

謝謝!

編輯:

這是將要被解碼的字符串:

04-10 13:50:51.608: I/Location(25065): String to decode: [email protected]}@[email protected]{[email protected]@[email protected]@[email protected]@[email protected]~ZwDtZuC`FKbCVjA`[email protected]@[email protected]][email protected]}DhC{PlBcM~GaY|DyS`BmPRy]yBu\UsNvAqObAuEnC}[email protected][}[email protected]}[email protected]`@~G}\|@aDdDoLn`@}[email protected]`JyV|[email protected]@{ZyBwVkBmOwB{^[email protected]@qYcCyS_DkPmAaK{@gRN{RbCkWrFgUbHmPxLsP|JwIpPwN|G}JfE}I|[email protected]]jCmXbHg\pIgSpGaLnN}P`JsHfVaNbQkHtZyIrOsCnTaCx\aA`[email protected]@nSRz]K`J{AxJiDfNkJjU{WbKkJpGeEpVkPpEiEzMcQjQw]nJyM~IoJ`IoKnH{NrOaWtIeJdNgNrLcPjKqOhIuI~MeJxKgErR{Cn]EjQkBjHqBfJeE|\yTlI_JvEqJxHsS|[email protected]~IeR|[email protected]@sNOoL_B}[email protected]]}N`CuO`D}GjHoHtFwC|[email protected]}BtHaF~D_FjLqSfGqE|[email protected]`BzNeAxQfAlJ{@jIwEjE}FvBuF|B{NtCsNrBgEdHiIdGuIxDoFpGkFhDaBrHyBbF[[email protected]{D|[email protected]@nE_F|Im`@tO_ZxCyEzJmKtHyElG_ClZeF|[email protected]|EuChGkHnK{[email protected][email protected]}[email protected]|BeGlEiYpD}[email protected]}[email protected]`ImMfMmXtFySpCkXRuN][email protected]}LxB{NvD{OjJaYbFsLnCcEtLoMfJyXzIiXbIiL~D_EzQcMjDeF|AcFhA_M`BkXpC_KjCsDnDeClQcHvEgElFqJfF_Jp\[email protected]]`WkWlVy`@nOcTz`@[email protected]_ZbNkQ~Tu^jJaUhCuIpHgUrPi\[email protected]@~McQh\e]vTaU~KcF~KoGhG{KzF{HzGmDbDwBfDiEzB}[email protected]@[email protected]@tDgC`ZeJnXkHrKmB~EeB~C{A`[email protected][email protected]|A}EvAwFdDgAfGSrHUJ\[email protected]@_A|[email protected]|C}[email protected]~Ds][email protected][email protected] 

如果有經緯度甲你的意思是創建的經緯度對象的方式,你可以在decodePoly方法見。這些經緯度對象添加到的PolylineOptions對象,而這添加到地圖中,是這樣的:

PolylineOption ruta=new PolylineOptions(); 
for(int i=0;i<puntos.size();i++){ 
ruta.add(new LatLng(puntos.get(i).latitude, puntos.get(i).longitude));      
}//puntos is an array where the array returned by the decodePoly method are stored     
ruta.color(Color.RED).width(7);      
Polyline polygon=mapa.addPolyline(ruta); 
+0

Can你表明你的迴應是什麼?和你的latlong隊友? – GrIsHu 2013-04-10 11:50:26

+0

添加示例回覆。最有可能的是1E6格式造成麻煩。 – 2013-04-10 12:31:35

+0

我試過在decodePoly方法中做'new LatLng(lat,lng)',並且沒有結果。也嘗試刪除1E6部分,並沒有結果... – Fustigador 2013-04-10 13:00:53

回答

27

我改變,我用這一個我在谷歌長期搜索後發現decodePoly,現在該路線繪製得當。

http://wptrafficanalyzer.in/blog/route-between-two-locations-with-waypoints-in-google-map-android-api-v2/

更改

LatLng p = new LatLng((int) (((double) lat /1E5)* 1E6), (int) (((double) lng/1E5 * 1E6))); 

LatLng p = new LatLng((((double) lat/1E5)),(((double) lng/1E5))); 

而現在的作品。

+0

非常感謝:) – Nizam 2014-08-10 14:36:14

+4

[android-maps-utils](https://github.com/googlemaps/android-maps-utils)有這方面的實用方法和許多其他有用的東西,你可以在谷歌地圖上做 – Zharf 2014-10-22 10:21:25

+0

我也必須做出@Fustigador提到的那種改變,但是直到我花了20分鐘才弄清楚自己,然後在意識到他已經爲此發佈修復之前搖頭,我沒有看到他關於該改變的說明。大聲笑我是個假人。 – BigSauce 2016-01-03 06:02:14

1

這是您在Visual Basic中的功能,我經常使用它。

Structure LatLng 
    Dim Lat As Decimal 
    Dim Lon As Decimal 

End Structure 

Function decodePoly(ByRef encoded As String) As List(Of LatLng) 
    Dim poly As List(Of LatLng) = New List(Of LatLng) 
    Dim index As Integer = 0 
    Dim len As Integer = encoded.Length() 
    Dim lat As Integer = 0 
    Dim lng As Integer = 0 

    While (index < len) 
     Dim b As Integer 
     Dim shift As Integer = 0 
     Dim result As Integer = 0 
     Do 
      b = AscW(encoded.Chars(index)) - 63 
      index += 1 
      result = result Or (b And &H1F) << shift 
      shift += 5 
     Loop While (b >= &H20) 
     Dim dlat As Integer    
     If (result And 1) <> 0 Then 
      dlat = Not (result >> 1) 
     Else 
      dlat = result >> 1 
     End If 
     lat += dlat 

     shift = 0 
     result = 0 
     Do 
      b = AscW(encoded.Chars(index)) - 63 
      index += 1 
      result = result Or (b And &H1F) << shift 
      shift += 5 
     Loop While (b >= &H20) 
     Dim dlng As Integer 
     If (result And 1) <> 0 Then 
      dlng = Not (result >> 1) 
     Else 
      dlng = result >> 1 
     End If 
     lng += dlng 

     Dim p As LatLng = New LatLng With {.Lat = (lat/100000.0), .Lon = (lng/100000.0)} 
     poly.Add(p) 

    End While 

    decodePoly = poly 

End Function 
+0

我不明白這個答案將如何幫助人們閱讀標籤爲[android]的問題。你在Android上使用VB嗎? – 2015-03-12 01:33:41

+0

不,但這是我發現的唯一一個用於解碼多義線的不錯例程。 C#代碼無需修改即可在Windows中運行。也許有人來了,發現誰使用Windows,需要它在VB中。 – 2015-03-26 20:49:44

0

我發佈了類似的用於Android/Java的answer to this question on another post。解碼poly並返回Latlng而不是Geopoint。

+0

這個問題是舊的...我會說這是非常老式的,它不工作了 – Fustigador 2015-09-29 08:09:55

+0

@Fustigador什麼部分不工作了?我最近偶然發現了這個問題並找到了解決辦法。 – Marlon 2015-09-29 08:18:26

+0

我只是猜測,由於時間我的問題 – Fustigador 2015-09-29 08:51:54

0

以下是iOS中的實現,對於任何人來說都很好奇,完全基於@ Fustigador的答案,但轉換爲iOS。請注意,我沒有相應地對代碼進行格式化。爲了返回承諾的對象,我只添加了一些變量。

- (GMSPath *)decodedPolylinePathFromEncodedPolylineString:(NSString *)encodedPolylineString { 


    NSString *decodedPolylineString = @""; 
    GMSMutablePath *decodedPolylinePath = [GMSMutablePath new]; 
    CLLocationCoordinate2D decodedCoordinate; 
    CLLocationDegrees latitude, longitude; 

    int index = 0; 
    NSUInteger len = encodedPolylineString.length; 

    int lat = 0, lng = 0; 

    while (index < len) { 
     int b, shift = 0, result = 0; 
     do { 

      b = [encodedPolylineString characterAtIndex:index++] - 63; 
      result |= (b & 0x1f) << shift; 
      shift += 5; 
     } while (b >= 0x20); 
     int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); 
     lat += dlat; 

     shift = 0; 
     result = 0; 
     do { 
      b = [encodedPolylineString characterAtIndex:index++] - 63; 
      result |= (b & 0x1f) << shift; 
      shift += 5; 
     } while (b >= 0x20); 
     int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); 
     lng += dlng; 

     latitude = (((double) lat/1E5)); 
     longitude = (((double) lng/1E5)); 

     decodedCoordinate = CLLocationCoordinate2DMake(latitude, longitude); 

     decodedPolylineString = [NSString stringWithFormat:@"%f%f", latitude, longitude]; 
     ; 
     NSLog(@"%@",decodedPolylineString); 

     [decodedPolylinePath addCoordinate:decodedCoordinate]; 
    } 


    return decodedPolylinePath; 
} 
3

同樣在Javascript

function decodePolyline(encoded) { 
     if (!encoded) { 
      return []; 
     } 
     var poly = []; 
     var index = 0, len = encoded.length; 
     var lat = 0, lng = 0; 

     while (index < len) { 
      var b, shift = 0, result = 0; 

      do { 
       b = encoded.charCodeAt(index++) - 63; 
       result = result | ((b & 0x1f) << shift); 
       shift += 5; 
      } while (b >= 0x20); 

      var dlat = (result & 1) != 0 ? ~(result >> 1) : (result >> 1); 
      lat += dlat; 

      shift = 0; 
      result = 0; 

      do { 
       b = encoded.charCodeAt(index++) - 63; 
       result = result | ((b & 0x1f) << shift); 
       shift += 5; 
      } while (b >= 0x20); 

      var dlng = (result & 1) != 0 ? ~(result >> 1) : (result >> 1); 
      lng += dlng; 

      var p = { 
       latitude: lat/1e5, 
       longitude: lng/1e5, 
      }; 
      poly.push(p); 
     } 
     return poly; 
    } 
8

對於那些誰現在需要這個,有一個開放源碼庫,關於谷歌地圖Android的API,包括解碼和折線的編碼了很多有用的東西。

查看Android Maps UtilsAndroid Maps Util Github。 與編碼和解碼使用:

PolyUtil.decode(String encodedPath); 
PolyUtil.encode(List<LatLng> path); 
+1

這應該是現在正確的方式去,而不是自己寫解碼器。 – 2017-03-10 06:49:41

0

相同帕斯卡(DELPHI):

var lat,lon,lat_f,lon_f:Double; 
    var index:Integer; 
    var len:Integer; 
    var b:Integer; 
    var shift:Integer; 
    var result:Integer; 
    var encoded:String; 
    var dlat:Integer; 
    var dlng:Integer; 

    encoded:='ibgqGq}ycIMvM'; 
    len:= Length(encoded); 

    lat:=0; 
    lon:=0; 
    While (index <=len) do 
    begin 
    b:=$20; 
    shift:=0; 
    result:=0; 
    While (b >= $20) do 
     begin 
     b:=ord(encoded[index]); 
     b:=b-63; 
     index:= index+1; 
     result:= result OR (b AND $1f) Shl shift; 
     shift:=shift + 5; 
     end; 

     If (result And 1) <> 0 Then 
     dlat:= Not (result Shr 1) 
     Else 
     dlat:= result Shr 1; 
     lat:=lat+dlat; 

     shift:= 0; 
     result:= 0; 
     b:=$20; 
     While (b >= $20) do 
     begin 
     b:=ord(encoded[index]); 
     b:=b-63; 
     index:= index+1; 
     result:= result OR (b AND $1f) Shl shift; 
     shift:=shift + 5; 
     end; 

     If (result And 1) <> 0 Then 
      dlng:= Not (result Shr 1) 
     Else 
      dlng:= result Shr 1; 
     lon:=lon+dlng; 
{ The coordinates of the point are used for our purposes } 
     lon_f:=lon/100000.0; 
     lat_f:=lat/100000.0; 
    end; //while 
0

此方法對於解碼折線有用

private List<LatLng> decodePoly(String encoded) { 
    List<LatLng> poly = new ArrayList<>(); 
    int index = 0, len = encoded.length(); 
    int lat = 0, lng = 0; 

    while (index < len) { 
     int b, shift = 0, result = 0; 
     do { 
      b = encoded.charAt(index++) - 63; 
      result |= (b & 0x1f) << shift; 
      shift += 5; 
     } while (b >= 0x20); 
     int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); 
     lat += dlat; 

     shift = 0; 
     result = 0; 
     do { 
      b = encoded.charAt(index++) - 63; 
      result |= (b & 0x1f) << shift; 
      shift += 5; 
     } while (b >= 0x20); 
     int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); 
     lng += dlng; 

     LatLng p = new LatLng((((double) lat/1E5)), 
       (((double) lng/1E5))); 
     poly.add(p); 
    } 

    return poly; 
} 

這是如何我得到折線

JSONObject poly = route.getJSONObject("overview_polyline"); 
String polyline = poly.getString("points"); 
polyLineList = decodePoly(polyline);