Google Directions API の encoded poly line をデコード

[Google Directions API ](https://developers.google.com/maps/documentation/directions/quickstart)を使用すると、地図上の経路を返してくれます。

```
https://maps.googleapis.com/maps/api/directions/json?origin=東京&destination=大阪&key=YOUR_API_KEY
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/58063398-ade2-e5ab-631e-dc664c3884e3.png)

返してはくれるのですが、ルートは

```
{
   "geocoded_waypoints" : [
      {
         "geocoder_status" : "OK",
         "place_id" : "ChIJXSModoWLGGARILWiCfeu2M0",
         "types" : [ "colloquial_area", "locality", "political" ]
      },

 :
 :
                     "polyline" : {
                        "points" : "qywxEesatYm@]_@Q_Ag@mAo@k@]oAw@a@W]Qa@UaA_@GCcBu@CA[Mo@U[KQCEAI?IBYL[ZWREB}@j@CBm@^MFA@[PWNGDYNe@Xs@`@[TSNUNWRUNUPOJi@\\a@\\IHWPWRQLo@d@A@WTSNKJA?QPIHGJKNEFGPADCDCJCJGRCNANA@AHCXE\\AHCVAJAHBX"
                     },
 :
 :

```
qywxEesatYm@]... のようにエンコードされた形で返ってきます。
エンコードルールは[こちら](https://developers.google.com/maps/documentation/utilities/polylinealgorithm?hl=ja)

エンコードされた結果は[こちらのページ](https://developers.google.com/maps/documentation/utilities/polylineutility?hl=ja)でデコードできるのですが、自動で変換するためのソースコードを[こちら](https://stackoverflow.com/questions/15924834/decoding-polyline-with-new-google-maps-api)にアップしてくれている方がいました。

今回はこれをUnityから使えるようC#にコンバートしてみました。

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace TmLib
{
    static public class TmMapsLib
    {
        //https://stackoverflow.com/questions/15924834/decoding-polyline-with-new-google-maps-api
        public struct LatLng
        {
            public double lat;
            public double lng;
            public LatLng(double _lat, double _lng)
            {
                lat = _lat;
                lng = _lng;
            }
        }
        static public List<LatLng> DecodePoly(string encoded)
        {
            List<LatLng> poly = new List<LatLng>();
            int index = 0, len = encoded.Length;
            int lat = 0, lng = 0;
            char[] charArr = encoded.ToCharArray();

            while (index < len)
            {
                int b, shift = 0, result = 0;
                do
                {
                    b = charArr[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 = charArr[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;
        }
    }
}

```

使い方はこんな感じです

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PolyLineDecodeTest : MonoBehaviour
{
    string points = "}gwrEkzexXRIBABAJEDCDCDGHKDG?AFMBK@E@I?G?Q?GAICQAACGACCGEIEIEEGEACAAEEGISOUQMKUUKMCCOOQKw@q@IKWUY_@KYAAEEIMIOIOIQMWGMGMCAMYSa@Q]EKIQCEMWWi@Ym@GKKSKU_@q@IQUa@A?Ua@QUOWIKGKEEEESWQWMSIKWa@AAUa@EGMWMWGKSc@?AQa@MYM]Se@GQQe@GSIQOg@IQIUOc@IUEOY{@_@oAGOGSGQ_@oAMe@Og@A?Mg@Oe@Og@EI_@qA_@kA[}@?COa@ACGMKUISEKAEIOISGKKSACSc@GOIOKWGMAAEMEKGQCGGSGSGSMg@GSCM?AEQKk@Ic@QeAUoACQCWM{@CYEWASAGAI?AKqACa@Gu@IuACc@G{@OiC?OC_AAUAo@AkBAwB?_@?K?i@?k@Ak@?S?k@?E?s@?W?YA[?y@?G?_@A[ASAQCe@AGAOM{@I_@Ma@Qk@M[ACIQ[k@EGq@_AQSg@i@q@s@k@q@OMCCACCCAC]g@IMACCCIMIQGMEKIQEOGOK_@K_@AEIa@CIG_@Ii@AGYoBG]Kq@CSEUIc@?CScAIc@Ka@Om@CKSq@EQQe@GSWy@IUGOQe@EIK[i@wA]_AIUGO_@cA_@aA[{@Qe@ACACEOc@mAg@qAEMa@gAACc@mAa@gAQe@Qe@Oa@Y{@[{@?AOi@Mc@CCACCKCKEOK_@AIKe@Ka@GWCOAEEUIi@Ko@M_ACUGg@?CMoA?EIuAEgAAQAQAKCiACk@AS?UCk@Ak@Ck@EwA?MAM?SAQAQAQ?I?IKoDQuGEeA?QGsB?SASAOIyCAY?OKyCEqBCi@Ag@AY?AAO?MMyECi@AWCmAAo@?m@AG?GEoA?GA{@A[Ac@?EAk@Aq@AqA?AAi@?W?_A?aB?g@?c@?a@FuDDoA?SB}@?W@K?K?O?O?G?m@?_@?KAgA?OAc@KsF?WAk@?i@?o@?K?K@S?Q?S?UBwA@i@@k@?y@?M?k@?UCg@Ag@AYCO?GEa@C[AOK{@E_@Iu@Ee@E[E[CUQ_B?ACQCSIm@Eg@EWK{@Gk@E[AMGi@WuBAIGi@AIESCQAIAGEYEUEU?CQu@Me@CMEMWaAKe@GOCK[iACKACSs@Ma@g@gBKc@Su@_@uAo@yBIYK[EMCKISGSAGCG?A_@gAACYy@[y@[w@GOSe@[w@[s@Sg@e@eASe@{@mBSc@g@gAEICIISKQAECCmAqCSe@CEc@aAaAyBg@gASc@?CS_@?ASa@?AGMKUWk@CGCGIUKSEIEMGM_@y@Sc@Se@Sc@GMM[Q]CIiAgCSe@O]CEQe@MYACACSc@Qe@Sc@]y@m@aBAECEEKEKGQGSc@kAQe@Qe@Oc@?AQe@Oe@]cAAEAGAACEGQEUQe@CKAEAE_@mAo@uBOe@AAMe@Oe@_@mAAEACCG?AAAOe@Og@CKKYOg@GUGOOe@Og@Mc@ACACCGK]_@mAOg@_@mASo@K]?A[cACGSq@Wy@Og@g@aBYy@Og@Oe@GSGSOg@Me@?AGQQo@Mg@Os@CEAICKEOGWKe@?CAA]aBGWI]S{@?CAEAECKACGYCKCKAGCOAC?CQu@GUCOEMI_@k@iC}@cEOo@I[AIAGGUQ{@WiAOo@Ki@]}AOo@Om@AICIIa@Sy@Sy@W_AIYACAECIM]K_@CGIY_@cAOe@CGkB}EM_@MY{@_CKUq@iBEKEM{@}BKWeAwCc@iAMa@CEEGCIGSK[GWIUIYMg@CM]aBCMCOEWYcBGYW{AUwAKk@O}@Qy@?AAKMu@Ig@Ki@O}@EUO{@O}@AGSmAKo@Kq@G_@UsAc@oCEWSoAAIG[?EAEAGSuAIs@CWCW?GCQAQM_BCm@AWCe@EgACm@AS?UASAOOuDAO?OAYEy@Cs@Ca@Aa@AIC_ACk@Ci@?MAOAO?G?G?ACg@Cm@AaAAk@AS?m@?u@?_@?S?W@G?c@@c@?E@O@[?WD_B?KBk@@i@@W?K?E@G?G?G?M?KBu@Ba@@i@@o@@M?MDuA@k@Bk@DcB?]B}@@Y@W?M@M?U@W?K@KJoD?EJsD?I@K@i@@S?WBk@@k@Bu@?K@KB}@@O@M?KB[HiAFm@BUDYBMFc@F_@Ha@J_@Li@VaAd@wABIFSBGBIBEBGRg@HSNa@\\u@Ra@b@{@h@_An@eAtA}BrBgD|@yA`@o@DIDIDIFGFKFILU`@q@Xg@P[R[vBsDDGBEBEFI";
    // Start is called before the first frame update
    void Start()
    {

        List<TmLib.TmMapsLib.LatLng> list = TmLib.TmMapsLib.DecodePoly(points);
        foreach(TmLib.TmMapsLib.LatLng latlng in list)
        {
            Debug.Log(latlng.lat+","+latlng.lng);
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/1bb1f9b4-88c0-fcdc-9fbb-cf4c12ec69fa.png)

また、OpenStreetMap APIを使用しても同様なエンコード文字列を返してくれます。

```https://router.project-osrm.org/route/v1/driving/```