SDK for Android 開発者ガイド

プラットフォームデータ拡張子

プラットフォームデータ拡張機能 (PDE) を使用 すると、 SDK for Android からプラットフォームデータ拡張機能 API に簡単にアクセスできます。 この拡張機能を使用すると、さまざまな用途で後で使用できる幅広いデータにアクセスできます。 道路の高度、斜面、交通標識の表示などがあります。 使用例および PDE を介してアクセスできるデータのタイプの詳細については 、プラットフォーム Data Extension API 開発者ガイドを参照してください。

PDE 主題図レイヤ

PDE では、マップの内容が複数の主題図レイヤに分割されます。 各主題図データレイヤは特定のユースケースを提供し、道路高度など、そのレイヤに必要なデータのみを含みます。 PDE を使用するには、まずアプリに必要なデータを決定し、それに応じて PDE 主題図レイヤを選択する必要があります。 使用可能な主題図レイヤは、 PDE Layers API を介して検索できます。 その後、個 々の Layer API を使用して、対象の主題図レイヤを確認できます。 アプリで PDE を使用する前に、正しい主題図レイヤを選択して、使用するデータとその使用方法を決定する必要があります。 これは極めて重要なステップです。

注 : 小規模な道路でのルートの開始、より大きな道路への登坂、主要な部分の高速道路での滞在、目的地に近づいたときに小規模な道路に再び降りることが一般的です。 ルート全体の小さな道路に関するすべての情報を取得するに は、大量のデータが必要になるため、道路リンクに関連する主題図のレイヤーは、実際には 5 つのレイヤーに分割され、 HERE マップの機能的な道路クラスに対応します。 機能的なクラス 1 の道路は一般に高速道路ですが、機能的なクラス 5 の道路は目的地の近くでのみ使用される小さな道路です。 これらのレイヤーを使用するには、機能クラスのサフィックス 「_FCx" を追加してタイルレイヤーを指定する必要があります。xは 1 ~ 5 の数値です。 たとえば、 ROAD_GEOM_FC1です。 レイヤーが道路のリンクに関連付けられていない場合 ( PSTLCB_GEN レイヤーなど )_FCxは、サフィックス "" を追加してタイルレイヤーを指定する必要はありません。

PDE クラス

クラス 説明
PlatformDataRequest 指定したレイヤーおよび GeoBoundingBox オブジェクトを使用して PDE データリクエストを作成および実行するために使用されます。
PlatformDataResult PDE データリクエストを実行した結果。 レイヤー名でアクセスできる、要求されたレイヤーのデータが含まれています。 この java.util.Map クラスのオブジェクトは変更できませんが、使いやすさと相互運用性のためにインターフェイスを実装します。 Map<String, List<Map<String, String>>> 抽出メソッドを提供して、結果を基になるデータの生の表現であるに変換します。
PlatformDataItemCollection レイヤーデータを PlatformDataItem オブジェクトの配列で表します。 これは、platformDataResult.get("ROAD_GEOM_FC1")を呼び出すなどして、特定のレイヤーPlatformDataResultを要求することで得られます。このクラスのオブジェクトは変更できませんが、使いやすさと相互運用性を確保するためにjava.util.ListインターフェイスをPlatformDataItemCollection実装します。 extract() コレクションを List<Map<String, String>> オブジェクトに変換するメソッドも提供されます。
PlatformDataItem レイヤー内の実際のデータレコードを属性名と値のマップとして表します。 PlatformDataItemCollection これは、その内容を反復処理するか、または特定のインデックスでアイテムを要求することで取得できます。 複数の属性にショートカットメソッドが用意されていることに注意してください。たとえば、item.get("LINK_ID")の代わりにショートカットメソッドitem.getLinkId()を使用できます。 この java.util.Map クラスのオブジェクトは変更できませんが、使いやすさと相互運用性のためにインターフェイスを実装します。 extract() オブジェクトに変換するメソッドを提供 Map<String, String> します。

要約すると、PlatformDataRequestは、PlatformDataResultPlatformDataItemCollectionオブジェクトに対するレイヤー名の 1 つMapを作成します。このレイヤー名はPlatformDataItemオブジェクトの名前Listになり、各レイヤーにはMapの形式の属性名とその値が含まれます。

例 : PDE データを要求しています

次の例は、 PDE データを使用して機能を実装する方法を示しています。 目標は、平均的な高さに基づいて各道路セグメントを色分けすることです。 この機能を使用するには、ROAD_GEOM_FC1レイヤーとBASIC_HEIGHT_FC1レイヤーの PDE データが必要です。 現在、 PDE データを要求する唯一の方法は、で指定されたレイヤーを必要と GeoBoundingBoxするようになりました。

注意 :ROAD_GEOM_FC[number]BASIC_HEIGHT_FC[number] レイヤーはデータが複数のタイルに分割されるため、「タイル」レイヤーとも呼ばれます。 サーバーの制限により、一度に最大 15 のタイルを要求できます。 PDE では、非タイルレイヤーもサポートされています。

両方のレイヤーのデータを使用するに LINK_ID は、プロパティを使用して 2 つのレイヤーを結合する必要があります。 これについては、次のセクションで説明します。

次に、 Layer 要求のサンプル結果を示します。

ROAD_GEOM_FC1 レイヤーの API 結果 :

{
  "description": "Ungeneralized road, ferry and rail ferry geometry (polylines).<br/>If a road link crosses a tile boundary, it will be written into each of the tiles, each including the full link geometry. This simplifies use cases other than pure display of all geometry within a rectangle.",
  "attributes": {
    "LINK_ID": "Permanent link ID. Positive 64 bit Integer that globally identifies the road, carto or buildin footprint link, also across map releases. Link IDs are never reused.",
    "LONG_HAUL": "This link or polygon or POI is of major importance. It should be displayed at high zoom levels, and it should be included for routing in/through regions where no detailed routing is supported.",
    "NAME": "A name of this road line. Roads can have multiple names, in the same or multiple languages. This field contains any of those.",
    "NAMES": "List of all names for this object, in all languages [...]",
    "TUNNEL": "Is this navigable link or railroad a tunnel?",
    "BRIDGE": "Is this navigable link or railroad a bridge?",
    "LAT": "Latitude coordinates [10^-5 degree WGS84] along the polyline. ",
    "LON": "Longitude coordinates [10^-5 degree WGS84] along the polyline. ",
    "ZLEVEL": "(-4 ... 11) indicates the height of the point relative to another point on a grade separated crossing with any other line. Comma separated. If z-level is null then the value '0' is left out."
  },
  "referencedStaticContents": [],
  "tileRequestsLevel": 9,
  "tileX": 499,
  "tileY": 403,
  "isStaticContent": false
}

BASIC_HEIGHT_FC1 レイヤーの API 結果 :

{
  "description": "Link height values computed from a Digital Terrain Model, cleaned up for continuity along links, bridges and tunnels. Less accurate than ADAS link height values, but full coverage and sufficient for certain use cases.",
  "attributes": {
    "LINK_ID": "Permanent link ID. Positive 64 bit Integer that globally identifies the road, carto or building footprint link, also across map releases. Link IDs are never reused.",
    "DTM_MIN_HEIGHT": "The minimum height [cm above WGS84 ellipsoid] encountered along the link.",
    "DTM_MAX_HEIGHT": "The maximum height [cm above WGS84 ellipsoid] encountered along the link.",
    "DTM_AVG_HEIGHT": "The average height [cm above WGS84 ellipsoid] along the link.",
    "DTM_REF_ZCOORD": "Height [cm above WGS84 ellipsoid] at the reference node of the link.",
    "DTM_NONREF_ZCOORD": "Height [cm above WGS84 ellipsoid] at the non-reference node of the link."
  },
  "referencedStaticContents": [],
  "tileRequestsLevel": 9,
  "tileX": 496,
  "tileY": 358,
  "isStaticContent": false
}

PDE レイヤーの使用を開始するには PlatformDataRequest 、オブジェクトを作成します。

Set<String> layers = new HashSet<String>(Arrays.asList("LINK_FC1", "BASIC_HEIGHT_FC1"));
GeoBoundingBox box = mapView.getBoundingBox();
PlatformDataRequest request =
  PlatformDataRequest.createBoundingBoxRequest(RoadElevationProcessor.LAYERS, box);

無効なパラメータを使用してリクエストを作成しよう java.lang.IllegalArgumentExceptionとすると、が発生することに注意してください。

次に Listener<PlatformDataResult> 、リクエストの結果を取得するオブジェクトを指定する必要があります。

request.execute(new PlatformDataRequest.Listener<PlatformDataResult>() {
  @Override
  public void onCompleted(PlatformDataResult data, PlatformDataRequest.Error error) {
    if (error != null) {
      Log.w(TAG, "PlatformDataRequest failed with error: " + error);
    } else {
      // process received data
      RoadElevationProcessor processor = new RoadElevationProcessor(data);
      processor.process(new Listener<List<MapObject>>() {
        @Override
        public void onResult(List<MapObject> result) {
          m_elevationPolylines = result;
          m_elevationLegend.setVisibility(View.VISIBLE);
          m_map.addMapObjects(m_elevationPolylines);
          onRequestEnd(null);
        }
      });
    }
  }
});

例 : PDE データを処理しています

データの結果が正常に取得された後、データを処理する必要があります。 上記の例では、マップ ビューバウンディング ボックスで制限されているROAD_GEOM_FC1BASIC_HEIGHT_FC1データを要求しています。 チュートリアル用 PlatformDataProcessorに、サンプルのデータプロセッサクラスを実装しました。このクラスは、レイヤーを結合するメソッドを提供し、結合されたデータを使用するように拡張できます。 これらのクラスを使用して、色機能を実装します。

public abstract class PlatformDataProcessor<T> {
  protected final PlatformDataResult m_data;
  private Handler m_handler = new Handler(Looper.getMainLooper());

  public PlatformDataProcessor(PlatformDataResult data) {
    m_data = data;
  }

  public void process(final Listener<T> listener) {
    new Thread(new Runnable() {
      @Override
      public void run() {
        final T result = doProcess();
        m_handler.post(new Runnable() {
          @Override
          public void run() {
            listener.onResult(result);
          }
        });
      }
    }).start();
  }

  protected abstract T doProcess();

  protected Map<String, PlatformDataItem> map(Indexer indexer, PlatformDataItemCollection items) {
    Map<String, PlatformDataItem> ret = new HashMap<String, PlatformDataItem>();
    map(indexer, items, ret);
    return ret;
  }

  protected void map(Indexer indexer, PlatformDataItemCollection items,
      Map<String, PlatformDataItem> output) {
    for (PlatformDataItem item : items) {
      output.put(indexer.getIndexValue(item), item);
    }
  }

  protected Map<String, List<PlatformDataItem>> multimap(MultiIndexer indexer,
      PlatformDataItemCollection items) {
    Map<String, List<PlatformDataItem>> ret = new HashMap<String, List<PlatformDataItem>>();
    multimap(indexer, items, ret);
    return ret;
  }

  protected void multimap(MultiIndexer indexer, PlatformDataItemCollection items,
      Map<String, List<PlatformDataItem>> output) {
    for (PlatformDataItem item : items) {
      for (String value : indexer.getIndexValue(item)) {
        List<PlatformDataItem> entry = output.get(value);
        if (entry == null) {
          entry = new ArrayList<PlatformDataItem>();
          output.put(value, entry);
        }
        entry.add(item);
      }
    }
  }

  protected Map<PlatformDataItem, PlatformDataItem> join(Indexer commonIndexer,
      PlatformDataItemCollection mainLayer, PlatformDataItemCollection otherLayer) {
    return join(commonIndexer, mainLayer, commonIndexer, otherLayer);
  }

  protected Map<PlatformDataItem, PlatformDataItem> join(Indexer mainIndexer,
      PlatformDataItemCollection mainLayer, Indexer otherIndexer,
      PlatformDataItemCollection otherLayer) {
    Map<PlatformDataItem, PlatformDataItem> ret =
        new HashMap<PlatformDataItem, PlatformDataItem>();
    Map<String, PlatformDataItem> mappedItems = map(otherIndexer, otherLayer);

    for (PlatformDataItem item : mainLayer) {
      String value = mainIndexer.getIndexValue(item);
      PlatformDataItem matchedItem = mappedItems.get(value);
      ret.put(item, matchedItem);
    }
    return ret;
  }

  protected Map<PlatformDataItem, List<PlatformDataItem>> join(MultiIndexer mainIndexer,
      PlatformDataItemCollection mainLayer, PlatformDataItemCollection otherLayer) {
    return join(mainIndexer, mainLayer, mainIndexer, otherLayer);
  }

  protected Map<PlatformDataItem, List<PlatformDataItem>> join(MultiIndexer mainIndexer,
      PlatformDataItemCollection mainLayer, MultiIndexer otherIndexer,
      PlatformDataItemCollection otherLayer) {
    Map<String, List<PlatformDataItem>> mappedItems = multimap(otherIndexer, otherLayer);
    Map<PlatformDataItem, List<PlatformDataItem>> ret =
        new HashMap<PlatformDataItem, List<PlatformDataItem>>();
    for (PlatformDataItem item : mainLayer) {
      for (String value : mainIndexer.getIndexValue(item)) {
        List<PlatformDataItem> matchedItems = mappedItems.get(value);
        List<PlatformDataItem> entry = ret.get(item);
        if (entry == null) {
          entry = new ArrayList<PlatformDataItem>();
          ret.put(item, entry);
        }
        if (matchedItems != null) {
          entry.addAll(matchedItems);
        }
      }
    }
    return ret;
  }

  interface Indexer {
    String getIndexValue(PlatformDataItem item);
  }

  interface MultiIndexer {
    String[] getIndexValue(PlatformDataItem item);
  }

  interface Listener<T> {
    void onResult(T result);
  }
}

PlatformDataProcessor.join() 複数のデータ項目を使用できるプロパティを使用して主題図レイヤを内部結合する方法を使用します。 たとえば TRAFFIC_SIGN_FCx 、主題図レイヤ LINK_IDS には LINK_ID、最大 2 つのが含まれるプロパティがあります。

次に、 createRoadElevationProcessor.RoadElevationProcessorclass は、道路セグメントの平均高さに従って色分けするためにPlatformDataProcessor拡張されます。 このクラスには、結果と MapPolyline 、そのオブジェクトを対象とした専用のマップコンテナが必要です。 提供 PlatformDataProcessor されているインデクサブロックに応じて、基本クラスが主題図レイヤデータの内部結合を実行することに注意 RoadElevationProcessor してください。クラスは、結合されたデータを使用して、目的の機能を実装します。

public class RoadElevationProcessor extends PlatformDataProcessor<List<MapObject>> {
  public static final String ROAD_GEOM_LAYER = "ROAD_GEOM_FC1";
  public static final String BASIC_HEIGHT_LAYER = "BASIC_HEIGHT_FC1";
  public static final Set<String> LAYERS = new HashSet<String>(Arrays.asList(ROAD_GEOM_LAYER,
      BASIC_HEIGHT_LAYER));

  public RoadElevationProcessor(PlatformDataResult data) {
    super(data);
  }

  protected List<MapObject> doProcess() {
    List<MapObject> polylines = new ArrayList<MapObject>();
    PlatformDataItemCollection roadGeomLayer = m_data.get(ROAD_GEOM_LAYER);
    PlatformDataItemCollection basicHeightLayer = m_data.get(BASIC_HEIGHT_LAYER);

    Map<PlatformDataItem, PlatformDataItem> combinedData =
        join(LINK_ID_INDEXER, roadGeomLayer, basicHeightLayer);

    for (Map.Entry<PlatformDataItem, PlatformDataItem> entry : combinedData.entrySet()) {
      PlatformDataItem roadGeomItem = entry.getKey();
      PlatformDataItem basicHeightItem = entry.getValue();
      List<GeoCoordinate> linkGeometry = roadGeomItem.getCoordinates();
      if (linkGeometry.size() > 1) {
        GeoPolyline geoPolyline = new GeoPolyline(linkGeometry);
        MapPolyline mapPolyline = new MapPolyline(geoPolyline);
        mapPolyline.setLineColor(calculateColor(basicHeightItem.getAverageHeight()));
        mapPolyline.setLineWidth(10);
        polylines.add(mapPolyline);
      }
    }

    return polylines;
  }

  private int calculateColor(int height) {
    if (height > 75000) {
      return 0xff00695c;
    } else if (height > 25000) {
      return 0xff009688;
    } else if (height > 0) {
      return 0xff4db6ac;
    } else if (height > -25000) {
      return 0xff7986cb;
    } else if (height > -75000) {
      return 0xff5c6bc0;
    } else {
      return 0xff3f51b5;
    }
  }

  private Indexer LINK_ID_INDEXER = new Indexer() {
    @Override
    public String getIndexValue(PlatformDataItem item) {
      return item.getLinkId();
    }
  };
}

RoadElevationProcessor クラスの主なメソッドは doProcess() method です。

このメソッドの最初の処理は、 2 つの異なる主題図レイヤからのデータを " インデクサ " ブロックに結合することです。 HERE データは LINK_IDの経由で結合されます。 linkId プロパティは PlatformDataItem 、クラスのショートカットプロパティとして使用できます。 データを結合すると、各 ROAD_GEOM_FC1 データ項目が関連 BASIC_HEIGHT_FC1 するデータ項目と内部的に結合 Map<PlatformDataItem, PlatformDataItem>され、結合されたデータが実際の型があるディクショナリとして返されます。 各キーと値のペアは、この機能に必要なデータを提供します。ROAD_GEOM_FC1主題図のレイヤデータを表すキーPlatformDataItemは、道路セグメントの座標などの道路のジオメトリを提供し、BASIC_HEIGHT_FC1主題図のレイヤデータを表すPlatformDataItemタイプの値はその道路セグメントの平均高さを提供します。 結合されたデータは、目的の機能の実装に必要なすべてのデータを提供します。

{
  BRIDGE = N;
  LAT = "5246124,2";
  "LINK_ID" = 936938339;
  LON = "1342560,24";
  "LONG_HAUL" = Y;
  NAME = A100;
  NAMES = "GERBNTunnel BritzGERY\"tU|n@l \"brItsGERBNA100GERN\"?a: \"hUn|d6t;GERN\"?aU|to:|ba:n ?aIn|\"hUn|d6t;GERY\"?a: ?aIn|\"hUn|d6t;GERN\"?aU|to:|ba:n \"hUn|d6tGERBNStadtring BerlinGERY\"Stat|rIN bEr|\"li:n";
  TUNNEL = Y;
  ZLEVEL = ",";
} = {
  "DTM_AVG_HEIGHT" = 8500;
  "DTM_MAX_HEIGHT" = 8693;
  "DTM_MIN_HEIGHT" = 8099;
  "DTM_NONREF_ZCOORD" = 8500;
  "DTM_REF_ZCOORD" = 8500;
  "LINK_ID" = 936938339;
}

キーと値のペアが同じで LINK_IDあることに注意してください。