Pergunta

I have json response from the following URL:

http://maps.googleapis.com/maps/api/directions/json?origin=Chicago,IL&destination=Los%20Angeles,CA&sensor=false

JSON path routes[x].legs[y].steps[z].polyline.points:

"azq~Fhc{uOAlB?jB?^?P?P?B@V@|J@fA?xA@xA?h@?B?F?@?tA@xD?h@BnA@|A@rB@f@?d@@v@AxB?d@AZEzA?BIjB?@Cx@?@EzAAlC?F?F?T?B?f@DhHBhD?@?R?l@?R?|CCpDAj@E|DGnDKzCCb@OtBa@rFGfAAb@?@?FAp@?ADbJD|F@bF@@@fERhd@BrEFdDBtBAvBAx@@l@?n@@^@bANnQ?rABnM?jC?hH@fA?@BF?vC?hB?@BpM?@?j@@p@@|KB~Q@pFBbHBvF@z@?f@@jB?nA@z@DzD@VJ~CLfC\|E?B?@HnANtAVpDRpCLbB^dFTxC@LZvDF^HrALlCHEB|H?DBpEB~V?^BhDJR?@@\?~A?nABrL?@?jD@vD@vA?h@?BLx[?x@?B?\?F@pA?h@D~H?@Bz@Dr@RbCLfA\rBPv@@@T~@t@bCPf@z@xBd@rAf@dB\zAN~@PjAT~BFrADxAHX?z@?@HfW?x@?F?@@dD@^F|Y@v@D|JBzH?rB@tAApABxB?bA@dBBxABlAJ~CJrBDfANhBNjCLlCLpBHlBFnB@C?|A?v@AlBCdA?r@EjEC|BItEMdGEtAIfEI|BKzDOzGEjCCl@?@MnDWHSrFSlFAd@?@qA|[Ct@Cj@At@AbA?hBAdBClBQjFQnECr@EAYjFIzAWxDQpCYpEAFItACt@S~C]|GSlEMnCMtCGdAKlBQxDg@bLAT?BKrCAn@Ad@?x@?p@?J?|@@lA@z@BbABn@Bt@@@HnAPxB@LB^LATBPAP~@Z~ALn@?@@Fd@|BjAfGd@dDd@|D\bFDf@D~@@f@B|@@xCJP?dBBEDtE@bADlAREJlABh@Dp@F@@xEJdBHlCF~C@nA?@?@DfG?ADhLBbD@x@?F@~C?dCNbTDrIBxDLbO@~AVY?@DfHEvDGlC]fHGhD?lHPlP?@?B?R?@BfBNbRBpENfQDrGBvCDrEBtEBzABfABx@B~@^FHx@H|@@bDPxAZpCTbDNDBlC@j@@j@BhAHhLBvC?p@BlB?jAAfAAx@C@MzDM|B_@tDq@pF]fB]zAo@fCc@~Am@jBo@dBoCxG?@?@Sd@g@vAY~@St@W|@_@bBUhA_@zBWhBKAOpAKfAEp@Gz@Cb@GpACZAVAh@Ad@AX?f@At@CpB"

I want to decode the Polyline points string to lat long values returned by the above URL using PHP.

I have found some results in Java and Objective C , but I need it in PHP.

Foi útil?

Solução 2

You can have a look to this repo on Github: Google Maps Polyline Encoding Tool

A simple PHP class for translating polyline into an encoded strings for Google Maps.

Outras dicas

Python Implementation

This isn't in PHP, but this thread is near the top of the search results if you're looking to decode polyline strings from Google Maps. In case anyone else needs it (much like I did), here's a Python implementation for decoding polyline strings. This is ported from the Mapbox JavaScript version; more info found on my repo page.

def decode_polyline(polyline_str):
    index, lat, lng = 0, 0, 0
    coordinates = []
    changes = {'latitude': 0, 'longitude': 0}

    # Coordinates have variable length when encoded, so just keep
    # track of whether we've hit the end of the string. In each
    # while loop iteration, a single coordinate is decoded.
    while index < len(polyline_str):
        # Gather lat/lon changes, store them in a dictionary to apply them later
        for unit in ['latitude', 'longitude']: 
            shift, result = 0, 0

            while True:
                byte = ord(polyline_str[index]) - 63
                index+=1
                result |= (byte & 0x1f) << shift
                shift += 5
                if not byte >= 0x20:
                    break

            if (result & 1):
                changes[unit] = ~(result >> 1)
            else:
                changes[unit] = (result >> 1)

        lat += changes['latitude']
        lng += changes['longitude']

        coordinates.append((lat / 100000.0, lng / 100000.0))

    return coordinates
<?php

# Do steps 1-11 given here 
# https://developers.google.com/maps/documentation/utilities/polylinealgorithm
# in reverse order and inverted (i.e. left shift -> right shift, add -> subtract)

$string = "udgiEctkwIldeRe}|x@cfmXq|flA`nrvApihC";
# Step 11) unpack the string as unsigned char 'C'
$byte_array = array_merge(unpack('C*', $string));
$results = array();

$index = 0; # tracks which char in $byte_array
do {
  $shift = 0;
  $result = 0;
  do {
    $char = $byte_array[$index] - 63; # Step 10
    # Steps 9-5
    # get the least significat 5 bits from the byte
    # and bitwise-or it into the result
    $result |= ($char & 0x1F) << (5 * $shift);
    $shift++; $index++;
  } while ($char >= 0x20); # Step 8 most significant bit in each six bit chunk
    # is set to 1 if there is a chunk after it and zero if it's the last one
    # so if char is less than 0x20 (0b100000), then it is the last chunk in that num

  # Step 3-5) sign will be stored in least significant bit, if it's one, then 
  # the original value was negated per step 5, so negate again
  if ($result & 1)
    $result = ~$result;
  # Step 4-1) shift off the sign bit by right-shifting and multiply by 1E-5
  $result = ($result >> 1) * 0.00001;
  $results[] = $result;
} while ($index < count($byte_array));

# to save space, lat/lons are deltas from the one that preceded them, so we need to 
# adjust all the lat/lon pairs after the first pair
for ($i = 2; $i < count($results); $i++) {
  $results[$i] += $results[$i - 2];
}

# chunk the array into pairs of lat/lon values
var_dump(array_chunk($results, 2));

# Test correctness by using Google's polylineutility here:
# https://developers.google.com/maps/documentation/utilities/polylineutility

?>

The simplest possible solution to this problem..

Here's a Link to the Github Repo which includes the class for Encoding/Decoding. It also has the simplest possible usage description.

NOTE: I had to change the class a little bit for decoding a polyline in function decodeValue, the last line in while loop. I had to replace 100000 with 1000000

$points[] = array('x' => $lat/1000000, 'y' => $lng/1000000);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top