Placesを検索

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

  • placesの検索: この巨大なデータベースから、カテゴリ別、または検索語を設定して、世界中のPlacesを検索して発見できます。
  • Autosuggestを生成: 検索条件を入力して検索を完了するときに、Placesを検索します。
  • 住所をリバースジオコード: 特定の地理座標に属する住所を検索します。
  • 住所でのジオコード : 住所に属する地理座標を検索します。
  • ID で検索: HERE Place IDで特定されたPlacesを検索します。
  • ルートに沿って検索: ルート全体に沿ったPlacesを検索します。
  • ルートに沿ってカテゴリで検索: ルート全体のカテゴリに基づいてPlacesを検索します。 この機能はベータ版です。
  • 個人データの持ち込み( BYOD ): 独自の Places データを追加して、実行時に無条件の検索リクエストにアクセスできるようにします。
  • オフラインで検索: インターネットに接続できない場合は、OfflineSearchEngineに切り替えて、キャッシュ済みのマップ データまたは事前にロードされたオフライン地図データを検索できます。

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

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

HERE Location Services が提供するPlacesの膨大なデータベースは、 HERE SDKのSearchEngineで簡単に見つけることができます。 例を見てみましょう。 まず、新しい SearchEngine インスタンスを作成します。

try {
  _searchEngine = SearchEngine();
} on InstantiationException {
  throw Exception("Initialization of SearchEngine failed.");
}

新しい SearchEngine インスタンスを作成すると、 InstantiationException 前述のように処理する必要のあるをスローできます。

Placesを検索

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

SearchOptions searchOptions = SearchOptions();
searchOptions.languageCode = LanguageCode.enUs;
searchOptions.maxItems = 30;

ここで SearchOptions は、目的のデータを保持する新しいオブジェクトを作成します。

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

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

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

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

検索する領域と用語を同時に指定できます。 たとえば、以下のように queryString 「 pizza 」に設定できます。

GeoBox viewportGeoBox = _getMapViewGeoBox();
TextQueryArea queryArea = TextQueryArea.withBox(viewportGeoBox);
TextQuery query = TextQuery.withArea(queryString, queryArea);

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

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

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

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

_searchEngine.searchByText(query, searchOptions, (SearchError? searchError, List<Place>? list) async {
  if (searchError != null) {
    _showDialog("Search", "Error: " + searchError.toString());
    return;
  }

  // If error is null, list is guaranteed to be not empty.
  int listLength = list!.length;
  _showDialog("Search for $queryString", "Results: $listLength. Tap marker to see details.");

  // Add new marker for each search result on map.
  for (Place searchResult in list) {
    // ...
  }
});

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

検索応答にエラーまたは結果が含まれています : SearchError および List<Place> 。 両方とも同時にヌルにすることはできません。また、同時にヌルにすることもできません。

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

// If error is null, list is guaranteed to be not empty.
int listLength = list!.length;
_showDialog("Search for $queryString", "Results: $listLength. Tap marker to see details.");

// Add new marker for each search result on map.
for (Place searchResult in list) {
  Metadata metadata = Metadata();
  metadata.setCustomValue("key_search_result", SearchResultMetadata(searchResult));
  // Note: getGeoCoordinates() may return null only for Suggestions.
  addPoiMapMarker(searchResult.geoCoordinates!, metadata);
}

SearchResultMetadata は、次のようなカスタムクラスです。

import 'package:here_sdk/core.dart';
import 'package:here_sdk/search.dart';

class SearchResultMetadata implements CustomMetadataValue {
  Place searchResult;

  SearchResultMetadata(Place place) : searchResult = place;

  
  String getTag() {
    return "SearchResult Metadata";
  }

  
  void release() {
    // Deprecated. Nothing to do here.
  }
}

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

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

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

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

MapMarker topmostMapMarker = mapMarkerList.first;
Metadata? metadata = topmostMapMarker.metadata;
if (metadata != null) {
  CustomMetadataValue? customMetadataValue = metadata.getCustomValue("key_search_result");
  if (customMetadataValue != null) {
    SearchResultMetadata searchResultMetadata = customMetadataValue as SearchResultMetadata;
    String title = searchResultMetadata.searchResult.title;
    String vicinity = searchResultMetadata.searchResult.address.addressText;
    _showDialog("Picked Search Result", title + ". Vicinity: " + vicinity);
    return;
  }
}

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

利用可能な nullを入力可能なフィールドの詳細については、 API リファレンス を参照してください。

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

GitHub search_app例の一部 として、このセクションおよび次のセクションのすべてのコードを見つけることができます。

Placesにズーム

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

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

// Keep default orientation for bearing and tilt.
_hereMapController.camera.lookAtAreaWithGeoOrientation(geoBox, GeoOrientationUpdate(null, null));

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

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

var origin = Point2D(5, 5);
var sizeInPixels = Size2D(_hereMapController.viewportSize.width - 10, _hereMapController.viewportSize.height - 10);
var paddedViewRectangle = Rectangle2D(origin, sizeInPixels);

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

Placesカテゴリを検索

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

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

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

void searchForCategories() {
  List<PlaceCategory> categoryList = [];
  categoryList.add(PlaceCategory(PlaceCategory.eatAndDrink));
  categoryList.add(PlaceCategory(PlaceCategory.shoppingElectronics));

  var queryArea = CategoryQueryArea.withCenter(GeoCoordinates(52.520798, 13.409408));
  CategoryQuery categoryQuery = CategoryQuery.withCategoriesInArea(categoryList, queryArea);

  SearchOptions searchOptions = SearchOptions();
  searchOptions.languageCode = LanguageCode.enUs;
  searchOptions.maxItems = 30;

  _searchEngine.searchByCategory(categoryQuery, searchOptions, (SearchError? searchError, List<Place>? list) async {
    if (searchError != null) {
      // Handle error.
      return;
    }

    // If error is null, list is guaranteed to be not empty.
    int listLength = list!.length;

    // Add new marker for each search result on map.
    for (Place searchResult in list) {
      // Handle results.
    }
  });
}

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

Autosuggestを検索

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

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

HERE SDKは 、UIや完全に統合されたAutosuggestソリューションを提供していません。 このようなソリューションは、必要に応じてアプリケーションによって実装できます。 このフィーチャーSuggestionを使用すると、TextQueryの条件に基づいて結果 Place が得られます。 これらのPlacesから、タイトルテキスト(「Pizza XL」)またはその他の関連する場所情報(住所など)を使用して、ユーザーにフィードバックを提供できます。たとえば、クリック可能な完了結果を提案することができます。 しかし、そのようなソリューションはアプリケーションの個々の要件に依存し、プラットフォームAPIを使用してアプリケーション側で実装する必要があります。

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

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

GeoCoordinates centerGeoCoordinates = _getMapViewCenter();

SearchOptions searchOptions = SearchOptions();
searchOptions.languageCode = LanguageCode.enUs;
searchOptions.maxItems = 5;

TextQueryArea queryArea = TextQueryArea.withCenter(centerGeoCoordinates);

// Simulate a user typing a search term.
_searchEngine.suggest(
    TextQuery.withArea(
        "p", // User typed "p".
        queryArea),
    searchOptions, (SearchError? searchError, List<Suggestion>? list) async {
  _handleSuggestionResults(searchError, list);
});

_searchEngine.suggest(
    TextQuery.withArea(
        "pi", // User typed "pi".
        queryArea),
    searchOptions, (SearchError? searchError, List<Suggestion>? list) async {
  _handleSuggestionResults(searchError, list);
});

_searchEngine.suggest(
    TextQuery.withArea(
        "piz", // User typed "piz".
        queryArea),
    searchOptions, (SearchError? searchError, List<Suggestion>? list) async {
  _handleSuggestionResults(searchError, list);
});

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

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

suggest()メソッドは、 TaskHandle 進行中のコールのステータスを確認するため、またはコールをキャンセルするためにオプションで使用できるを返します。

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

void _handleSuggestionResults(SearchError? searchError, List<Suggestion>? list) {
  if (searchError != null) {
    print("Autosuggest Error: " + searchError.toString());
    return;
  }

  // If error is null, list is guaranteed to be not empty.
  int listLength = list!.length;
  print("Autosuggest results: $listLength.");

  for (Suggestion autosuggestResult in list) {
    String addressText = "Not a place.";
    Place? place = autosuggestResult.place;
    if (place != null) {
      addressText = place.address.addressText;
    }

    print("Autosuggest result: " + autosuggestResult.title + " addressText: " + addressText);
  }
}

HERE では、で見つかったリストアイテムを記録し Suggestionます。 エラーがない場合、エンジンは結果のリストを保証します。エラーがない場合は null になります。

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

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

Suggestionは、 OfflineSearchEngineでも使用できます。 この場合は、OfflineSearchEngine のインスタンスSearchEngine とスワップします 。 この操作を行うには、マップ データ をダウンロードまたはキャッシュする必要があります。 この例について は、 GitHub で検索できる SearchHybrid のサンプルアプリ を参照してください。

リバースジオコード:地理座標から住所を検索

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

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

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

Future<void> _getAddressForCoordinates(GeoCoordinates geoCoordinates) async {
  SearchOptions reverseGeocodingOptions = SearchOptions();
  reverseGeocodingOptions.languageCode = LanguageCode.enGb;
  reverseGeocodingOptions.maxItems = 1;

  _searchEngine.searchByCoordinates(geoCoordinates, reverseGeocodingOptions,
      (SearchError? searchError, List<Place>? list) async {
    if (searchError != null) {
      _showDialog("Reverse geocoding", "Error: " + searchError.toString());
      return;
    }

    // If error is null, list is guaranteed to be not empty.
    _showDialog("Reverse geocoded address:", list!.first.address.addressText);
  });
}

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

リバースジオ コーディング応答には、エラーまたは結果が含ま SearchError れています。結果リストは、同時にヌルにすることも、同時にヌルにしないこともできます。

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

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

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

ジオコード:アドレスから場所への変換

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

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

ここでその方法をご案内します。 まず、検索したい場所の近くの座標を指定する必要があります。queryStringとして、正確な場所を見つけたい住所を設定します。

AddressQuery query = AddressQuery.withAreaCenter(queryString, geoCoordinates);

SearchOptions searchOptions = SearchOptions();
searchOptions.languageCode = LanguageCode.deDe;
searchOptions.maxItems = 30;

_searchEngine.searchByAddress(query, searchOptions, (SearchError? searchError, List<Place>? list) async {
  if (searchError != null) {
    _showDialog("Geocoding", "Error: " + searchError.toString());
    return;
  }

  String locationDetails = "";

  // If error is null, list is guaranteed to be not empty.
  for (Place geocodingResult in list!) {
    // ...
  }

  int itemsCount = list!.length;
  _showDialog("Geocoding result: $itemsCount", locationDetails);
});

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

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

関数がエラーなく完了したことを確認した後 Place 、要素の一覧表を確認します。

searchError が null の場合、結果 list は null ではないことが保証され、その逆も同様です。

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

for (Place geocodingResult in list!) {
  // Note: getGeoCoordinates() may return null only for Suggestions.
  GeoCoordinates geoCoordinates = geocodingResult.geoCoordinates!;
  Address address = geocodingResult.address;
  locationDetails = address.addressText +
      ". GeoCoordinates: " +
      geoCoordinates.latitude.toString() +
      ", " +
      geoCoordinates.longitude.toString();

  // ...    
}

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

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

ルートに沿って検索

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

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

HERE SDK には GeoCorridor 、ルートの実際の形状から検索領域を判断できるクラスがあります。 この方法では、パスの上または下にある検索結果のみが含まれます。

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

// Perform a search for charging stations along the found route.
void _searchAlongARoute(here.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.
  int halfWidthInMeters = 200;
  GeoCorridor routeCorridor = GeoCorridor(route.geometry.vertices, halfWidthInMeters);
  TextQueryArea queryArea =
      TextQueryArea.withCorridor(routeCorridor, _hereMapController.camera.state.targetCoordinates);
  TextQuery textQuery = TextQuery.withArea("charging station", queryArea);

  SearchOptions searchOptions = SearchOptions();
  searchOptions.languageCode = LanguageCode.enUs;
  searchOptions.maxItems = 30;

  _searchEngine.searchByText(textQuery, searchOptions, (SearchError? searchError, List<Place>? items) {
    if (searchError != null) {
      if (searchError == SearchError.polylineTooLong) {
        // Increasing halfWidthInMeters will result in less precise results with the benefit of a less
        // complex route shape.
        print("Search: Route too long or halfWidthInMeters too small.");
      } else {
        print("Search: 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: Search along route found ${items.length} charging stations:");
    for (Place place in items) {
      // ...
    }
  });
}

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

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

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

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

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

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

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

独自のデータの取り込み

HERE SDK は、場所を検索するときに、実行時に BYOD (個人データの持ち込み)をサポートします。 OfflineSearchEngineで検索できる場所にカスタムデータを挿入できます。 このような個人的な場所は、定期的な問い合わせで見つけることができます。 結果は、 HERE から直接送られてきた他の場所としてランク付けされます。

GeoPlace カスタムの Place データを含めることができる複数のインスタンスを作成できます。 これらのインスタンスは、データソースMyPlacesに追加できます。

List<GeoPlace> geoPlaces = [
        GeoPlace.makeMyPlace("Pizza Pino", GeoCoordinates(52.518032, 13.420632)),
        GeoPlace.makeMyPlace("PVR mdh", GeoCoordinates(52.51772, 13.42038)),
        GeoPlace.makeMyPlace("Harley's bar", GeoCoordinates(52.51764, 13.42062))
    ];

    _myPlaces.addPlaces(geoPlaces, (TaskOutcome taskOutcome) {
      if (taskOutcome == TaskOutcome.completed) {
        // Task completed.
      } else {
        // Task cancelled.
      }
    });

このデータソースは、次の場所OfflineSearchEngineに添付できます。

offlineSearchEngine.attach(_myPlaces, (TaskOutcome taskOutcome) {
  if (taskOutcome == TaskOutcome.completed) {
    // Task completed.
  } else {
    // Task cancelled.
  }
});

addPlaces()attach() は、アプリケーションによって一度に数千の場所が追加される可能性があるため、非同期で操作できます。 両方のメソッドがTaskHandleを返し、それにより操作をキャンセルできます。 操作が完了すると、イベントTaskOutcomeが通知されます。

以下に、そのような場所を見つける方法の例を示します。

double radiusInMeters = 100.0;
var queryArea = TextQueryArea.withCircle(GeoCircle(GeoCoordinates(52.518032, 13.420632), radiusInMeters));
TextQuery textQuery = TextQuery.withArea("Pizza Pino", queryArea);
offlineSearchEngine.searchByText(textQuery, SearchOptions(), (searchError, placeList) {
  // ...
});

インスタンス offlineSearchEngine がアクティブである限り、追加された場所はメモリに残ります。

SearchEngineに加えて、オフラインの使用例にも相当するものがあります。 OfflineSearchEngine :すでに上記で示したオンライン版と同じ方法で構築できます。

try {
  // Allows to search on already downloaded or cached map data.
  _offlineSearchEngine = OfflineSearchEngine();
} on InstantiationException {
  throw ("Initialization of OfflineSearchEngine failed.");
}

OfflineSearchEngineSearchEngineとほぼ同じインターフェイスを提供しますが、結果は、 HERE バックエンドサービスへの新しい要求を開始するのではなく、すでにダウンロードまたはキャッシュされているマップ データから取得されたものであるため、若干異なる場合があります。

この方法 では、たとえば、SearchEngineを使用しているときに受信したデータよりも古いデータを使用できます。 一方、このクラスでは、オンライン接続が不要なため、より迅速に結果を提供できます。

すでにキャッシュ されている か、または事前にロードされているオフラインの地図データのみを検索できます。 キャッシュされたマップ データのみを使用する場合、すべてのタイルがロードされているわけではありません。 この場合、これらのタイルもロードされるまで結果は見つかりません。 オフラインの地図では、この問題は発生しません。また、必要なマップ データがダウンロードした地域で利用可能であることが保証されます。 したがって、キャッシュされたマップ データに依存しないことをお勧めします。

使用可能 なOfflineSearchEngineインターフェイスのほとんどはSearchEngineで使用できますが 、それとは異なります。単に、すべてのオンライン機能がオフラインデータからもアクセスできるわけではありません。

また 、HERE Places API内の場所を特定するplaces ID は、オフライン検索結果とは異なります。

通常、自由形式な TextQueryであれば、オフラインのplacesは少なくとも半径 62.5 km 以内にあります。 首都はどこからでもグローバルに見つけることができます。 クエリ文字列に都市名などの専用の場所を追加すると、その場所の近くを検索します。

現在、日本ではオフラインでの検索はできません。また、検索結果は見つかりません。

以下に、OfflineSearchEngineで使用できるユースケースを示します 。 たとえば、移動中に接続が一時的に失われることがあります。 このような場合は、すでにダウンロードされているマップ データで検索することをお勧めします。

そのためには、まずデバイスの接続が失われていないかを確認する必要があります。 2 番目のステップとして、優先検索エンジンを使用できます。

if (useOnlineSearchEngine) {
  _onlineSearchEngine.searchByText(query, searchOptions, (SearchError? searchError, List<Place>? list) async {
    _handleSearchResults(searchError, list, queryString);
  });
} else {
  _offlineSearchEngine.searchByText(query, searchOptions, (SearchError? searchError, List<Place>? list) async {
    _handleSearchResults(searchError, list, queryString);
  });
}

検索結果を処理するに _handleSearchResults() は、サンプルアプリの一部として表示されている関数を使用します。結果を処理するコードはすでに上に表示されています。

同様に、アドレスをリバースジオコードすることもできます。

if (useOnlineSearchEngine) {
  _onlineSearchEngine.searchByCoordinates(geoCoordinates, reverseGeocodingOptions,
      (SearchError? searchError, List<Place>? list) async {
    _handleReverseGeocodingResults(searchError, list);
  });
} else {
  _offlineSearchEngine.searchByCoordinates(geoCoordinates, reverseGeocodingOptions,
      (SearchError? searchError, List<Place>? list) async {
    _handleReverseGeocodingResults(searchError, list);
  });
}

または、次のものを使用して、アドレスをジオコードして地理座標に変換できます。

if (useOnlineSearchEngine) {
  _onlineSearchEngine.searchByAddress(query, geocodingOptions, (SearchError? searchError, List<Place>? list) async {
    _handleGeocodingResults(searchError, list, queryString);
  });
} else {
  _offlineSearchEngine.searchByAddress(query, geocodingOptions, (SearchError? searchError, List<Place>? list) async {
    _handleGeocodingResults(searchError, list, queryString);
  });
}

デバイスがオンラインかどうかを確認するコードが HERE から削除されていることに注意してください。 この目的でサードパーティのプラグインを使用するか、実際の接続を試みることができます。その場合は OfflineSearchEngine 、次のようにして - または別の方法に切り替えることができます。 まずオフライン検索を試して、ユーザーに高速な操作環境を提供できますが、マップ データが利用できない場合は、オンラインで試すことができます。

このセクションのすべてのコードは、 GitHubsearch_hybrid_app例の一部として入手できます。

インデックスを作成

OfflineSearchEngine の検索結果を改善するために 、OfflineSearchIndex.Optionsを設定できます。 デフォルトでは、インデックス作成は無効になっています。

インデックス作成は、提供されている検索センターから離れている場合でも、インストールされているデータ Region の場所を検索するメカニズムを提供します。 これは、オンラインでのみ動作するため、検索インデックスを作成する必要がなく、デフォルトでこれを行う SearchEngine の動作と一致させるのに役立ちます。

オフラインマップ 」セクションのインデックス付けの詳細については、こちらを参照してください。

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

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