ルート検索APIの選択肢：Azure MapsとZENRIN Maps APIの比較と活用法

## はじめに

<strong>本記事の目的</strong>
この記事では、Azure MapsとZENRIN Maps APIを使用して大型車のルート検索を行う方法を比較します。どちらのサービスも地図上でルートを検索し、表示する機能を提供していますが、使い方や特徴は異なります。
<strong>対象読者</strong>
この記事は、地図APIを利用してルート検索を行いたい開発者や、Azure MapsとZENRIN Maps APIの違いを知りたい方を対象にしています。

## 両サービスの概要
<strong>Azure Maps</strong>
Azure Mapsは、Microsoftが提供する地図サービスで、ルート検索やジオコーディング、トラフィック情報の取得などが可能です。
特に、大型車のルート検索には、車両の寸法や積載物の種類を考慮したルートを提供する機能があります。
日本のジオコーディングの対象範囲は、市区町村レベルがサポートされています。
[Azure Maps でのジオコーディングの対象範囲](https://learn.microsoft.com/ja-jp/azure/azure-maps/geocoding-coverage)

<strong>ZENRIN Maps API</strong>
ZENRIN Maps APIは、ゼンリンが提供する地図サービスで、日本国内の詳細な地図データを提供しています。
ルート検索機能もあり、特に日本国内での利用に適しています。
また、ルート検索時に「車高」「車幅」「車重」を設定でき、車種を設定すると料金も算出してくれます。
[リファレンス：自動車ルート検索2.0](https://developers.zmaps-api.com/v20/reference/webAPI/route_mbn/drive_ptp.html)

## APIキーの取得
<strong>Azure Maps</strong>
１．[無料アカウント](https://azure.microsoft.com/en-us/pricing/purchase-options/azure-account?icid=azurefreeaccount)で試します。
![Azure1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965389/3aee1574-015c-5747-f90f-618e8ec985d5.png)

２．アカウントを作成します。
![Azure2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965389/4326516c-bcca-c95f-7596-4467f68d76af.png)

３．必須項目とカード情報を入力します。
![Azure4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965389/63058379-a5d7-084c-73d9-36b4f24360ad.png)
![Azure5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965389/118e3df2-5c32-fa4d-97e9-25d7dfa9a758.png)

４．[Microsoft Azureポータル](https://portal.azure.com/#home)にログインします。

５．リソースの作成をします。
![Azure6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965389/cb7dc966-2f38-2b22-b183-98bc27b9ce8b.png)

６．「Azure Maps」を検索ボックスに入力します。
![Azure7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965389/7af9db9c-0757-ef11-0daf-b50d0a5eca3a.png)

７．MarketplaceからAzure Mapsの作成をクリック
![Azure8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965389/d8a1a4d4-c0e3-7a40-d01a-34cba706cb61.png)

８．基本情報を入力します。
![Azure9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965389/23094c07-bd95-0322-f9bd-e8cc90536649.png)

９.リソースの概要画面で「認証」をクリックするとキー情報が表示されます。
![Azure10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965389/ef19a7ef-826b-b8c0-e95d-76a7b7c040c5.png)

<strong>ZENRIN Maps API</strong>
１．検証用IDとパスワード（PW）取得
ZENRIN Maps APIを使用するためには、検証用IDとPWを取得します。

１－１．検証用IDとPWの発行を依頼
[ZENRIN Maps API　無料お試しID　お申込みフォーム（※2か月お試し無料）](https://www.zenrin-datacom.net/solution/zenrin-maps-api/trial?fm_cp=6757baf3203e3a00bb118509&fm_mu=678de84ec56cde026bb22d7f&utm_campaign=6757baf3203e3a00bb118509&utm_medium=else&utm_source=Qiita70)から必要事項を入力して送信します。
![ZMA_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965389/bd6879b2-4ccd-e78b-7cf5-e48d47b7ac73.png)

１－２．検証用IDとPWの確認
フォーム送信から3営業日以内にメールにて検証用IDとPWが発行されます。

２．コンソールにログイン
以下のURLでメールにて送られてきたIDとPWを入力し、[ログイン](https://test-console.zmaps-api.com/)をします。
![ZMA_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965389/3e184372-64c3-1a2d-774c-b049f73f3a4c.png)

３．ユーザーの設定
ユーザー設定にて、「コンソール管理者メールアドレス」と「情報配信用メールアドレス」を設定します。
特にコンソール管理者メールアドレスはZENRIN Maps API コンソールのパスワードを忘れて再設定が必要となった場合に必要になります。
![ZMA_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965389/a9948b72-b0c8-e751-2531-5d1153c1446b.png)

４．チャネルの認証方式の設定、チャネル名変更
チャネルの設定変更は左メニューの「チャネル設定」から行うことができます。
「チャネル設定」押下後表示される画面にはチャネルの一覧が表示されています。
設定を行うチャネルの「編集」ボタンを押下してください。
![ZMA_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965389/6e53e2f0-61f3-e67b-48f4-4454411c2fd4.png)

認証方式は3種類あり、設定したいタブを押下するとそれぞれの認証方式の設定項目が表示されます。
認証方式を有効にするには、「無効」を「有効」に変更してください。
有効にしたい認証方式が複数ある場合は、それぞれの認証方式のタブで「有効」状態に変更してください。
それぞれの設定項目を入力後「変更」ボタンを押下すると有効状態と設定項目が反映されます。
![ZMA_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965389/19bfbee6-b973-3e4b-adde-7e6319ea2b05.png)

５．APIキーの取得・API利用開始
「チャネル一覧」のグレーアウトされている箇所にマウスオーバーすると表示される「APIキー」を使い、
[APIリファレンス](https://developers.zmaps-api.com/v20/reference/)に則りAPIの利用を開始してください。

これで準備は完了です。
![ZMA_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965389/0ff5f1b3-46dd-efe6-55ce-6bdab4a2005f.png)

 ## サンプルコード
<strong>Azure Maps</strong>
```Azure_route.html
﻿<!DOCTYPE html>
<html lang="en">

<head>
    <title>Azure Mapsの大型車ルート検索</title>

    <meta charset="utf-8" />
    <link rel="shortcut icon" href="/favicon.ico" />

    <!-- Azure MapsのCSSとJavaScriptファイルの読み込み -->
    <link href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.css" rel="stylesheet" />
    <script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.js"></script>

    <!-- Azure Maps Rest Helper JavaScriptファイルの読み込み -->
    <script src="https://samples.azuremaps.com/lib/azure-maps/azure-maps-helper.min.js"></script>

    <script>
        var map, datasource;

        // URL for the Azure Maps Route API.
        var routeUrl = 'https://atlas.microsoft.com/route/directions/json?api-version=1.0&routeRepresentation=polyline&view=Auto';

        function getMap() {
            // 地図インスタンスの作成
            map = new atlas.Map('myMap', {
                center: [35.68109033123879, 139.76702393263224],
                zoom: 12,
                view: 'Auto',

                authOptions: {
                    authType: 'subscriptionKey',
                    subscriptionKey: 'YOUR_API_KEY_HERE'
                }
            });

            // 地図が準備されたら実行されるイベント
            map.events.add('ready', function () {
                // データソースの作成と追加
                datasource = new atlas.source.DataSource();
                map.sources.add(datasource);

                // ルートラインを描画するレイヤーの追加
                map.layers.add(new atlas.layer.LineLayer(datasource, null, {
                    strokeColor: '#2272B9',
                    strokeWidth: 5,
                    lineJoin: 'round',
                    lineCap: 'round'
                }), 'labels');

                // ポイントデータを描画するレイヤーの追加
                map.layers.add(new atlas.layer.SymbolLayer(datasource, null, {
                    iconOptions: {
                        image: ['get', 'iconImage'],
                        allowOverlap: true,
                        ignorePlacement: true
                    },
                    textOptions: {
                        textField: ['get', 'title'],
                        offset: [0, 1]
                    },
                    filter: ['any', ['==', ['geometry-type'], 'Point'], ['==', ['geometry-type'], 'MultiPoint']] //Only render Point or MultiPoints in this layer.
                }));

                // ルートの開始点と終了点のGeoJSONオブジェクトを作成
                var startPosition = [139.6238227792696,35.64718448457993];
                var startPoint = new atlas.data.Feature(new atlas.data.Point(startPosition), {
                    title: '千歳船橋駅',
                    iconImage: 'pin-blue'
                });

                var endPosition = [139.65796597840765,35.633385088380514];
                var endPoint = new atlas.data.Feature(new atlas.data.Point(endPosition), {
                    title: '駒沢小学校',
                    iconImage: 'pin-red'
                });


                // データソースにデータを追加
                datasource.add([startPoint, endPoint]);

                 // 地図画面を開始位置と終了位置で定義された値に合わせる
                map.setCamera({
                    bounds: atlas.data.BoundingBox.fromPositions([startPosition, endPosition]),
                    padding: 250
                });

                // ルートリクエストのURLを作成
                var routeRequestURL = routeUrl + '&query=' + query ;

                var routeRequest = {
                    travelMode: 'truck',
                    vehicleAxleWeight: 10000,
                    vehicleWidth: 2.5,
                    vehicleHeight: 4.0,
                    vehicleLength: 12.0,
                    vehicleMaxSpeed: 80,
                    vehicleWeight: 20000,
                    vehicleLoadType: 'USHazmatClass2'
                };

                // ルートリクエストを処理し、結果を地図に描画
                processRequest(routeRequestURL + '&' + new URLSearchParams(routeRequest)).then(directions => {
                    // 道順から最初のルートを抽出する
                    const route = directions.routes[0];

                    // すべての座標を1つの配列にまとめる
                    const routeCoordinates = route.legs.flatMap(leg => leg.points.map(point => [point.longitude, point.latitude]));

                    // ルートを作成
                    const routeLine = new atlas.data.LineString(routeCoordinates);

                    // データソースにルートを追加
                    datasource.add(routeLine);
                });
            });
        }
    </script>
    <!-- スタイル設定 -->
    <style>
        html,
        body {
            width: 100%;
            height: 100%;
            padding: 0;
            margin: 0;
        }

        #myMap {
            width: 100%;
            height: 100%;
        }
    </style>
</head>
<body onload="getMap()">
    <div id="myMap"></div>
</body>
</html>
```

<strong>ZENRIN Maps API</strong>
```zma_route.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ZENRIN Maps API Route Display</title>
<style>
    body { margin: 0; padding: 0; }
    #ZMap { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
<script src="https://test-js.zmaps-api.com/zma_loader.js?key=[APIキー]&auth=referer"></script>
<script src="js/zma_route.js"></script>
</head>
<body>
<div id="ZMap"></div>
</body>
</html>
```
```zma_route.js
ZMALoader.setOnLoad(function (mapOptions, error) {
    if (error) {
        console.error(error);
        return;
    }

    const mapElement = document.getElementById('ZMap');

    // 地図の初期設定
    mapOptions.center = new ZDC.LatLng(35.633385088380514, 139.65796597840765); //駒沢小学校
    mapOptions.zoom = 15;
    mapOptions.mouseWheelReverseZoom = true; // ★マウスホイールのズーム方向の反転を指定


    const map = new ZDC.Map(mapElement, mapOptions, function() {
        // 地図生成成功時の処理

        // コントロールを追加
        map.addControl(new ZDC.ZoomButton('top-left'));
        map.addControl(new ZDC.Compass('top-right'));
        map.addControl(new ZDC.ScaleBar('bottom-left'));
        
        const start = new ZDC.LatLng(35.64718448457993, 139.6238227792696);//千歳船橋駅
        const end = new ZDC.LatLng(35.633385088380514, 139.65796597840765); //駒沢小学校

        const startMarker = new ZDC.Marker(start);
        const endMarker = new ZDC.Marker(end);
        map.addWidget(startMarker);
        map.addWidget(endMarker);

        const routeUrl = `https://test-web.zmaps-api.com/route/route_mbn/drive_ptp?search_type=1&from=${start.lng},${start.lat}&to=${end.lng},${end.lat}&regulation_type=121200&toll_type=large`;

        fetch(routeUrl, {
            method: 'GET',
            headers: {
                'x-api-key': '[APIキー]',
                'Authorization': 'referer'
            },
        })
        .then(response => response.json())
        .then(data => {
            if (data.status === 'OK' && data.result?.item?.length > 0) {
                const routeItem = data.result.item[0];
                const links = routeItem.route?.link;

                if (Array.isArray(links) && links.length > 0) {
                    const decodedPath = [];
                    links.forEach(link => {
                        if (Array.isArray(link.line.coordinates)) {
                            link.line.coordinates.forEach(coord => {
                                if (Array.isArray(coord) && coord.length === 2) {
                                    decodedPath.push(new ZDC.LatLng(coord[1], coord[0]));
                                }
                            });
                        }
                    });

                    console.log("デコードされた座標:", decodedPath);

                    if (decodedPath.length > 0) {
                        const routeLine = new ZDC.Polyline(
                            decodedPath,
                            {
                                color: '#008dcb',
                                width: 5,
                                opacity: 0.7
                            }
                        );
                        map.addWidget(routeLine);
                    } else {
                        console.error("デコードされたルートデータが空です。");
                    }
                } else {
                    console.error("リンクデータが存在しません。");
                }
            } else {
                console.error("ルート検索に失敗しました。レスポンス:", data);
            }
        })
        .catch(error => console.error('ルート検索エラー:', error));
    }, function() {
        console.error('地図の生成に失敗しました');
    });
});

```


 ## 地図表示
<strong>Azure Maps</strong>
![Azure_千歳船橋駅.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965389/ff697a21-de12-cd48-1729-582e844964de.png)
<strong>ZENRIN Maps API</strong>
[ZENRINMapsAPI 大型車ルート検索](https://goldiek24.github.io/qiita_zma_largeroute_chitosefunabashi/zma_route.html)
![ZMA大型ルート検索_千歳船橋駅.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965389/80e591ad-1ea8-0eed-fab9-80c67b150289.png)

## 解説
### Azure Maps
#### １．HTML構造
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <!-- タイトルやメタ情報 -->
    <title>Azure Mapsの大型車ルート検索</title>
    <meta charset="utf-8" />
    <link rel="shortcut icon" href="/favicon.ico" />

    <!-- Azure MapsのCSSとJavaScriptファイルの読み込み -->
    <link href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.css" rel="stylesheet" />
    <script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.js"></script>

    <!-- Azure Maps Rest Helper JavaScriptファイルの読み込み -->
    <script src="https://samples.azuremaps.com/lib/azure-maps/azure-maps-helper.min.js"></script>

    <!-- スタイル設定 -->
    <style>
        html,
        body {
            width: 100%;
            height: 100%;
            padding: 0;
            margin: 0;
        }

        #myMap {
            width: 100%;
            height: 100%;
        }
    </style>
</head>

<body onload="getMap()">
    <!-- 地図を表示するdiv要素 -->
    <div id="myMap"></div>
</body>
</html>
```

#### ２．変数の宣言とURL設定
ここでは、地図やデータソースを保持する変数を宣言し、Azure MapsのルートAPIのURLを設定しています。
```javascript
// 変数の宣言
var map, datasource;

// ルートAPIのURL
var routeUrl = 'https://atlas.microsoft.com/route/directions/json?api-version=1.0&routeRepresentation=polyline&view=Auto';
```

#### ３．地図の初期化
ここでは、Azure Mapsの地図インスタンスを作成し、初期位置とズームレベルを設定しています。
また、認証オプションとしてサブスクリプションキーを使用しています。
```javascript
// 地図を初期化する関数
function getMap() {
    // 地図インスタンスの作成
    map = new atlas.Map('myMap', {
        center: [35.68109033123879, 139.76702393263224],
        zoom: 12,
        view: 'Auto',
        authOptions: {
            authType: 'subscriptionKey',
            subscriptionKey: 'YOUR_API_KEY_HERE'
        }
    });
```

#### ４．地図準備完了イベント
このイベントは、地図が完全に読み込まれた後に実行されます。
```javascript
map.events.add('ready', function () {
    // ...
});
```

#### ５．データソースとレイヤーの作成
ここでは、データソースを作成し、それを地図に追加します。また、ルートラインとポイントデータを描画するためのレイヤーを追加しています。
```javascript
// データソースの作成と追加
datasource = new atlas.source.DataSource();
map.sources.add(datasource);

// ルートラインを描画するレイヤーの追加
map.layers.add(new atlas.layer.LineLayer(datasource, null, {
    strokeColor: '#2272B9',
    strokeWidth: 5,
    lineJoin: 'round',
    lineCap: 'round'
}), 'labels');

// ポイントデータを描画するレイヤーの追加
map.layers.add(new atlas.layer.SymbolLayer(datasource, null, {
    iconOptions: {
        image: ['get', 'iconImage'],
        allowOverlap: true,
        ignorePlacement: true
    },
    textOptions: {
        textField: ['get', 'title'],
        offset: [0, 1]
    },
    filter: ['any', ['==', ['geometry-type'], 'Point'], ['==', ['geometry-type'], 'MultiPoint']]
}));
```

#### ６．ルートの開始点と終了点の設定
ここでは、ルートの開始点と終了点をGeoJSONオブジェクトとして作成し、それらをデータソースに追加しています。
```javascript
// ルートの開始点と終了点のGeoJSONオブジェクトを作成
var startPosition = [139.6238227792696, 35.64718448457993];
var startPoint = new atlas.data.Feature(new atlas.data.Point(startPosition), {
    title: '千歳船橋駅',
    iconImage: 'pin-blue'
});

var endPosition = [139.65796597840765, 35.633385088380514];
var endPoint = new atlas.data.Feature(new atlas.data.Point(endPosition), {
    title: '駒沢小学校',
    iconImage: 'pin-red'
});

// データソースにデータを追加
datasource.add([startPoint, endPoint]);
```

#### ７．地図表示時に開始位置と終了位置で定義された値に合わせる
ここでは、地図の表示範囲を開始点と終了点に合わせて設定しています。
```javascript
// 地図画面を開始位置と終了位置で定義された値に合わせる
map.setCamera({
    bounds: atlas.data.BoundingBox.fromPositions([startPosition, endPosition]),
    padding: 250
});
```

#### ８．ルートリクエストの送信
```javascript
// ルートリクエストのURLを作成
var routeRequestURL = routeUrl + '&query=' + query ;

//大型車を設定
var routeRequest = {
    travelMode: 'truck',
    vehicleAxleWeight: 10000,
    vehicleWidth: 2.5,
    vehicleHeight: 4.0,
    vehicleLength: 12.0,
    vehicleMaxSpeed: 80,
    vehicleWeight: 20000,
    vehicleLoadType: 'USHazmatClass2'
};

// ルートリクエストを処理し、結果を地図に描画
processRequest(routeRequestURL + '&' + new URLSearchParams(routeRequest)).then(directions => {
    // ...
});
```

#### ９．ルート結果の描画
ここでは、ルート結果を取得し、それを地図上に描画しています。ルートの座標を取得し、LineStringオブジェクトを作成してデータソースに追加します。
```javascript
// ルート結果を地図に描画
const route = directions.routes[0];
const routeCoordinates = route.legs.flatMap(leg => leg.points.map(point => [point.longitude, point.latitude]));
const routeLine = new atlas.data.LineString(routeCoordinates);
datasource.add(routeLine);
```

### ZENRIN Maps API
#### １．地図の初期化
ZENRINMapsAPIの初期化と地図の生成を行っています。ZMALoader.setOnLoad関数を使用してAPIのロードを待ち、地図のオプションを設定し、ZDC.Mapオブジェクトを作成しています。
 ```zma_route.js
 ZMALoader.setOnLoad(function (mapOptions, error) {
    if (error) {
        console.error(error);
        return;
    }

    const mapElement = document.getElementById('ZMap');

    // 地図の初期設定
    mapOptions.center = new ZDC.LatLng(35.681406, 139.767132); // 東京駅
    mapOptions.zoom = 13;

    const map = new ZDC.Map(mapElement, mapOptions, function() {
        // 地図生成成功時の処理
    }, function() {
        console.error('地図の生成に失敗しました');
    });
});
```

#### ２．地図コントロールの追加
ここでは、地図上にズームボタン、コンパス、スケールバーなどのコントロールを追加しています。これらのコントロールにより、ユーザーは地図の操作や情報の確認が容易になります。
 ```zma_route.js
 // コントロールを追加
map.addControl(new ZDC.ZoomButton('top-left'));
map.addControl(new ZDC.Compass('top-right'));
map.addControl(new ZDC.ScaleBar('bottom-left'));
 ```

#### ３．マーカーの設定
ルートの始点（日本大学認定こども園）と終点（青葉学園野沢こども園）にマーカーを設置しています。ZDC.Markerオブジェクトを作成し、map.addWidgetメソッドで地図上に追加しています。
 ```zma_route.js
const start = new ZDC.LatLng(35.64718448457993, 139.6238227792696);//千歳船橋駅
const end = new ZDC.LatLng(35.633385088380514, 139.65796597840765); //駒沢小学校
const startMarker = new ZDC.Marker(start);
const endMarker = new ZDC.Marker(end);
map.addWidget(startMarker);
map.addWidget(endMarker);
 ```

#### ４．ルート検索APIリクエスト
ZENRINMapsAPIのルート検索エンドポイントにリクエストを送信しています。fetch関数を使用してHTTPリクエストを行い、APIキーと認証情報をヘッダーに含めています。
リクエストパラメータに「ルート探索用車種(regulation_type=121200)」を設定しています。
 ```zma_route.js
const routeUrl = `https://test-web.zmaps-api.com/route/route_mbn/drive_ptp?search_type=1&from=${start.lng},${start.lat}&to=${end.lng},${end.lat}&regulation_type=121200`;

fetch(routeUrl, {
    method: 'GET',
    headers: {
        'x-api-key': '[APIキー]',
        'Authorization': 'referer'
    },
})
.then(response => response.json())
.then(data => {
    // ルートデータの処理
})
.catch(error => console.error('ルート検索エラー:', error));
```

#### ５．ルートデータの処理とポリライン描画
APIから返されたルートデータを処理し、ポリラインとして地図上に描画しています。ルートの座標データをZDC.LatLngオブジェクトに変換し、ZDC.Polylineを使用してルートを描画しています。
```zma_route.js
if (data.status === 'OK' && data.result?.item?.length > 0) {
    const routeItem = data.result.item[0];
    const links = routeItem.route?.link;

    if (Array.isArray(links) && links.length > 0) {
        const decodedPath = [];
        links.forEach(link => {
            if (Array.isArray(link.line.coordinates)) {
                link.line.coordinates.forEach(coord => {
                    if (Array.isArray(coord) && coord.length === 2) {
                        decodedPath.push(new ZDC.LatLng(coord[1], coord[0]));
                    }
                });
            }
        });

        if (decodedPath.length > 0) {
            const routeLine = new ZDC.Polyline(
                decodedPath,
                {
                    color: '#008dcb',
                    width: 5,
                    opacity: 0.7
                }
            );
            map.addWidget(routeLine);
        }
    }
}
```

## API比較
### 1. ルート検索機能
**Azure Maps**
Azure Mapsは、車両の寸法や積載物の種類を考慮したルート検索が可能です。
特に、travelModeをtruckに設定することで、大型車向けのルートを取得できます。
**ZENRIN Maps API**
ZENRIN Maps APIは、日本国内の詳細な地図データを活用したルート検索が可能です。
特に、search_typeパラメータでルートの優先順位を指定できます（例: 所要時間優先、距離優先）。

### 2. APIエンドポイント
**Azure Maps**
 ルート検索には`https://atlas.microsoft.com/route/directions/json`エンドポイントを使用します。
 パラメータとしてquery、travelMode、vehicleAxleWeightなどを指定できます。
 **ZENRIN Maps API**
ルート検索には`https://test-web.zmaps-api.com/route/route_mbn/drive_ptp`エンドポイントを使用します。
パラメータとしてfrom、to、search_typeなどを指定できます。

### 3. 認証方式
**Azure Maps**
Azure Mapsは、以下の3つの認証方式をサポートしています。
１．**Shared Key認証:** Azure Mapsアカウントで生成されるプライマリーキーとセカンダリーキーを使用して認証します。
リクエストURLにサブスクリプションキーを含めることで、Azure Mapsのサービスにアクセスできます。
２．**Microsoft Entra ID認証:** Azureサブスクリプションに関連付けられたMicrosoft Entraテナントを使用して、OAuth 2.0アクセストークンで認証します。
この方法は、ユーザーまたはアプリケーションに細かいアクセス制御を提供します。
３．**Shared Access Signature (SAS) Token認証:** SASトークンは、Azure Mapsアカウントのプライマリーキーまたはセカンダリーキーを使用して生成され、特定の期間やリージョンで制限されたアクセスを提供します。

**ZENRIN Maps API**
ZENRIN Maps APIは、以下の認証方式を使用します。
１．**APIキー認証:** ZENRIN Maps APIでは、APIキーを使用して認証します。APIキーは、リクエストヘッダーに含めることで、APIにアクセスするための認証情報として使用されます。
２．**リファラーベースの認証:** ZENRIN Maps APIは、リファラーベースの認証もサポートしています。これにより、特定のドメインからのリクエストのみを許可することができます。

## まとめ
**Azure Maps**
Azure Mapsは、グローバルな地図データと豊富な機能が特徴です。
大型車のルート検索APIも提供しており、車両情報を細かく設定できます。
地図表示機能も充実しており、スタイルのカスタマイズや交通情報の表示も可能です。
**ZENRIN Maps API**
ZENRIN Maps APIは、日本国内の詳細な地図データに強みがあります。
特に、大型車のルート検索APIは、日本の道路事情に合わせたルートを探索できます。
住所検索や施設検索など、地図データに関連する機能も充実しています。
地図は年12回更新しています。
**どちらのAPIを選ぶべきか**
グローバルな地図データや豊富な機能が必要な場合は、**Azure Maps**がおすすめです。
日本国内の詳細な地図データや日本の道路事情に合わせたルート検索が必要な場合は、**ZENRIN Maps API**がおすすめです。

---

### 参考情報
Azure Mapsチュートリアル
チュートリアル:Azure Maps Route Service とマップ コントロールを使用してルートの道順を表示する方法
https://learn.microsoft.com/ja-jp/azure/azure-maps/tutorial-route-location