検索

世界中の数億の POI とポイントアドレスを集めた HERE のグローバルデータセットをソースとする HERE SDK for iOS を使用すると、すばやく簡単に検索できます。 HERE SDK を使用すると、検索に関連するさまざまなタスクを 1 つ SearchEngineの内から解決できます。

  • 場所を探す: この巨大なデータベースから、カテゴリ別、または検索語を設定して、世界中の場所を検索して発見できます。
  • 自動提案を生成: 検索条件を入力して検索を完了するときに、場所を検索します。
  • 住所を逆引き( Reverse ジオコード an address ): 特定の地理座標に属する住所を検索します。
  • ジオコード AN アドレス: 住所に属する地理座標を検索します。
  • ID で検索: HERE の場所 ID で特定された場所を検索します。
  • ルートに沿って検索: ルート全体に沿った場所を検索します。
  • ルートに沿ってカテゴリで検索: ルート全体のカテゴリに基づいて場所を検索します。 この機能はベータ版です。

すべての検索バリアントに共通する機能の 1 つ は、検索する場所または領域を指定できることです。 領域の設定は、で指定された矩形領域 GeoBox 、またはで指定された円領域を通過することで行う GeoCircleことができます。 指定した領域外にある潜在的な検索結果は、関連するグローバルな結果を除いて、優先度の低いものでランク付けされます。たとえば、ベルリンで「 Manhattan 」を検索する場合です。 基本となる検索アルゴリズムが最適化され、結果のリストを絞り込むことができるようになり、ユーザーに迅速でわかりやすい結果が提供されます。

注 : 各検索リクエストは非同期で実行されます。 オンライン接続が必要です。

HERE の位置情報サービスが提供する場所の大規模なデータベースは、 HERE SDK で簡単に見つける SearchEngineことができます。 例を見てみましょう。 まず、新しい SearchEngine インスタンスを作成します。

do {
    try searchEngine = SearchEngine()
} catch let engineInstantiationError {
    fatalError("Failed to initialize SearchEngine. Cause: \(engineInstantiationError)")
}

新しい SearchEngine インスタンスを作成すると、上の図のように処理する必要があるエラーがスローされることがあります。 このようなエラーは、たとえば、 HERE SDK の初期化が事前に失敗した場合に発生することがあります。

場所を検索します

デバイスに表示されている現在の地図センターの周りにあるすべての「ピザ」の場所を探しているとします。 検索を開始する前に、詳細をいくつか指定する必要があります。

let searchOptions = SearchOptions(languageCode: LanguageCode.enUs,
                                  maxItems: 30)

上記のコード スニペットから SearchOptions 、目的のデータを保持する新しいオブジェクトを作成しました。

  • を設定する LanguageCodeことで、返される検索結果の言語を指定できます。
  • maxItems は、応答で配信する結果アイテムの最大数を定義するように設定されています。 上の例では、結果を 30 に制限しています。 リクエストよりも多くの検索結果が見つかった場合、最も関連性の高い 30 件の検索結果のみが返されます。

現在のビューポイント内のすべての結果を検索するために、 1 つのボックスで検索を行います。 で SearchEngine は、次の 3 つの方法で検索場所を指定できます。

  • 検索場所 GeoCoordinates: 指定した座標系を中心に非同期の検索リクエストを実行し、近隣で最も関連性の高い検索結果を提供します。
  • GeoCircle エリア内を検索 : 上記と似ていますが、指定した円領域内で結果を検索します。この領域は、中心地理座標およびメートル単位の半径で定義されます。
  • GeoBox エリア内を検索 : 上記と同様ですが、指定した矩形領域内で結果を検索します。この領域は、パラメーターとして渡された南西および北東の座標によって定義されます。

ワンボックス検索 は、近隣の場所を探すのに最適です。 入力すると、さまざまな言語 ( ラテン、キリル、アラビア、ギリシャ料理など ) で自由形式のテキストを提供できます。

検索する語句と一緒に領域を指定できます。 たとえば queryString 、「 pizza 」のように設定できます。

let queryArea = TextQuery.Area(inBox: getMapViewGeoBox())
let textQuery = TextQuery(queryString, area: queryArea)

HERE さんがコードを削除しまし getMapViewGeoBox()た。 GeoBox ユースケースに適した任意のを作成して渡すことができます。 実装の可能性については、付属のサンプルアプリを参照してください。

できれば、指定した地図範囲内の結果が返されます。 検索結果が見つからなかった場合は、グローバル検索結果が返されることがあります。 ただし、指定した検索場所に関係なく、主要都市や州などの関連するグローバルな結果が含まれる場合があります。

注 : クエリー文字列には、検索するコンテンツの任意のテキスト記述を含めることができます。 複数の検索語を使用して、コンマで区切って検索結果を絞り込むことができます。 「ピザショーシー通り」と「ピザ、ショーシー通り」は同じ結果をもたらします。通り「チャウゼー通り」にあるピザレストランのみが見つかります。 また、空のクエリ文字列を渡すとエラーになります。この場合、検索は失敗します。

最後に、非同期で検索を開始できます。

_ = searchEngine.search(textQuery: textQuery,
                        options: searchOptions,
                        completion: onSearchCompleted)

...

// Completion handler to receive search results.
func onSearchCompleted(error: SearchError?, items: [Place]?) {
    if let searchError = error {
        showDialog(title: "Search", message: "Error: \(searchError)")
        return
    }

    // If error is nil, it is guaranteed that the items will not be nil.
    showDialog(title: "Search in viewport for: 'Pizza'.",
               message: "Found  \(items!.count) results.")

    // Add a new marker for each search result on map.
    for searchResult in items! {
        //...
    }
}

メモ

また、完了ハンドラのインライン化には、終了条件式を使用できます。

_ = searchEngine.search(textQuery: textQuery,
                        options: searchOptions) { (searchError, searchResultItems) in
   // Handle results here.
}

もちろん、 HERE SDK で利用できる他のすべての完了処理についても同じことが可能です。 このガイドでは、関数 呼び出し式を使用 して、すべての種類の情報を保持することをお勧めします。

提供されているすべての search() メソッドが TaskHandle を返します。このメソッドは、進行中のコールのステータスの確認、またはコールのキャンセルに任意で使用できます。 必要でない場合は、上に示したように、そのままにしておくことができます。

結果を確認する前 SearchErrorに、可能性を確認する必要があります。 たとえば、デバイスがオフラインの場合、検索項目のリストは nil になり、エラー 列挙型 (enum) が原因を示します。 この場合、ヘルパーメソッドを呼び出し showDialog() て、エラーの説明をユーザーに表示します。 の実装の可能 showDialog() 性は、付随する「検索」の例のソースコードからアクセスできます。このコードには、 HERE SDK 固有のコードは含まれていません。

エラーが発生した場合は事前に削除しておくため、検索アイテムリストの折り返しを安全に解除できます。

メモ

検索応答にはエラーまたは結果が含まれています。また、 error items nil と nil は同時に指定することはできません。

ここで、結果を確認しましょう。 一致する結果が見つからない場合は、事前にエラーが検出されている可能性があります。

// If error is nil, it is guaranteed that the items will not be nil.
showDialog(title: "Search in viewport for: 'Pizza'.",
           message: "Found  \(items!.count) results.")

// Add a new marker for each search result on map.
for searchResult in items! {
    let metadata = Metadata()
    metadata.setCustomValue(key: "key_search_result", value: SearchResultMetadata(searchResult))
    // Note that geoCoordinates are always set, but can be nil for suggestions only.
    addPoiMapMarker(geoCoordinates: searchResult.geoCoordinates!, metadata: metadata)
}

...

// Class to store search results as Metadata.
private class SearchResultMetadata : CustomMetadataValue {

    var searchResult: Place

    init(_ searchResult: Place) {
        self.searchResult = searchResult
    }

    func getTag() -> String {
        return "SearchResult Metadata"
    }
}

最後に、結果のリストについて反復処理を行います。 各に Place は、検索結果を説明するさまざまなフィールドが含まれています。

この例では、地図にマーカーを追加するために、その場所に関心があります。 さらに Metadata 、を保存できるオブジェクトを作成します SearchResult

注 : Metadata オブジェクトには、マップ マーカーと結果データを簡単に関連付けることができるように、さまざまなデータ型を含めることができます。 このようにして、マップ マーカーに関連するすべての情報を 1 つのオブジェクトに保持できます。これは、ユーザーがマップ マーカーをタップした後などに、このデータを表示する場合に便利です。 上記 CustomMetadataValue のように、インターフェイスを実装することで、複雑なデータオブジェクトも保存できます。

addPoiMapMarker()の実装方法としては、付随する「検索」のサンプルソースコードからアクセス できます。このガイドの「マップマーカーについて」も参照してください。 ピックしたマップ マーカーを手元に置いておくと Metadata 、前のステップで設定した情報を取得できます。

if let searchResultMetadata =
    topmostMapMarker.metadata?.getCustomValue(key: "key_search_result") as? SearchResultMetadata {

    let title = searchResultMetadata.searchResult.title
    let vicinity = searchResultMetadata.searchResult.address.addressText
    showDialog(title: "Picked Search Result",
               message: "Title: \(title), Vicinity: \(vicinity)")
    return
}

すべての地図マーカーにが含まれているわけでは Metadataありませ Metadata 事前にを設定していない場合 getMetadata() 、は nil を返します。 この例では、保存されているデータ "key_search_result" が nil でないかどうかを確認するだけで、データに検索データが含まれている必要があることがわかります。 その後、 SearchResultMetadata 目的のを保持するカスタムタイプにダウンキャストでき Placeます。

使用可能なオプションのフィールドの詳細については、 API リファレンス を参照してください。

スクリーンショット: 選択した検索結果をタイトルと近隣で表示しています。

メモ

このセクションおよび以降のセクションのすべてのコードは Search、 GitHub のサンプルアプリの一部として入手できます。

[ 場所 ] にズームします

上記のコードでは、を使用 GeoBox して、表示されている地図ビューポイント を直接検索します。そのため、検索結果をズームする必要はありません。 GeoBoxの代わり に、CountryCode値のリストを渡すことで、 a GeoCircleの内側、 a GeoCorridorに沿って、または内側の国を囲む位置を検索することもできます ( 「自分の周りを検索」 ) 。 TextQuery.Area サポートされているすべてのタイプについては、を参照

検索領域が表示されている地図ビューポイント と異なる場合 は、次のコードを使用してGeoCoordinatesの一覧からGeoBoxを作成し、結果をズームできます。 GeoBox からを取得 GeoBox.containing(geoCoordinates: geoCoordinatesList)します。

// Set null values to keep the default map orientation.
camera.lookAt(area: geoBox,
              orientation: GeoOrientationUpdate(bearing: nil, tilt: nil))

これでカメラが即座に移動します。 必要に応じて、さまざまなアニメーションスタイルを適用して、カメラを目的の領域にフライすることもできます。 このMapCameraセクションを参照 して、 GitHubCameraKeyframeTracks サンプルアプリ を確認します。

追加のパディングを適用する場合 は、viewRectangleを追加のパラメーターとして受け取るオーバーロードされたlookAt()メソッドを使用します。 矩形は GeoBox 、が表示されている内部のマップ ビュー を参照するピクセル単位で指定されます。

let origin = Point2D(5, 5)
let sizeInPixels = Size2D(width: mapView.viewportSize.width - 10, height: mapView.viewportSize.height - 10)
let paddedViewRectangle = Rectangle2D(origin: origin, size: sizeInPixels)

上記のコードでは、 GeoBox マップビューポイント に表示されている任意の周囲に 5 ピクセルのパディングを追加するために使用できる矩形を作成します。

場所のカテゴリを検索します

TextQuery 上記のようにを使用してキーワード検索を行う代わり Place に、カテゴリを検索して結果を予想されるカテゴリに限定することもできます。

カテゴリ ID は特定の形式に従い、 HERE platform では 700 を超えるカテゴリを使用できます。 HERE SDK には、カテゴリ検索を簡単に使用できるように定義済みの値のセットが用意されています。 必要に応じて、 xxx-xxxx-xxxx の形式でカスタムカテゴリ文字列を渡すこともできます。各グループは、 1 、 2 、 3 の各レベルのカテゴリを表します。 1 番目のレベルがメインカテゴリを表し、 3 番目のレベルが 2 番目のレベルのサブカテゴリのサブカテゴリを表します。 各カテゴリレベルは 、プレースカテゴリシステムで番号として定義されます。

例として、「飲食」カテゴリまたは「ショッピングエレクトロニクス」カテゴリに属するすべての場所を以下から検索します。

private func searchForCategories() {
    let categoryList = [PlaceCategory(id: PlaceCategory.eatAndDrink),
                        PlaceCategory(id: PlaceCategory.shoppingElectronics)]
    let queryArea = CategoryQuery.Area(areaCenter: GeoCoordinates(latitude: 52.520798,
                                                                  longitude: 13.409408))
    let categoryQuery = CategoryQuery(categoryList, area: queryArea)
    let searchOptions = SearchOptions(languageCode: LanguageCode.enUs,
                                      maxItems: 30)

    _ = searchEngine.search(categoryQuery: categoryQuery,
                            options: searchOptions,
                            completion: onSearchCompleted)
}

public func onSearchCompleted(error: SearchError?, items: [Place]?) {
    if let searchError = error {
        print("Search Error: \(searchError)")
        return
    }

    // If error is nil, it is guaranteed that the items will not be nil.
    showDialog(title: "Search Result", message: "\(items!.count) result(s) found. See log for details.")

    for place in items! {
        let addressText = place.address.addressText
        print(addressText)
    }
}

PlaceCategory を受け入れます String。 HERE では、事前定義されたカテゴリ eatAndDrink およびを使用し shoppingElectronicsます。 String この値には、プレースカテゴリシステムで表される ID が含まれています。 ここでも、 SearchEngine のオーバーロードされた search() メソッドを使用して、カテゴリリストと場所を探す地理的座標を含む CategoryQuery オブジェクトを渡します。

自動提案を検索します

ほとんどの場合、「撮影地」検索を提供するアプリケーションでは、ユーザーが希望の検索用語を編集可能なテキストフィールドコンポーネントに入力できます。 入力中に、可能性のある用語の予測を取得すると便利です。

エンジンによって提示された提案がランク付けされ、最も関連性の高い用語が結果リストの一番上に表示されます。 たとえば、最初のリストアイテムを使用して、ユーザーが現在入力している検索語の自動補完を提供できます。 または - ユーザーの入力中に更新された一致候補のリストを表示できます。 ユーザーは、提案のリストから適切なキーワードを選択して、選択した用語の新しい検索を開始できます。または 、タイトル近隣などの結果の詳細情報をすでに取得し てユーザーに提示できます。

通常のテキストクエリと比較して、候補の検索では、入力したクエリの用語について、優先度でランク付けされた高速な結果が提供されます。

エンジンを使用して提案を検索する方法を確認しましょう。

let centerGeoCoordinates = getMapViewCenter()
let autosuggestOptions = SearchOptions(languageCode: LanguageCode.enUs,
                                       maxItems: 5)

let queryArea = TextQuery.Area(areaCenter: centerGeoCoordinates)

// Simulate a user typing a search term.
_ = searchEngine.suggest(textQuery: TextQuery("p", area: queryArea),
                         options: autosuggestOptions,
                         completion: onSearchCompleted)

_ = searchEngine.suggest(textQuery: TextQuery("pi", area: queryArea),
                         options: autosuggestOptions,
                         completion: onSearchCompleted)

_ = searchEngine.suggest(textQuery: TextQuery("piz", area: queryArea),
                         options: autosuggestOptions,
                         completion: onSearchCompleted)

ヘルパーメソッド getMapViewCenter() は HERE から削除され、付属のサンプルアプリで確認できます。 GeoCoordinates マップ ビューの中央に現在表示されているを返すだけです。

新しいテキスト入力ごとに、次のリクエストを作成します。 ユーザーが「 Pizza 」と入力することを計画していると仮定します。まず「 p 」の結果を探し、次に「 pi 」の結果を探し、最後に「 piz 」の結果を探します。 ユーザーが実際に「ピザ」を検索する場合は、 3 度目の呼び出しで十分な興味深い提案があるはずです。

SearchEngine の他の search() メソッドと同様に、 suggest() メソッドは TaskHandle を返します。このメソッドを使用すると、進行中のコールのステータスを確認したり、コールをキャンセルしたりできます。

結果の取得方法を確認しましょう。

// Completion handler to receive auto suggestion results.
func onSearchCompleted(error: SearchError?, items: [Suggestion]?) {
    if let searchError = error {
        print("Autosuggest Error: \(searchError)")
        return
    }

    // If error is nil, it is guaranteed that the items will not be nil.
    print("Autosuggest: Found \(items!.count) result(s).")

    for autosuggestResult in items! {
        var addressText = "Not a place."
        if let place = autosuggestResult.place {
            addressText = place.address.addressText
        }
        print("Autosuggest result: \(autosuggestResult.title), addressText: \(addressText)")
    }
}

HERE では、で見つかったリストアイテムをログに記録する完了ハンドラを定義します Suggestion。 エラーがない場合、エンジンは結果のリストを保証します。エラーがない場合、結果は nil になります。

すべての提案があるわけではありません。 たとえば、「シスコ」などの一般的な用語を使用して、新しい検索に入力できます。 一般的な用語では、 Suggestion 結果に Place オブジェクトは含まれませんが、特定の場所を参照せずにテキストを表すのは A title だけです。 Suggestion 結果の使用可能なすべてのフィールドについては、『 API リファレンス 』を参照してください。

結果の順序はランク付けされますが、完了イベントが到着する順序については保証がありません。 そのため、まれに、「 PI 」の結果よりも前に「 Piz 」の結果が表示されることがあります。

地理座標から住所を反転( Reverse ジオコード)します

これで、地図上の特定の場所または地域で場所を検索する方法を確認できました。 ただし、場所のみがわかっている場合は、どうすればよいですか。 このユースケースで最も一般的なのは、マップで何らかのアクションを実行しているユーザーです。 たとえば、長押しジェスチャを使用すると、ユーザーが地図を操作した場所の緯度座標と経度座標が表示されます。 ユーザーは地図上の場所を参照できますが、その場所に属する住所情報などの他の属性は把握できません。

リバースジオ コーディング が役立つ場所です。

関心のある場所は GeoCoordinates インスタンスで表されます。たとえば、マップをタップしたユーザーから取得できます。 その場所を「ジオコード」する方法については、次のコードを参照してください。

private func getAddressForCoordinates(geoCoordinates: GeoCoordinates) {
    // By default results are localized in EN_US.
    let reverseGeocodingOptions = SearchOptions(languageCode: LanguageCode.enGb,
                                                maxItems: 1)
    _ = searchEngine.search(coordinates: geoCoordinates,
                            options: reverseGeocodingOptions,
                            completion: onReverseGeocodingCompleted)
}

// Completion handler to receive reverse geocoding results.
func onReverseGeocodingCompleted(error: SearchError?, items: [Place]?) {
    if let searchError = error {
        showDialog(title: "ReverseGeocodingError", message: "Error: \(searchError)")
        return
    }

    // If error is nil, it is guaranteed that the place list will not be empty.
    let addressText = items!.first!.address.addressText
    showDialog(title: "Reverse geocoded address:", message: addressText)
}

SearchEngine によって提供される他の検索機能と同様に、必要な LanguageCode を設定するための SearchOptions インスタンスを提供する必要があります。 結果の住所の言語を指定します。 その後、エンジン search()のメソッドを呼び出して、渡された座標のアドレスをオンラインで検索できます。 デバイスがオフラインのときなど、エラーが発生 SearchError した場合は、エラーの原因が保持されます。

メモ

逆方向のジオ コーディング応答には、エラーまたは結果が含ま SearchError れています。また、アイテムリストは、一度に nil にすることも、同時に nil にすることもできません。

AddressPlace インスタンス内に含まれるオブジェクトはデータクラス String で、国、市区町村、番地などの生の場所の住所を記述する複数のフィールドが含まれています。 詳細については、 API リファレンス を参照してください。 読み取り可能なアドレス表現の受信のみに関心がある場合 addressTextは、上の例に示すようにににアクセスできます。 String これは、その場所のタイトルを含む、最も関連性の高い住所の詳細を含むです。

スクリーンショット: 住所に解決された印刷機の長い座標を表示しています。

Reverse ジオ コーディングでは、特定の検索領域は必要ありません。 世界中の住所に座標を解決できます。

ジオコード住所を特定の場所に移動します

Reverse ジオ コーディング を使用すると、未加工の座標から住所を取得できますが 、 Forward ジオ コーディング では逆の処理が行われ、道路名や都市などの住所の詳細を入力するだけで、未加工の座標やその他の位置情報を検索できます。

注 : ほとんどの場合、リバースジオ コーディングでは 1 つの結果しか得られませんが、ジオ コーディングでは 1 つ以上の結果が得られます。

HERE がその方法をご案内します。 まず、検索する場所の近くの座標を指定し、 queryString正確な場所を検索する住所を設定します。

let query = AddressQuery(queryString, near: geoCoordinates)
let geocodingOptions = SearchOptions(languageCode: LanguageCode.deDe,
                                     maxItems: 25)
_ = searchEngine.search(addressQuery: query,
                        options: geocodingOptions,
                        completion: onGeocodingCompleted)

この例では、 HERE の Berlin HQ "Invalidenstra ß e 116" の通りの名前をクエリー文字列として渡します ( 任意で都市を指定します ) 。 これはドイツ語の通り名な deDe ので、ドイツの言語コードを入力します。 これにより、返される結果の言語も決まります。

注 : 結果は指定した場所から遠く離れていてもかまいませんが、指定した座標に近い結果が高い順にランク付けされ、できれば返されます。

次のステップでは、完了ハンドラを実装する必要があります。

// Completion handler to receive geocoding results.
func onGeocodingCompleted(error: SearchError?, items: [Place]?) {
    if let searchError = error {
        showDialog(title: "Geocoding", message: "Error: \(searchError)")
        return
    }

    // If error is nil, it is guaranteed that the items will not be nil.
    for geocodingResult in items! {
        //...
    }
}

完了ハンドラがエラーを受信しなかったことを確認した後 Place 、要素の一覧表を確認します。

メモ

searchError が nil の場合 items 、結果は nil ではないことが保証され、その逆も同様です。 そのため、オプションの一覧表をラップ解除しても安全です。

結果は 、未加工の座標を含むPlacesオブジェクトにラップ されます。また、Addressオブジェクトや、 HERE Places API 内の位置を特定する場所 ID など、その他の住所の詳細情報もラップされます。 以下では、一覧表について繰り返し、住所のテキストと座標を取得します。

for geocodingResult in items! {
    // Note that geoCoordinates are always set, but can be nil for suggestions only.
    let geoCoordinates = geocodingResult.geoCoordinates!
    let address = geocodingResult.address
    let locationDetails = address.addressText
        + ". Coordinates: \(geoCoordinates.latitude)"
        + ", \(geoCoordinates.longitude)"
    //...
}

ユーザーがマップからこのような結果を選択した場合の表示例については、以下のスクリーンショットを参照してください。 ご希望の場合は、添付の「検索」のサンプルアプリを参照して、住所のテキストを検索し、地図上の見つかった場所に地図マーカーを配置する方法を確認してください。

スクリーンショット: 選択したジオ コーディング結果を表示しています。

ルート沿いを検索します

SearchEngineは、長方形または円の領域で検索せずに、GeoPolylineおよび他のパラメーターで定義できるより複雑なGeoCorridor領域で検索する場合に、特殊な検索ケースをサポートします。

このような場合の最も一般的なシナリオ Route は、を検索してレストランを探すことです。 ルートオブジェクトがすでに計算されているとします。 経路の計算方法については、経路のセクションを参照してください。 を指定すると TextQuery、ルート全体を含む長方形の領域を簡単に定義できます。

let textQuery = TextQuery("restaurants", in: route.boundingBox)

ただし、より長いルートの場合、およびルートの形状によっては、が route.boundingBox ルート全体を長方形の領域に包含する必要があるため、結果が実際のルートパスから非常に離れている場合があります。

HERE SDK は GeoCorridor 、ルートの実際の形状から検索領域を判断できるクラスを提供することで、より正確なソリューションを提供します。 この方法 では、パスの上または下にある検索結果のみが含まれます。

以下に、ルートに沿ってチャージステーションを検索する方法の例を示します。

private func searchAlongARoute(route: Route) {
    // We specify here that we only want to include results
    // within a max distance of xx meters from any point of the route.
    let routeCorridor = GeoCorridor(polyline: route.geometry.vertices,
                                    halfWidthInMeters: Int32(200))
    let queryArea = TextQuery.Area(inCorridor: routeCorridor, near: mapView.camera.state.targetCoordinates)
    let textQuery = TextQuery("charging station", area: queryArea)

    let searchOptions = SearchOptions(languageCode: LanguageCode.enUs,
                                      maxItems: 30)
    searchEngine.search(textQuery: textQuery,
                        options: searchOptions,
                        completion: onSearchCompleted)
}

// Completion handler to receive results for found charging stations along the route.
func onSearchCompleted(error: SearchError?, items: [Place]?) {
    if let searchError = error {
        if searchError == .polylineTooLong {
            // Increasing halfWidthInMeters will result in less precise results with the benefit of a less
            // complex route shape.
            print("Route too long or halfWidthInMeters too small.")
        } else {
            print("No charging stations found along the route. Error: \(searchError)")
        }
        return
    }

    // If error is nil, it is guaranteed that the items will not be nil.
    print("Search along route found \(items!.count) charging stations:")

    for place in items! {
        // ...
    }
}

ご覧の ように、GeoCorridorはルートGeoPolylinehalfWidthInMeters を必要とします。 このパラメータでは、ポリライン上の任意のポイントから廊下の端までの最も遠いエッジを定義します。 小さな値を指定すると、実際のルートに沿って非常に近いエリアが結果の廊下によって定義されます。

スクリーンショット: ルートに沿って見つかった充電ステーションを表示しています。

ルートの始点と終点の座標では、廊下は丸い形になります。一定の厚さのスネークが頭と尾に丸いエッジを持つようなものを想像してください。 上記のスクリーンショットと混同しないでください。ルートの始点と終点を示す緑色の円が表示されます。

特に長いルートの場合、内部的に検索アルゴリズムが検索経路の最適化を試行します。 ただし、ポリラインが長すぎる可能性があります。 上記のコード スニペットに示されているように、このケースをキャッチして、最終的にはより複雑でないルートの検索を再トリガすることにします。 これは halfWidthInMeters パラメータで制御できます。値を大きくすると、廊下の複雑さが軽減され、結果の精度が低下しますが、少なくともこの方法ではより多くの結果が得られます。

ルートの複雑さは、フードの下の複数の要因によって決まります。そのため、ルートの明確な長さは一般に指定できません。

エラーが発生しなかっ Place た場合は、上記のセクションにすでに示されているように結果を処理できます。

メモ

このセクションのすべてのコードは EVRouting、 GitHub のサンプルアプリの一部として入手できます。

」に一致する結果は 件です

    」に一致する結果はありません